aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/driver/Driver.cpp242
-rw-r--r--tools/driver/Driver.h5
-rw-r--r--tools/driver/Platform.cpp25
-rw-r--r--tools/driver/Platform.h56
-rw-r--r--tools/lldb-mi/Driver.cpp1299
-rw-r--r--tools/lldb-mi/Driver.h163
-rw-r--r--tools/lldb-mi/MICmdArgContext.cpp255
-rw-r--r--tools/lldb-mi/MICmdArgContext.h61
-rw-r--r--tools/lldb-mi/MICmdArgSet.cpp420
-rw-r--r--tools/lldb-mi/MICmdArgSet.h109
-rw-r--r--tools/lldb-mi/MICmdArgValBase.cpp171
-rw-r--r--tools/lldb-mi/MICmdArgValBase.h157
-rw-r--r--tools/lldb-mi/MICmdArgValConsume.cpp119
-rw-r--r--tools/lldb-mi/MICmdArgValConsume.h63
-rw-r--r--tools/lldb-mi/MICmdArgValFile.cpp204
-rw-r--r--tools/lldb-mi/MICmdArgValFile.h61
-rw-r--r--tools/lldb-mi/MICmdArgValListBase.cpp221
-rw-r--r--tools/lldb-mi/MICmdArgValListBase.h103
-rw-r--r--tools/lldb-mi/MICmdArgValListOfN.cpp189
-rw-r--r--tools/lldb-mi/MICmdArgValListOfN.h98
-rw-r--r--tools/lldb-mi/MICmdArgValNumber.cpp167
-rw-r--r--tools/lldb-mi/MICmdArgValNumber.h65
-rw-r--r--tools/lldb-mi/MICmdArgValOptionLong.cpp319
-rw-r--r--tools/lldb-mi/MICmdArgValOptionLong.h109
-rw-r--r--tools/lldb-mi/MICmdArgValOptionShort.cpp128
-rw-r--r--tools/lldb-mi/MICmdArgValOptionShort.h65
-rw-r--r--tools/lldb-mi/MICmdArgValString.cpp502
-rw-r--r--tools/lldb-mi/MICmdArgValString.h76
-rw-r--r--tools/lldb-mi/MICmdArgValThreadGrp.cpp173
-rw-r--r--tools/lldb-mi/MICmdArgValThreadGrp.h66
-rw-r--r--tools/lldb-mi/MICmdBase.cpp263
-rw-r--r--tools/lldb-mi/MICmdBase.h156
-rw-r--r--tools/lldb-mi/MICmdCmd.cpp174
-rw-r--r--tools/lldb-mi/MICmdCmd.h104
-rw-r--r--tools/lldb-mi/MICmdCmdBreak.cpp1026
-rw-r--r--tools/lldb-mi/MICmdCmdBreak.h292
-rw-r--r--tools/lldb-mi/MICmdCmdData.cpp1365
-rw-r--r--tools/lldb-mi/MICmdCmdData.h374
-rw-r--r--tools/lldb-mi/MICmdCmdEnviro.cpp143
-rw-r--r--tools/lldb-mi/MICmdCmdEnviro.h69
-rw-r--r--tools/lldb-mi/MICmdCmdExec.cpp982
-rw-r--r--tools/lldb-mi/MICmdCmdExec.h310
-rw-r--r--tools/lldb-mi/MICmdCmdFile.cpp184
-rw-r--r--tools/lldb-mi/MICmdCmdFile.h71
-rw-r--r--tools/lldb-mi/MICmdCmdGdbInfo.cpp232
-rw-r--r--tools/lldb-mi/MICmdCmdGdbInfo.h93
-rw-r--r--tools/lldb-mi/MICmdCmdGdbSet.cpp260
-rw-r--r--tools/lldb-mi/MICmdCmdGdbSet.h96
-rw-r--r--tools/lldb-mi/MICmdCmdGdbThread.cpp100
-rw-r--r--tools/lldb-mi/MICmdCmdGdbThread.h61
-rw-r--r--tools/lldb-mi/MICmdCmdMiscellanous.cpp588
-rw-r--r--tools/lldb-mi/MICmdCmdMiscellanous.h175
-rw-r--r--tools/lldb-mi/MICmdCmdStack.cpp634
-rw-r--r--tools/lldb-mi/MICmdCmdStack.h184
-rw-r--r--tools/lldb-mi/MICmdCmdSupportInfo.cpp129
-rw-r--r--tools/lldb-mi/MICmdCmdSupportInfo.h69
-rw-r--r--tools/lldb-mi/MICmdCmdSupportList.cpp102
-rw-r--r--tools/lldb-mi/MICmdCmdSupportList.h63
-rw-r--r--tools/lldb-mi/MICmdCmdTarget.cpp217
-rw-r--r--tools/lldb-mi/MICmdCmdTarget.h70
-rw-r--r--tools/lldb-mi/MICmdCmdThread.cpp207
-rw-r--r--tools/lldb-mi/MICmdCmdThread.h76
-rw-r--r--tools/lldb-mi/MICmdCmdTrace.cpp99
-rw-r--r--tools/lldb-mi/MICmdCmdTrace.h61
-rw-r--r--tools/lldb-mi/MICmdCmdVar.cpp1492
-rw-r--r--tools/lldb-mi/MICmdCmdVar.h382
-rw-r--r--tools/lldb-mi/MICmdCommands.cpp135
-rw-r--r--tools/lldb-mi/MICmdCommands.h36
-rw-r--r--tools/lldb-mi/MICmdData.cpp24
-rw-r--r--tools/lldb-mi/MICmdData.h74
-rw-r--r--tools/lldb-mi/MICmdFactory.cpp229
-rw-r--r--tools/lldb-mi/MICmdFactory.h99
-rw-r--r--tools/lldb-mi/MICmdInterpreter.cpp301
-rw-r--r--tools/lldb-mi/MICmdInterpreter.h78
-rw-r--r--tools/lldb-mi/MICmdInvoker.cpp333
-rw-r--r--tools/lldb-mi/MICmdInvoker.h118
-rw-r--r--tools/lldb-mi/MICmdMgr.cpp257
-rw-r--r--tools/lldb-mi/MICmdMgr.h83
-rw-r--r--tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp110
-rw-r--r--tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h88
-rw-r--r--tools/lldb-mi/MICmnBase.cpp144
-rw-r--r--tools/lldb-mi/MICmnBase.h60
-rw-r--r--tools/lldb-mi/MICmnConfig.h50
-rw-r--r--tools/lldb-mi/MICmnLLDBBroadcaster.cpp89
-rw-r--r--tools/lldb-mi/MICmnLLDBBroadcaster.h61
-rw-r--r--tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp1312
-rw-r--r--tools/lldb-mi/MICmnLLDBDebugSessionInfo.h236
-rw-r--r--tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp570
-rw-r--r--tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h139
-rw-r--r--tools/lldb-mi/MICmnLLDBDebugger.cpp707
-rw-r--r--tools/lldb-mi/MICmnLLDBDebugger.h125
-rw-r--r--tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp1566
-rw-r--r--tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h97
-rw-r--r--tools/lldb-mi/MICmnLLDBProxySBValue.cpp153
-rw-r--r--tools/lldb-mi/MICmnLLDBProxySBValue.h47
-rw-r--r--tools/lldb-mi/MICmnLLDBUtilSBValue.cpp324
-rw-r--r--tools/lldb-mi/MICmnLLDBUtilSBValue.h71
-rw-r--r--tools/lldb-mi/MICmnLog.cpp355
-rw-r--r--tools/lldb-mi/MICmnLog.h143
-rw-r--r--tools/lldb-mi/MICmnLogMediumFile.cpp420
-rw-r--r--tools/lldb-mi/MICmnLogMediumFile.h96
-rw-r--r--tools/lldb-mi/MICmnMIOutOfBandRecord.cpp161
-rw-r--r--tools/lldb-mi/MICmnMIOutOfBandRecord.h110
-rw-r--r--tools/lldb-mi/MICmnMIResultRecord.cpp142
-rw-r--r--tools/lldb-mi/MICmnMIResultRecord.h106
-rw-r--r--tools/lldb-mi/MICmnMIValue.cpp64
-rw-r--r--tools/lldb-mi/MICmnMIValue.h64
-rw-r--r--tools/lldb-mi/MICmnMIValueConst.cpp98
-rw-r--r--tools/lldb-mi/MICmnMIValueConst.h72
-rw-r--r--tools/lldb-mi/MICmnMIValueList.cpp203
-rw-r--r--tools/lldb-mi/MICmnMIValueList.h70
-rw-r--r--tools/lldb-mi/MICmnMIValueResult.cpp141
-rw-r--r--tools/lldb-mi/MICmnMIValueResult.h75
-rw-r--r--tools/lldb-mi/MICmnMIValueTuple.cpp227
-rw-r--r--tools/lldb-mi/MICmnMIValueTuple.h76
-rw-r--r--tools/lldb-mi/MICmnResources.cpp409
-rw-r--r--tools/lldb-mi/MICmnResources.h351
-rw-r--r--tools/lldb-mi/MICmnStreamStderr.cpp257
-rw-r--r--tools/lldb-mi/MICmnStreamStderr.h76
-rw-r--r--tools/lldb-mi/MICmnStreamStdin.cpp421
-rw-r--r--tools/lldb-mi/MICmnStreamStdin.h125
-rw-r--r--tools/lldb-mi/MICmnStreamStdinLinux.cpp212
-rw-r--r--tools/lldb-mi/MICmnStreamStdinLinux.h75
-rw-r--r--tools/lldb-mi/MICmnStreamStdinWindows.cpp279
-rw-r--r--tools/lldb-mi/MICmnStreamStdinWindows.h81
-rw-r--r--tools/lldb-mi/MICmnStreamStdout.cpp230
-rw-r--r--tools/lldb-mi/MICmnStreamStdout.h75
-rw-r--r--tools/lldb-mi/MICmnThreadMgrStd.cpp167
-rw-r--r--tools/lldb-mi/MICmnThreadMgrStd.h134
-rw-r--r--tools/lldb-mi/MIDataTypes.h100
-rw-r--r--tools/lldb-mi/MIDriver.cpp1276
-rw-r--r--tools/lldb-mi/MIDriver.h182
-rw-r--r--tools/lldb-mi/MIDriverBase.cpp195
-rw-r--r--tools/lldb-mi/MIDriverBase.h78
-rw-r--r--tools/lldb-mi/MIDriverMain.cpp393
-rw-r--r--tools/lldb-mi/MIDriverMgr.cpp762
-rw-r--r--tools/lldb-mi/MIDriverMgr.h138
-rw-r--r--tools/lldb-mi/MIReadMe.txt261
-rw-r--r--tools/lldb-mi/MIUtilDateTimeStd.cpp84
-rw-r--r--tools/lldb-mi/MIUtilDateTimeStd.h55
-rw-r--r--tools/lldb-mi/MIUtilDebug.cpp128
-rw-r--r--tools/lldb-mi/MIUtilDebug.h96
-rw-r--r--tools/lldb-mi/MIUtilFileStd.cpp290
-rw-r--r--tools/lldb-mi/MIUtilFileStd.h65
-rw-r--r--tools/lldb-mi/MIUtilMapIdToVariant.cpp124
-rw-r--r--tools/lldb-mi/MIUtilMapIdToVariant.h148
-rw-r--r--tools/lldb-mi/MIUtilSingletonBase.h71
-rw-r--r--tools/lldb-mi/MIUtilSingletonHelper.h95
-rw-r--r--tools/lldb-mi/MIUtilString.cpp680
-rw-r--r--tools/lldb-mi/MIUtilString.h85
-rw-r--r--tools/lldb-mi/MIUtilSystemLinux.cpp119
-rw-r--r--tools/lldb-mi/MIUtilSystemLinux.h57
-rw-r--r--tools/lldb-mi/MIUtilSystemOsx.cpp125
-rw-r--r--tools/lldb-mi/MIUtilSystemOsx.h57
-rw-r--r--tools/lldb-mi/MIUtilSystemWindows.cpp151
-rw-r--r--tools/lldb-mi/MIUtilSystemWindows.h56
-rw-r--r--tools/lldb-mi/MIUtilTermios.cpp69
-rw-r--r--tools/lldb-mi/MIUtilTermios.h30
-rw-r--r--tools/lldb-mi/MIUtilThreadBaseStd.cpp339
-rw-r--r--tools/lldb-mi/MIUtilThreadBaseStd.h170
-rw-r--r--tools/lldb-mi/MIUtilVariant.cpp392
-rw-r--r--tools/lldb-mi/MIUtilVariant.h288
-rw-r--r--tools/lldb-mi/Platform.cpp109
-rw-r--r--tools/lldb-mi/Platform.h109
-rw-r--r--tools/lldb-platform/lldb-platform.cpp7
165 files changed, 37063 insertions, 146 deletions
diff --git a/tools/driver/Driver.cpp b/tools/driver/Driver.cpp
index 78d3a7e1c037..854310031c37 100644
--- a/tools/driver/Driver.cpp
+++ b/tools/driver/Driver.cpp
@@ -15,6 +15,14 @@
#include <limits.h>
#include <fcntl.h>
+// Includes for pipe()
+#if defined(_WIN32)
+#include <io.h>
+#include <fcntl.h>
+#else
+#include <unistd.h>
+#endif
+
#include <string>
#include <thread>
@@ -477,63 +485,19 @@ Driver::GetScriptLanguage() const
}
void
-Driver::ExecuteInitialCommands (bool before_file)
+Driver::WriteInitialCommands (bool before_file, SBStream &strm)
{
- size_t num_commands;
- std::vector<std::pair<bool, std::string> > *command_set;
- if (before_file)
- command_set = &(m_option_data.m_initial_commands);
- else
- command_set = &(m_option_data.m_after_file_commands);
+ std::vector<std::pair<bool, std::string> > &command_set = before_file ? m_option_data.m_initial_commands :
+ m_option_data.m_after_file_commands;
- num_commands = command_set->size();
- SBCommandReturnObject result;
- bool old_async = GetDebugger().GetAsync();
- GetDebugger().SetAsync(false);
- for (size_t idx = 0; idx < num_commands; idx++)
+ for (const auto &command_pair : command_set)
{
- bool is_file = (*command_set)[idx].first;
- const char *command = (*command_set)[idx].second.c_str();
- char command_string[PATH_MAX * 2];
- const bool dump_stream_only_if_no_immediate = true;
- const char *executed_command = command;
- if (is_file)
- {
- ::snprintf (command_string, sizeof(command_string), "command source -s %i '%s'", m_option_data.m_source_quietly, command);
- executed_command = command_string;
- }
-
- m_debugger.GetCommandInterpreter().HandleCommand (executed_command, result, false);
- if (!m_option_data.m_source_quietly || result.Succeeded() == false)
- {
- const size_t output_size = result.GetOutputSize();
- if (output_size > 0)
- {
- const char *cstr = result.GetOutput(dump_stream_only_if_no_immediate);
- if (cstr)
- printf ("%s", cstr);
- }
- const size_t error_size = result.GetErrorSize();
- if (error_size > 0)
- {
- const char *cstr = result.GetError(dump_stream_only_if_no_immediate);
- if (cstr)
- printf ("%s", cstr);
- }
- }
-
- if (result.Succeeded() == false)
- {
- const char *type = before_file ? "before file" : "after_file";
- if (is_file)
- ::fprintf(stderr, "Aborting %s command execution, command file: '%s' failed.\n", type, command);
- else
- ::fprintf(stderr, "Aborting %s command execution, command: '%s' failed.\n", type, command);
- break;
- }
- result.Clear();
+ const char *command = command_pair.second.c_str();
+ if (command_pair.first)
+ strm.Printf("command source -s %i '%s'\n", m_option_data.m_source_quietly, command);
+ else
+ strm.Printf("%s\n", command);
}
- GetDebugger().SetAsync(old_async);
}
bool
@@ -857,8 +821,8 @@ Driver::MainLoop ()
m_debugger.SetErrorFileHandle (stderr, false);
m_debugger.SetOutputFileHandle (stdout, false);
- m_debugger.SetInputFileHandle (stdin, true);
-
+ m_debugger.SetInputFileHandle (stdin, false); // Don't take ownership of STDIN yet...
+
m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
struct winsize window_size;
@@ -882,77 +846,61 @@ Driver::MainLoop ()
}
// Now we handle options we got from the command line
- // First source in the commands specified to be run before the file arguments are processed.
- ExecuteInitialCommands(true);
-
- // Was there a core file specified?
- std::string core_file_spec("");
- if (!m_option_data.m_core_file.empty())
- core_file_spec.append("--core ").append(m_option_data.m_core_file);
+ SBStream commands_stream;
- char command_string[PATH_MAX * 2];
+ // First source in the commands specified to be run before the file arguments are processed.
+ WriteInitialCommands(true, commands_stream);
+
const size_t num_args = m_option_data.m_args.size();
if (num_args > 0)
{
char arch_name[64];
if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
- ::snprintf (command_string,
- sizeof (command_string),
- "target create --arch=%s %s \"%s\"",
- arch_name,
- core_file_spec.c_str(),
- m_option_data.m_args[0].c_str());
+ commands_stream.Printf("target create --arch=%s \"%s\"", arch_name, m_option_data.m_args[0].c_str());
else
- ::snprintf (command_string,
- sizeof(command_string),
- "target create %s \"%s\"",
- core_file_spec.c_str(),
- m_option_data.m_args[0].c_str());
-
- m_debugger.HandleCommand (command_string);
+ commands_stream.Printf("target create \"%s\"", m_option_data.m_args[0].c_str());
+
+ if (!m_option_data.m_core_file.empty())
+ {
+ commands_stream.Printf(" --core \"%s\"", m_option_data.m_core_file.c_str());
+ }
+ commands_stream.Printf("\n");
if (num_args > 1)
{
- m_debugger.HandleCommand ("settings clear target.run-args");
- char arg_cstr[1024];
+ commands_stream.Printf ("settings set -- target.run-args ");
for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
{
- ::snprintf (arg_cstr,
- sizeof(arg_cstr),
- "settings append target.run-args \"%s\"",
- m_option_data.m_args[arg_idx].c_str());
- m_debugger.HandleCommand (arg_cstr);
+ const char *arg_cstr = m_option_data.m_args[arg_idx].c_str();
+ if (strchr(arg_cstr, '"') == NULL)
+ commands_stream.Printf(" \"%s\"", arg_cstr);
+ else
+ commands_stream.Printf(" '%s'", arg_cstr);
}
+ commands_stream.Printf("\n");
}
}
- else if (!core_file_spec.empty())
+ else if (!m_option_data.m_core_file.empty())
{
- ::snprintf (command_string,
- sizeof(command_string),
- "target create %s",
- core_file_spec.c_str());
- m_debugger.HandleCommand (command_string);;
+ commands_stream.Printf("target create --core \"%s\"\n", m_option_data.m_core_file.c_str());
}
else if (!m_option_data.m_process_name.empty())
{
- ::snprintf (command_string,
- sizeof(command_string),
- "process attach --name '%s'%s",
- m_option_data.m_process_name.c_str(),
- m_option_data.m_wait_for ? " --waitfor" : "");
- m_debugger.HandleCommand (command_string);
+ commands_stream.Printf ("process attach --name \"%s\"", m_option_data.m_process_name.c_str());
+
+ if (m_option_data.m_wait_for)
+ commands_stream.Printf(" --waitfor");
+
+ commands_stream.Printf("\n");
+
}
else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid)
{
- ::snprintf (command_string,
- sizeof(command_string),
- "process attach --pid %" PRIu64,
- m_option_data.m_process_pid);
- m_debugger.HandleCommand (command_string);
+ commands_stream.Printf ("process attach --pid %" PRIu64 "\n", m_option_data.m_process_pid);
}
- ExecuteInitialCommands(false);
-
+ WriteInitialCommands(false, commands_stream);
+
// Now that all option parsing is done, we try and parse the .lldbinit
// file in the current working directory
sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
@@ -964,6 +912,90 @@ Driver::MainLoop ()
bool handle_events = true;
bool spawn_thread = false;
+
+ // Check if we have any data in the commands stream, and if so, save it to a temp file
+ // so we can then run the command interpreter using the file contents.
+ const char *commands_data = commands_stream.GetData();
+ const size_t commands_size = commands_stream.GetSize();
+ if (commands_data && commands_size)
+ {
+ enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE
+
+ bool success = true;
+ int fds[2] = { -1, -1 };
+ int err = 0;
+#ifdef _WIN32
+ err = _pipe(fds, commands_size, O_BINARY);
+#else
+ err = pipe(fds);
+#endif
+ if (err == 0)
+ {
+ if (write (fds[WRITE], commands_data, commands_size) == commands_size)
+ {
+ // Close the write end of the pipe so when we give the read end to
+ // the debugger/command interpreter it will exit when it consumes all
+ // of the data
+#ifdef _WIN32
+ _close(fds[WRITE]); fds[WRITE] = -1;
+#else
+ close(fds[WRITE]); fds[WRITE] = -1;
+#endif
+ // Now open the read file descriptor in a FILE * that we can give to
+ // the debugger as an input handle
+ FILE *commands_file = fdopen(fds[READ], "r");
+ if (commands_file)
+ {
+ fds[READ] = -1; // The FILE * 'commands_file' now owns the read descriptor
+ // Hand ownership if the FILE * over to the debugger for "commands_file".
+ m_debugger.SetInputFileHandle (commands_file, true);
+ m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
+ }
+ else
+ {
+ fprintf(stderr, "error: fdopen(%i, \"r\") failed (errno = %i) when trying to open LLDB commands pipe\n", fds[READ], errno);
+ success = false;
+ }
+ }
+ }
+ else
+ {
+ fprintf(stderr, "error: can't create pipe file descriptors for LLDB commands\n");
+ success = false;
+ }
+
+ // Close any pipes that we still have ownership of
+ if ( fds[WRITE] != -1)
+ {
+#ifdef _WIN32
+ _close(fds[WRITE]); fds[WRITE] = -1;
+#else
+ close(fds[WRITE]); fds[WRITE] = -1;
+#endif
+
+ }
+
+ if ( fds[READ] != -1)
+ {
+#ifdef _WIN32
+ _close(fds[READ]); fds[READ] = -1;
+#else
+ close(fds[READ]); fds[READ] = -1;
+#endif
+ }
+
+ // Something went wrong with command pipe
+ if (!success)
+ {
+ exit(1);
+ }
+
+ }
+
+ // Now set the input file handle to STDIN and run the command
+ // interpreter again in interactive mode and let the debugger
+ // take ownership of stdin
+ m_debugger.SetInputFileHandle (stdin, true);
m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
reset_stdin_termios();
@@ -1032,6 +1064,12 @@ sigcont_handler (int signo)
int
main (int argc, char const *argv[], const char *envp[])
{
+#ifdef _MSC_VER
+ // disable buffering on windows
+ setvbuf(stdout, NULL, _IONBF, 0);
+ setvbuf(stdin , NULL, _IONBF, 0);
+#endif
+
SBDebugger::Initialize();
SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
diff --git a/tools/driver/Driver.h b/tools/driver/Driver.h
index 699244685d06..8b6c6eebdd56 100644
--- a/tools/driver/Driver.h
+++ b/tools/driver/Driver.h
@@ -23,9 +23,6 @@
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBError.h"
-#define ASYNC true
-#define NO_ASYNC false
-
class IOChannel;
class Driver : public lldb::SBBroadcaster
@@ -55,7 +52,7 @@ public:
GetScriptLanguage() const;
void
- ExecuteInitialCommands (bool before_file);
+ WriteInitialCommands (bool before_file, lldb::SBStream &strm);
bool
GetDebugMode() const;
diff --git a/tools/driver/Platform.cpp b/tools/driver/Platform.cpp
index 5b5286e68114..a49161540872 100644
--- a/tools/driver/Platform.cpp
+++ b/tools/driver/Platform.cpp
@@ -8,17 +8,14 @@
//===----------------------------------------------------------------------===//
// this file is only relevant for Visual C++
-#if defined( _MSC_VER )
+#if defined( _WIN32 )
#include <process.h>
#include <assert.h>
+#include <stdlib.h>
#include "Platform.h"
-// index one of the variable arguments
-// presuming "(EditLine *el, ..." is first in the argument list
-#define GETARG( Y, X ) ( (void* ) *( ( (int**) &(Y) ) + (X) ) )
-
// the control handler or SIGINT handler
static sighandler_t _ctrlHandler = NULL;
@@ -42,14 +39,16 @@ ioctl (int d, int request, ...)
// request the console windows size
case ( TIOCGWINSZ ):
{
- // locate the window size structure on stack
- winsize *ws = (winsize*) GETARG( d, 2 );
+ va_list vl;
+ va_start(vl,request);
+ // locate the window size structure on stack
+ winsize *ws = va_arg(vl, winsize*);
// get screen buffer information
CONSOLE_SCREEN_BUFFER_INFO info;
- GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &info );
- // fill in the columns
- ws->ws_col = info.dwMaximumWindowSize.X;
- //
+ if ( GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &info ) == TRUE )
+ // fill in the columns
+ ws->ws_col = info.dwMaximumWindowSize.X;
+ va_end(vl);
return 0;
}
break;
@@ -85,6 +84,7 @@ tcgetattr (int fildes, struct termios *termios_p)
return -1;
}
+#ifdef _MSC_VER
sighandler_t
signal (int sig, sighandler_t sigFunc)
{
@@ -107,5 +107,6 @@ signal (int sig, sighandler_t sigFunc)
}
return 0;
}
+#endif
-#endif \ No newline at end of file
+#endif
diff --git a/tools/driver/Platform.h b/tools/driver/Platform.h
index faa2991bf6f3..e26610711aca 100644
--- a/tools/driver/Platform.h
+++ b/tools/driver/Platform.h
@@ -10,22 +10,18 @@
#ifndef lldb_Platform_h_
#define lldb_Platform_h_
-#if defined( _MSC_VER )
+#include "lldb/Host/HostGetOpt.h"
+
+#if defined( _WIN32 )
// this will stop signal.h being included
#define _INC_SIGNAL
-
#include <io.h>
+#if defined( _MSC_VER )
#include <eh.h>
+#endif
#include <inttypes.h>
- #include "lldb/Host/windows/Windows.h"
- #include "lldb/Host/HostGetOpt.h"
-
- struct timeval
- {
- long tv_sec;
- long tv_usec;
- };
+ #include "lldb/Host/windows/windows.h"
struct winsize
{
@@ -42,6 +38,17 @@
// ioctls.h
#define TIOCGWINSZ 0x5413
+
+ // signal handler function pointer type
+ typedef void(*sighandler_t)(int);
+
+ // signal.h
+ #define SIGINT 2
+ // default handler
+ #define SIG_DFL ( (sighandler_t) -1 )
+ // ignored
+ #define SIG_IGN ( (sighandler_t) -2 )
+
// signal.h
#define SIGPIPE 13
#define SIGCONT 18
@@ -64,34 +71,31 @@
speed_t c_ospeed; // output speed
};
- typedef long pid_t;
- #define STDIN_FILENO 0
- #define PATH_MAX MAX_PATH
+#ifdef _MSC_VER
+ struct timeval
+ {
+ long tv_sec;
+ long tv_usec;
+ };
+ typedef long pid_t;
#define snprintf _snprintf
+ extern sighandler_t signal( int sig, sighandler_t );
+ #define PATH_MAX MAX_PATH
+#endif
+
+ #define STDIN_FILENO 0
extern int ioctl( int d, int request, ... );
extern int kill ( pid_t pid, int sig );
extern int tcsetattr( int fd, int optional_actions, const struct termios *termios_p );
extern int tcgetattr( int fildes, struct termios *termios_p );
- // signal handler function pointer type
- typedef void (*sighandler_t)(int);
-
- // signal.h
- #define SIGINT 2
- // default handler
- #define SIG_DFL ( (sighandler_t) -1 )
- // ignored
- #define SIG_IGN ( (sighandler_t) -2 )
- extern sighandler_t signal( int sig, sighandler_t );
-
#else
#include <inttypes.h>
- #include <getopt.h>
#include <libgen.h>
#include <sys/ioctl.h>
#include <termios.h>
@@ -101,7 +105,7 @@
#include <pthread.h>
#include <sys/time.h>
- #if defined(__FreeBSD__)
+ #if defined(__FreeBSD__) || defined(__NetBSD__)
#include <readline/readline.h>
#else
#include <editline/readline.h>
diff --git a/tools/lldb-mi/Driver.cpp b/tools/lldb-mi/Driver.cpp
new file mode 100644
index 000000000000..a59b4b74eb0a
--- /dev/null
+++ b/tools/lldb-mi/Driver.cpp
@@ -0,0 +1,1299 @@
+//===-- Driver.cpp ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// In-house headers:
+#include "MICmnConfig.h"
+
+#if MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
+
+#ifndef _MSC_VER
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <string>
+#endif // _MSC_VER
+
+#include "Platform.h" // CODETAG_IOR_SIGNALS
+#include "Driver.h"
+
+#ifdef _MSC_VER
+#include <lldb\Host\windows\getopt\GetOptInc.h>
+#endif // _MSC_VER
+#include <lldb/API/SBBreakpoint.h>
+#include <lldb/API/SBCommandInterpreter.h>
+#include <lldb/API/SBCommandReturnObject.h>
+#include <lldb/API/SBCommunication.h>
+#include <lldb/API/SBEvent.h>
+#include <lldb/API/SBHostOS.h>
+#include <lldb/API/SBListener.h>
+#include <lldb/API/SBStream.h>
+#include <lldb/API/SBTarget.h>
+#include <lldb/API/SBThread.h>
+#include <lldb/API/SBProcess.h>
+
+using namespace lldb;
+
+static void reset_stdin_termios ();
+static bool g_old_stdin_termios_is_valid = false;
+static struct termios g_old_stdin_termios;
+
+static char *g_debugger_name = (char *) "";
+Driver *g_driver = NULL;
+
+// In the Driver::MainLoop, we change the terminal settings. This function is
+// added as an atexit handler to make sure we clean them up.
+static void
+reset_stdin_termios ()
+{
+ if (g_old_stdin_termios_is_valid)
+ {
+ g_old_stdin_termios_is_valid = false;
+ ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
+ }
+}
+
+typedef struct
+{
+ uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0
+ // then this option belongs to option set n.
+ bool required; // This option is required (in the current usage level)
+ const char * long_option; // Full name for this option.
+ int short_option; // Single character for this option.
+ int option_has_arg; // no_argument, required_argument or optional_argument
+ uint32_t completion_type; // Cookie the option class can use to do define the argument completion.
+ lldb::CommandArgumentType argument_type; // Type of argument this option takes
+ const char * usage_text; // Full text explaining what this options does and what (if any) argument to
+ // pass it.
+} OptionDefinition;
+
+#define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5
+#define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5
+
+static OptionDefinition g_options[] =
+{
+ { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , 0, eArgTypeNone,
+ "Prints out the usage information for the LLDB debugger." },
+ { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , 0, eArgTypeNone,
+ "Prints out the current version number of the LLDB debugger." },
+ { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, 0, eArgTypeArchitecture,
+ "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must "
+ "be one of the architectures for which the program was compiled." },
+ { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, 0, eArgTypeFilename,
+ "Tells the debugger to use the file <filename> as the program to be debugged." },
+ { LLDB_OPT_SET_3, false, "core" , 'c', required_argument, 0, eArgTypeFilename,
+ "Tells the debugger to use the fullpath to <path> as the core file." },
+ { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, 0, eArgTypePid,
+ "Tells the debugger to attach to a process with the given pid." },
+ { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, 0, eArgTypeProcessName,
+ "Tells the debugger to attach to a process with the given name." },
+ { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , 0, eArgTypeNone,
+ "Tells the debugger to wait for a process with the given pid or name to launch before attaching." },
+ { LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename,
+ "Tells the debugger to read in and execute the lldb commands in the given file, after any file provided on the command line has been loaded." },
+ { LLDB_3_TO_5, false, "one-line" , 'o', required_argument, 0, eArgTypeNone,
+ "Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded." },
+ { LLDB_3_TO_5, false, "source-before-file" , 'S', required_argument, 0, eArgTypeFilename,
+ "Tells the debugger to read in and execute the lldb commands in the given file, before any file provided on the command line has been loaded." },
+ { LLDB_3_TO_5, false, "one-line-before-file" , 'O', required_argument, 0, eArgTypeNone,
+ "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." },
+ { LLDB_3_TO_5, false, "source-quietly" , 'Q', no_argument , 0, eArgTypeNone,
+ "Tells the debugger suppress output from commands provided in the -s, -S, -O and -o commands." },
+ { LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone,
+ "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
+ { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone,
+ "Do not automatically parse any '.lldbinit' files." },
+ { LLDB_3_TO_5, false, "no-use-colors" , 'X', no_argument , 0, eArgTypeNone,
+ "Do not use colors." },
+ { LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone,
+ "Prints out the path to the lldb.py file for this version of lldb." },
+ { LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, eArgTypeScriptLang,
+ "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. "
+ "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python "
+ "extensions have been implemented." },
+ { LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone,
+ "Tells the debugger to print out extra information for debugging itself." },
+ { 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL }
+};
+
+static const uint32_t last_option_set_with_args = 2;
+
+Driver::Driver () :
+ SBBroadcaster ("Driver"),
+ m_debugger (SBDebugger::Create(false)),
+ m_option_data ()
+{
+ // We want to be able to handle CTRL+D in the terminal to have it terminate
+ // certain input
+ m_debugger.SetCloseInputOnEOF (false);
+ g_debugger_name = (char *) m_debugger.GetInstanceName();
+ if (g_debugger_name == NULL)
+ g_debugger_name = (char *) "";
+ g_driver = this;
+}
+
+Driver::~Driver ()
+{
+ g_driver = NULL;
+ g_debugger_name = NULL;
+}
+
+
+// This function takes INDENT, which tells how many spaces to output at the front
+// of each line; 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
+OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns)
+{
+ int len = strlen (text);
+ std::string text_string (text);
+
+ // Force indentation to be reasonable.
+ if (indent >= output_max_columns)
+ indent = 0;
+
+ // Will it all fit on one line?
+
+ if (len + indent < output_max_columns)
+ // Output as a single line
+ fprintf (out, "%*s%s\n", indent, "", text);
+ else
+ {
+ // We need to break it up into multiple lines.
+ int text_width = output_max_columns - indent - 1;
+ int start = 0;
+ int end = start;
+ int final_end = len;
+ int sub_len;
+
+ while (end < final_end)
+ {
+ // Dont 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;
+ std::string substring = text_string.substr (start, sub_len);
+ fprintf (out, "%*s%s\n", indent, "", substring.c_str());
+ start = end + 1;
+ }
+ }
+}
+
+void
+ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
+{
+ uint32_t screen_width = 80;
+ uint32_t indent_level = 0;
+ const char *name = "lldb";
+
+ fprintf (out, "\nUsage:\n\n");
+
+ indent_level += 2;
+
+
+ // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
+ // <cmd> [options-for-level-1]
+ // etc.
+
+ uint32_t num_options;
+ uint32_t num_option_sets = 0;
+
+ for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options)
+ {
+ uint32_t this_usage_mask = option_table[num_options].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;
+ }
+ }
+ }
+ }
+
+ 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)
+ fprintf (out, "\n");
+ fprintf (out, "%*s%s", indent_level, "", name);
+ bool is_help_line = false;
+
+ for (uint32_t i = 0; i < num_options; ++i)
+ {
+ if (option_table[i].usage_mask & opt_set_mask)
+ {
+ CommandArgumentType arg_type = option_table[i].argument_type;
+ const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
+ // This is a bit of a hack, but there's no way to say certain options don't have arguments yet...
+ // so we do it by hand here.
+ if (option_table[i].short_option == 'h')
+ is_help_line = true;
+
+ if (option_table[i].required)
+ {
+ if (option_table[i].option_has_arg == required_argument)
+ fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name);
+ else if (option_table[i].option_has_arg == optional_argument)
+ fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name);
+ else
+ fprintf (out, " -%c", option_table[i].short_option);
+ }
+ else
+ {
+ if (option_table[i].option_has_arg == required_argument)
+ fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name);
+ else if (option_table[i].option_has_arg == optional_argument)
+ fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name);
+ else
+ fprintf (out, " [-%c]", option_table[i].short_option);
+ }
+ }
+ }
+ if (!is_help_line && (opt_set <= last_option_set_with_args))
+ fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]");
+ }
+
+ fprintf (out, "\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.
+
+ Driver::OptionData::OptionSet options_seen;
+ Driver::OptionData::OptionSet::iterator pos;
+
+ indent_level += 5;
+
+ for (uint32_t i = 0; i < num_options; ++i)
+ {
+ // Only print this option if we haven't already seen it.
+ pos = options_seen.find (option_table[i].short_option);
+ if (pos == options_seen.end())
+ {
+ CommandArgumentType arg_type = option_table[i].argument_type;
+ const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type);
+
+ options_seen.insert (option_table[i].short_option);
+ fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option);
+ if (arg_type != eArgTypeNone)
+ fprintf (out, "<%s>", arg_name);
+ fprintf (out, "\n");
+ fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option);
+ if (arg_type != eArgTypeNone)
+ fprintf (out, "<%s>", arg_name);
+ fprintf (out, "\n");
+ indent_level += 5;
+ OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width);
+ indent_level -= 5;
+ fprintf (out, "\n");
+ }
+ }
+
+ indent_level -= 5;
+
+ fprintf (out, "\n%*sNotes:\n",
+ indent_level, "");
+ indent_level += 5;
+
+ fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed from left to right in order, "
+ "\n%*swith the source files and commands interleaved. The same is true of the \"-S\" and \"-O\" options."
+ "\n%*sThe before file and after file sets can intermixed freely, the command parser will sort them out."
+ "\n%*sThe order of the file specifiers (\"-c\", \"-f\", etc.) is not significant in this regard.\n\n",
+ indent_level, "",
+ indent_level, "",
+ indent_level, "",
+ indent_level, "");
+
+ fprintf (out, "\n%*sIf you don't provide -f then the first argument will be the file to be debugged"
+ "\n%*swhich means that '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
+ "\n%*sBut remember to end the options with \"--\" if any of your arguments have a \"-\" in them.\n\n",
+ indent_level, "",
+ indent_level, "",
+ name,
+ indent_level, "");
+}
+
+void
+BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table,
+ uint32_t num_options)
+{
+ if (num_options == 0)
+ return;
+
+ uint32_t i;
+ uint32_t j;
+ std::bitset<256> option_seen;
+
+ getopt_table.resize (num_options + 1);
+
+ for (i = 0, j = 0; i < num_options; ++i)
+ {
+ char short_opt = expanded_option_table[i].short_option;
+
+ if (option_seen.test(short_opt) == false)
+ {
+ getopt_table[j].name = expanded_option_table[i].long_option;
+ getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
+ getopt_table[j].flag = NULL;
+ getopt_table[j].val = expanded_option_table[i].short_option;
+ option_seen.set(short_opt);
+ ++j;
+ }
+ }
+
+ getopt_table[j].name = NULL;
+ getopt_table[j].has_arg = 0;
+ getopt_table[j].flag = NULL;
+ getopt_table[j].val = 0;
+
+}
+
+Driver::OptionData::OptionData () :
+ m_args(),
+ m_script_lang (lldb::eScriptLanguageDefault),
+ m_core_file (),
+ m_crash_log (),
+ m_initial_commands (),
+ m_after_file_commands (),
+ m_debug_mode (false),
+ m_source_quietly(false),
+ m_print_version (false),
+ m_print_python_path (false),
+ m_print_help (false),
+ m_wait_for(false),
+ m_process_name(),
+ m_process_pid(LLDB_INVALID_PROCESS_ID),
+ m_use_external_editor(false),
+ m_seen_options()
+{
+}
+
+Driver::OptionData::~OptionData ()
+{
+}
+
+void
+Driver::OptionData::Clear ()
+{
+ m_args.clear ();
+ m_script_lang = lldb::eScriptLanguageDefault;
+ m_initial_commands.clear ();
+ m_after_file_commands.clear ();
+ m_debug_mode = false;
+ m_source_quietly = false;
+ m_print_help = false;
+ m_print_version = false;
+ m_print_python_path = false;
+ m_use_external_editor = false;
+ m_wait_for = false;
+ m_process_name.erase();
+ m_process_pid = LLDB_INVALID_PROCESS_ID;
+}
+
+void
+Driver::OptionData::AddInitialCommand (const char *command, bool before_file, bool is_file, SBError &error)
+{
+ std::vector<std::pair<bool, std::string> > *command_set;
+ if (before_file)
+ command_set = &(m_initial_commands);
+ else
+ command_set = &(m_after_file_commands);
+
+ if (is_file)
+ {
+ SBFileSpec file(command);
+ if (file.Exists())
+ command_set->push_back (std::pair<bool, std::string> (true, optarg));
+ else if (file.ResolveExecutableLocation())
+ {
+ char final_path[PATH_MAX];
+ file.GetPath (final_path, sizeof(final_path));
+ std::string path_str (final_path);
+ command_set->push_back (std::pair<bool, std::string> (true, path_str));
+ }
+ else
+ error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg);
+ }
+ else
+ command_set->push_back (std::pair<bool, std::string> (false, optarg));
+}
+
+void
+Driver::ResetOptionValues ()
+{
+ m_option_data.Clear ();
+}
+
+const char *
+Driver::GetFilename() const
+{
+ if (m_option_data.m_args.empty())
+ return NULL;
+ return m_option_data.m_args.front().c_str();
+}
+
+const char *
+Driver::GetCrashLogFilename() const
+{
+ if (m_option_data.m_crash_log.empty())
+ return NULL;
+ return m_option_data.m_crash_log.c_str();
+}
+
+lldb::ScriptLanguage
+Driver::GetScriptLanguage() const
+{
+ return m_option_data.m_script_lang;
+}
+
+void
+Driver::ExecuteInitialCommands (bool before_file)
+{
+ size_t num_commands;
+ std::vector<std::pair<bool, std::string> > *command_set;
+ if (before_file)
+ command_set = &(m_option_data.m_initial_commands);
+ else
+ command_set = &(m_option_data.m_after_file_commands);
+
+ num_commands = command_set->size();
+ SBCommandReturnObject result;
+ bool old_async = GetDebugger().GetAsync();
+ GetDebugger().SetAsync(false);
+ for (size_t idx = 0; idx < num_commands; idx++)
+ {
+ bool is_file = (*command_set)[idx].first;
+ const char *command = (*command_set)[idx].second.c_str();
+ char command_string[PATH_MAX * 2];
+ const bool dump_stream_only_if_no_immediate = true;
+ const char *executed_command = command;
+ if (is_file)
+ {
+ ::snprintf (command_string, sizeof(command_string), "command source -s %i '%s'", m_option_data.m_source_quietly, command);
+ executed_command = command_string;
+ }
+
+ m_debugger.GetCommandInterpreter().HandleCommand (executed_command, result, false);
+ if (!m_option_data.m_source_quietly || result.Succeeded() == false)
+ {
+ const size_t output_size = result.GetOutputSize();
+ if (output_size > 0)
+ {
+ const char *cstr = result.GetOutput(dump_stream_only_if_no_immediate);
+ if (cstr)
+ printf ("%s", cstr);
+ }
+ const size_t error_size = result.GetErrorSize();
+ if (error_size > 0)
+ {
+ const char *cstr = result.GetError(dump_stream_only_if_no_immediate);
+ if (cstr)
+ printf ("%s", cstr);
+ }
+ }
+
+ if (result.Succeeded() == false)
+ {
+ const char *type = before_file ? "before file" : "after_file";
+ if (is_file)
+ ::fprintf(stderr, "Aborting %s command execution, command file: '%s' failed.\n", type, command);
+ else
+ ::fprintf(stderr, "Aborting %s command execution, command: '%s' failed.\n", type, command);
+ break;
+ }
+ result.Clear();
+ }
+ GetDebugger().SetAsync(old_async);
+}
+
+bool
+Driver::GetDebugMode() const
+{
+ return m_option_data.m_debug_mode;
+}
+
+
+// Check the arguments that were passed to this program to make sure they are valid and to get their
+// argument values (if any). Return a boolean value indicating whether or not to start up the full
+// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR
+// if the user only wanted help or version information.
+
+SBError
+Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting)
+{
+ ResetOptionValues ();
+
+ SBCommandReturnObject result;
+
+ SBError error;
+ std::string option_string;
+ struct option *long_options = NULL;
+ std::vector<struct option> long_options_vector;
+ uint32_t num_options;
+
+ for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options)
+ /* Do Nothing. */;
+
+ if (num_options == 0)
+ {
+ if (argc > 1)
+ error.SetErrorStringWithFormat ("invalid number of options");
+ return error;
+ }
+
+ BuildGetOptTable (g_options, long_options_vector, num_options);
+
+ if (long_options_vector.empty())
+ long_options = NULL;
+ else
+ long_options = &long_options_vector.front();
+
+ if (long_options == NULL)
+ {
+ error.SetErrorStringWithFormat ("invalid long options");
+ return error;
+ }
+
+ // Build the option_string argument for call to getopt_long_only.
+
+ for (int i = 0; long_options[i].name != NULL; ++i)
+ {
+ if (long_options[i].flag == NULL)
+ {
+ option_string.push_back ((char) long_options[i].val);
+ switch (long_options[i].has_arg)
+ {
+ default:
+ case no_argument:
+ break;
+ case required_argument:
+ option_string.push_back (':');
+ break;
+ case optional_argument:
+ option_string.append ("::");
+ break;
+ }
+ }
+ }
+
+ // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't
+ // know at that point whether we should read in init files yet. So we don't read them in in the
+ // Driver constructor, then set the flags back to "read them in" here, and then if we see the
+ // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the
+ // main loop.
+
+ m_debugger.SkipLLDBInitFiles (false);
+ m_debugger.SkipAppInitFiles (false);
+
+ // Prepare for & make calls to getopt_long_only.
+#if __GLIBC__
+ optind = 0;
+#else
+ optreset = 1;
+ optind = 1;
+#endif
+ int val;
+ while (1)
+ {
+ int long_options_index = -1;
+ val = ::getopt_long_only (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index);
+
+ if (val == -1)
+ break;
+ else if (val == '?')
+ {
+ m_option_data.m_print_help = true;
+ error.SetErrorStringWithFormat ("unknown or ambiguous option");
+ break;
+ }
+ else if (val == 0)
+ continue;
+ else
+ {
+ m_option_data.m_seen_options.insert ((char) val);
+ 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;
+ }
+ }
+ }
+
+ if (long_options_index >= 0)
+ {
+ const int short_option = g_options[long_options_index].short_option;
+
+ switch (short_option)
+ {
+ case 'h':
+ m_option_data.m_print_help = true;
+ break;
+
+ case 'v':
+ m_option_data.m_print_version = true;
+ break;
+
+ case 'P':
+ m_option_data.m_print_python_path = true;
+ break;
+
+ case 'c':
+ {
+ SBFileSpec file(optarg);
+ if (file.Exists())
+ {
+ m_option_data.m_core_file = optarg;
+ }
+ else
+ error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg);
+ }
+ break;
+
+ case 'e':
+ m_option_data.m_use_external_editor = true;
+ break;
+
+ case 'x':
+ m_debugger.SkipLLDBInitFiles (true);
+ m_debugger.SkipAppInitFiles (true);
+ break;
+
+ case 'X':
+ m_debugger.SetUseColor (false);
+ break;
+
+ case 'f':
+ {
+ SBFileSpec file(optarg);
+ if (file.Exists())
+ {
+ m_option_data.m_args.push_back (optarg);
+ }
+ else if (file.ResolveExecutableLocation())
+ {
+ char path[PATH_MAX];
+ file.GetPath (path, sizeof(path));
+ m_option_data.m_args.push_back (path);
+ }
+ else
+ error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg);
+ }
+ break;
+
+ case 'a':
+ if (!m_debugger.SetDefaultArchitecture (optarg))
+ error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg);
+ break;
+
+ case 'l':
+ m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg);
+ break;
+
+ case 'd':
+ m_option_data.m_debug_mode = true;
+ break;
+
+ case 'Q':
+ m_option_data.m_source_quietly = true;
+ break;
+
+ case 'n':
+ m_option_data.m_process_name = optarg;
+ break;
+
+ case 'w':
+ m_option_data.m_wait_for = true;
+ break;
+
+ case 'p':
+ {
+ char *remainder;
+ m_option_data.m_process_pid = strtol (optarg, &remainder, 0);
+ if (remainder == optarg || *remainder != '\0')
+ error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.",
+ optarg);
+ }
+ break;
+ case 's':
+ m_option_data.AddInitialCommand(optarg, false, true, error);
+ break;
+ case 'o':
+ m_option_data.AddInitialCommand(optarg, false, false, error);
+ break;
+ case 'S':
+ m_option_data.AddInitialCommand(optarg, true, true, error);
+ break;
+ case 'O':
+ m_option_data.AddInitialCommand(optarg, true, false, error);
+ break;
+ default:
+ m_option_data.m_print_help = true;
+ error.SetErrorStringWithFormat ("unrecognized option %c", short_option);
+ break;
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("invalid option with value %i", val);
+ }
+ if (error.Fail())
+ {
+ return error;
+ }
+ }
+ }
+
+ if (error.Fail() || m_option_data.m_print_help)
+ {
+ ShowUsage (out_fh, g_options, m_option_data);
+ exiting = true;
+ }
+ else if (m_option_data.m_print_version)
+ {
+ ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
+ exiting = true;
+ }
+ else if (m_option_data.m_print_python_path)
+ {
+ SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath();
+ if (python_file_spec.IsValid())
+ {
+ char python_path[PATH_MAX];
+ size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX);
+ if (num_chars < PATH_MAX)
+ {
+ ::fprintf (out_fh, "%s\n", python_path);
+ }
+ else
+ ::fprintf (out_fh, "<PATH TOO LONG>\n");
+ }
+ else
+ ::fprintf (out_fh, "<COULD NOT FIND PATH>\n");
+ exiting = true;
+ }
+ else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID)
+ {
+ // Any arguments that are left over after option parsing are for
+ // the program. If a file was specified with -f then the filename
+ // is already in the m_option_data.m_args array, and any remaining args
+ // are arguments for the inferior program. If no file was specified with
+ // -f, then what is left is the program name followed by any arguments.
+
+ // Skip any options we consumed with getopt_long_only
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0)
+ {
+ for (int arg_idx=0; arg_idx<argc; ++arg_idx)
+ {
+ const char *arg = argv[arg_idx];
+ if (arg)
+ m_option_data.m_args.push_back (arg);
+ }
+ }
+
+ }
+ else
+ {
+ // Skip any options we consumed with getopt_long_only
+ argc -= optind;
+ //argv += optind; // Commented out to keep static analyzer happy
+
+ if (argc > 0)
+ ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n");
+ }
+
+ return error;
+}
+
+void
+Driver::MainLoop ()
+{
+ if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
+ {
+ g_old_stdin_termios_is_valid = true;
+ atexit (reset_stdin_termios);
+ }
+
+ ::setbuf (stdin, NULL);
+ ::setbuf (stdout, NULL);
+
+ m_debugger.SetErrorFileHandle (stderr, false);
+ m_debugger.SetOutputFileHandle (stdout, false);
+ m_debugger.SetInputFileHandle (stdin, true);
+
+ m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
+
+ struct winsize window_size;
+ if (isatty (STDIN_FILENO)
+ && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
+ {
+ if (window_size.ws_col > 0)
+ m_debugger.SetTerminalWidth (window_size.ws_col);
+ }
+
+ SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
+
+ // Before we handle any options from the command line, we parse the
+ // .lldbinit file in the user's home directory.
+ SBCommandReturnObject result;
+ sb_interpreter.SourceInitFileInHomeDirectory(result);
+ if (GetDebugMode())
+ {
+ result.PutError (m_debugger.GetErrorFileHandle());
+ result.PutOutput (m_debugger.GetOutputFileHandle());
+ }
+
+ // Now we handle options we got from the command line
+ // First source in the commands specified to be run before the file arguments are processed.
+ ExecuteInitialCommands(true);
+
+ // Was there a core file specified?
+ std::string core_file_spec("");
+ if (!m_option_data.m_core_file.empty())
+ core_file_spec.append("--core ").append(m_option_data.m_core_file);
+
+ char command_string[PATH_MAX * 2];
+ const size_t num_args = m_option_data.m_args.size();
+ if (num_args > 0)
+ {
+ char arch_name[64];
+ if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
+ ::snprintf (command_string,
+ sizeof (command_string),
+ "target create --arch=%s %s \"%s\"",
+ arch_name,
+ core_file_spec.c_str(),
+ m_option_data.m_args[0].c_str());
+ else
+ ::snprintf (command_string,
+ sizeof(command_string),
+ "target create %s \"%s\"",
+ core_file_spec.c_str(),
+ m_option_data.m_args[0].c_str());
+
+ m_debugger.HandleCommand (command_string);
+
+ if (num_args > 1)
+ {
+ m_debugger.HandleCommand ("settings clear target.run-args");
+ char arg_cstr[1024];
+ for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
+ {
+ ::snprintf (arg_cstr,
+ sizeof(arg_cstr),
+ "settings append target.run-args \"%s\"",
+ m_option_data.m_args[arg_idx].c_str());
+ m_debugger.HandleCommand (arg_cstr);
+ }
+ }
+ }
+ else if (!core_file_spec.empty())
+ {
+ ::snprintf (command_string,
+ sizeof(command_string),
+ "target create %s",
+ core_file_spec.c_str());
+ m_debugger.HandleCommand (command_string);;
+ }
+ else if (!m_option_data.m_process_name.empty())
+ {
+ ::snprintf (command_string,
+ sizeof(command_string),
+ "process attach --name '%s'%s",
+ m_option_data.m_process_name.c_str(),
+ m_option_data.m_wait_for ? " --waitfor" : "");
+ m_debugger.HandleCommand (command_string);
+ }
+ else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid)
+ {
+ ::snprintf (command_string,
+ sizeof(command_string),
+ "process attach --pid %" PRIu64,
+ m_option_data.m_process_pid);
+ m_debugger.HandleCommand (command_string);
+ }
+
+ ExecuteInitialCommands(false);
+
+ // Now that all option parsing is done, we try and parse the .lldbinit
+ // file in the current working directory
+ sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
+ if (GetDebugMode())
+ {
+ result.PutError(m_debugger.GetErrorFileHandle());
+ result.PutOutput(m_debugger.GetOutputFileHandle());
+ }
+
+ bool handle_events = true;
+ bool spawn_thread = false;
+ m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
+
+ reset_stdin_termios();
+ fclose (stdin);
+
+ SBDebugger::Destroy (m_debugger);
+}
+
+void
+Driver::ResizeWindow (unsigned short col)
+{
+ GetDebugger().SetTerminalWidth (col);
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Setup *this driver so it works as pass through (child) driver for the MI
+// driver. Called by the parent (MI driver) driver.
+// This driver has setup code in two places. The original in MainLoop() and
+// in int main() (when MICONFIG_COMPILE_MIDRIVER_VERSION == 0) so that code can
+// remain as much near to the original code as possible. If MI driver is the main
+// driver (when MICONFIG_COMPILE_MIDRIVER_VERSION == 1) then this function is
+// used to set up the Driver to work with the MI driver.
+// Type: Method.
+// Args: vwErrMsg - (W) On failure current error discription.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool Driver::MISetup( CMIUtilString & vwErrMsg )
+{
+ bool bOk = MIstatus::success;
+
+ // Is *this driver a pass through driver to the MI driver
+ CMIDriverBase * pParent = GetDriversParent();
+ if( pParent == nullptr )
+ {
+ // No it is not.
+ // If MI is the main driver (which passes through to *this driver) then
+ // *this driver needs to be initialized after MI is initialize to have a valid
+ // pointer to the parent driver. *this is the parent's pass thru driver.
+ assert( pParent == nullptr );
+ return MIstatus::success; // Allow success for if Driver is the main driver
+ }
+
+ // MI driver may have streams it wants *this driver to use - still to be sorted
+ m_debugger.SetErrorFileHandle( pParent->GetStderr(), false ); // MI may redirect to its own stream
+ m_debugger.SetOutputFileHandle( pParent->GetStdout(), false ); // MI likely to NULL this
+ m_debugger.SetInputFileHandle( pParent->GetStdin(), false ); // MI could use this to feed input
+
+ // ToDo: Do I need this?
+ m_debugger.SetUseExternalEditor( m_option_data.m_use_external_editor );
+
+ // ToDo: Do I need this?
+ struct winsize window_size;
+ if( isatty( STDIN_FILENO ) && ::ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) == 0 )
+ {
+ if( window_size.ws_col > 0 )
+ m_debugger.SetTerminalWidth( window_size.ws_col );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize setup *this driver ready for use.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool Driver::DoInitialize( void )
+{
+ // Do nothing
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Unbind detach or release resources used by *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool Driver::DoShutdown( void )
+{
+ SBDebugger::Destroy( m_debugger );
+
+ // Is *this driver a pass through driver to the MI driver
+ CMIDriverBase * pParent = GetDriversParent();
+ if( pParent == nullptr )
+ {
+ // See DoInitialize().
+ assert( pParent == nullptr );
+ return MIstatus::success;
+ }
+
+ // Put stuff here when *this driver is a pass thru driver to the MI driver
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the name for *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Driver name.
+// Throws: None.
+//--
+const CMIUtilString & Driver::GetName( void ) const
+{
+ static CMIUtilString name( "LLDB driver" );
+ return name;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve *this driver's last error condition.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString - Text description.
+// Throws: None.
+//--
+CMIUtilString Driver::GetError( void ) const
+{
+ // Do nothing - to implement
+ return CMIUtilString();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Call this function puts *this driver to work.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool Driver::DoMainLoop( void )
+{
+ MainLoop();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Call *this driver to resize the console window.
+// Type: Overridden.
+// Args: vTermWidth - (R) New window column size.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+void Driver::DoResizeWindow( const uint32_t vTermWidth )
+{
+ ResizeWindow( (unsigned short) vTermWidth );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Call *this driver to return it's debugger.
+// Type: Overridden.
+// Args: None.
+// Return: lldb::SBDebugger & - LLDB debugger object reference.
+// Throws: None.
+//--
+lldb::SBDebugger & Driver::GetTheDebugger( void )
+{
+ return GetDebugger();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Proxy function to allow the driver implementation to validate executable
+// command line arguments.
+// Type: Overrideable.
+// Args: argc - (R) An integer that contains the count of arguments that follow in
+// argv. The argc parameter is always greater than or equal to 1.
+// argv - (R) An array of null-terminated strings representing command-line
+// arguments entered by the user of the program. By convention,
+// argv[0] is the command with which the program is invoked.
+// vpStdOut - (R) Pointer to a standard output stream.
+// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s),
+// version information only.
+// False = Continue to work, start debugger i.e. Command
+// interpreter.
+// Return: lldb::SBError - LLDB current error status.
+// Throws: None.
+//--
+lldb::SBError Driver::DoParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting )
+{
+ return ParseArgs( argc, argv, vpStdOut, vwbExiting );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: A client can ask if *this driver is GDB/MI compatible.
+// Type: Overridden.
+// Args: None.
+// Return: True - GBD/MI compatible LLDB front end.
+// False - Not GBD/MI compatible LLDB front end.
+// Throws: None.
+//--
+bool Driver::GetDriverIsGDBMICompatibleDriver( void ) const
+{
+ return false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: This function allows *this driver to call on another driver to perform work
+// should this driver not be able to handle the client data input.
+// SetDriverToFallThruTo() specifies the fall through to driver.
+// Check the error message if the function returns a failure.
+// Type: Overridden.
+// Args: vCmd - (R) Command instruction to interpret.
+// vwErrMsg - (W) Error description on command failing.
+// Return: MIstatus::success - Command succeeded.
+// MIstatus::failure - Command failed.
+// Throws: None.
+//--
+bool Driver::DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg )
+{
+ bool bOk = MIstatus::success;
+ vwErrMsg.empty();
+
+ // ToDo: Implement do work on other driver after this driver said "Give up you try"
+ // This may nto be required if the feature to 'fall through' is not required
+ SBCommandReturnObject returnObj = lldb::SBCommandReturnObject();
+ SBCommandInterpreter cmdIntrp = m_debugger.GetCommandInterpreter();
+ const lldb::ReturnStatus cmdResult = cmdIntrp.HandleCommand( vCmd.c_str(), returnObj ); MIunused( cmdResult );
+ if( returnObj.Succeeded() == false )
+ {
+ bOk = MIstatus::failure;
+ vwErrMsg = returnObj.GetError();
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: This function allows *this driver to call functionality on the parent driver
+// ask for information for example.
+// Type: Overridden.
+// Args: vrOtherDriver - (R) Reference to another driver object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool Driver::SetDriverParent( const CMIDriverBase & vrOtherDriver )
+{
+ m_pDriverParent = const_cast< CMIDriverBase * >( &vrOtherDriver );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set a unique ID for *this driver. It cannot be empty.
+// Type: Overridden.
+// Args: vId - (R) Text description.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool Driver::SetId( const CMIUtilString & vId )
+{
+ if( vId.empty() )
+ {
+ // Invalid to have it empty
+ return MIstatus::failure;
+ }
+
+ m_strDriverId = vId;
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the unique ID for *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & Driver::GetId( void ) const
+{
+ return m_strDriverId;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Create *this driver. Function contains functionality that needs to be called
+// prior to constructing the *this driver.
+// Type: Static method.
+// Args: None.
+// Return: Driver * - Ptr to the LLDB driver object.
+// Throws: None.
+//--
+Driver * Driver::CreateSelf( void )
+{
+ lldb::SBDebugger::Initialize();
+
+ Driver * pDriver = new Driver;
+ return pDriver;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the name for *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString - Driver name.
+// Throws: None.
+//--
+const CMIUtilString & Driver::GetDriverName( void ) const
+{
+ return GetName();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the unique ID for *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & Driver::GetDriverId( void ) const
+{
+ return GetId();
+}
+
+#endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
+
diff --git a/tools/lldb-mi/Driver.h b/tools/lldb-mi/Driver.h
new file mode 100644
index 000000000000..39577c49bf05
--- /dev/null
+++ b/tools/lldb-mi/Driver.h
@@ -0,0 +1,163 @@
+//===-- Driver.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// In-house headers:
+#include "MICmnConfig.h"
+#if MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
+
+#ifndef lldb_Driver_h_
+#define lldb_Driver_h_
+
+//#include "Platform.h" // IOR removed
+#include <lldb/Utility/PseudoTerminal.h>
+
+#include <set>
+#include <bitset>
+#include <string>
+#include <vector>
+
+#include <lldb/API/SBDefines.h>
+#include <lldb/API/SBBroadcaster.h>
+#include <lldb/API/SBDebugger.h>
+#include <lldb/API/SBError.h>
+#include "MIDriverMgr.h"
+#include "MIDriverBase.h"
+
+#define ASYNC true
+#define NO_ASYNC false
+
+class IOChannel;
+
+class Driver : public lldb::SBBroadcaster, public CMIDriverBase, public CMIDriverMgr::IDriver
+{
+// MI required code:
+// Static:
+public:
+ static Driver * CreateSelf( void );
+
+// Methods:
+public:
+ bool MISetup( CMIUtilString & vwErrMsg );
+
+// Overridden:
+public:
+ // From CMIDriverMgr::IDriver
+ virtual bool DoInitialize( void );
+ virtual bool DoShutdown( void );
+ virtual bool DoMainLoop( void );
+ virtual void DoResizeWindow( const uint32_t vWindowSizeWsCol );
+ virtual lldb::SBError DoParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting );
+ virtual CMIUtilString GetError( void ) const;
+ virtual const CMIUtilString & GetName( void ) const;
+ virtual lldb::SBDebugger & GetTheDebugger( void );
+ virtual bool GetDriverIsGDBMICompatibleDriver( void ) const;
+ virtual bool SetId( const CMIUtilString & vID );
+ virtual const CMIUtilString & GetId( void ) const;
+ // From CMIDriverBase
+ virtual bool DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg );
+ virtual bool SetDriverParent( const CMIDriverBase & vrOtherDriver );
+ virtual const CMIUtilString & GetDriverName( void ) const;
+ virtual const CMIUtilString & GetDriverId( void ) const;
+
+// Original code:
+public:
+ Driver ();
+
+ virtual
+ ~Driver ();
+
+ void
+ MainLoop ();
+
+ lldb::SBError
+ ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &do_exit);
+
+ const char *
+ GetFilename() const;
+
+ const char *
+ GetCrashLogFilename() const;
+
+ const char *
+ GetArchName() const;
+
+ lldb::ScriptLanguage
+ GetScriptLanguage() const;
+
+ void
+ ExecuteInitialCommands (bool before_file);
+
+ bool
+ GetDebugMode() const;
+
+ class OptionData
+ {
+ public:
+ OptionData ();
+ ~OptionData ();
+
+ void
+ Clear();
+
+ void
+ AddInitialCommand (const char *command, bool before_file, bool is_file, lldb::SBError &error);
+
+ //static OptionDefinition m_cmd_option_table[];
+
+ std::vector<std::string> m_args;
+ lldb::ScriptLanguage m_script_lang;
+ std::string m_core_file;
+ std::string m_crash_log;
+ std::vector<std::pair<bool,std::string> > m_initial_commands;
+ std::vector<std::pair<bool,std::string> > m_after_file_commands;
+ bool m_debug_mode;
+ bool m_source_quietly;
+ bool m_print_version;
+ bool m_print_python_path;
+ bool m_print_help;
+ bool m_wait_for;
+ std::string m_process_name;
+ lldb::pid_t m_process_pid;
+ bool m_use_external_editor; // FIXME: When we have set/show variables we can remove this from here.
+ typedef std::set<char> OptionSet;
+ OptionSet m_seen_options;
+ };
+
+
+ static lldb::SBError
+ SetOptionValue (int option_idx,
+ const char *option_arg,
+ Driver::OptionData &data);
+
+
+ lldb::SBDebugger &
+ GetDebugger()
+ {
+ return m_debugger;
+ }
+
+ void
+ ResizeWindow (unsigned short col);
+
+private:
+ lldb::SBDebugger m_debugger;
+ OptionData m_option_data;
+
+ void
+ ResetOptionValues ();
+
+ void
+ ReadyForCommand ();
+};
+
+extern Driver * g_driver;
+
+#endif // lldb_Driver_h_
+
+#endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
diff --git a/tools/lldb-mi/MICmdArgContext.cpp b/tools/lldb-mi/MICmdArgContext.cpp
new file mode 100644
index 000000000000..b6efa9660c3b
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgContext.cpp
@@ -0,0 +1,255 @@
+//===-- MICmnArgContext.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnArgContext.cpp
+//
+// Overview: CMICmdArgContext implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdArgContext.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgContext constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgContext::CMICmdArgContext( void )
+: m_constCharSpace( ' ' )
+, m_constStrSpace( " " )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgContext constructor.
+// Type: Method.
+// Args: vrCmdLineArgsRaw - (R) The text description of the arguments options.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgContext::CMICmdArgContext( const CMIUtilString & vrCmdLineArgsRaw )
+: m_strCmdArgsAndOptions( vrCmdLineArgsRaw )
+, m_constCharSpace( ' ' )
+, m_constStrSpace( " " )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgContext destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgContext::~CMICmdArgContext( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the remainder of the command's argument options left to parse.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - Argument options text.
+// Throws: None.
+//--
+const CMIUtilString & CMICmdArgContext::GetArgsLeftToParse( void ) const
+{
+ return m_strCmdArgsAndOptions;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Ask if this arguments string has any arguments.
+// Type: Method.
+// Args: None.
+// Return: bool - True = Has one or more arguments present, false = no arguments.
+// Throws: None.
+//--
+bool CMICmdArgContext::IsEmpty( void ) const
+{
+ return m_strCmdArgsAndOptions.empty();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Remove the argument from the options text and any space after the argument
+// if applicable.
+// Type: Method.
+// Args: vArg - (R) The name of the argument.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgContext::RemoveArg( const CMIUtilString & vArg )
+{
+ if( vArg.empty() )
+ return MIstatus::success;
+
+ const MIuint nLen = vArg.length();
+ const MIuint nLenCntxt = m_strCmdArgsAndOptions.length();
+ if( nLen > nLenCntxt )
+ return MIstatus::failure;
+
+ MIuint nExtraSpace = 0;
+ MIint nPos = m_strCmdArgsAndOptions.find( vArg );
+ while( 1 )
+ {
+ if( nPos == (MIint) std::string::npos )
+ return MIstatus::success;
+
+ bool bPass1 = false;
+ if( nPos != 0 )
+ {
+ if( m_strCmdArgsAndOptions[ nPos - 1 ] == m_constCharSpace )
+ bPass1 = true;
+ }
+ else
+ bPass1 = true;
+
+ const MIuint nEnd = nPos + nLen;
+
+ if( bPass1 )
+ {
+ bool bPass2 = false;
+ if( nEnd < nLenCntxt )
+ {
+ if( m_strCmdArgsAndOptions[ nEnd ] == m_constCharSpace )
+ {
+ bPass2 = true;
+ nExtraSpace = 1;
+ }
+ }
+ else
+ bPass2 = true;
+
+ if( bPass2 )
+ break;
+ }
+
+ nPos = m_strCmdArgsAndOptions.find( vArg, nEnd );
+ }
+
+ const MIuint nPosEnd = nLen + nExtraSpace;
+ m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.replace( nPos, nPosEnd, "" ).c_str();
+ m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.Trim();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Remove the argument at the Nth word position along in the context string.
+// Any space after the argument is removed if applicable. A search is not
+// performed as there may be more than one vArg with the same 'name' in the
+// context string.
+// Type: Method.
+// Args: vArg - (R) The name of the argument.
+// nArgIndex - (R) The word count position to which to remove the vArg word.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgContext::RemoveArgAtPos( const CMIUtilString & vArg, const MIuint nArgIndex )
+{
+ MIuint nWordIndex = 0;
+ CMIUtilString strBuildContextUp;
+ const CMIUtilString::VecString_t vecWords( GetArgs() );
+ const bool bSpaceRequired( GetNumberArgsPresent() > 2 );
+
+ CMIUtilString::VecString_t::const_iterator it = vecWords.begin();
+ const CMIUtilString::VecString_t::const_iterator itEnd = vecWords.end();
+ while( it != itEnd )
+ {
+ const CMIUtilString & rWord( *it );
+ if( nWordIndex++ != nArgIndex )
+ {
+ // Single words
+ strBuildContextUp += rWord;
+ if( bSpaceRequired )
+ strBuildContextUp += m_constStrSpace;
+ }
+ else
+ {
+ // If quoted loose quoted text
+ if( ++it != itEnd )
+ {
+ CMIUtilString words = rWord;
+ while( vArg != words )
+ {
+ if( bSpaceRequired )
+ words += m_constStrSpace;
+ words += *it;
+ if( ++it == itEnd )
+ break;
+ }
+ if( it != itEnd )
+ --it;
+ }
+ }
+
+ // Next
+ if( it != itEnd )
+ ++it;
+ }
+
+ m_strCmdArgsAndOptions = strBuildContextUp;
+ m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.Trim();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve number of arguments or options present in the command's option text.
+// Type: Method.
+// Args: None.
+// Return: MIuint - 0 to n arguments present.
+// Throws: None.
+//--
+MIuint CMICmdArgContext::GetNumberArgsPresent( void ) const
+{
+ CMIUtilString::VecString_t vecOptions;
+ return m_strCmdArgsAndOptions.SplitConsiderQuotes( m_constStrSpace, vecOptions );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve all the arguments or options remaining in *this context.
+// Type: Method.
+// Args: None.
+// Return: MIUtilString::VecString_t - List of args remaining.
+// Throws: None.
+//--
+CMIUtilString::VecString_t CMICmdArgContext::GetArgs( void ) const
+{
+ CMIUtilString::VecString_t vecOptions;
+ m_strCmdArgsAndOptions.SplitConsiderQuotes( m_constStrSpace, vecOptions );
+ return vecOptions;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Copy assignment operator.
+// Type: Method.
+// Args: vOther - (R) The variable to copy from.
+// Return: CMIUtilString & - this object.
+// Throws: None.
+//--
+CMICmdArgContext & CMICmdArgContext::operator= ( const CMICmdArgContext & vOther )
+{
+ if( this != &vOther )
+ {
+ m_strCmdArgsAndOptions = vOther.m_strCmdArgsAndOptions;
+ }
+
+ return *this;
+} \ No newline at end of file
diff --git a/tools/lldb-mi/MICmdArgContext.h b/tools/lldb-mi/MICmdArgContext.h
new file mode 100644
index 000000000000..699bac13e014
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgContext.h
@@ -0,0 +1,61 @@
+//===-- MICmdArgContext.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgContext.h
+//
+// Overview: CMICmdArgContext interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MIUtilString.h"
+
+//++ ============================================================================
+// Details: MI common code class. Command arguments and options string. Holds
+// the context string.
+// Based on the Interpreter pattern.
+// Gotchas: None.
+// Authors: Illya Rudkin 14/04/2014.
+// Changes: None.
+//--
+class CMICmdArgContext
+{
+// Methods:
+public:
+ /* ctor */ CMICmdArgContext( void );
+ /* ctor */ CMICmdArgContext( const CMIUtilString & vrCmdLineArgsRaw );
+ //
+ const CMIUtilString & GetArgsLeftToParse( void ) const;
+ MIuint GetNumberArgsPresent( void ) const;
+ CMIUtilString::VecString_t GetArgs( void ) const;
+ bool IsEmpty( void ) const;
+ bool RemoveArg( const CMIUtilString & vArg );
+ bool RemoveArgAtPos( const CMIUtilString & vArg, const MIuint nArgIndex );
+ //
+ CMICmdArgContext & operator= ( const CMICmdArgContext & vOther );
+
+// Overridden:
+public:
+ // From CMIUtilString
+ /* dtor */ virtual ~CMICmdArgContext( void );
+
+// Attributes:
+private:
+ CMIUtilString m_strCmdArgsAndOptions;
+ const MIchar m_constCharSpace;
+ const CMIUtilString m_constStrSpace;
+};
diff --git a/tools/lldb-mi/MICmdArgSet.cpp b/tools/lldb-mi/MICmdArgSet.cpp
new file mode 100644
index 000000000000..b0bee357cd6b
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgSet.cpp
@@ -0,0 +1,420 @@
+//===-- MICmdArgSet.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgSet.cpp
+//
+// Overview: CMICmdArgSet implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdArgSet.h"
+#include "MICmdArgValBase.h"
+#include "MICmnResources.h"
+#include "MICmnLog.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgSet constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgSet::CMICmdArgSet( void )
+: m_bIsArgsPresentButNotHandledByCmd( false )
+, m_constStrCommaSpc( ", " )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgSet destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgSet::~CMICmdArgSet( void )
+{
+ // Tidy up
+ Destroy();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources used by *this container object.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMICmdArgSet::Destroy( void )
+{
+ // Delete command argument objects
+ if( !m_setCmdArgs.empty() )
+ {
+ SetCmdArgs_t::iterator it = m_setCmdArgs.begin();
+ while( it != m_setCmdArgs.end() )
+ {
+ CMICmdArgValBase * pArg( *it );
+ delete pArg;
+
+ // Next
+ ++it;
+ }
+ m_setCmdArgs.clear();
+ }
+
+ m_setCmdArgsThatNotValid.clear();
+ m_setCmdArgsThatAreMissing.clear();
+ m_setCmdArgsNotHandledByCmd.clear();
+ m_setCmdArgsMissingInfo.clear();
+ m_bIsArgsPresentButNotHandledByCmd = false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the state flag indicating that the command set up ready to parse
+// command arguments or options found that one or more arguments was indeed
+// present but not handled. This is given as a warning in the MI log file.
+// Type: Method.
+// Args: None.
+// Return: bool - True = one or more args not handled, false = all args handled
+// Throws: None.
+//--
+bool CMICmdArgSet::IsArgsPresentButNotHandledByCmd( void ) const
+{
+ return m_bIsArgsPresentButNotHandledByCmd;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add the list of command's arguments to parse and validate another one.
+// Type: Method.
+// Args: vArg - (R) A command argument object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgSet::Add( const CMICmdArgValBase & vArg )
+{
+ CMICmdArgValBase * pArg = const_cast< CMICmdArgValBase * >( &vArg );
+ m_setCmdArgs.push_back( pArg );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: After validating an options line of text (the context) and there is a failure,
+// it is likely a mandatory command argument that is required is missing. This
+// function returns the argument that should be present.
+// Type: Method.
+// Args: None.
+// Return: SetCmdArgs_t & - Set of argument objects.
+// Throws: None.
+//--
+const CMICmdArgSet::SetCmdArgs_t & CMICmdArgSet::GetArgsThatAreMissing( void ) const
+{
+ return m_setCmdArgsThatAreMissing;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: After validating an options line of text (the context) and there is a failure,
+// it may be because one or more arguments were unable to extract a value. This
+// function returns the argument that were found to be invalid.
+// Type: Method.
+// Args: None.
+// Return: SetCmdArgs_t & - Set of argument objects.
+// Throws: None.
+//--
+const CMICmdArgSet::SetCmdArgs_t & CMICmdArgSet::GetArgsThatInvalid( void ) const
+{
+ return m_setCmdArgsThatNotValid;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The list of argument or option (objects) that were specified by the command
+// and so recognised when parsed but were not handled. Ideally the command
+// should handle all arguments and options presented to it. The command sends
+// warning to the MI log file to say that these options were not handled.
+// Used as one way to determine option that maybe should really be implemented
+// and not just ignored.
+// Type: Method.
+// Args: None.
+// Return: SetCmdArgs_t & - Set of argument objects.
+// Throws: None.
+//--
+const CMICmdArgSet::SetCmdArgs_t & CMICmdArgSet::GetArgsNotHandledByCmd( void ) const
+{
+ return m_setCmdArgsNotHandledByCmd;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Given a set of command argument objects parse the context option string to
+// find those argument and retrieve their value. If the function fails call
+// GetArgsThatAreMissing() to see which commands that were mandatory were
+// missing or failed to parse.
+// Type: Method.
+// Args: vStrMiCmd - (R) Command's name.
+// vCmdArgsText - (RW) A command's options or argument.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgSet::Validate( const CMIUtilString & vStrMiCmd, CMICmdArgContext & vwCmdArgsText )
+{
+ m_cmdArgContext = vwCmdArgsText;
+
+ // Iterate all the arguments or options required by a command
+ const MIuint nArgs = vwCmdArgsText.GetNumberArgsPresent();
+ MIuint nArgsMandatoryCnt = 0;
+ SetCmdArgs_t::const_iterator it = m_setCmdArgs.begin();
+ while( it != m_setCmdArgs.end() )
+ {
+ const CMICmdArgValBase * pArg( *it );
+ const CMIUtilString & rArgName( pArg->GetName() ); MIunused( rArgName );
+ if( pArg->GetIsMandatory() )
+ nArgsMandatoryCnt++;
+ if( !const_cast< CMICmdArgValBase * >( pArg )->Validate( vwCmdArgsText ) )
+ {
+ if( pArg->GetIsMandatory() && !pArg->GetFound() )
+ m_setCmdArgsThatAreMissing.push_back( const_cast< CMICmdArgValBase * >( pArg ) );
+ else if( pArg->GetFound() )
+ {
+ if( pArg->GetIsMissingOptions() )
+ m_setCmdArgsMissingInfo.push_back( const_cast< CMICmdArgValBase * >( pArg ) );
+ else if( !pArg->GetValid() )
+ m_setCmdArgsThatNotValid.push_back( const_cast< CMICmdArgValBase * >( pArg ) );
+ }
+ }
+ if( pArg->GetFound() && !pArg->GetIsHandledByCmd() )
+ {
+ m_bIsArgsPresentButNotHandledByCmd = true;
+ m_setCmdArgsNotHandledByCmd.push_back( const_cast< CMICmdArgValBase * >( pArg ) );
+ }
+
+ // Next
+ ++it;
+ }
+
+ // Check that one or more argument objects have any issues to report...
+
+ if( nArgs < nArgsMandatoryCnt )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_N_OPTIONS_REQUIRED ), nArgsMandatoryCnt ) );
+ return MIstatus::failure;
+ }
+
+ if( IsArgsPresentButNotHandledByCmd() )
+ WarningArgsNotHandledbyCmdLogFile( vStrMiCmd );
+
+ return ValidationFormErrorMessages( vwCmdArgsText );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Having validated the command's options text and failed for some reason form
+// the error message made up with the faults found.
+// Type: Method.
+// vCmdArgsText - (RW) A command's options or argument.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgSet::ValidationFormErrorMessages( const CMICmdArgContext & vwCmdArgsText )
+{
+ CMIUtilString strListMissing;
+ CMIUtilString strListInvalid;
+ CMIUtilString strListMissingInfo;
+ const bool bArgsMissing = (m_setCmdArgsThatAreMissing.size() > 0);
+ const bool bArgsInvalid = (m_setCmdArgsThatNotValid.size() > 0);
+ const bool bArgsMissingInfo = (m_setCmdArgsMissingInfo.size() > 0);
+ if( !(bArgsMissing || bArgsInvalid || bArgsMissingInfo) )
+ return MIstatus::success;
+ if( bArgsMissing )
+ {
+ MIuint i = 0;
+ SetCmdArgs_t::const_iterator it = m_setCmdArgsThatAreMissing.begin();
+ while( it != m_setCmdArgsThatAreMissing.end() )
+ {
+ if( i++ > 0 )
+ strListMissing += m_constStrCommaSpc;
+
+ const CMICmdArgValBase * pArg( *it );
+ strListMissing += pArg->GetName();
+
+ // Next
+ ++it;
+ }
+ }
+ if( bArgsInvalid )
+ {
+ MIuint i = 0;
+ SetCmdArgs_t::const_iterator it = m_setCmdArgsThatNotValid.begin();
+ while( it != m_setCmdArgsThatNotValid.end() )
+ {
+ if( i++ > 0 )
+ strListMissing += m_constStrCommaSpc;
+
+ const CMICmdArgValBase * pArg( *it );
+ strListInvalid += pArg->GetName();
+
+ // Next
+ ++it;
+ }
+ }
+ if( bArgsMissingInfo )
+ {
+ MIuint i = 0;
+ SetCmdArgs_t::const_iterator it = m_setCmdArgsMissingInfo.begin();
+ while( it != m_setCmdArgsMissingInfo.end() )
+ {
+ if( i++ > 0 )
+ strListMissingInfo += m_constStrCommaSpc;
+
+ const CMICmdArgValBase * pArg( *it );
+ strListMissingInfo += pArg->GetName();
+
+ // Next
+ ++it;
+ }
+ }
+
+ bool bHaveOneError = false;
+ CMIUtilString strError = MIRSRC( IDS_CMD_ARGS_ERR_PREFIX_MSG );
+ if( bArgsMissing && bArgsInvalid )
+ {
+ bHaveOneError = true;
+ strError += CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID ), strListMissing.c_str(), strListInvalid.c_str() );
+ }
+ if( bArgsMissing )
+ {
+ if( bHaveOneError )
+ strError += ". ";
+ bHaveOneError = true;
+ strError += CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY ), strListMissing.c_str() );
+ }
+ if( bArgsMissingInfo )
+ {
+ if( bHaveOneError )
+ strError += ". ";
+ bHaveOneError = true;
+ strError += CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF ), strListMissingInfo.c_str() );
+ }
+ if( bArgsInvalid )
+ {
+ if( bHaveOneError )
+ strError += ". ";
+ bHaveOneError = true;
+ strError += CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_INVALID ), strListInvalid.c_str() );
+ }
+ if( !vwCmdArgsText.IsEmpty() )
+ {
+ if( bHaveOneError )
+ strError += ". ";
+ bHaveOneError = true;
+ strError += CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN ), vwCmdArgsText.GetArgsLeftToParse().c_str() );
+ }
+
+ if( bHaveOneError )
+ {
+ SetErrorDescription( strError );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Ask if the command's argument options text had any arguments.
+// Type: Method.
+// Args: None.
+// Return: bool - True = Has one or more arguments present, false = no arguments.
+// Throws: None.
+//--
+bool CMICmdArgSet::IsArgContextEmpty( void ) const
+{
+ return m_cmdArgContext.IsEmpty();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the number of arguments that are being used for the command.
+// Type: Method.
+// Args: None.
+// Return: MIuint - Argument count.
+// Throws: None.
+//--
+MIuint CMICmdArgSet::GetCount( void ) const
+{
+ return m_setCmdArgs.size();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Given a set of command argument objects retrieve the argument with the
+// specified name.
+// Type: Method.
+// Args: vpArg - (W) A pointer to a command's argument object.
+// Return: True - Argument found.
+// False - Argument not found.
+// Throws: None.
+//--
+bool CMICmdArgSet::GetArg( const CMIUtilString & vArgName, CMICmdArgValBase *& vpArg ) const
+{
+ bool bFound = false;
+ SetCmdArgs_t::const_iterator it = m_setCmdArgs.begin();
+ while( it != m_setCmdArgs.end() )
+ {
+ CMICmdArgValBase * pArg( *it );
+ if( pArg->GetName() == vArgName )
+ {
+ bFound = true;
+ vpArg = pArg;
+ break;
+ }
+
+ // Next
+ ++it;
+ }
+
+ return bFound;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Write a warning message to the MI Log file about the command's arguments or
+// options that were found present but not handled.
+// Type: Method.
+// Args: vrCmdName - (R) The command's name.
+// Return: None.
+// Throws: None.
+//--
+void CMICmdArgSet::WarningArgsNotHandledbyCmdLogFile( const CMIUtilString & vrCmdName )
+{
+#if MICONFIG_GIVE_WARNING_CMD_ARGS_NOT_HANDLED
+
+ CMIUtilString strArgsNotHandled;
+ const CMICmdArgSet::SetCmdArgs_t & rSetArgs = GetArgsNotHandledByCmd();
+ MIuint nCnt = 0;
+ CMICmdArgSet::SetCmdArgs_t::const_iterator it = rSetArgs.begin();
+ while( it != rSetArgs.end() )
+ {
+ if( nCnt++ > 0 )
+ strArgsNotHandled += m_constStrCommaSpc;
+ const CMICmdArgValBase * pArg = *it;
+ strArgsNotHandled += pArg->GetName();
+
+ // Next
+ ++it;
+ }
+
+ const CMIUtilString strWarningMsg( CMIUtilString::Format( MIRSRC( IDS_CMD_WRN_ARGS_NOT_HANDLED ), vrCmdName.c_str(), strArgsNotHandled.c_str() ) );
+ m_pLog->WriteLog( strWarningMsg );
+
+#endif // MICONFIG_GIVE_WARNING_CMD_ARGS_NOT_HANDLED
+}
diff --git a/tools/lldb-mi/MICmdArgSet.h b/tools/lldb-mi/MICmdArgSet.h
new file mode 100644
index 000000000000..5f8f5049d9af
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgSet.h
@@ -0,0 +1,109 @@
+//===-- MICmdArgSet.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgSet.h
+//
+// Overview: CMICmdArgSet interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <vector>
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MICmdArgContext.h"
+
+// Declarations:
+class CMICmdArgValBase;
+
+//++ ============================================================================
+// Details: MI common code class. Command arguments container class.
+// A command may have one or more arguments of which some may be optional.
+// *this class contains a list of the command's arguments which are
+// validates against the commands argument options string (context string).
+// Each argument tries to extract the value it is looking for.
+// Argument objects added to *this container are owned by this container
+// and are deleted when this container goes out of scope. Allocate argument
+// objects on the heap.
+// It is assummed the arguments to be parsed are read from left to right in
+// order. The order added to *this container is the order they will parsed.
+// Gotchas: None.
+// Authors: Illya Rudkin 14/04/2014.
+// Changes: None.
+//--
+class CMICmdArgSet : public CMICmnBase
+{
+// Classes:
+public:
+ //++
+ // Description: ArgSet's interface for command arguments to implement.
+ //--
+ class IArg
+ {
+ public:
+ virtual bool GetFound( void ) const = 0;
+ virtual bool GetIsHandledByCmd( void ) const = 0;
+ virtual bool GetIsMandatory( void ) const = 0;
+ virtual bool GetIsMissingOptions( void ) const = 0;
+ virtual const CMIUtilString & GetName( void ) const = 0;
+ virtual bool GetValid( void ) const = 0;
+ virtual bool Validate( CMICmdArgContext & vwArgContext ) = 0;
+
+ /* dtor */ virtual ~IArg( void ) {};
+ };
+
+// Typedefs:
+public:
+ typedef std::vector< CMICmdArgValBase * > SetCmdArgs_t;
+
+// Methods:
+public:
+ /* ctor */ CMICmdArgSet( void );
+
+ bool Add( const CMICmdArgValBase & vArg );
+ bool GetArg( const CMIUtilString & vArgName, CMICmdArgValBase *& vpArg ) const;
+ const SetCmdArgs_t & GetArgsThatAreMissing( void ) const;
+ const SetCmdArgs_t & GetArgsThatInvalid( void ) const;
+ MIuint GetCount( void ) const;
+ bool IsArgContextEmpty( void ) const;
+ bool IsArgsPresentButNotHandledByCmd( void ) const;
+ void WarningArgsNotHandledbyCmdLogFile( const CMIUtilString & vrCmdName );
+ bool Validate( const CMIUtilString & vStrMiCmd, CMICmdArgContext & vwCmdArgsText );
+
+// Overrideable:
+public:
+ /* dtor */ virtual ~CMICmdArgSet( void );
+
+// Methods:
+private:
+ const SetCmdArgs_t & GetArgsNotHandledByCmd( void ) const;
+ void Destroy( void ); // Release resources used by *this object
+ bool ValidationFormErrorMessages( const CMICmdArgContext & vwCmdArgsText );
+
+// Attributes:
+private:
+ bool m_bIsArgsPresentButNotHandledByCmd; // True = The driver's client presented the command with options recognised but not handled by a command, false = all args handled
+ SetCmdArgs_t m_setCmdArgs; // The set of arguments that are that the command is expecting to find in the options string
+ SetCmdArgs_t m_setCmdArgsThatAreMissing; // The set of arguments that are required by the command but are missing
+ SetCmdArgs_t m_setCmdArgsThatNotValid; // The set of arguments found in the text but for some reason unable to extract a value
+ SetCmdArgs_t m_setCmdArgsNotHandledByCmd; // The set of arguments specified by the command which were present to the command but not handled
+ SetCmdArgs_t m_setCmdArgsMissingInfo; // The set of arguments that were present but were found to be missing additional information i.e. --thread 3 but 3 is missing
+ CMICmdArgContext m_cmdArgContext; // Copy of the command's argument options text before validate takes place (empties it of content)
+ const CMIUtilString m_constStrCommaSpc;
+};
+
diff --git a/tools/lldb-mi/MICmdArgValBase.cpp b/tools/lldb-mi/MICmdArgValBase.cpp
new file mode 100644
index 000000000000..ceab1a494865
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValBase.cpp
@@ -0,0 +1,171 @@
+//===-- MICmdArgValBase.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValBase.cpp
+//
+// Overview: CMICmdArgValBase implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdArgValBase.h"
+#include "MIUtilString.h"
+#include "MICmdArgContext.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValBase constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValBase::CMICmdArgValBase( void )
+: m_bFound( false )
+, m_bValid( false )
+, m_bMandatory( false )
+, m_bHandled( false )
+, m_bIsMissingOptions( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValBase constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValBase::CMICmdArgValBase( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd )
+: m_bFound( false )
+, m_bValid( false )
+, m_bMandatory( vbMandatory )
+, m_strArgName( vrArgName )
+, m_bHandled( vbHandleByCmd )
+, m_bIsMissingOptions( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValBase destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValBase::~CMICmdArgValBase( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the state flag of whether the argument is handled by the command or
+// not.
+// Type: Method.
+// Args: None.
+// Return: True - Command needs more information.
+// False - All information is present as expected.
+// Throws: None.
+//--
+bool CMICmdArgValBase::GetIsMissingOptions( void ) const
+{
+ return m_bIsMissingOptions;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the state flag of whether the argument is handled by the command or
+// not.
+// Type: Method.
+// Args: None.
+// Return: True - Command handles *this argument or option.
+// False - Not handled (argument specified but ignored).
+// Throws: None.
+//--
+bool CMICmdArgValBase::GetIsHandledByCmd( void ) const
+{
+ return m_bHandled;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the name of *this argument.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - Return the text name.
+// Throws: None.
+//--
+const CMIUtilString & CMICmdArgValBase::GetName( void ) const
+{
+ return m_strArgName;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the state flag of whether the argument was found in the command's
+// argument / options string.
+// Type: Method.
+// Args: None.
+// Return: True - Argument found.
+// False - Argument not found.
+// Throws: None.
+//--
+bool CMICmdArgValBase::GetFound( void ) const
+{
+ return m_bFound;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the state flag indicating whether the value was obtained from the
+// text arguments string and is valid.
+// Type: Method.
+// Args: None.
+// Return: True - Argument valid.
+// False - Argument not valid.
+// Throws: None.
+//--
+bool CMICmdArgValBase::GetValid( void ) const
+{
+ return m_bValid;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the state flag indicating whether *this argument is a mandatory
+// argument for the command or is optional to be present.
+// Type: Method.
+// Args: None.
+// Return: True - Mandatory.
+// False - Optional.
+// Throws: None.
+//--
+bool CMICmdArgValBase::GetIsMandatory( void ) const
+{
+ return m_bMandatory;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Parse the command's argument options string and try to extract the value *this
+// argument is looking for.
+// Type: Overrideable.
+// Args: vArgContext - (RW) The command's argument options string.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValBase::Validate( CMICmdArgContext & vwArgContext )
+{
+ MIunused( vwArgContext );
+
+ // Override to implement
+
+ return MIstatus::failure;
+} \ No newline at end of file
diff --git a/tools/lldb-mi/MICmdArgValBase.h b/tools/lldb-mi/MICmdArgValBase.h
new file mode 100644
index 000000000000..b367cb88ce29
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValBase.h
@@ -0,0 +1,157 @@
+//===-- Platform.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValBase.h
+//
+// Overview: CMICmdArgValBase interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MIUtilString.h"
+#include "MICmdArgSet.h"
+
+//++ ============================================================================
+// Details: MI common code class. Command argument base class. Arguments objects
+// needing specialization derived from *this class. An argument knows
+// what type of argument it is and how it is to interpret the options
+// (context) string to find and validate a matching argument and so
+// extract a value from it.
+// Argument objects are added to the CMICmdArgSet container object.
+// Once added the container they belong to that contain and will be
+// deleted when the container goes out of scope. Allocate argument
+// objects on the heap and pass in to the Add().
+// Note the code is written such that a command will produce an error
+// should it be presented with arguments or options it does not understand.
+// A command can recognise an option or argument then ignore if it
+// wishes (a warning is sent to the MI's Log file). This is so it is
+// hardwired to fail and catch arguments or options that presented by
+// different driver clients.
+// Based on the Interpreter pattern.
+// Gotchas: None.
+// Authors: Illya Rudkin 14/04/2014.
+// Changes: None.
+//--
+class CMICmdArgValBase : public CMICmdArgSet::IArg
+{
+// Methods:
+public:
+ /* ctor */ CMICmdArgValBase( void );
+ /* ctor */ CMICmdArgValBase( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd );
+
+// Overrideable:
+public:
+ /* dtor */ virtual ~CMICmdArgValBase( void );
+
+// Overridden:
+public:
+ // From CMICmdArgSet::IArg
+ virtual bool GetFound( void ) const;
+ virtual bool GetIsHandledByCmd( void ) const;
+ virtual bool GetIsMandatory( void ) const;
+ virtual bool GetIsMissingOptions( void ) const;
+ virtual const CMIUtilString & GetName( void ) const;
+ virtual bool GetValid( void ) const;
+ virtual bool Validate( CMICmdArgContext & vwArgContext );
+
+// Attributes:
+protected:
+ bool m_bFound; // True = yes found in arguments options text, false = not found
+ bool m_bValid; // True = yes argument parsed and valid, false = not valid
+ bool m_bMandatory; // True = yes arg must be present, false = optional argument
+ CMIUtilString m_strArgName;
+ bool m_bHandled; // True = Command processes *this option, false = not handled
+ bool m_bIsMissingOptions; // True = Command needs more information, false = ok
+};
+
+//++ ============================================================================
+// Details: MI common code class. Templated command argument base class.
+// Gotchas: None.
+// Authors: Illya Rudkin 14/04/2014.
+// Changes: None.
+//--
+template< class T >
+class CMICmdArgValBaseTemplate : public CMICmdArgValBase
+{
+// Methods:
+public:
+ /* ctor */ CMICmdArgValBaseTemplate( void );
+ /* ctor */ CMICmdArgValBaseTemplate( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd );
+ //
+ const T & GetValue( void ) const;
+
+// Overrideable:
+public:
+ /* dtor */ virtual ~CMICmdArgValBaseTemplate( void );
+
+// Attributes:
+protected:
+ T m_argValue;
+};
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValBaseTemplate constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+template< class T >
+CMICmdArgValBaseTemplate< T >::CMICmdArgValBaseTemplate( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValBaseTemplate constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
+// Return: None.
+// Throws: None.
+//--
+template< class T >
+CMICmdArgValBaseTemplate< T >::CMICmdArgValBaseTemplate( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd )
+: CMICmdArgValBase( vrArgName, vbMandatory, vbHandleByCmd )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValBaseTemplate destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+template< class T >
+CMICmdArgValBaseTemplate< T >::~CMICmdArgValBaseTemplate( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the value the argument parsed from the command's argument / options
+// text string.
+// Type: Method.
+// Args: None.
+// Return: Template type & - The arg value of *this object.
+// Throws: None.
+//--
+template< class T >
+const T & CMICmdArgValBaseTemplate< T >::GetValue( void ) const
+{
+ return m_argValue;
+}
diff --git a/tools/lldb-mi/MICmdArgValConsume.cpp b/tools/lldb-mi/MICmdArgValConsume.cpp
new file mode 100644
index 000000000000..72a57f870ad4
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValConsume.cpp
@@ -0,0 +1,119 @@
+//===-- MICmdArgValConsume.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValConsume.cpp
+//
+// Overview: CMICmdArgValConsume implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdArgValConsume.h"
+#include "MICmdArgContext.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValConsume constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValConsume::CMICmdArgValConsume( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValConsume constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValConsume::CMICmdArgValConsume( const CMIUtilString & vrArgName, const bool vbMandatory )
+: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, true )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValConsume destructor.
+// Type: Overidden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValConsume::~CMICmdArgValConsume( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Parse the command's argument options string and try to extract the value *this
+// argument is looking for.
+// Type: Overridden.
+// Args: vwArgContext - (R) The command's argument options string.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValConsume::Validate( CMICmdArgContext & vwArgContext )
+{
+ if( vwArgContext.IsEmpty() )
+ return MIstatus::success;
+
+ if( vwArgContext.GetNumberArgsPresent() == 1 )
+ {
+ const CMIUtilString & rArg( vwArgContext.GetArgsLeftToParse() );
+ m_bFound = true;
+ m_bValid = true;
+ vwArgContext.RemoveArg( rArg );
+ return MIstatus::success;
+ }
+
+ // In reality there are more than one option, if so the file option
+ // is the last one (don't handle that here - find the best looking one)
+ const CMIUtilString::VecString_t vecOptions( vwArgContext.GetArgs() );
+ CMIUtilString::VecString_t::const_iterator it = vecOptions.begin();
+ while( it != vecOptions.end() )
+ {
+ const CMIUtilString & rTxt( *it );
+ m_bFound = true;
+
+ if( vwArgContext.RemoveArg( rTxt ) )
+ {
+ m_bValid = true;
+ return MIstatus::success;
+ }
+ else
+ return MIstatus::success;
+
+ // Next
+ ++it;
+ }
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Nothing to examine as we just want to consume the argument or option (ignore
+// it).
+// Type: Method.
+// Args: None.
+// Return: bool - True = yes ok, false = not ok.
+// Throws: None.
+//--
+bool CMICmdArgValConsume::IsOk( void ) const
+{
+ return true;
+}
diff --git a/tools/lldb-mi/MICmdArgValConsume.h b/tools/lldb-mi/MICmdArgValConsume.h
new file mode 100644
index 000000000000..a113d89458f3
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValConsume.h
@@ -0,0 +1,63 @@
+//===-- MICmdArgValConsume.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValConsume.h
+//
+// Overview: CMICmdArgValConsume interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdArgValBase.h"
+
+// Declarations:
+class CMICmdArgContext;
+
+//++ ============================================================================
+// Details: MI common code class. Command argument class. Arguments object
+// needing specialization derived from the CMICmdArgValBase class.
+// An argument knows what type of argument it is and how it is to
+// interpret the options (context) string to find and validate a matching
+// argument. This type having recognised its argument name just consumes
+// that argument or option (ignores it). This is the so the validation
+// process can then ask if all arguments or options have been recognised
+// other an error will occurred "argument not recognised". For example
+// this can be used to consume the "--" text which is not an argument in
+// itself. Normally the GetValue() function (in base class) would return
+// a value for the argument but is not the case for *this argument type
+// object.
+// Based on the Interpreter pattern.
+// Gotchas: None.
+// Authors: Illya Rudkin 20/05/2014.
+// Changes: None.
+//--
+class CMICmdArgValConsume : public CMICmdArgValBaseTemplate< CMIUtilString >
+{
+// Methods:
+public:
+ /* ctor */ CMICmdArgValConsume( void );
+ /* ctor */ CMICmdArgValConsume( const CMIUtilString & vrArgName, const bool vbMandatory );
+ //
+ bool IsOk( void ) const;
+
+// Overridden:
+public:
+ // From CMICmdArgValBase
+ /* dtor */ virtual ~CMICmdArgValConsume( void );
+ // From CMICmdArgSet::IArg
+ virtual bool Validate( CMICmdArgContext & vwArgContext );
+};
diff --git a/tools/lldb-mi/MICmdArgValFile.cpp b/tools/lldb-mi/MICmdArgValFile.cpp
new file mode 100644
index 000000000000..d5cc52b90b44
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValFile.cpp
@@ -0,0 +1,204 @@
+//===-- MICmdArgValFile.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValFile.cpp
+//
+// Overview: CMICmdArgValFile implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdArgValFile.h"
+#include "MICmdArgContext.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValFile constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValFile::CMICmdArgValFile( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValFile constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValFile::CMICmdArgValFile( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd )
+: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, vbHandleByCmd )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValFile destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValFile::~CMICmdArgValFile( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Parse the command's argument options string and try to extract the value *this
+// argument is looking for.
+// Type: Overridden.
+// Args: vwArgContext - (R) The command's argument options string.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValFile::Validate( CMICmdArgContext & vwArgContext )
+{
+ if( vwArgContext.IsEmpty() )
+ return MIstatus::success;
+
+ // The GDB/MI spec suggests there is only parameter
+
+ if( vwArgContext.GetNumberArgsPresent() == 1 )
+ {
+ const CMIUtilString & rFile( vwArgContext.GetArgsLeftToParse() );
+ if( IsFilePath( rFile ) )
+ {
+ m_bFound = true;
+ m_bValid = true;
+ m_argValue = rFile.Trim( '"' );
+ vwArgContext.RemoveArg( rFile );
+ return MIstatus::success;
+ }
+ else
+ return MIstatus::failure;
+ }
+
+ // In reality there are more than one option, if so the file option
+ // is the last one (don't handle that here - find the best looking one)
+ const CMIUtilString::VecString_t vecOptions( vwArgContext.GetArgs() );
+ CMIUtilString::VecString_t::const_iterator it = vecOptions.begin();
+ while( it != vecOptions.end() )
+ {
+ const CMIUtilString & rTxt( *it );
+ if( IsFilePath( rTxt ) )
+ {
+ m_bFound = true;
+
+ if( vwArgContext.RemoveArg( rTxt ) )
+ {
+ m_bValid = true;
+ m_argValue = rTxt.Trim( '"' );
+ return MIstatus::success;
+ }
+ else
+ return MIstatus::success;
+ }
+
+ // Next
+ ++it;
+ }
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Given some text extract the file name path from it. If a space is found in
+// path done return the path surrounded in quotes.
+// Type: Method.
+// Args: vrTxt - (R) The text to extract the file name path from.
+// Return: CMIUtilString - File name and or path.
+// Throws: None.
+//--
+CMIUtilString CMICmdArgValFile::GetFileNamePath( const CMIUtilString & vrTxt ) const
+{
+ CMIUtilString fileNamePath( vrTxt );
+
+ // Look for a space in the path
+ const MIchar cSpace = ' ';
+ const MIint nPos = fileNamePath.find( cSpace );
+ if( nPos != (MIint) std::string::npos )
+ fileNamePath = CMIUtilString::Format( "\"%s\"", fileNamePath.c_str() );
+
+ return fileNamePath;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the string and determine if it is a valid file name path.
+// Type: Method.
+// Args: vrFileNamePath - (R) File's name and directory path.
+// Return: bool - True = yes valid file path, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValFile::IsFilePath( const CMIUtilString & vrFileNamePath ) const
+{
+ if( vrFileNamePath.empty() )
+ return false;
+
+ const bool bHavePosSlash = (vrFileNamePath.find_first_of( "/" ) != std::string::npos);
+ const bool bHaveBckSlash = (vrFileNamePath.find_first_of( "\\" ) != std::string::npos);
+
+ // Look for --someLongOption
+ MIint nPos = vrFileNamePath.find_first_of( "--" );
+ const bool bLong = (nPos == 0);
+ if( bLong )
+ return false;
+
+ // Look for -f type short parameters
+ nPos = vrFileNamePath.find_first_of( "-" );
+ const bool bShort = (nPos == 0);
+ if( bShort )
+ return false;
+
+ // Look for i1 i2 i3....
+ nPos = vrFileNamePath.find_first_of( "i" );
+ const bool bFoundI1 = ((nPos == 0) && (::isdigit( vrFileNamePath[ 1 ] )) );
+ if( bFoundI1 )
+ return false;
+
+ const bool bValidChars = IsValidChars( vrFileNamePath );
+ if( bValidChars || bHavePosSlash || bHaveBckSlash )
+ return true;
+
+ return false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine if the path contains valid characters for a file path. Letters can be
+// either upper or lower case.
+// Type: Method.
+// Args: vrText - (R) The text data to examine.
+// Return: bool - True = yes valid, false = one or more chars is valid.
+// Throws: None.
+//--
+bool CMICmdArgValFile::IsValidChars( const CMIUtilString & vrText ) const
+{
+ const MIchar * pPtr = const_cast< MIchar * >( vrText.c_str() );
+ for( MIuint i = 0; i < vrText.length(); i++, pPtr++ )
+ {
+ const MIchar c = *pPtr;
+ if( ::isalnum( (int) c ) == 0 )
+ {
+ if( (c != '.') && (c != '-') && (c != '_') )
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/tools/lldb-mi/MICmdArgValFile.h b/tools/lldb-mi/MICmdArgValFile.h
new file mode 100644
index 000000000000..071727401454
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValFile.h
@@ -0,0 +1,61 @@
+//===-- MICmdArgValFile.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValFile.h
+//
+// Overview: CMICmdArgValFile interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdArgValBase.h"
+
+// Declarations:
+class CMICmdArgContext;
+
+//++ ============================================================================
+// Details: MI common code class. Command argument class. Arguments object
+// needing specialization derived from the CMICmdArgValBase class.
+// An argument knows what type of argument it is and how it is to
+// interpret the options (context) string to find and validate a matching
+// argument and so extract a value from it .
+// Based on the Interpreter pattern.
+// Gotchas: None.
+// Authors: Illya Rudkin 15/04/2014.
+// Changes: None.
+//--
+class CMICmdArgValFile : public CMICmdArgValBaseTemplate< CMIUtilString >
+{
+// Methods:
+public:
+ /* ctor */ CMICmdArgValFile( void );
+ /* ctor */ CMICmdArgValFile( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd );
+ //
+ bool IsFilePath( const CMIUtilString & vrFileNamePath ) const;
+ CMIUtilString GetFileNamePath( const CMIUtilString & vrTxt ) const;
+
+// Overridden:
+public:
+ // From CMICmdArgValBase
+ /* dtor */ virtual ~CMICmdArgValFile( void );
+ // From CMICmdArgSet::IArg
+ virtual bool Validate( CMICmdArgContext & vwArgContext );
+
+// Methods:
+private:
+ bool IsValidChars( const CMIUtilString & vrText ) const;
+};
diff --git a/tools/lldb-mi/MICmdArgValListBase.cpp b/tools/lldb-mi/MICmdArgValListBase.cpp
new file mode 100644
index 000000000000..37b729e42741
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValListBase.cpp
@@ -0,0 +1,221 @@
+//===-- MICmdArgValListBase.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValListBase.cpp
+//
+// Overview: CMICmdArgValListBase implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdArgValListBase.h"
+#include "MICmdArgContext.h"
+#include "MICmdArgValFile.h"
+#include "MICmdArgValNumber.h"
+#include "MICmdArgValOptionLong.h"
+#include "MICmdArgValOptionShort.h"
+#include "MICmdArgValString.h"
+#include "MICmdArgValThreadGrp.h"
+#include "MICmdArgValConsume.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValListBase constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValListBase::CMICmdArgValListBase( void )
+: m_eArgType( eArgValType_invalid )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValListBase constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValListBase::CMICmdArgValListBase( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd )
+: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, vbHandleByCmd )
+, m_eArgType( eArgValType_invalid )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValListBase constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
+// veType - (R) The type of argument to look for and create argument object of a certain type.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValListBase::CMICmdArgValListBase( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType )
+: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, vbHandleByCmd )
+, m_eArgType( veType )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValListBase destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValListBase::~CMICmdArgValListBase( void )
+{
+ // Tidy up
+ Destroy();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Tear down resources used by *this object.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMICmdArgValListBase::Destroy( void )
+{
+ // Tidy up
+ VecArgObjPtr_t::const_iterator it = m_argValue.begin();
+ while( it != m_argValue.end() )
+ {
+ CMICmdArgValBase * pArgObj = *it;
+ delete pArgObj;
+
+ // Next
+ ++it;
+ }
+ m_argValue.clear();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Create an CMICmdArgValBase derived object matching the type specified
+// and put the option or argument's value inside it.
+// Type: Method.
+// Args: vrTxt - (R) Text version the option or argument.
+// veType - (R) The type of argument or option object to create.
+// Return: CMICmdArgValBase * - Option object holding the value.
+// - NULL = Functional failed.
+// Throws: None.
+//--
+CMICmdArgValBase * CMICmdArgValListBase::CreationObj( const CMIUtilString & vrTxt, const ArgValType_e veType ) const
+{
+ CMICmdArgValBase * pOptionObj = nullptr;
+ switch( veType )
+ {
+ case eArgValType_File:
+ pOptionObj = new CMICmdArgValFile();
+ break;
+ case eArgValType_Consume:
+ pOptionObj = new CMICmdArgValConsume();
+ break;
+ case eArgValType_Number:
+ pOptionObj = new CMICmdArgValNumber();
+ break;
+ case eArgValType_OptionLong:
+ pOptionObj = new CMICmdArgValOptionLong();
+ break;
+ case eArgValType_OptionShort:
+ pOptionObj = new CMICmdArgValOptionShort();
+ break;
+ case eArgValType_String:
+ pOptionObj = new CMICmdArgValString();
+ break;
+ case eArgValType_StringQuoted:
+ pOptionObj = new CMICmdArgValString( true, false, false );
+ break;
+ case eArgValType_StringQuotedNumber:
+ pOptionObj = new CMICmdArgValString( true, true, false );
+ break;
+ case eArgValType_StringQuotedNumberPath:
+ pOptionObj = new CMICmdArgValString( true, true, true );
+ break;
+ case eArgValType_StringAnything:
+ pOptionObj = new CMICmdArgValString( true );
+ break;
+ case eArgValType_ThreadGrp:
+ pOptionObj = new CMICmdArgValThreadGrp();
+ break;
+ default:
+ return nullptr;
+ }
+
+ CMICmdArgContext argCntxt( vrTxt );
+ if( !pOptionObj->Validate( argCntxt ) )
+ return nullptr;
+
+ return pOptionObj;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Validate the option or argument is the correct type.
+// Type: Method.
+// Args: vrTxt - (R) Text version the option or argument.
+// veType - (R) The type of value to expect.
+// Return: bool - True = Yes expected type present, False = no.
+// Throws: None.
+//--
+bool CMICmdArgValListBase::IsExpectedCorrectType( const CMIUtilString & vrTxt, const ArgValType_e veType ) const
+{
+ bool bValid = false;
+ switch( veType )
+ {
+ case eArgValType_File:
+ bValid = CMICmdArgValFile().IsFilePath( vrTxt );
+ break;
+ case eArgValType_Consume:
+ bValid = CMICmdArgValConsume().IsOk();
+ break;
+ case eArgValType_Number:
+ bValid = CMICmdArgValNumber().IsArgNumber( vrTxt );
+ break;
+ case eArgValType_OptionLong:
+ bValid = CMICmdArgValOptionLong().IsArgLongOption( vrTxt );
+ break;
+ case eArgValType_OptionShort:
+ bValid = CMICmdArgValOptionShort().IsArgShortOption( vrTxt );
+ break;
+ case eArgValType_String:
+ bValid = CMICmdArgValString().IsStringArg( vrTxt );
+ break;
+ case eArgValType_StringQuoted:
+ bValid = CMICmdArgValString( true, false, false ).IsStringArg( vrTxt );
+ break;
+ case eArgValType_StringQuotedNumber:
+ bValid = CMICmdArgValString( true, true, false ).IsStringArg( vrTxt );
+ break;
+ case eArgValType_StringQuotedNumberPath:
+ bValid = CMICmdArgValString( true, true, true ).IsStringArg( vrTxt );
+ break;
+ case eArgValType_StringAnything:
+ bValid = CMICmdArgValString( true ).IsStringArg( vrTxt );
+ break;
+ case eArgValType_ThreadGrp:
+ bValid = CMICmdArgValThreadGrp().IsArgThreadGrp( vrTxt );
+ break;
+ default:
+ return false;
+ }
+
+ return bValid;
+}
diff --git a/tools/lldb-mi/MICmdArgValListBase.h b/tools/lldb-mi/MICmdArgValListBase.h
new file mode 100644
index 000000000000..2798efa19a48
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValListBase.h
@@ -0,0 +1,103 @@
+//===-- MICmdArgValListBase.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValListBase.h
+//
+// Overview: CMICmdArgValListBase interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <vector>
+
+// In-house headers:
+#include "MICmdArgValBase.h"
+
+// Declarations:
+class CMICmdArgContext;
+
+//++ ============================================================================
+// Details: MI common code class. Command argument with addition options class.
+// For example --recurse 1 2 4 [group ...]. Arguments object that
+// require a list of options associated with them derive from the
+// CMICmdArgValListBase class. Additional options are also extracted from
+// the command arguments text string.
+// An argument knows what type of argument it is and how it is to
+// interpret the options (context) string to find and validate a matching
+// options and so extract a values from it .
+// The CMICmdArgValBase objects are added to the derived argument class's
+// container. The option arguments belong to that derived class and will
+// be deleted that object goes out of scope.
+// Based on the Interpreter pattern.
+// Gotchas: None.
+// Authors: Illya Rudkin 16/04/2014.
+// Changes: None.
+//--
+class CMICmdArgValListBase : public CMICmdArgValBaseTemplate< std::vector< CMICmdArgValBase * > >
+{
+// Typedef:
+public:
+ typedef std::vector< CMICmdArgValBase * > VecArgObjPtr_t;
+
+// Enums:
+public:
+ //++ ---------------------------------------------------------------------------------
+ // Details: CMICmdArgValListBase needs to know what type of argument to look for in
+ // the command options text. It also needs to create argument objects of
+ // a specific type.
+ //--
+ enum ArgValType_e
+ {
+ eArgValType_File = 0,
+ eArgValType_Consume,
+ eArgValType_Number,
+ eArgValType_OptionLong,
+ eArgValType_OptionShort,
+ eArgValType_String,
+ eArgValType_StringQuoted,
+ eArgValType_StringQuotedNumber,
+ eArgValType_StringQuotedNumberPath,
+ eArgValType_StringAnything, // Accept any words for a string 'type' even if they look like --longOptions for example
+ eArgValType_ThreadGrp,
+ eArgValType_count, // Always the last one
+ eArgValType_invalid
+ };
+
+// Methods:
+public:
+ /* ctor */ CMICmdArgValListBase( void );
+ /* ctor */ CMICmdArgValListBase( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd );
+ /* ctor */ CMICmdArgValListBase( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType );
+
+// Overridden:
+public:
+ // From CMICmdArgValBase
+ /* dtor */ virtual ~CMICmdArgValListBase( void );
+
+// Methods:
+protected:
+ bool IsExpectedCorrectType( const CMIUtilString & vrTxt, const ArgValType_e veType ) const;
+ CMICmdArgValBase * CreationObj( const CMIUtilString & vrTxt, const ArgValType_e veType ) const;
+
+// Attributes:
+protected:
+ ArgValType_e m_eArgType;
+
+// Methods:
+private:
+ void Destroy( void );
+};
diff --git a/tools/lldb-mi/MICmdArgValListOfN.cpp b/tools/lldb-mi/MICmdArgValListOfN.cpp
new file mode 100644
index 000000000000..246fa2c9445d
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValListOfN.cpp
@@ -0,0 +1,189 @@
+//===-- MICmdArgValListOfN.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValListOfN.cpp
+//
+// Overview: CMICmdArgValListOfN implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdArgValListOfN.h"
+#include "MICmdArgContext.h"
+#include "MICmdArgValFile.h"
+#include "MICmdArgValNumber.h"
+#include "MICmdArgValOptionLong.h"
+#include "MICmdArgValOptionShort.h"
+#include "MICmdArgValString.h"
+#include "MICmdArgValThreadGrp.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValListOfN constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValListOfN::CMICmdArgValListOfN( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValListOfN constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
+// veType - (R) The type of argument to look for and create argument object of a certain type.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValListOfN::CMICmdArgValListOfN( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType )
+: CMICmdArgValListBase( vrArgName, vbMandatory, vbHandleByCmd, veType )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValListOfN destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValListOfN::~CMICmdArgValListOfN( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Parse the command's argument options string and try to extract the list of
+// arguments based on the argument object type to look for.
+// Type: Overridden.
+// Args: vwArgContext - (RW) The command's argument options string.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValListOfN::Validate( CMICmdArgContext & vwArgContext )
+{
+ if( m_eArgType >= eArgValType_count )
+ {
+ m_eArgType = eArgValType_invalid;
+ return MIstatus::failure;
+ }
+
+ if( vwArgContext.IsEmpty() )
+ return MIstatus::success;
+
+ const CMIUtilString & rArg( vwArgContext.GetArgsLeftToParse() );
+ if( IsListOfN( rArg ) && CreateList( rArg ) )
+ {
+ m_bFound = true;
+ m_bValid = true;
+ vwArgContext.RemoveArg( rArg );
+ return MIstatus::success;
+ }
+ else
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Create list of argument objects each holding a value extract from the command
+// options line.
+// Type: Method.
+// Args: vrTxt - (R) Some options text.
+// Return: bool - True = yes valid arg, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValListOfN::CreateList( const CMIUtilString & vrTxt )
+{
+ CMIUtilString::VecString_t vecOptions;
+ if( (m_eArgType == eArgValType_StringQuoted) ||
+ (m_eArgType == eArgValType_StringQuotedNumber) ||
+ (m_eArgType == eArgValType_StringQuotedNumberPath) ||
+ (m_eArgType == eArgValType_StringAnything) )
+ {
+ if( vrTxt.SplitConsiderQuotes( " ", vecOptions ) == 0 )
+ return MIstatus::failure;
+ }
+ else
+ if( vrTxt.Split( " ", vecOptions ) == 0 )
+ return MIstatus::failure;
+
+ CMIUtilString::VecString_t::const_iterator it = vecOptions.begin();
+ while( it != vecOptions.end() )
+ {
+ const CMIUtilString & rOption = *it;
+ CMICmdArgValBase * pOption = CreationObj( rOption, m_eArgType );
+ if( pOption != nullptr )
+ m_argValue.push_back( pOption );
+ else
+ return MIstatus::failure;
+
+ // Next
+ ++it;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the string and determine if it is a valid string type argument.
+// Type: Method.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes valid arg, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValListOfN::IsListOfN( const CMIUtilString & vrTxt ) const
+{
+ CMIUtilString::VecString_t vecOptions;
+ if( (m_eArgType == eArgValType_StringQuoted) ||
+ (m_eArgType == eArgValType_StringQuotedNumber) ||
+ (m_eArgType == eArgValType_StringQuotedNumberPath) ||
+ (m_eArgType == eArgValType_StringAnything) )
+ {
+ if( vrTxt.SplitConsiderQuotes( " ", vecOptions ) == 0 )
+ return false;
+ }
+ else
+ if( vrTxt.Split( " ", vecOptions ) == 0 )
+ return false;
+
+ CMIUtilString::VecString_t::const_iterator it = vecOptions.begin();
+ while( it != vecOptions.end() )
+ {
+ const CMIUtilString & rOption = *it;
+ if( !IsExpectedCorrectType( rOption, m_eArgType ) )
+ break;
+
+ // Next
+ ++it;
+ }
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the list of CMICmdArgValBase derived option objects found following
+// *this long option argument. For example "list-thread-groups [ --recurse 1 ]"
+// where 1 is the list of expected option to follow.
+// Type: Method.
+// Args: None.
+// Return: CMICmdArgValListBase::VecArgObjPtr_t & - List of options.
+// Throws: None.
+//--
+const CMICmdArgValListBase::VecArgObjPtr_t & CMICmdArgValListOfN::GetExpectedOptions( void ) const
+{
+ return m_argValue;
+}
diff --git a/tools/lldb-mi/MICmdArgValListOfN.h b/tools/lldb-mi/MICmdArgValListOfN.h
new file mode 100644
index 000000000000..0fe5d2f4f831
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValListOfN.h
@@ -0,0 +1,98 @@
+//===-- MICmdArgValListOfN.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValListOfN.h
+//
+// Overview: CMICmdArgValListOfN interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <vector>
+
+// In-house headers:
+#include "MICmdArgValListBase.h"
+
+// Declarations:
+class CMICmdArgContext;
+
+//++ ============================================================================
+// Details: MI common code class. Command argument class. Arguments object
+// needing specialization derived from the CMICmdArgValBase class.
+// An argument knows what type of argument it is and how it is to
+// interpret the options (context) string to find and validate a matching
+// argument and so extract a value from it .
+// The CMICmdArgValBase objects added to *this ListOfN container belong
+// to this container and will be deleted when *this object goes out of
+// scope.
+// To parse arguments like 'thread-id ...' i.e. 1 10 12 13 ...
+// If vbMandatory argument is true it takes on the (...)+ specification
+// otherwise assumed to be (...)* specification.
+// Based on the Interpreter pattern.
+// Gotchas: None.
+// Authors: Illya Rudkin 16/04/2014.
+// Changes: None.
+//--
+class CMICmdArgValListOfN : public CMICmdArgValListBase
+{
+// Methods:
+public:
+ /* ctor */ CMICmdArgValListOfN( void );
+ /* ctor */ CMICmdArgValListOfN( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType );
+ //
+ const VecArgObjPtr_t & GetExpectedOptions( void ) const;
+ template< class T1, typename T2 >
+ bool GetExpectedOption( T2 & vrwValue ) const;
+
+// Overridden:
+public:
+ // From CMICmdArgValBase
+ /* dtor */ virtual ~CMICmdArgValListOfN( void );
+ // From CMICmdArgSet::IArg
+ virtual bool Validate( CMICmdArgContext & vArgContext );
+
+// Methods:
+private:
+ bool IsListOfN( const CMIUtilString & vrTxt ) const;
+ bool CreateList( const CMIUtilString & vrTxt );
+};
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the first argument or option value from the list of 1 or more options
+// parsed from the command's options string.
+// Type: Template method.
+// Args: vrwValue - (W) Templated type return value.
+// T1 - The argument value's class type of the data hold in the list of options.
+// T2 - The type pf the variable which holds the value wanted.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed. List of object was empty.
+// Throws: None.
+//--
+template< class T1, typename T2 >
+bool CMICmdArgValListOfN::GetExpectedOption( T2 & vrwValue ) const
+{
+ const VecArgObjPtr_t & rVecOptions( GetExpectedOptions() );
+ VecArgObjPtr_t::const_iterator it2 = rVecOptions.begin();
+ if( it2 != rVecOptions.end() )
+ {
+ const T1 * pOption = static_cast< T1 * >( *it2 );
+ vrwValue = pOption->GetValue();
+ return MIstatus::success;
+ }
+
+ return MIstatus::failure;
+}
diff --git a/tools/lldb-mi/MICmdArgValNumber.cpp b/tools/lldb-mi/MICmdArgValNumber.cpp
new file mode 100644
index 000000000000..18bdccdc9ac5
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValNumber.cpp
@@ -0,0 +1,167 @@
+//===-- MICmdArgValNumber.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValNumber.cpp
+//
+// Overview: CMICmdArgValNumber implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdArgValNumber.h"
+#include "MICmdArgContext.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValNumber constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValNumber::CMICmdArgValNumber( void )
+: m_nNumber( 0 )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValNumber constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValNumber::CMICmdArgValNumber( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd )
+: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, vbHandleByCmd )
+, m_nNumber( 0 )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValNumber destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValNumber::~CMICmdArgValNumber( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Parse the command's argument options string and try to extract the value *this
+// argument is looking for.
+// Type: Overridden.
+// Args: vwArgContext - (RW) The command's argument options string.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValNumber::Validate( CMICmdArgContext & vwArgContext )
+{
+ if( vwArgContext.IsEmpty() )
+ return MIstatus::success;
+
+ if( vwArgContext.GetNumberArgsPresent() == 1 )
+ {
+ const CMIUtilString & rArg( vwArgContext.GetArgsLeftToParse() );
+ if( IsArgNumber( rArg ) && ExtractNumber( rArg ) )
+ {
+ m_bFound = true;
+ m_bValid = true;
+ m_argValue = GetNumber();
+ vwArgContext.RemoveArg( rArg );
+ return MIstatus::success;
+ }
+ else
+ return MIstatus::failure;
+ }
+
+ // More than one option...
+ const CMIUtilString::VecString_t vecOptions( vwArgContext.GetArgs() );
+ CMIUtilString::VecString_t::const_iterator it = vecOptions.begin();
+ while( it != vecOptions.end() )
+ {
+ const CMIUtilString & rArg( *it );
+ if( IsArgNumber( rArg ) && ExtractNumber( rArg ) )
+ {
+ m_bFound = true;
+
+ if( vwArgContext.RemoveArg( rArg ) )
+ {
+ m_bValid = true;
+ m_argValue = GetNumber();
+ return MIstatus::success;
+ }
+ else
+ return MIstatus::failure;
+ }
+
+ // Next
+ ++it;
+ }
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the string and determine if it is a valid string type argument.
+// Type: Method.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes valid arg, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValNumber::IsArgNumber( const CMIUtilString & vrTxt ) const
+{
+ // Look for --someLongOption
+ if( std::string::npos != vrTxt.find( "--" ) )
+ return false;
+
+ return vrTxt.IsNumber();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Extract the thread group number from the thread group argument.
+// Type: Method.
+// Args: vrTxt - (R) Some text.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValNumber::ExtractNumber( const CMIUtilString & vrTxt )
+{
+ MIint64 nNumber = 0;
+ bool bOk = vrTxt.ExtractNumber( nNumber );
+ if( bOk )
+ {
+ m_nNumber = static_cast< MIint >( nNumber );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the thread group ID found in the argument.
+// Type: Method.
+// Args: None.
+// Return: MIuint - Thread group ID.
+// Throws: None.
+//--
+MIint64 CMICmdArgValNumber::GetNumber( void ) const
+{
+ return m_nNumber;
+}
+
diff --git a/tools/lldb-mi/MICmdArgValNumber.h b/tools/lldb-mi/MICmdArgValNumber.h
new file mode 100644
index 000000000000..219b040a257d
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValNumber.h
@@ -0,0 +1,65 @@
+//===-- MICmdArgValNumber.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValNumber.h
+//
+// Overview: CMICmdArgValNumber interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdArgValBase.h"
+
+// Declarations:
+class CMICmdArgContext;
+
+//++ ============================================================================
+// Details: MI common code class. Command argument class. Arguments object
+// needing specialization derived from the CMICmdArgValBase class.
+// An argument knows what type of argument it is and how it is to
+// interpret the options (context) string to find and validate a matching
+// argument and so extract a value from it .
+// Based on the Interpreter pattern.
+// Gotchas: None.
+// Authors: Illya Rudkin 14/04/2014.
+// Changes: None.
+//--
+class CMICmdArgValNumber : public CMICmdArgValBaseTemplate< MIint64 >
+{
+// Methods:
+public:
+ /* ctor */ CMICmdArgValNumber( void );
+ /* ctor */ CMICmdArgValNumber( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd );
+ //
+ bool IsArgNumber( const CMIUtilString & vrTxt ) const;
+
+// Overridden:
+public:
+ // From CMICmdArgValBase
+ /* dtor */ virtual ~CMICmdArgValNumber( void );
+ // From CMICmdArgSet::IArg
+ virtual bool Validate( CMICmdArgContext & vwArgContext );
+
+// Methods:
+private:
+ bool ExtractNumber( const CMIUtilString & vrTxt );
+ MIint64 GetNumber( void ) const;
+
+// Attributes:
+private:
+ MIint64 m_nNumber;
+};
diff --git a/tools/lldb-mi/MICmdArgValOptionLong.cpp b/tools/lldb-mi/MICmdArgValOptionLong.cpp
new file mode 100644
index 000000000000..6c87984ba811
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValOptionLong.cpp
@@ -0,0 +1,319 @@
+//===-- MICmdArgValOptionLong.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValOptionLong.cpp
+//
+// Overview: CMICmdArgValOptionLong implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdArgValOptionLong.h"
+#include "MICmdArgContext.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValOptionLong constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValOptionLong::CMICmdArgValOptionLong( void )
+: m_nExpectingNOptions( 0 )
+, m_eExpectingOptionType( eArgValType_invalid )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValOptionLong constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValOptionLong::CMICmdArgValOptionLong( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd )
+: CMICmdArgValListBase( vrArgName, vbMandatory, vbHandleByCmd )
+, m_nExpectingNOptions( 0 )
+, m_eExpectingOptionType( eArgValType_invalid )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValOptionLong constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
+// veType - (R) The type of argument to look for and create argument object of a certain type.
+// vnExpectingNOptions - (R) The number of options expected to read following *this argument.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValOptionLong::CMICmdArgValOptionLong( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType, const MIuint vnExpectingNOptions )
+: CMICmdArgValListBase( vrArgName, vbMandatory, vbHandleByCmd )
+, m_nExpectingNOptions( vnExpectingNOptions )
+, m_eExpectingOptionType( veType )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValOptionLong destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValOptionLong::~CMICmdArgValOptionLong( void )
+{
+ // Tidy up
+ Destroy();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Tear down resources used by *this object.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMICmdArgValOptionLong::Destroy( void )
+{
+ // Tidy up
+ VecArgObjPtr_t::const_iterator it = m_vecArgsExpected.begin();
+ while( it != m_vecArgsExpected.end() )
+ {
+ CMICmdArgValBase * pOptionObj = *it;
+ delete pOptionObj;
+
+ // Next
+ ++it;
+ }
+ m_vecArgsExpected.clear();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Parse the command's argument options string and try to extract the long
+// argument *this argument type is looking for.
+// Type: Overridden.
+// Args: vwArgContext - (RW) The command's argument options string.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValOptionLong::Validate( CMICmdArgContext & vwArgContext )
+{
+ if( vwArgContext.IsEmpty() )
+ return MIstatus::success;
+
+ if( vwArgContext.GetNumberArgsPresent() == 1 )
+ {
+ const CMIUtilString & rArg( vwArgContext.GetArgsLeftToParse() );
+ if( IsArgLongOption( rArg ) && ArgNameMatch( rArg ) )
+ {
+ m_bFound = true;
+
+ if( !vwArgContext.RemoveArg( rArg ) )
+ return MIstatus::failure;
+
+ if( m_nExpectingNOptions == 0 )
+ {
+ m_bValid = true;
+ return MIstatus::success;
+ }
+
+ m_bIsMissingOptions = true;
+ return MIstatus::failure;
+ }
+ else
+ return MIstatus::failure;
+ }
+
+ // More than one option...
+ MIuint nArgIndex = 0;
+ const CMIUtilString::VecString_t vecOptions( vwArgContext.GetArgs() );
+ CMIUtilString::VecString_t::const_iterator it = vecOptions.begin();
+ while( it != vecOptions.end() )
+ {
+ const CMIUtilString & rArg( *it );
+ if( IsArgOptionCorrect( rArg ) && ArgNameMatch( rArg ) )
+ {
+ m_bFound = true;
+
+ if( !vwArgContext.RemoveArg( rArg ) )
+ return MIstatus::failure;
+
+ if( m_nExpectingNOptions != 0 )
+ {
+ if( ExtractExpectedOptions( vwArgContext, nArgIndex ) )
+ {
+ m_bValid = true;
+ return MIstatus::success;
+ }
+
+ m_bIsMissingOptions = true;
+ return MIstatus::failure;
+ }
+ else
+ {
+ m_bValid = true;
+ return MIstatus::success;
+ }
+ }
+
+ // Next
+ ++it;
+ ++nArgIndex;
+ }
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Parse the text following *this argument and extract the options the values of
+// CMICmdArgValListBase::m_eArgType forming argument objects for each of those
+// options extracted.
+// Type: Method.
+// Args: vrwTxt - (RW) The command's argument options string.
+// nArgIndex - (R) The Nth arg position in argument context from the left.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValOptionLong::ExtractExpectedOptions( CMICmdArgContext & vrwTxt, const MIuint nArgIndex )
+{
+ CMIUtilString::VecString_t vecOptions;
+ MIuint nOptionsPresent = 0;
+ if( (m_eExpectingOptionType != eArgValType_StringQuoted) &&
+ (m_eExpectingOptionType != eArgValType_StringQuotedNumber) &&
+ (m_eExpectingOptionType != eArgValType_StringQuotedNumberPath) )
+ nOptionsPresent = vrwTxt.GetArgsLeftToParse().Split( " ", vecOptions );
+ else
+ nOptionsPresent = vrwTxt.GetArgsLeftToParse().SplitConsiderQuotes( " ", vecOptions );
+ if( nOptionsPresent == 0 )
+ return MIstatus::failure;
+
+ MIuint nArgIndexCnt = 0;
+ MIuint nTypeCnt = 0;
+ MIuint nTypeCnt2 = 0;
+ MIuint nFoundNOptionsCnt = 0;
+ CMIUtilString::VecString_t::const_iterator it = vecOptions.begin();
+ while( it != vecOptions.end() )
+ {
+ // Move to the Nth argument position from left before do validation/checking
+ if( nArgIndexCnt++ == nArgIndex )
+ {
+ nTypeCnt++;
+ const CMIUtilString & rOption( *it );
+ if( IsExpectedCorrectType( rOption, m_eExpectingOptionType ) )
+ {
+ nTypeCnt2++;
+ CMICmdArgValBase * pOptionObj = CreationObj( rOption, m_eExpectingOptionType );
+ if( (pOptionObj != nullptr) && vrwTxt.RemoveArgAtPos( rOption, nArgIndex ) )
+ {
+ nFoundNOptionsCnt++;
+ m_vecArgsExpected.push_back( pOptionObj );
+ }
+ }
+
+ // Is the sequence 'options' of same type broken. Expecting the same type until the
+ // next argument.
+ if( nTypeCnt != nTypeCnt2 )
+ return MIstatus::failure;
+
+ if( nFoundNOptionsCnt == m_nExpectingNOptions )
+ return MIstatus::success;
+ }
+
+ // Next
+ ++it;
+ }
+ if( nFoundNOptionsCnt != m_nExpectingNOptions )
+ return MIstatus::failure;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the string and determine if it is a valid long type option argument.
+// Long type argument looks like --someLongOption.
+// Type: Method.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes valid arg, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValOptionLong::IsArgLongOption( const CMIUtilString & vrTxt ) const
+{
+ const bool bHavePosSlash = (vrTxt.find_first_of( "/" ) != std::string::npos);
+ const bool bHaveBckSlash = (vrTxt.find_first_of( "\\" ) != std::string::npos);
+ if( bHavePosSlash || bHaveBckSlash )
+ return false;
+
+ const MIint nPos = vrTxt.find_first_of( "--" );
+ if( nPos != 0 )
+ return false;
+
+ if( vrTxt.length() < 3 )
+ return false;
+
+ const CMIUtilString strArg = vrTxt.substr( 2 ).c_str();
+ if( strArg.IsNumber() )
+ return false;
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the string and determine if it is a valid long type option argument.
+// Long type argument looks like --someLongOption.
+// Type: Overideable.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes valid arg, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValOptionLong::IsArgOptionCorrect( const CMIUtilString & vrTxt ) const
+{
+ return IsArgLongOption( vrTxt );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Does the argument name of the argument being parsed ATM match the name of
+// *this argument object.
+// Type: Method.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes arg name matched, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValOptionLong::ArgNameMatch( const CMIUtilString & vrTxt ) const
+{
+ const CMIUtilString strArg = vrTxt.substr( 2 ).c_str();
+ return (strArg == GetName() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the list of CMICmdArgValBase derived option objects found following
+// *this long option argument. For example "list-thread-groups [ --recurse 1 ]"
+// where 1 is the list of expected option to follow.
+// Type: Method.
+// Args: None.
+// Return: CMICmdArgValListBase::VecArgObjPtr_t & - List of options.
+// Throws: None.
+//--
+const CMICmdArgValListBase::VecArgObjPtr_t & CMICmdArgValOptionLong::GetExpectedOptions( void ) const
+{
+ return m_vecArgsExpected;
+}
+
diff --git a/tools/lldb-mi/MICmdArgValOptionLong.h b/tools/lldb-mi/MICmdArgValOptionLong.h
new file mode 100644
index 000000000000..3baae416c93a
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValOptionLong.h
@@ -0,0 +1,109 @@
+//===-- MICmdArgValOptionLong.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValOptionLong.h
+//
+// Overview: CMICmdArgValOptionLong interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdArgValListBase.h"
+
+// Declarations:
+class CMICmdArgContext;
+class CMIUtilString;
+
+//++ ============================================================================
+// Details: MI common code class. Command argument class. Arguments object
+// needing specialization derived from the CMICmdArgValBase class.
+// An argument knows what type of argument it is and how it is to
+// interpret the options (context) string to find and validate a matching
+// argument and so extract a value from it.
+// If *this argument has expected options following it the option objects
+// created to hold each of those option's values belong to *this argument
+// object and so are deleted when *this object goes out of scope.
+// Based on the Interpreter pattern.
+// Gotchas: None.
+// Authors: Illya Rudkin 16/04/2014.
+// Changes: None.
+//--
+class CMICmdArgValOptionLong : public CMICmdArgValListBase
+{
+// Methods:
+public:
+ /* ctor */ CMICmdArgValOptionLong( void );
+ /* ctor */ CMICmdArgValOptionLong( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd );
+ /* ctor */ CMICmdArgValOptionLong( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType, const MIuint vnExpectingNOptions );
+ //
+ bool IsArgLongOption( const CMIUtilString & vrTxt ) const;
+ const VecArgObjPtr_t & GetExpectedOptions( void ) const;
+ template< class T1, typename T2 >
+ bool GetExpectedOption( T2 & vrwValue ) const;
+
+// Overridden:
+public:
+ // From CMICmdArgValBase
+ /* dtor */ virtual ~CMICmdArgValOptionLong( void );
+ // From CMICmdArgSet::IArg
+ virtual bool Validate( CMICmdArgContext & vArgContext );
+
+// Methods:
+protected:
+ bool ExtractExpectedOptions( CMICmdArgContext & vrwTxt, const MIuint nArgIndex );
+
+// Overrideable:
+protected:
+ virtual bool IsArgOptionCorrect( const CMIUtilString & vrTxt ) const;
+ virtual bool ArgNameMatch( const CMIUtilString & vrTxt ) const;
+
+// Methods:
+private:
+ void Destroy( void );
+
+// Attributes:
+private:
+ MIuint m_nExpectingNOptions; // The number of options expected to read following *this argument
+ VecArgObjPtr_t m_vecArgsExpected; // The option objects holding the value extracted following *this argument
+ ArgValType_e m_eExpectingOptionType; // The type of options expected to read following *this argument
+};
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the first argument or option value from the list of 1 or more options
+// parsed from the command's options string.
+// Type: Template method.
+// Args: vrwValue - (W) Templated type return value.
+// T1 - The argument value's class type of the data hold in the list of options.
+// T2 - The type pf the variable which holds the value wanted.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed. List of object was empty.
+// Throws: None.
+//--
+template< class T1, typename T2 >
+bool CMICmdArgValOptionLong::GetExpectedOption( T2 & vrwValue ) const
+{
+ const VecArgObjPtr_t & rVecOptions( GetExpectedOptions() );
+ VecArgObjPtr_t::const_iterator it2 = rVecOptions.begin();
+ if( it2 != rVecOptions.end() )
+ {
+ const T1 * pOption = static_cast< T1 * >( *it2 );
+ vrwValue = pOption->GetValue();
+ return MIstatus::success;
+ }
+
+ return MIstatus::failure;
+}
diff --git a/tools/lldb-mi/MICmdArgValOptionShort.cpp b/tools/lldb-mi/MICmdArgValOptionShort.cpp
new file mode 100644
index 000000000000..76adb7f11493
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValOptionShort.cpp
@@ -0,0 +1,128 @@
+//===-- MICmdArgValOptionShort.cpp ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValOptionShort.cpp
+//
+// Overview: CMICmdArgValOptionShort implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdArgValOptionShort.h"
+#include "MICmdArgContext.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValOptionShort constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValOptionShort::CMICmdArgValOptionShort( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValOptionShort constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValOptionShort::CMICmdArgValOptionShort( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd )
+: CMICmdArgValOptionLong( vrArgName, vbMandatory, vbHandleByCmd )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValOptionLong constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
+// veType - (R) The type of argument to look for and create argument object of a certain type.
+// vnExpectingNOptions - (R) The number of options expected to read following *this argument.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValOptionShort::CMICmdArgValOptionShort( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType, const MIuint vnExpectingNOptions )
+: CMICmdArgValOptionLong( vrArgName, vbMandatory, vbHandleByCmd, veType, vnExpectingNOptions )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValOptionShort destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValOptionShort::~CMICmdArgValOptionShort( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the string and determine if it is a valid short type option argument.
+// Type: Method.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes valid arg, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValOptionShort::IsArgShortOption( const CMIUtilString & vrTxt ) const
+{
+ // Look for --someLongOption
+ MIint nPos = vrTxt.find( "--" );
+ if( nPos == 0 )
+ return false;
+
+ // Look for -f short option
+ nPos = vrTxt.find( "-" );
+ if( nPos != 0 )
+ return false;
+
+ if( vrTxt.length() > 2 )
+ return false;
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the string and determine if it is a valid short type option argument.
+// Long type argument looks like -f some short option.
+// Type: Overridden.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes valid arg, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValOptionShort::IsArgOptionCorrect( const CMIUtilString & vrTxt ) const
+{
+ return IsArgShortOption( vrTxt );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Does the argument name of the argument being parsed ATM match the name of
+// *this argument object.
+// Type: Overridden.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes arg name matched, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValOptionShort::ArgNameMatch( const CMIUtilString & vrTxt ) const
+{
+ const CMIUtilString strArg = vrTxt.substr( 1 ).c_str();
+ return (strArg == GetName() );
+}
diff --git a/tools/lldb-mi/MICmdArgValOptionShort.h b/tools/lldb-mi/MICmdArgValOptionShort.h
new file mode 100644
index 000000000000..7af038377123
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValOptionShort.h
@@ -0,0 +1,65 @@
+//===-- MICmdArgValOptionShort.h --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValOptionShort.h
+//
+// Overview: CMICmdArgValOptionShort interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdArgValOptionLong.h"
+
+// Declarations:
+class CMICmdArgContext;
+class CMIUtilString;
+
+//++ ============================================================================
+// Details: MI common code class. Command argument class. Arguments object
+// needing specialization derived from the CMICmdArgValOptionLong class.
+// An argument knows what type of argument it is and how it is to
+// interpret the options (context) string to find and validate a matching
+// argument and so extract a value from it.
+// If *this argument has expected options following it the option objects
+// created to hold each of those option's values belong to *this argument
+// object and so are deleted when *this object goes out of scope.
+// Based on the Interpreter pattern.
+// Gotchas: None.
+// Authors: Illya Rudkin 16/04/2014.
+// Changes: None.
+//--
+class CMICmdArgValOptionShort : public CMICmdArgValOptionLong
+{
+// Methods:
+public:
+ /* ctor */ CMICmdArgValOptionShort( void );
+ /* ctor */ CMICmdArgValOptionShort( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd );
+ /* ctor */ CMICmdArgValOptionShort( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const ArgValType_e veType, const MIuint vnExpectingNOptions );
+ //
+ bool IsArgShortOption( const CMIUtilString & vrTxt ) const;
+
+// Overridden:
+public:
+ // From CMICmdArgValBase
+ /* dtor */ virtual ~CMICmdArgValOptionShort( void );
+
+// Overridden:
+private:
+ // From CMICmdArgValOptionLong
+ virtual bool IsArgOptionCorrect( const CMIUtilString & vrTxt ) const;
+ virtual bool ArgNameMatch( const CMIUtilString & vrTxt ) const;
+};
diff --git a/tools/lldb-mi/MICmdArgValString.cpp b/tools/lldb-mi/MICmdArgValString.cpp
new file mode 100644
index 000000000000..06818b1dc571
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValString.cpp
@@ -0,0 +1,502 @@
+//===-- MICmdArgValString.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValString.cpp
+//
+// Overview: CMICmdArgValString implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdArgValString.h"
+#include "MICmdArgContext.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValString constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValString::CMICmdArgValString( void )
+: m_bHandleQuotedString( false )
+, m_bAcceptNumbers( false )
+, m_bHandleDirPaths( false )
+, m_bHandleAnything( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValString constructor.
+// Type: Method.
+// Args: vbAnything - (R) True = Parse a string and accept anything, false = do not accept anything.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValString::CMICmdArgValString( const bool vbAnything )
+: m_bHandleQuotedString( false )
+, m_bAcceptNumbers( false )
+, m_bHandleDirPaths( false )
+, m_bHandleAnything( vbAnything )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValString constructor.
+// Type: Method.
+// Args: vbHandleQuotes - (R) True = Parse a string surrounded by quotes spaces are not delimitors, false = only text up to next delimiting space character.
+// vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised as string types.
+// vbHandleDirPaths - (R) True = Parse a string and accept as a file path if a path, false = file paths are not recognised as string types.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValString::CMICmdArgValString( const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths )
+: m_bHandleQuotedString( vbHandleQuotes )
+, m_bAcceptNumbers( vbAcceptNumbers )
+, m_bHandleDirPaths( vbHandleDirPaths )
+, m_bHandleAnything( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValString constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
+// vbHandleQuotes - (R) True = Parse a string surrounded by quotes spaces are not delimitors, false = only text up to next delimiting space character. (Dflt = false)
+// vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised as string types. (Dflt = false)
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValString::CMICmdArgValString( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const bool vbHandleQuotes /* = false */, const bool vbAcceptNumbers /* = false */ )
+: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, vbHandleByCmd )
+, m_bHandleQuotedString( vbHandleQuotes )
+, m_bAcceptNumbers( vbAcceptNumbers )
+, m_bHandleDirPaths( false )
+, m_bHandleAnything( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValString destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValString::~CMICmdArgValString( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Parse the command's argument options string and try to extract the value *this
+// argument is looking for.
+// Type: Overridden.
+// Args: vrwArgContext - (RW) The command's argument options string.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValString::Validate( CMICmdArgContext & vrwArgContext )
+{
+ if( vrwArgContext.IsEmpty() )
+ return MIstatus::success;
+
+ if( m_bHandleQuotedString )
+ return (ValidateQuotedText( vrwArgContext ) || ValidateQuotedTextEmbedded( vrwArgContext ) );
+
+ return ValidateSingleText( vrwArgContext );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Parse the command's argument options string and try to extract only the next
+// word delimited by the next space.
+// Type: Method.
+// Args: vrwArgContext - (RW) The command's argument options string.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValString::ValidateSingleText( CMICmdArgContext & vrwArgContext )
+{
+ if( vrwArgContext.GetNumberArgsPresent() == 1 )
+ {
+ const CMIUtilString & rArg( vrwArgContext.GetArgsLeftToParse() );
+ if( IsStringArg( rArg ) )
+ {
+ m_bFound = true;
+ m_bValid = true;
+ m_argValue = rArg;
+ vrwArgContext.RemoveArg( rArg );
+ return MIstatus::success;
+ }
+ else
+ return MIstatus::failure;
+ }
+
+ // More than one option...
+ const CMIUtilString::VecString_t vecOptions( vrwArgContext.GetArgs() );
+ CMIUtilString::VecString_t::const_iterator it = vecOptions.begin();
+ while( it != vecOptions.end() )
+ {
+ const CMIUtilString & rArg( *it );
+ if( IsStringArg( rArg ) )
+ {
+ m_bFound = true;
+
+ if( vrwArgContext.RemoveArg( rArg ) )
+ {
+ m_bValid = true;
+ m_argValue = rArg;
+ return MIstatus::success;
+ }
+ else
+ return MIstatus::failure;
+ }
+
+ // Next
+ ++it;
+ }
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Parse the command's argument options string and try to extract all the words
+// between quotes then delimited by the next space. Can fall through to
+// ValidateSingleText() or ValidateQuotedQuotedTextEmbedded().
+// Type: Method.
+// Args: vrwArgContext - (RW) The command's argument options string.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValString::ValidateQuotedText( CMICmdArgContext & vrwArgContext )
+{
+ // CODETAG_QUOTEDTEXT_SIMILAR_CODE
+ CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse();
+ const MIchar cQuote = '"';
+
+ // Look for first quote of two
+ MIint nPos = strOptions.find( cQuote );
+ if( nPos == (MIint) std::string::npos )
+ return ValidateSingleText( vrwArgContext );
+
+ // Is one and only quote at end of the string
+ const MIint nLen = strOptions.length();
+ if( nPos == (MIint)(nLen - 1) )
+ return MIstatus::failure;
+
+ // Quote must be the first character in the string or be preceeded by a space
+ if( (nPos > 0) && (strOptions[ nPos - 1 ] != ' ') )
+ return MIstatus::failure;
+
+ // Need to find the other quote
+ const MIint nPos2 = strOptions.rfind( cQuote );
+ if( nPos2 == (MIint) std::string::npos )
+ return MIstatus::failure;
+
+ // Is there quotes surrounding string formatting embedded quotes
+ if( IsStringArgQuotedQuotedTextEmbedded( strOptions ) )
+ return ValidateQuotedQuotedTextEmbedded( vrwArgContext );
+
+ // Make sure not same back quote, need two quotes
+ if( nPos == nPos2 )
+ return MIstatus::failure;
+
+ // Extract quoted text
+ const CMIUtilString strQuotedTxt = strOptions.substr( nPos, nPos2 - nPos + 1 ).c_str();
+ if( vrwArgContext.RemoveArg( strQuotedTxt ) )
+ {
+ m_bFound = true;
+ m_bValid = true;
+ m_argValue = strOptions.substr( nPos + 1, nPos2 - nPos - 1 ).c_str();
+ return MIstatus::success;
+ }
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Parse the command's argument options string and try to extract all the words
+// between quotes then delimited by the next space. If there any string format
+// characters '\\' used to embed quotes these are ignored i.e. "\\\"%5d\\\""
+// becomes "%5d". Can fall through to ValidateQuotedText().
+// Type: Method.
+// Args: vrwArgContext - (RW) The command's argument options string.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValString::ValidateQuotedTextEmbedded( CMICmdArgContext & vrwArgContext )
+{
+ // CODETAG_QUOTEDTEXT_SIMILAR_CODE
+ CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse();
+ const MIchar cBckSlash = '\\';
+ const MIint nPos = strOptions.find( cBckSlash );
+ if( nPos == (MIint) std::string::npos )
+ return ValidateQuotedText( vrwArgContext );
+
+ // Back slash must be the first character in the string or be preceeded by a space
+ // or '\\'
+ const MIchar cSpace = ' ';
+ if( (nPos > 0) && (strOptions[ nPos - 1 ] != cSpace) )
+ return MIstatus::failure;
+
+ // Need to find the other back slash
+ const MIint nPos2 = strOptions.rfind( cBckSlash );
+ if( nPos2 == (MIint) std::string::npos )
+ return MIstatus::failure;
+
+ // Make sure not same back slash, need two slashs
+ if( nPos == nPos2 )
+ return MIstatus::failure;
+
+ // Look for the two quotes
+ const MIint nLen = strOptions.length();
+ const MIchar cQuote = '"';
+ const MIint nPosQuote1 = nPos + 1;
+ const MIint nPosQuote2 = (nPos2 < nLen) ? nPos2 + 1 : nPos2;
+ if( (nPosQuote1 != nPosQuote2) &&
+ (strOptions[ nPosQuote1 ] != cQuote) && (strOptions[ nPosQuote2 ] != cQuote) )
+ return MIstatus::failure;
+
+ // Extract quoted text
+ const CMIUtilString strQuotedTxt = strOptions.substr( nPos, nPosQuote2 - nPos + 1 ).c_str();
+ if( vrwArgContext.RemoveArg( strQuotedTxt ) )
+ {
+ m_bFound = true;
+ m_bValid = true;
+ m_argValue = strQuotedTxt;
+ return MIstatus::success;
+ }
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Parse the command's argument options string and try to extract all the words
+// between quotes then delimited by the next space. If there any string format
+// characters '\\' used to embed quotes these are ignored i.e. "\\\"%5d\\\""
+// becomes "%5d".
+// Type: Method.
+// Args: vrwArgContext - (RW) The command's argument options string.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValString::ValidateQuotedQuotedTextEmbedded( CMICmdArgContext & vrwArgContext )
+{
+ // CODETAG_QUOTEDTEXT_SIMILAR_CODE
+ CMIUtilString strOptions = vrwArgContext.GetArgsLeftToParse();
+ const MIint nPos = strOptions.find( "\"\\\"" );
+ if( nPos == (MIint) std::string::npos )
+ return MIstatus::failure;
+
+ const MIint nPos2 = strOptions.rfind( "\\\"\"" );
+ if( nPos2 == (MIint) std::string::npos )
+ return MIstatus::failure;
+
+ const MIint nLen = strOptions.length();
+ if( (nLen > 5) && ((nPos + 2) == (nPos2 - 2)) )
+ return MIstatus::failure;
+
+ // Quote must be the first character in the string or be preceeded by a space
+ // or '\\'
+ const MIchar cSpace = ' ';
+ if( (nPos > 0) && (strOptions[ nPos - 1 ] != cSpace) )
+ return MIstatus::failure;
+
+ // Extract quoted text
+ const CMIUtilString strQuotedTxt = strOptions.substr( nPos, nPos2 - nPos + 3 ).c_str();
+ if( vrwArgContext.RemoveArg( strQuotedTxt ) )
+ {
+ m_bFound = true;
+ m_bValid = true;
+ m_argValue = strQuotedTxt;
+ return MIstatus::success;
+ }
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the string and determine if it is a valid string type argument.
+// Type: Method.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes valid arg, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValString::IsStringArg( const CMIUtilString & vrTxt ) const
+{
+ if( m_bHandleQuotedString )
+ return (IsStringArgQuotedText( vrTxt ) ||
+ IsStringArgQuotedTextEmbedded( vrTxt ) ||
+ IsStringArgQuotedQuotedTextEmbedded( vrTxt ) ||
+ IsStringArgSingleText( vrTxt ) ); // Still test for this as could just be one word still
+
+ return IsStringArgSingleText( vrTxt );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the string and determine if it is a valid string type argument or
+// option value. If the string looks like a long option, short option, a thread
+// group ID or just a number it is rejected as a string type value. There is an
+// option to allow the string to accept a number as a string type.
+// Type: Method.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes valid argument value, false = something else.
+// Throws: None.
+//--
+bool CMICmdArgValString::IsStringArgSingleText( const CMIUtilString & vrTxt ) const
+{
+ // Accept anything as string word
+ if( m_bHandleAnything )
+ return true;
+
+ if( !m_bHandleDirPaths )
+ {
+ // Look for directory file paths, if found reject
+ const bool bHavePosSlash = (vrTxt.find_first_of( "/" ) != std::string::npos);
+ const bool bHaveBckSlash = (vrTxt.find_first_of( "\\" ) != std::string::npos);
+ if( bHavePosSlash || bHaveBckSlash )
+ return false;
+ }
+
+ // Look for --someLongOption, if found reject
+ if( 0 == vrTxt.find( "--" ) )
+ return false;
+
+ // Look for -f type short options, if found reject
+ if( (0 == vrTxt.find( "-" )) && (vrTxt.length() == 2) )
+ return false;
+
+ // Look for thread group i1 i2 i3...., if found reject
+ if( (vrTxt.find( "i" ) == 0) && ::isdigit( vrTxt[ 1 ]) )
+ return false;
+
+ // Look for numbers, if found reject
+ if( !m_bAcceptNumbers && vrTxt.IsNumber() )
+ return false;
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the string and determine if it is a valid string type argument.
+// Take into account quotes surrounding the text. Note this function falls
+// through to IsStringArgSingleText() should the criteria match fail.
+// Type: Method.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes valid arg, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValString::IsStringArgQuotedText( const CMIUtilString & vrTxt ) const
+{
+ // CODETAG_QUOTEDTEXT_SIMILAR_CODE
+ const MIchar cQuote = '"';
+ const MIint nPos = vrTxt.find( cQuote );
+ if( nPos == (MIint) std::string::npos )
+ return false;
+
+ // Is one and only quote at end of the string
+ if( nPos == (MIint)(vrTxt.length() - 1) )
+ return false;
+
+ // Quote must be the first character in the string or be preceeded by a space
+ // Also check for embedded string formating quote
+ const MIchar cBckSlash = '\\';
+ const MIchar cSpace = ' ';
+ if( (nPos > 1) && (vrTxt[ nPos - 1 ] == cBckSlash) && (vrTxt[ nPos - 2 ] != cSpace) )
+ {
+ return false;
+ }
+ if( (nPos > 0) && (vrTxt[ nPos - 1 ] != cSpace) )
+ return false;
+
+ // Need to find the other quote
+ const MIint nPos2 = vrTxt.rfind( cQuote );
+ if( nPos2 == (MIint) std::string::npos )
+ return false;
+
+ // Make sure not same quote, need two quotes
+ if( nPos == nPos2 )
+ return MIstatus::failure;
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the string and determine if it is a valid string type argument.
+// Take into account quotes surrounding the text. Take into account string format
+// embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls
+// through to IsStringArgQuotedText() should the criteria match fail.
+// Type: Method.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes valid arg, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValString::IsStringArgQuotedTextEmbedded( const CMIUtilString & vrTxt ) const
+{
+ // CODETAG_QUOTEDTEXT_SIMILAR_CODE
+ const MIchar cBckSlash = '\\';
+ const MIint nPos = vrTxt.find( cBckSlash );
+ if( nPos == (MIint) std::string::npos )
+ return false;
+
+ // Slash must be the first character in the string or be preceeded by a space
+ const MIchar cSpace = ' ';
+ if( (nPos > 0) && (vrTxt[ nPos - 1 ] != cSpace) )
+ return false;
+
+ // Need to find the other matching slash
+ const MIint nPos2 = vrTxt.rfind( cBckSlash );
+ if( nPos2 == (MIint) std::string::npos )
+ return false;
+
+ // Make sure not same back slash, need two slashs
+ if( nPos == nPos2 )
+ return MIstatus::failure;
+
+ return false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the string and determine if it is a valid string type argument.
+// Take into account quotes surrounding the text. Take into account string format
+// embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls
+// through to IsStringArgQuotedTextEmbedded() should the criteria match fail.
+// Type: Method.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes valid arg, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValString::IsStringArgQuotedQuotedTextEmbedded( const CMIUtilString & vrTxt ) const
+{
+ const MIint nPos = vrTxt.find( "\"\\\"" );
+ if( nPos == (MIint) std::string::npos )
+ return false;
+
+ const MIint nPos2 = vrTxt.rfind( "\\\"\"" );
+ if( nPos2 == (MIint) std::string::npos )
+ return false;
+
+ const MIint nLen = vrTxt.length();
+ if( (nLen > 5) && ((nPos + 2) == (nPos2 - 2)) )
+ return false;
+
+ return true;
+}
diff --git a/tools/lldb-mi/MICmdArgValString.h b/tools/lldb-mi/MICmdArgValString.h
new file mode 100644
index 000000000000..ab411a02dc88
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValString.h
@@ -0,0 +1,76 @@
+//===-- MICmdArgValString.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValString.h
+//
+// Overview: CMICmdArgValString interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdArgValBase.h"
+
+// Declarations:
+class CMICmdArgContext;
+
+//++ ============================================================================
+// Details: MI common code class. Command argument class. Arguments object
+// needing specialization derived from the CMICmdArgValBase class.
+// An argument knows what type of argument it is and how it is to
+// interpret the options (context) string to find and validate a matching
+// argument and so extract a value from it .
+// Based on the Interpreter pattern.
+// Gotchas: None.
+// Authors: Illya Rudkin 15/04/2014.
+// Changes: None.
+//--
+class CMICmdArgValString : public CMICmdArgValBaseTemplate< CMIUtilString >
+{
+// Methods:
+public:
+ /* ctor */ CMICmdArgValString( void );
+ /* ctor */ CMICmdArgValString( const bool vbAnything );
+ /* ctor */ CMICmdArgValString( const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths );
+ /* ctor */ CMICmdArgValString( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd, const bool vbHandleQuotes = false, const bool vbAcceptNumbers = false );
+ //
+ bool IsStringArg( const CMIUtilString & vrTxt ) const;
+
+// Overridden:
+public:
+ // From CMICmdArgValBase
+ /* dtor */ virtual ~CMICmdArgValString( void );
+ // From CMICmdArgSet::IArg
+ virtual bool Validate( CMICmdArgContext & vrwArgContext );
+
+// Methods:
+private:
+ bool ValidateSingleText( CMICmdArgContext & vrwArgContext );
+ bool ValidateQuotedText( CMICmdArgContext & vrwArgContext );
+ bool ValidateQuotedTextEmbedded( CMICmdArgContext & vrwArgContext );
+ bool ValidateQuotedQuotedTextEmbedded( CMICmdArgContext & vrwArgContext );
+ bool IsStringArgSingleText( const CMIUtilString & vrTxt ) const;
+ bool IsStringArgQuotedText( const CMIUtilString & vrTxt ) const;
+ bool IsStringArgQuotedTextEmbedded( const CMIUtilString & vrTxt ) const;
+ bool IsStringArgQuotedQuotedTextEmbedded( const CMIUtilString & vrTxt ) const;
+
+// Attribute:
+private:
+ bool m_bHandleQuotedString; // True = Parse a string surrounded by quotes spaces are not delimitors, false = only text up to next delimiting space character
+ bool m_bAcceptNumbers; // True = Parse a string and accept as a number if number, false = numbers not recognised as string types
+ bool m_bHandleDirPaths; // True = Parse a string and accept directory file style string if present, false = directory file path not accepted
+ bool m_bHandleAnything; // True = Parse a string and accept anything if present, false = validate for criteria matches
+};
diff --git a/tools/lldb-mi/MICmdArgValThreadGrp.cpp b/tools/lldb-mi/MICmdArgValThreadGrp.cpp
new file mode 100644
index 000000000000..7d3290482119
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValThreadGrp.cpp
@@ -0,0 +1,173 @@
+//===-- MICmdArgValThreadGrp.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValThreadGrp.cpp
+//
+// Overview: CMICmdArgValThreadGrp implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdArgValThreadGrp.h"
+#include "MICmdArgContext.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValThreadGrp constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValThreadGrp::CMICmdArgValThreadGrp( void )
+: m_nThreadGrp( 0 )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValThreadGrp constructor.
+// Type: Method.
+// Args: vrArgName - (R) Argument's name to search by.
+// vbMandatory - (R) True = Yes must be present, false = optional argument.
+// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValThreadGrp::CMICmdArgValThreadGrp( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd )
+: CMICmdArgValBaseTemplate( vrArgName, vbMandatory, vbHandleByCmd )
+, m_nThreadGrp( 0 )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdArgValThreadGrp destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdArgValThreadGrp::~CMICmdArgValThreadGrp( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Parse the command's argument options string and try to extract the value *this
+// argument is looking for.
+// Type: Overridden.
+// Args: vwArgContext - (RW) The command's argument options string.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValThreadGrp::Validate( CMICmdArgContext & vwArgContext )
+{
+ if( vwArgContext.IsEmpty() )
+ return MIstatus::success;
+
+ if( vwArgContext.GetNumberArgsPresent() == 1 )
+ {
+ const CMIUtilString & rArg( vwArgContext.GetArgsLeftToParse() );
+ if( IsArgThreadGrp( rArg ) && ExtractNumber( rArg ) )
+ {
+ m_bFound = true;
+ m_bValid = true;
+ m_argValue = GetNumber();
+ vwArgContext.RemoveArg( rArg );
+ return MIstatus::success;
+ }
+ else
+ return MIstatus::failure;
+ }
+
+ // More than one option...
+ const CMIUtilString::VecString_t vecOptions( vwArgContext.GetArgs() );
+ CMIUtilString::VecString_t::const_iterator it = vecOptions.begin();
+ while( it != vecOptions.end() )
+ {
+ const CMIUtilString & rArg( *it );
+ if( IsArgThreadGrp( rArg ) && ExtractNumber( rArg ) )
+ {
+ m_bFound = true;
+
+ if( vwArgContext.RemoveArg( rArg ) )
+ {
+ m_bValid = true;
+ m_argValue = GetNumber();
+ return MIstatus::success;
+ }
+ else
+ return MIstatus::failure;
+ }
+
+ // Next
+ ++it;
+ }
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the string and determine if it is a valid string type argument.
+// Type: Method.
+// Args: vrTxt - (R) Some text.
+// Return: bool - True = yes valid arg, false = no.
+// Throws: None.
+//--
+bool CMICmdArgValThreadGrp::IsArgThreadGrp( const CMIUtilString & vrTxt ) const
+{
+ // Look for i1 i2 i3....
+ const MIint nPos = vrTxt.find_first_of( "i" );
+ if( nPos != 0 )
+ return false;
+
+ const CMIUtilString strNum = vrTxt.substr( 1 ).c_str();
+ if( !strNum.IsNumber() )
+ return false;
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Extract the thread group number from the thread group argument.
+// Type: Method.
+// Args: vrTxt - (R) Some text.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdArgValThreadGrp::ExtractNumber( const CMIUtilString & vrTxt )
+{
+ const CMIUtilString strNum = vrTxt.substr( 1 ).c_str();
+ MIint64 nNumber = 0;
+ bool bOk = strNum.ExtractNumber( nNumber );
+ if( bOk )
+ {
+ m_nThreadGrp = static_cast< MIuint >( nNumber );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the thread group ID found in the argument.
+// Type: Method.
+// Args: None.
+// Return: MIuint - Thread group ID.
+// Throws: None.
+//--
+MIuint CMICmdArgValThreadGrp::GetNumber( void ) const
+{
+ return m_nThreadGrp;
+}
+
diff --git a/tools/lldb-mi/MICmdArgValThreadGrp.h b/tools/lldb-mi/MICmdArgValThreadGrp.h
new file mode 100644
index 000000000000..8903597dbca1
--- /dev/null
+++ b/tools/lldb-mi/MICmdArgValThreadGrp.h
@@ -0,0 +1,66 @@
+//===-- MICmdArgValThreadGrp.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdArgValThreadGrp.h
+//
+// Overview: CMICmdArgValThreadGrp interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdArgValBase.h"
+
+// Declarations:
+class CMICmdArgContext;
+
+//++ ============================================================================
+// Details: MI common code class. Command argument class. Arguments object
+// needing specialization derived from the CMICmdArgValBase class.
+// An argument knows what type of argument it is and how it is to
+// interpret the options (context) string to find and validate a matching
+// argument and so extract a value from it. Thread group looks like
+// "i1" in the options text.
+// Based on the Interpreter pattern.
+// Gotchas: None.
+// Authors: Illya Rudkin 15/04/2014.
+// Changes: None.
+//--
+class CMICmdArgValThreadGrp : public CMICmdArgValBaseTemplate< MIuint >
+{
+// Methods:
+public:
+ /* ctor */ CMICmdArgValThreadGrp( void );
+ /* ctor */ CMICmdArgValThreadGrp( const CMIUtilString & vrArgName, const bool vbMandatory, const bool vbHandleByCmd );
+ //
+ bool IsArgThreadGrp( const CMIUtilString & vrTxt ) const;
+
+// Overridden:
+public:
+ // From CMICmdArgValBase
+ /* dtor */ virtual ~CMICmdArgValThreadGrp( void );
+ // From CMICmdArgSet::IArg
+ virtual bool Validate( CMICmdArgContext & vArgContext );
+
+// Methods:
+private:
+ bool ExtractNumber( const CMIUtilString & vrTxt );
+ MIuint GetNumber( void ) const;
+
+// Attributes:
+private:
+ MIuint m_nThreadGrp;
+};
diff --git a/tools/lldb-mi/MICmdBase.cpp b/tools/lldb-mi/MICmdBase.cpp
new file mode 100644
index 000000000000..cedcba7e042f
--- /dev/null
+++ b/tools/lldb-mi/MICmdBase.cpp
@@ -0,0 +1,263 @@
+//===-- MICmdBase.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdBase.cpp
+//
+// Overview: CMICmdBase implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdBase.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdBase constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdBase::CMICmdBase( void )
+: m_pSelfCreatorFn( nullptr )
+, m_rLLDBDebugSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() )
+, m_bHasResultRecordExtra( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdBase destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdBase::~CMICmdBase( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function.
+// Type: Overridden.
+// Args: None.
+// Return: SMICmdData & - *this command's present status/data/information.
+// Throws: None.
+//--
+const SMICmdData & CMICmdBase::GetCmdData( void ) const
+{
+ return m_cmdData;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - *this command's current error description.
+// Empty string indicates command status ok.
+// Throws: None.
+//--
+const CMIUtilString & CMICmdBase::GetErrorDescription( void ) const
+{
+ return m_strCurrentErrDescription;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The CMICmdFactory requires this function. Retrieve the command and argument
+// options description string.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Command decription.
+// Throws: None.
+//--
+const CMIUtilString & CMICmdBase::GetMiCmd( void ) const
+{
+ return m_strMiCmd;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. A command must be given working data and
+// provide data about its status or provide information to other objects.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdBase::SetCmdData( const SMICmdData & vCmdData )
+{
+ m_cmdData = vCmdData;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The command factory requires this function. The factory calls this function
+// so it can obtain *this command's creation function.
+// Type: Overridden.
+// Args: None.
+// Return: CMICmdFactory::CmdCreatorFnPtr - Function pointer.
+// Throws: None.
+//--
+CMICmdFactory::CmdCreatorFnPtr CMICmdBase::GetCmdCreatorFn( void ) const
+{
+ return m_pSelfCreatorFn;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: If a command is an event type (has callbacks registered with SBListener) it
+// needs to inform the Invoker that it has finished its work so that the
+// Invoker can tidy up and call the commands Acknowledge function (yes the
+// command itself could call the Acknowledge itself but not doing that way).
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMICmdBase::CmdFinishedTellInvoker( void ) const
+{
+ CMICmdInvoker::Instance().CmdExecuteFinished( const_cast< CMICmdBase & >( *this ) );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Returns the final version of the MI result record built up in the command's
+// Acknowledge function. The one line text of MI result.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - MI text version of the MI result record.
+// Throws: None.
+//--
+const CMIUtilString & CMICmdBase::GetMIResultRecord( void ) const
+{
+ return m_miResultRecord.GetString();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve from the command additional MI result to its 1 line response.
+// Because of using LLDB addtional 'fake'/hack output is sometimes required to
+// help the driver client operate i.e. Eclipse.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - MI text version of the MI result record.
+// Throws: None.
+//--
+const CMIUtilString & CMICmdBase::GetMIResultRecordExtra( void ) const
+{
+ return m_miResultRecordExtra;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Hss *this command got additional MI result to its 1 line response.
+// Because of using LLDB addtional 'fake'/hack output is sometimes required to
+// help the driver client operate i.e. Eclipse.
+// Type: Overridden.
+// Args: None.
+// Return: bool - True = Yes have additional MI output, false = no nothing extra.
+// Throws: None.
+//--
+bool CMICmdBase::HasMIResultRecordExtra( void ) const
+{
+ return m_bHasResultRecordExtra;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Short cut function to enter error information into the command's metadata
+// object and set the command's error status.
+// Type: Method.
+// Args: rErrMsg - (R) Error description.
+// Return: None.
+// Throws: None.
+//--
+void CMICmdBase::SetError( const CMIUtilString & rErrMsg )
+{
+ m_cmdData.bCmdValid = false;
+ m_cmdData.strErrorDescription = rErrMsg;
+ m_cmdData.bCmdExecutedSuccessfully = false;
+
+ const CMICmnMIValueResult valueResult( "msg", CMICmnMIValueConst( rErrMsg ) );
+ const CMICmnMIResultRecord miResultRecord( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, valueResult );
+ m_miResultRecord = miResultRecord;
+ m_cmdData.strMiCmdResultRecord = miResultRecord.GetString();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Ask a command to provide its unique identifier.
+// Type: Method.
+// Args: A unique identifier for this command class.
+// Return: None.
+// Throws: None.
+//--
+MIuint CMICmdBase::GetGUID( void )
+{
+ MIuint64 vptr = reinterpret_cast< MIuint64 >( this );
+ MIuint id = (vptr ) & 0xFFFFFFFF;
+ id ^= (vptr >> 32) & 0xFFFFFFFF;
+
+ return id;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdBase::ParseArgs( void )
+{
+ // Do nothing - override to implement
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Having previously given CMICmdArgSet m_setCmdArgs all the argument or option
+// definitions for the command to handle proceed to parse and validate the
+// command's options text for those arguments and extract the values for each if
+// any.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdBase::ParseValidateCmdOptions( void )
+{
+ CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption );
+ if( m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) )
+ return MIstatus::success;
+
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) );
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: If the MI Driver is not operating via a client i.e. Eclipse but say operating
+// on a executable passed in as a argument to the drive then what should the driver
+// do on a command failing? Either continue operating or exit the application.
+// Override this function where a command failure cannot allow the driver to
+// continue operating.
+// Type: Overrideable.
+// Args: None.
+// Return: bool - True = Fatal if command fails, false = can continue if command fails.
+// Throws: None.
+//--
+bool CMICmdBase::GetExitAppOnCommandFailure( void ) const
+{
+ return false;
+}
diff --git a/tools/lldb-mi/MICmdBase.h b/tools/lldb-mi/MICmdBase.h
new file mode 100644
index 000000000000..b05e97d2082d
--- /dev/null
+++ b/tools/lldb-mi/MICmdBase.h
@@ -0,0 +1,156 @@
+//===-- MICmdBase.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdBase.h
+//
+// Overview: CMICmdBase interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MIUtilString.h"
+#include "MICmnBase.h"
+#include "MICmnResources.h"
+#include "MICmdInvoker.h"
+#include "MICmdFactory.h"
+#include "MICmdData.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmdArgSet.h"
+
+// Declarations:
+class CMICmnLLDBDebugSessionInfo;
+
+//++ ============================================================================
+// Details: MI command base class. MI commands derive from this base class.
+// The Command Factory creates command objects and passes them to the
+// Command Invoker. The Invoker takes ownersip of any commands created
+// which means it is the only object to delete them when a command is
+// finished working. Commands do not delete themselves.
+// There are two types of command implicitly defined by the state of
+// the m_bWaitForEventFromSBDebugger flag. There is the event type
+// command which registers (command fn) callbacks with the SBListener
+// does some work then wakes up again when called back, does more work
+// perhaps, ends, then the Invoker calls the command's Acknowledge
+// function. The other type of command is one that just does some work,
+// ends, then the Invoker calls the command's Acknowledge function. No
+// events set up.
+// A command's Execute(), Acknowledge() and event callback functions are
+// carried out in the main thread.
+// A command may use the argument derived object classes (CMICmdArgValBase)
+// to factor handling and parsing of different types of arguments
+// presented to a command. A command will produce an error should it
+// be presented with arguments or options it does not understand.
+// Gotchas: None.
+// Authors: Illya Rudkin 18/02/2014.
+// Changes: None.
+//--
+class CMICmdBase
+: public CMICmnBase
+, public CMICmdInvoker::ICmd
+, public CMICmdFactory::ICmd
+{
+// Methods:
+public:
+ /* ctor */ CMICmdBase( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual const SMICmdData & GetCmdData( void ) const;
+ virtual const CMIUtilString & GetErrorDescription( void ) const;
+ virtual bool SetCmdData( const SMICmdData & vCmdData );
+ virtual void CmdFinishedTellInvoker( void ) const;
+ virtual const CMIUtilString & GetMIResultRecord( void ) const;
+ virtual const CMIUtilString & GetMIResultRecordExtra( void ) const;
+ virtual bool HasMIResultRecordExtra( void ) const;
+ virtual bool ParseArgs( void );
+ // From CMICmdFactory::ICmd
+ virtual const CMIUtilString & GetMiCmd( void ) const;
+ virtual CMICmdFactory::CmdCreatorFnPtr GetCmdCreatorFn( void ) const;
+
+ virtual MIuint GetGUID( void );
+
+// Overrideable:
+public:
+ /* dtor */ virtual ~CMICmdBase( void );
+ virtual bool GetExitAppOnCommandFailure( void ) const;
+
+// Methods:
+protected:
+ void SetError( const CMIUtilString & rErrMsg );
+ template< class T >
+ T * GetOption( const CMIUtilString & vStrOptionName );
+ bool ParseValidateCmdOptions( void );
+
+// Attributes:
+protected:
+ CMICmdFactory::CmdCreatorFnPtr m_pSelfCreatorFn;
+ CMIUtilString m_strCurrentErrDescription; // Reason for Execute or Acknowledge function failure
+ SMICmdData m_cmdData; // Holds information/status of *this command. Used by other MI code to report or determine state of a command.
+ bool m_bWaitForEventFromSBDebugger; // True = yes event type command wait, false = command calls Acknowledge() straight after Execute() no waiting
+ CMIUtilString m_strMiCmd; // The MI text identifying *this command i.e. 'break-insert'
+ CMICmnMIResultRecord m_miResultRecord; // This is completed in the Acknowledge() function and returned to the Command Invoker to proceed stdout output. Each command forms 1 response to its input.
+ CMIUtilString m_miResultRecordExtra; // This is completed in the Acknowledge() function and returned to the Command Invoker to proceed stdout output. Hack command produce more response text to help the client because of using LLDB
+ CMICmnLLDBDebugSessionInfo & m_rLLDBDebugSessionInfo; // Access to command sharing information or data across any and all command based derived classes.
+ bool m_bHasResultRecordExtra; // True = Yes command produced additional MI output to its 1 line response, false = no extra MI output formed.
+ CMICmdArgSet m_setCmdArgs; // The list of arguments *this command needs to parse from the options string to carry out work.
+};
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the command argument or option object pointer so that it can be
+// examined. If the option found and valid get the value (number, string or list
+// - see CMICmdArgValBase class) from it to use with the command's decision
+// making. If the argument is not found the command's error description is set
+// describing the error condition.
+// Type: Template method.
+// Args: vStrOptionName - (R) The text name of the argument or option to search for in
+// the list of the command's possible arguments or options.
+// Return: T * - CMICmdArgValBase derived object.
+// - NULL = function has failed, unable to retrieve the option/arg object.
+// Throws: None.
+//--
+template< class T >
+T * CMICmdBase::GetOption( const CMIUtilString & vStrOptionName )
+{
+ CMICmdArgValBase * pPtrBase = nullptr;
+ if( !m_setCmdArgs.GetArg( vStrOptionName, pPtrBase ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), vStrOptionName.c_str() ) );
+ return nullptr;
+ }
+
+ return static_cast< T * >( pPtrBase );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the command argument or option object pointer using template function
+// CMICmdBase::GetOption(). Should the argument (by name) not be found the
+// command will exit with a failure (set in GetOption()).
+// Type: Preprocessor macro.
+// Args: a - (R) The actual variable's name.
+// b - (R) The type of variable (appended to CMICmdArgVal i.e. CMICmdArgValString).
+// c - (R) The text name of the argument or option to search for in the list of
+// the command's possible arguments or options.
+// Return: T * - CMICmdArgValBase derived object.
+// - NULL = function has failed, unable to retrieve the option/arg object.
+// Throws: None.
+//--
+#define CMICMDBASE_GETOPTION( a, b, c ) \
+ CMICmdArgVal##b * a = CMICmdBase::GetOption< CMICmdArgVal##b >( c );\
+ if( a == nullptr ) \
+ return MIstatus::failure;
+// This comment is to stop compile warning for #define
diff --git a/tools/lldb-mi/MICmdCmd.cpp b/tools/lldb-mi/MICmdCmd.cpp
new file mode 100644
index 000000000000..3c6d52b24769
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmd.cpp
@@ -0,0 +1,174 @@
+//===-- MICmdCmd.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmd.cpp
+//
+// Overview: CMICmdCmdEnablePrettyPrinting implementation.
+// CMICmdCmdSource implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdCmd.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdEnablePrettyPrinting constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdEnablePrettyPrinting::CMICmdCmdEnablePrettyPrinting( void )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "enable-pretty-printing";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdEnablePrettyPrinting::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdEnablePrettyPrinting destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdEnablePrettyPrinting::~CMICmdCmdEnablePrettyPrinting( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdEnablePrettyPrinting::Execute( void )
+{
+ // Do nothing
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdEnablePrettyPrinting::Acknowledge( void )
+{
+ const CMICmnMIValueConst miValueConst( "0" );
+ const CMICmnMIValueResult miValueResult( "supported", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdEnablePrettyPrinting::CreateSelf( void )
+{
+ return new CMICmdCmdEnablePrettyPrinting();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdSource constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdSource::CMICmdCmdSource( void )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "source";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdSource::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdSource destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdSource::~CMICmdCmdSource( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdSource::Execute( void )
+{
+ // Do nothing
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdSource::Acknowledge( void )
+{
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdSource::CreateSelf( void )
+{
+ return new CMICmdCmdSource();
+}
diff --git a/tools/lldb-mi/MICmdCmd.h b/tools/lldb-mi/MICmdCmd.h
new file mode 100644
index 000000000000..c2ab6896e689
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmd.h
@@ -0,0 +1,104 @@
+//===-- MICmdCmd.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmd.h
+//
+// Overview: CMICmdCmdEnablePrettyPrinting interface.
+// CMICmdCmdSource interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+/*
+MI commands implemented are:
+ See MICmdCommands.cpp
+*/
+
+#pragma once
+
+// Third party headers:
+#include <vector>
+#include <lldb/API/SBBreakpoint.h>
+#include <lldb/API/SBCommandReturnObject.h>
+
+// In-house headers:
+#include "MICmdBase.h"
+#include "MICmnMIValueTuple.h"
+#include "MICmnMIValueList.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "enable-pretty-printing".
+// Enables Python base pretty printing.
+// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html
+// Gotchas: None.
+// Authors: Illya Rudkin 03/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdEnablePrettyPrinting : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdEnablePrettyPrinting( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdEnablePrettyPrinting( void );
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "source".
+// Gotchas: None.
+// Authors: Illya Rudkin 05/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdSource
+ : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdSource( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdSource( void );
+};
diff --git a/tools/lldb-mi/MICmdCmdBreak.cpp b/tools/lldb-mi/MICmdCmdBreak.cpp
new file mode 100644
index 000000000000..f0e9acfe9082
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdBreak.cpp
@@ -0,0 +1,1026 @@
+//===-- MICmdCmdBreak.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdBreak.cpp
+//
+// Overview: CMICmdCmdBreakInsert implementation.
+// CMICmdCmdBreakDelete implementation.
+// CMICmdCmdBreakDisable implementation.
+// CMICmdCmdBreakEnable implementation.
+// CMICmdCmdBreakAfter implementation.
+// CMICmdCmdBreakCondition implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third Party Headers:
+#include <lldb/API/SBBreakpointLocation.h>
+
+// In-house headers:
+#include "MICmdCmdBreak.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnMIOutOfBandRecord.h"
+#include "MICmnLLDBDebugger.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MICmdArgValFile.h"
+#include "MICmdArgValNumber.h"
+#include "MICmdArgValString.h"
+#include "MICmdArgValThreadGrp.h"
+#include "MICmdArgValOptionLong.h"
+#include "MICmdArgValOptionShort.h"
+#include "MICmdArgValListOfN.h"
+#include "MICmnStreamStdout.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdBreakInsert constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdBreakInsert::CMICmdCmdBreakInsert( void )
+: m_bBrkPtIsTemp( false )
+, m_bBrkPtIsPending( false )
+, m_nBrkPtIgnoreCount( 0 )
+, m_bBrkPtEnabled( false )
+, m_bBrkPtCondition( false )
+, m_bBrkPtThreadId( false )
+, m_nBrkPtThreadId( 0 )
+, m_constStrArgNamedTempBrkPt( "t" )
+, m_constStrArgNamedHWBrkPt( "h" )
+, m_constStrArgNamedPendinfBrkPt( "f" )
+, m_constStrArgNamedDisableBrkPt( "d" )
+, m_constStrArgNamedTracePt( "a" )
+, m_constStrArgNamedConditionalBrkPt( "c" )
+, m_constStrArgNamedInoreCnt( "i" )
+, m_constStrArgNamedRestrictBrkPtToThreadId( "p" )
+, m_constStrArgNamedLocation( "location" )
+, m_constStrArgNamedThreadGroup( "thread-group" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "break-insert";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdBreakInsert::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdBreakInsert destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakInsert::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedTempBrkPt, false, true )) );
+ //Not implemented bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedHWBrkPt, false, false ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedPendinfBrkPt, false, true, CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedDisableBrkPt, false, false ) ) );
+ //Not implemented bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedTracePt, false, false ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedConditionalBrkPt, false, true, CMICmdArgValListBase::eArgValType_StringQuoted, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedInoreCnt, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedRestrictBrkPtToThreadId, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedLocation, false, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGroup, false, true, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakInsert::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgTempBrkPt, OptionShort, m_constStrArgNamedTempBrkPt );
+ CMICMDBASE_GETOPTION( pArgThreadGroup, OptionLong, m_constStrArgNamedThreadGroup );
+ CMICMDBASE_GETOPTION( pArgLocation, String, m_constStrArgNamedLocation );
+ CMICMDBASE_GETOPTION( pArgIgnoreCnt, OptionShort, m_constStrArgNamedInoreCnt );
+ CMICMDBASE_GETOPTION( pArgPendingBrkPt, OptionShort, m_constStrArgNamedPendinfBrkPt );
+ CMICMDBASE_GETOPTION( pArgDisableBrkPt, OptionShort, m_constStrArgNamedDisableBrkPt );
+ CMICMDBASE_GETOPTION( pArgConditionalBrkPt, OptionShort, m_constStrArgNamedConditionalBrkPt );
+ CMICMDBASE_GETOPTION( pArgRestrictBrkPtToThreadId, OptionShort, m_constStrArgNamedRestrictBrkPtToThreadId );
+
+ m_bBrkPtEnabled = !pArgDisableBrkPt->GetFound();
+ m_bBrkPtIsTemp = pArgTempBrkPt->GetFound();
+ m_bHaveArgOptionThreadGrp = pArgThreadGroup->GetFound();
+ if( m_bHaveArgOptionThreadGrp )
+ {
+ MIuint nThreadGrp = 0;
+ pArgThreadGroup->GetExpectedOption< CMICmdArgValThreadGrp, MIuint >( nThreadGrp );
+ m_strArgOptionThreadGrp = CMIUtilString::Format( "i%d", nThreadGrp );
+ }
+ m_bBrkPtIsPending = pArgPendingBrkPt->GetFound();
+ if( pArgLocation->GetFound() )
+ m_brkName = pArgLocation->GetValue();
+ else if( m_bBrkPtIsPending )
+ {
+ pArgPendingBrkPt->GetExpectedOption< CMICmdArgValString, CMIUtilString >( m_brkName );
+ }
+ if( pArgIgnoreCnt->GetFound() )
+ {
+ pArgIgnoreCnt->GetExpectedOption< CMICmdArgValNumber, MIuint >( m_nBrkPtIgnoreCount );
+ }
+ m_bBrkPtCondition = pArgConditionalBrkPt->GetFound();
+ if( m_bBrkPtCondition )
+ {
+ pArgConditionalBrkPt->GetExpectedOption< CMICmdArgValString, CMIUtilString >( m_brkPtCondition );
+ }
+ m_bBrkPtThreadId = pArgRestrictBrkPtToThreadId->GetFound();
+ if( m_bBrkPtCondition )
+ {
+ pArgRestrictBrkPtToThreadId->GetExpectedOption< CMICmdArgValNumber, MIuint >( m_nBrkPtThreadId );
+ }
+
+ // Determine if break on a file line or at a function
+ BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet;
+ const CMIUtilString cColon = ":";
+ CMIUtilString fileName;
+ MIuint nFileLine = 0;
+ CMIUtilString strFileFn;
+ const MIint nPosColon = m_brkName.find( cColon );
+ if( nPosColon != (MIint) std::string::npos )
+ {
+ CMIUtilString::VecString_t vecFileAndLocation;
+ const MIuint nSplits = m_brkName.Split( cColon, vecFileAndLocation ); MIunused( nSplits );
+ if( vecFileAndLocation.size() != 2 )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_LOCATION_FORMAT ), m_cmdData.strMiCmd.c_str(), m_brkName.c_str() ) );
+ return MIstatus::failure;
+ }
+ fileName = vecFileAndLocation.at( 0 );
+ const CMIUtilString & rStrLineOrFn( vecFileAndLocation.at( 1 ) );
+ if( rStrLineOrFn.empty() )
+ eBrkPtType = eBreakPoint_ByName;
+ else
+ {
+ MIint64 nValue = 0;
+ if( rStrLineOrFn.ExtractNumber( nValue ) )
+ {
+ nFileLine = static_cast< MIuint >( nValue );
+ eBrkPtType = eBreakPoint_ByFileLine;
+ }
+ else
+ {
+ strFileFn = rStrLineOrFn;
+ eBrkPtType = eBreakPoint_ByFileFn;
+ }
+ }
+ }
+
+ // Determine if break defined as an address
+ lldb::addr_t nAddress = 0;
+ if( eBrkPtType == eBreakPoint_NotDefineYet )
+ {
+ MIint64 nValue = 0;
+ if( m_brkName.ExtractNumber( nValue ) )
+ {
+ nAddress = static_cast< lldb::addr_t >( nValue );
+ eBrkPtType = eBreakPoint_ByAddress;
+ }
+ }
+
+ // Break defined as an function
+ if( eBrkPtType == eBreakPoint_NotDefineYet )
+ {
+ eBrkPtType = eBreakPoint_ByName;
+ }
+
+ // Ask LLDB to create a breakpoint
+ bool bOk = MIstatus::success;
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBTarget & rTarget = rSessionInfo.m_lldbTarget;
+ switch( eBrkPtType )
+ {
+ case eBreakPoint_ByAddress:
+ m_brkPt = rTarget.BreakpointCreateByAddress( nAddress );
+ break;
+ case eBreakPoint_ByFileFn:
+ m_brkPt = rTarget.BreakpointCreateByName( strFileFn.c_str(), fileName.c_str() );
+ break;
+ case eBreakPoint_ByFileLine:
+ m_brkPt = rTarget.BreakpointCreateByLocation( fileName.c_str(), nFileLine );
+ break;
+ case eBreakPoint_ByName:
+ m_brkPt = rTarget.BreakpointCreateByName( m_brkName.c_str(), rTarget.GetExecutable().GetFilename() );
+ break;
+ case eBreakPoint_count:
+ case eBreakPoint_NotDefineYet:
+ case eBreakPoint_Invalid:
+ bOk = MIstatus::failure;
+ break;
+ }
+
+ if( bOk )
+ {
+ m_brkPt.SetEnabled( m_bBrkPtEnabled );
+ m_brkPt.SetIgnoreCount( m_nBrkPtIgnoreCount );
+ if( m_bBrkPtCondition )
+ m_brkPt.SetCondition( m_brkPtCondition.c_str() );
+ if( m_bBrkPtThreadId )
+ m_brkPt.SetThreadID( m_nBrkPtThreadId );
+ if( !m_brkPt.IsValid() )
+ m_bBrkPtIsPending = pArgPendingBrkPt->GetFound();
+ }
+
+ // CODETAG_LLDB_BREAKPOINT_CREATION
+ // This is in the main thread
+ // Record break point information to be by LLDB event handler function
+ CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
+ sBrkPtInfo.m_id = m_brkPt.GetID();
+ sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp;
+ sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled;
+ sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp;
+ sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp;
+ sBrkPtInfo.m_strOrigLoc = m_brkName;
+ sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount;
+ sBrkPtInfo.m_bPending = m_bBrkPtIsPending;
+ sBrkPtInfo.m_bCondition = m_bBrkPtCondition;
+ sBrkPtInfo.m_strCondition = m_brkPtCondition;
+ sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId;
+ sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId;
+ bOk = bOk && rSessionInfo.RecordBrkPtInfo( m_brkPt.GetID(), sBrkPtInfo );
+
+ if( !bOk )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), m_brkName.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ // CODETAG_LLDB_BRKPT_ID_MAX
+ if( m_brkPt.GetID() > (lldb::break_id_t) rSessionInfo.m_nBrkPointCntMax )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_CNT_EXCEEDED ), m_cmdData.strMiCmd.c_str(), rSessionInfo.m_nBrkPointCntMax, m_brkName.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakInsert::Acknowledge( void )
+{
+ // Get breakpoint information
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
+ if( !rSessionInfo.GetBrkPtInfo( m_brkPt, sBrkPtInfo ) )
+ {
+ return MIstatus::failure;
+ }
+
+ // CODETAG_LLDB_BREAKPOINT_CREATION
+ // Add more breakpoint information or overwrite existing information
+ sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp;
+ sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled;
+ sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp;
+ sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp;
+ sBrkPtInfo.m_nTimes = m_brkPt.GetNumLocations();
+ sBrkPtInfo.m_strOrigLoc = m_brkName;
+ sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount;
+ sBrkPtInfo.m_bPending = m_bBrkPtIsPending;
+ sBrkPtInfo.m_bCondition = m_bBrkPtCondition;
+ sBrkPtInfo.m_strCondition = m_brkPtCondition;
+ sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId;
+ sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId;
+
+ // MI print "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",thread-groups=[\"%s\"],times=\"%d\",original-location=\"%s\"}"
+ CMICmnMIValueTuple miValueTuple;
+ if( !rSessionInfo.MIResponseFormBrkPtInfo( sBrkPtInfo, miValueTuple ) )
+ {
+ return MIstatus::failure;
+ }
+
+ const CMICmnMIValueResult miValueResultD( "bkpt", miValueTuple );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResultD );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdBreakInsert::CreateSelf( void )
+{
+ return new CMICmdCmdBreakInsert();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdBreakDelete constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdBreakDelete::CMICmdCmdBreakDelete( void )
+: m_constStrArgNamedBrkPt( "breakpoint" )
+, m_constStrArgNamedThreadGrp( "thread-group" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "break-delete";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdBreakDelete::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdBreakDelete destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakDelete::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakDelete::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt );
+
+ // ATM we only handle one break point ID
+ MIuint64 nBrk = UINT64_MAX;
+ if( !pArgBrkPt->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nBrk ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ const bool bBrkPt = rSessionInfo.m_lldbTarget.BreakpointDelete( static_cast< lldb::break_id_t >( nBrk ) );
+ if( !bBrkPt )
+ {
+ const CMIUtilString strBrkNum( CMIUtilString::Format( "%d", nBrk ) );
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), strBrkNum.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakDelete::Acknowledge( void )
+{
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdBreakDelete::CreateSelf( void )
+{
+ return new CMICmdCmdBreakDelete();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdBreakDisable constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdBreakDisable::CMICmdCmdBreakDisable( void )
+: m_constStrArgNamedThreadGrp( "thread-group" )
+, m_constStrArgNamedBrkPt( "breakpoint" )
+, m_bBrkPtDisabledOk( false )
+, m_nBrkPtId( 0 )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "break-disable";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdBreakDisable::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdBreakDisable destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakDisable::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakDisable::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt );
+
+ // ATM we only handle one break point ID
+ MIuint64 nBrk = UINT64_MAX;
+ if( !pArgBrkPt->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nBrk ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID( static_cast< lldb::break_id_t >( nBrk ) );
+ if( brkPt.IsValid() )
+ {
+ m_bBrkPtDisabledOk = true;
+ brkPt.SetEnabled( false );
+ m_nBrkPtId = nBrk;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakDisable::Acknowledge( void )
+{
+ if( m_bBrkPtDisabledOk )
+ {
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", m_nBrkPtId ) );
+ const CMICmnMIValueResult miValueResult( "number", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueConst miValueConst2( "n" );
+ const CMICmnMIValueResult miValueResult2( "enabled", miValueConst2 );
+ bool bOk = miValueTuple.Add( miValueResult2 );
+ const CMICmnMIValueResult miValueResult3( "bkpt", miValueTuple );
+ const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3 );
+ bOk = bOk && CMICmnStreamStdout::TextToStdout( miOutOfBandRecord.GetString() );
+
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+ return bOk;
+ }
+
+ const CMIUtilString strBrkPtId( CMIUtilString::Format( "%d", m_nBrkPtId ) );
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), strBrkPtId.c_str() ) );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdBreakDisable::CreateSelf( void )
+{
+ return new CMICmdCmdBreakDisable();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdBreakEnable constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdBreakEnable::CMICmdCmdBreakEnable( void )
+: m_constStrArgNamedThreadGrp( "thread-group" )
+, m_constStrArgNamedBrkPt( "breakpoint" )
+, m_bBrkPtEnabledOk( false )
+, m_nBrkPtId( 0 )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "break-enable";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdBreakEnable::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdBreakEnable destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakEnable::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakEnable::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt );
+
+ // ATM we only handle one break point ID
+ MIuint64 nBrk = UINT64_MAX;
+ if( !pArgBrkPt->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nBrk ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID( static_cast< lldb::break_id_t >( nBrk ) );
+ if( brkPt.IsValid() )
+ {
+ m_bBrkPtEnabledOk = true;
+ brkPt.SetEnabled( false );
+ m_nBrkPtId = nBrk;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakEnable::Acknowledge( void )
+{
+ if( m_bBrkPtEnabledOk )
+ {
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", m_nBrkPtId ) );
+ const CMICmnMIValueResult miValueResult( "number", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueConst miValueConst2( "y" );
+ const CMICmnMIValueResult miValueResult2( "enabled", miValueConst2 );
+ bool bOk = miValueTuple.Add( miValueResult2 );
+ const CMICmnMIValueResult miValueResult3( "bkpt", miValueTuple );
+ const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3 );
+ bOk = bOk && CMICmnStreamStdout::TextToStdout( miOutOfBandRecord.GetString() );
+
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+ return bOk;
+ }
+
+ const CMIUtilString strBrkPtId( CMIUtilString::Format( "%d", m_nBrkPtId ) );
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), strBrkPtId.c_str() ) );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdBreakEnable::CreateSelf( void )
+{
+ return new CMICmdCmdBreakEnable();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdBreakAfter constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdBreakAfter::CMICmdCmdBreakAfter( void )
+: m_constStrArgNamedThreadGrp( "thread-group" )
+, m_constStrArgNamedNumber( "number" )
+, m_constStrArgNamedCount( "count" )
+, m_nBrkPtId( 0 )
+, m_nBrkPtCount( 0 )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "break-after";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdBreakAfter::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdBreakAfter destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakAfter::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNamedNumber, true, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNamedCount, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakAfter::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgNumber, Number, m_constStrArgNamedNumber );
+ CMICMDBASE_GETOPTION( pArgCount, Number, m_constStrArgNamedCount );
+
+ m_nBrkPtId = pArgNumber->GetValue();
+ m_nBrkPtCount = pArgCount->GetValue();
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID( static_cast< lldb::break_id_t >( m_nBrkPtId ) );
+ if( brkPt.IsValid() )
+ {
+ brkPt.SetIgnoreCount( m_nBrkPtCount );
+
+ CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
+ if( !rSessionInfo.RecordBrkPtInfoGet( m_nBrkPtId, sBrkPtInfo ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_nBrkPtId ) );
+ return MIstatus::failure;
+ }
+ sBrkPtInfo.m_nIgnore = m_nBrkPtCount;
+ rSessionInfo.RecordBrkPtInfo( m_nBrkPtId, sBrkPtInfo );
+ }
+ else
+ {
+ const CMIUtilString strBrkPtId( CMIUtilString::Format( "%d", m_nBrkPtId ) );
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakAfter::Acknowledge( void )
+{
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdBreakAfter::CreateSelf( void )
+{
+ return new CMICmdCmdBreakAfter();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdBreakCondition constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdBreakCondition::CMICmdCmdBreakCondition( void )
+: m_constStrArgNamedThreadGrp( "thread-group" )
+, m_constStrArgNamedNumber( "number" )
+, m_constStrArgNamedExpr( "expr" )
+, m_constStrArgNamedExprNoQuotes( "expression not surround by quotes" ) // Not specified in MI spec, we need to handle expressions not surrounded by quotes
+, m_nBrkPtId( 0 )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "break-condition";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdBreakCondition::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdBreakCondition destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakCondition::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNamedNumber, true, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedExpr, true, true, true, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgNamedExprNoQuotes, true, false, CMICmdArgValListBase::eArgValType_StringQuotedNumber ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakCondition::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgNumber, Number, m_constStrArgNamedNumber );
+ CMICMDBASE_GETOPTION( pArgExpr, String, m_constStrArgNamedExpr );
+
+ m_nBrkPtId = pArgNumber->GetValue();
+ m_strBrkPtExpr = pArgExpr->GetValue();
+ m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes();
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID( static_cast< lldb::break_id_t >( m_nBrkPtId ) );
+ if( brkPt.IsValid() )
+ {
+ brkPt.SetCondition( m_strBrkPtExpr.c_str() );
+
+ CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
+ if( !rSessionInfo.RecordBrkPtInfoGet( m_nBrkPtId, sBrkPtInfo ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_nBrkPtId ) );
+ return MIstatus::failure;
+ }
+ sBrkPtInfo.m_strCondition = m_strBrkPtExpr;
+ rSessionInfo.RecordBrkPtInfo( m_nBrkPtId, sBrkPtInfo );
+ }
+ else
+ {
+ const CMIUtilString strBrkPtId( CMIUtilString::Format( "%d", m_nBrkPtId ) );
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdBreakCondition::Acknowledge( void )
+{
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdBreakCondition::CreateSelf( void )
+{
+ return new CMICmdCmdBreakCondition();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: A breakpoint expression can be passed to *this command as:
+// a single string i.e. '2' -> ok.
+// a quoted string i.e. "a > 100" -> ok
+// a non quoted string i.e. 'a > 100' -> not ok
+// CMICmdArgValString only extracts the first space seperated string, the "a".
+// This function using the optional argument type CMICmdArgValListOfN collects
+// the rest of the expression so that is may be added to the 'a' part to form a
+// complete expression string i.e. "a > 100".
+// If the expression value was guaranteed to be surrounded by quotes them this
+// function would not be necessary.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Rest of the breakpoint expression.
+// Throws: None.
+//--
+CMIUtilString CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes( void )
+{
+ CMIUtilString strExpression;
+
+ CMICmdArgValListOfN * pArgExprNoQuotes = CMICmdBase::GetOption< CMICmdArgValListOfN >( m_constStrArgNamedExprNoQuotes );
+ if( pArgExprNoQuotes != nullptr )
+ {
+ CMIUtilString strExpression;
+ const CMICmdArgValListBase::VecArgObjPtr_t & rVecExprParts( pArgExprNoQuotes->GetExpectedOptions() );
+ if( !rVecExprParts.empty() )
+ {
+ CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecExprParts.begin();
+ while( it != rVecExprParts.end() )
+ {
+ const CMICmdArgValString * pPartExpr = static_cast< CMICmdArgValString * >( *it );
+ const CMIUtilString & rPartExpr = pPartExpr->GetValue();
+ strExpression += " ";
+ strExpression += rPartExpr;
+
+ // Next
+ ++it;
+ }
+ strExpression = strExpression.Trim();
+ }
+ }
+
+ return strExpression;
+}
diff --git a/tools/lldb-mi/MICmdCmdBreak.h b/tools/lldb-mi/MICmdCmdBreak.h
new file mode 100644
index 000000000000..e5283d609905
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdBreak.h
@@ -0,0 +1,292 @@
+//===-- MICmdCmdBreak.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdBreak.h
+//
+// Overview: CMICmdCmdBreakInsert interface.
+// CMICmdCmdBreakDelete interface.
+// CMICmdCmdBreakDisable interface.
+// CMICmdCmdBreakEnable interface.
+// CMICmdCmdBreakAfter interface.
+// CMICmdCmdBreakCondition interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <lldb/API/SBBreakpoint.h>
+
+// In-house headers:
+#include "MICmdBase.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "break-insert".
+// This command does not follow the MI documentation exactly.
+// Gotchas: None.
+// Authors: Illya Rudkin 11/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdBreakInsert : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdBreakInsert( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdBreakInsert( void );
+
+// Enumerations:
+private:
+ //++ ===================================================================
+ // Details: The type of break point give in the MI command text.
+ //--
+ enum BreakPoint_e
+ {
+ eBreakPoint_Invalid = 0,
+ eBreakPoint_ByFileLine,
+ eBreakPoint_ByFileFn,
+ eBreakPoint_ByName,
+ eBreakPoint_ByAddress,
+ eBreakPoint_count,
+ eBreakPoint_NotDefineYet
+ };
+
+// Attributes:
+private:
+ bool m_bBrkPtIsTemp;
+ bool m_bHaveArgOptionThreadGrp;
+ CMIUtilString m_brkName;
+ CMIUtilString m_strArgOptionThreadGrp;
+ lldb::SBBreakpoint m_brkPt;
+ bool m_bBrkPtIsPending;
+ MIuint m_nBrkPtIgnoreCount;
+ bool m_bBrkPtEnabled;
+ bool m_bBrkPtCondition;
+ CMIUtilString m_brkPtCondition;
+ bool m_bBrkPtThreadId;
+ MIuint m_nBrkPtThreadId;
+ const CMIUtilString m_constStrArgNamedTempBrkPt;
+ const CMIUtilString m_constStrArgNamedHWBrkPt; // Not handled by *this command
+ const CMIUtilString m_constStrArgNamedPendinfBrkPt;
+ const CMIUtilString m_constStrArgNamedDisableBrkPt;
+ const CMIUtilString m_constStrArgNamedTracePt; // Not handled by *this command
+ const CMIUtilString m_constStrArgNamedConditionalBrkPt;
+ const CMIUtilString m_constStrArgNamedInoreCnt;
+ const CMIUtilString m_constStrArgNamedRestrictBrkPtToThreadId;
+ const CMIUtilString m_constStrArgNamedLocation;
+ const CMIUtilString m_constStrArgNamedThreadGroup; // Not specified in MI spec but Eclipse gives this option sometimes
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "break-delete".
+// Gotchas: None.
+// Authors: Illya Rudkin 11/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdBreakDelete : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdBreakDelete( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdBreakDelete( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgNamedBrkPt;
+ const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "break-disable".
+// Gotchas: None.
+// Authors: Illya Rudkin 19/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdBreakDisable : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdBreakDisable( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdBreakDisable( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgNamedBrkPt;
+ bool m_bBrkPtDisabledOk;
+ MIuint m_nBrkPtId;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "break-enable".
+// Gotchas: None.
+// Authors: Illya Rudkin 19/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdBreakEnable : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdBreakEnable( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdBreakEnable( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgNamedBrkPt;
+ bool m_bBrkPtEnabledOk;
+ MIuint m_nBrkPtId;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "break-after".
+// Gotchas: None.
+// Authors: Illya Rudkin 29/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdBreakAfter : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdBreakAfter( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdBreakAfter( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgNamedNumber;
+ const CMIUtilString m_constStrArgNamedCount;
+ MIuint m_nBrkPtId;
+ MIuint m_nBrkPtCount;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "break-condition".
+// Gotchas: None.
+// Authors: Illya Rudkin 29/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdBreakCondition : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdBreakCondition( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdBreakCondition( void );
+
+// Methods:
+private:
+ CMIUtilString GetRestOfExpressionNotSurroundedInQuotes( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgNamedNumber;
+ const CMIUtilString m_constStrArgNamedExpr;
+ const CMIUtilString m_constStrArgNamedExprNoQuotes; // Not specified in MI spec, we need to handle expressions not surrounded by quotes
+ MIuint m_nBrkPtId;
+ CMIUtilString m_strBrkPtExpr;
+};
diff --git a/tools/lldb-mi/MICmdCmdData.cpp b/tools/lldb-mi/MICmdCmdData.cpp
new file mode 100644
index 000000000000..69012ef042c4
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdData.cpp
@@ -0,0 +1,1365 @@
+//===-- MICmdCmdData.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdData.cpp
+//
+// Overview: CMICmdCmdDataEvaluateExpression implementation.
+// CMICmdCmdDataDisassemble implementation.
+// CMICmdCmdDataReadMemoryBytes implementation.
+// CMICmdCmdDataReadMemory implementation.
+// CMICmdCmdDataListRegisterNames implementation.
+// CMICmdCmdDataListRegisterValues implementation.
+// CMICmdCmdDataListRegisterChanged implementation.
+// CMICmdCmdDataWriteMemoryBytes implementation.
+// CMICmdCmdDataWriteMemory implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third Party Headers:
+#include <lldb/API/SBThread.h>
+#include <lldb/API/SBInstruction.h>
+#include <lldb/API/SBInstructionList.h>
+#include <lldb/API/SBStream.h>
+
+// In-house headers:
+#include "MICmdCmdData.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnLLDBDebugger.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MICmnLLDBProxySBValue.h"
+#include "MICmdArgValNumber.h"
+#include "MICmdArgValString.h"
+#include "MICmdArgValThreadGrp.h"
+#include "MICmdArgValOptionLong.h"
+#include "MICmdArgValOptionShort.h"
+#include "MICmdArgValListOfN.h"
+#include "MICmdArgValConsume.h"
+#include "MICmnLLDBDebugSessionInfoVarObj.h"
+#include "MICmnLLDBUtilSBValue.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataEvaluateExpression constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression( void )
+: m_bExpressionValid( true )
+, m_bEvaluatedExpression( true )
+, m_strValue( "??" )
+, m_bCompositeVarType( false )
+, m_bFoundInvalidChar( false )
+, m_cExpressionInvalidChar( 0x00 )
+, m_constStrArgThread( "thread" )
+, m_constStrArgFrame( "frame" )
+, m_constStrArgExpr( "expr" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "data-evaluate-expression";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdDataEvaluateExpression::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataEvaluateExpression destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataEvaluateExpression::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgFrame, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgExpr, true, true, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataEvaluateExpression::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgExpr, String, m_constStrArgExpr );
+
+ const CMIUtilString & rExpression( pArgExpr->GetValue() );
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+ lldb::SBThread thread = rProcess.GetSelectedThread();
+ m_bExpressionValid = (thread.GetNumFrames() > 0);
+ if( !m_bExpressionValid )
+ return MIstatus::success;
+
+ lldb::SBFrame frame = thread.GetSelectedFrame();
+ lldb::SBValue value = frame.EvaluateExpression( rExpression.c_str() );
+ if( !value.IsValid() )
+ value = frame.FindVariable( rExpression.c_str() );
+ if( !value.IsValid() )
+ {
+ m_bEvaluatedExpression = false;
+ return MIstatus::success;
+ }
+ const CMICmnLLDBUtilSBValue utilValue( value );
+ if( !utilValue.HasName() )
+ {
+ if( HaveInvalidCharacterInExpression( rExpression, m_cExpressionInvalidChar ) )
+ {
+ m_bFoundInvalidChar = true;
+ return MIstatus::success;
+ }
+
+ m_strValue = rExpression;
+ return MIstatus::success;
+ }
+ if( rExpression.IsQuoted() )
+ {
+ m_strValue = rExpression.Trim( '\"' );
+ return MIstatus::success;
+ }
+
+ MIuint64 nNumber = 0;
+ if( CMICmnLLDBProxySBValue::GetValueAsUnsigned( value, nNumber ) == MIstatus::success )
+ {
+ const lldb::ValueType eValueType = value.GetValueType(); MIunused( eValueType );
+ m_strValue = utilValue.GetValue();
+ CMIUtilString strCString;
+ if( CMICmnLLDBProxySBValue::GetCString( value, strCString ) )
+ {
+ m_strValue += CMIUtilString::Format( " '%s'", strCString.c_str() );
+ }
+ return MIstatus::success;
+ }
+
+ // Composite type i.e. struct
+ m_bCompositeVarType = true;
+ const MIuint nChild = value.GetNumChildren();
+ for( MIuint i = 0; i < nChild; i++ )
+ {
+ lldb::SBValue member = value.GetChildAtIndex( i );
+ const bool bValid = member.IsValid();
+ CMIUtilString strType( MIRSRC( IDS_WORD_UNKNOWNTYPE_BRKTS ) );
+ if( bValid )
+ {
+ const CMIUtilString strValue( CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted( member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural ) );
+ const char * pTypeName = member.GetName();
+ if( pTypeName != nullptr )
+ strType = pTypeName;
+
+ // MI print "{variable = 1, variable2 = 3, variable3 = 5}"
+ const bool bNoQuotes = true;
+ const CMICmnMIValueConst miValueConst( strValue, bNoQuotes );
+ const bool bUseSpaces = true;
+ const CMICmnMIValueResult miValueResult( strType, miValueConst, bUseSpaces );
+ m_miValueTuple.Add( miValueResult, bUseSpaces );
+ }
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataEvaluateExpression::Acknowledge( void )
+{
+ if( m_bExpressionValid )
+ {
+ if( m_bEvaluatedExpression )
+ {
+ if( m_bCompositeVarType )
+ {
+ const CMICmnMIValueConst miValueConst( m_miValueTuple.GetString() );
+ const CMICmnMIValueResult miValueResult( "value", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ if( m_bFoundInvalidChar )
+ {
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "Invalid character '%c' in expression", m_cExpressionInvalidChar ) );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ const CMICmnMIValueConst miValueConst( m_strValue );
+ const CMICmnMIValueResult miValueResult( "value", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ const CMICmnMIValueConst miValueConst( "Could not evaluate expression" );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ const CMICmnMIValueConst miValueConst( "Invalid expression" );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdDataEvaluateExpression::CreateSelf( void )
+{
+ return new CMICmdCmdDataEvaluateExpression();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Examine the expression string to see if it contains invalid characters.
+// Type: Method.
+// Args: vrExpr - (R) Expression string given to *this command.
+// vrwInvalidChar - (W) True = Invalid character found, false = nothing found.
+// Return: bool - True = Invalid character found, false = nothing found.
+// Throws: None.
+//--
+bool CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression( const CMIUtilString & vrExpr, MIchar & vrwInvalidChar )
+{
+ bool bFoundInvalidCharInExpression = false;
+ vrwInvalidChar = 0x00;
+
+ if( vrExpr.at( 0 ) == '\\' )
+ {
+ // Example: Mouse hover over "%5d" expression has \"%5d\" in it
+ bFoundInvalidCharInExpression = true;
+ vrwInvalidChar = '\\';
+ }
+
+ return bFoundInvalidCharInExpression;
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataDisassemble constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble( void )
+: m_constStrArgThread( "thread" )
+, m_constStrArgAddrStart( "s" )
+, m_constStrArgAddrEnd( "e" )
+, m_constStrArgConsume( "--" )
+, m_constStrArgMode( "mode" )
+, m_miValueList( true )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "data-disassemble";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdDataDisassemble::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataDisassemble destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataDisassemble::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgAddrStart, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgAddrEnd, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValConsume( m_constStrArgConsume, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgMode, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataDisassemble::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
+ CMICMDBASE_GETOPTION( pArgAddrStart, OptionShort, m_constStrArgAddrStart );
+ CMICMDBASE_GETOPTION( pArgAddrEnd, OptionShort, m_constStrArgAddrEnd );
+ CMICMDBASE_GETOPTION( pArgMode, Number, m_constStrArgMode );
+
+ // Retrieve the --thread option's thread ID (only 1)
+ MIuint64 nThreadId = UINT64_MAX;
+ if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_THREAD_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
+ return MIstatus::failure;
+ }
+ CMIUtilString strAddrStart;
+ if( !pArgAddrStart->GetExpectedOption< CMICmdArgValString, CMIUtilString >( strAddrStart ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_DISASM_ADDR_START_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str() ) );
+ return MIstatus::failure;
+ }
+ MIint64 nAddrStart = 0;
+ if( !strAddrStart.ExtractNumber( nAddrStart ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_DISASM_ADDR_START_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMIUtilString strAddrEnd;
+ if( !pArgAddrEnd->GetExpectedOption< CMICmdArgValString, CMIUtilString >( strAddrEnd ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_DISASM_ADDR_END_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str() ) );
+ return MIstatus::failure;
+ }
+ MIint64 nAddrEnd = 0;
+ if( !strAddrEnd.ExtractNumber( nAddrEnd ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_DISASM_ADDR_END_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str() ) );
+ return MIstatus::failure;
+ }
+ const MIuint nDisasmMode = pArgMode->GetValue();
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBTarget & rTarget = rSessionInfo.m_lldbTarget;
+ lldb::addr_t lldbStartAddr = static_cast< lldb::addr_t >( nAddrStart );
+ lldb::SBInstructionList instructions = rTarget.ReadInstructions( lldb::SBAddress( lldbStartAddr, rTarget ), nAddrEnd - nAddrStart );
+ const MIuint nInstructions = instructions.GetSize();
+ for( size_t i = 0; i < nInstructions; i++ )
+ {
+ const MIchar * pUnknown = "??";
+ lldb::SBInstruction instrt = instructions.GetInstructionAtIndex( i );
+ const MIchar * pStrMnemonic = instrt.GetMnemonic( rTarget );
+ pStrMnemonic = (pStrMnemonic != nullptr) ? pStrMnemonic : pUnknown;
+ lldb::SBAddress address = instrt.GetAddress();
+ lldb::addr_t addr = address.GetLoadAddress( rTarget );
+ const MIchar * pFnName = address.GetFunction().GetName();
+ pFnName = (pFnName != nullptr) ? pFnName : pUnknown;
+ lldb::addr_t addrOffSet = address.GetOffset();
+ const MIchar * pStrOperands = instrt.GetOperands( rTarget );
+ pStrOperands = (pStrOperands != nullptr) ? pStrOperands : pUnknown;
+
+ // MI "{address=\"0x%08llx\",func-name=\"%s\",offset=\"%lld\",inst=\"%s %s\"}"
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "0x%08llx", addr ) );
+ const CMICmnMIValueResult miValueResult( "address", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueConst miValueConst2( pFnName );
+ const CMICmnMIValueResult miValueResult2( "func-name", miValueConst2 );
+ miValueTuple.Add( miValueResult2 );
+ const CMICmnMIValueConst miValueConst3( CMIUtilString::Format( "0x%lld", addrOffSet ) );
+ const CMICmnMIValueResult miValueResult3( "offset", miValueConst3 );
+ miValueTuple.Add( miValueResult3 );
+ const CMICmnMIValueConst miValueConst4( CMIUtilString::Format( "%s %s", pStrMnemonic, pStrOperands ) );
+ const CMICmnMIValueResult miValueResult4( "inst", miValueConst4 );
+ miValueTuple.Add( miValueResult4 );
+
+ if( nDisasmMode == 1 )
+ {
+ lldb::SBLineEntry lineEntry = address.GetLineEntry();
+ const MIuint nLine = lineEntry.GetLine();
+ const MIchar * pFileName = lineEntry.GetFileSpec().GetFilename();
+ pFileName = (pFileName != nullptr) ? pFileName : pUnknown;
+
+ // MI "src_and_asm_line={line=\"%u\",file=\"%s\",line_asm_insn=[ ]}"
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "0x%u", nLine ) );
+ const CMICmnMIValueResult miValueResult( "line", miValueConst );
+ CMICmnMIValueTuple miValueTuple2( miValueResult );
+ const CMICmnMIValueConst miValueConst2( pFileName );
+ const CMICmnMIValueResult miValueResult2( "file", miValueConst2 );
+ miValueTuple2.Add( miValueResult2 );
+ const CMICmnMIValueList miValueList( miValueTuple );
+ const CMICmnMIValueResult miValueResult3( "line_asm_insn", miValueList );
+ miValueTuple2.Add( miValueResult3 );
+ const CMICmnMIValueResult miValueResult4( "src_and_asm_line", miValueTuple2 );
+ m_miValueList.Add( miValueResult4 );
+ }
+ else
+ {
+ m_miValueList.Add( miValueTuple );
+ }
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataDisassemble::Acknowledge( void )
+{
+ const CMICmnMIValueResult miValueResult( "asm_insns", m_miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdDataDisassemble::CreateSelf( void )
+{
+ return new CMICmdCmdDataDisassemble();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataReadMemoryBytes constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes( void )
+: m_constStrArgThread( "thread" )
+, m_constStrArgByteOffset( "o" )
+, m_constStrArgAddrStart( "address" )
+, m_constStrArgNumBytes( "count" )
+, m_pBufferMemory( nullptr )
+, m_nAddrStart( 0 )
+, m_nAddrNumBytesToRead( 0 )
+, m_nAddrOffset( 0 )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "data-read-memory-bytes";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdDataReadMemoryBytes::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataReadMemoryBytes destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes( void )
+{
+ if( m_pBufferMemory != nullptr )
+ {
+ delete [] m_pBufferMemory;
+ m_pBufferMemory = nullptr;
+ }
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataReadMemoryBytes::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgByteOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgAddrStart, true, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNumBytes, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataReadMemoryBytes::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgAddrStart, Number, m_constStrArgAddrStart );
+ CMICMDBASE_GETOPTION( pArgAddrOffset, Number, m_constStrArgByteOffset );
+ CMICMDBASE_GETOPTION( pArgNumBytes, Number, m_constStrArgNumBytes );
+
+ const MIuint64 nAddrStart = pArgAddrStart->GetValue();
+ const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue();
+ if( pArgAddrOffset->GetFound() )
+ m_nAddrOffset = pArgAddrOffset->GetValue();
+
+ m_pBufferMemory = new MIuchar[ nAddrNumBytes ];
+ if( m_pBufferMemory == nullptr )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_MEMORY_ALLOC_FAILURE ), m_cmdData.strMiCmd.c_str(), nAddrNumBytes ) );
+ return MIstatus::failure;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+ lldb::SBError error;
+ const MIuint64 nReadBytes = rProcess.ReadMemory( static_cast< lldb::addr_t >( nAddrStart ), (void *) m_pBufferMemory, nAddrNumBytes, error );
+ if( nReadBytes != nAddrNumBytes )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK ), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart ) );
+ return MIstatus::failure;
+ }
+ if( error.Fail() )
+ {
+ lldb::SBStream err;
+ const bool bOk = error.GetDescription( err ); MIunused( bOk );
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES ), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart, err.GetData() ) );
+ return MIstatus::failure;
+ }
+
+ m_nAddrStart = nAddrStart;
+ m_nAddrNumBytesToRead = nAddrNumBytes;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataReadMemoryBytes::Acknowledge( void )
+{
+ // MI: memory=[{begin=\"0x%08x\",offset=\"0x%08x\",end=\"0x%08x\",contents=\" \" }]"
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "0x%08x", m_nAddrStart ) );
+ const CMICmnMIValueResult miValueResult( "begin", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueConst miValueConst2( CMIUtilString::Format( "0x%08x", m_nAddrOffset ) );
+ const CMICmnMIValueResult miValueResult2( "offset", miValueConst2 );
+ miValueTuple.Add( miValueResult2 );
+ const CMICmnMIValueConst miValueConst3( CMIUtilString::Format( "0x%08x", m_nAddrStart + m_nAddrNumBytesToRead ) );
+ const CMICmnMIValueResult miValueResult3( "end", miValueConst3 );
+ miValueTuple.Add( miValueResult3 );
+
+ // MI: contents=\" \"
+ CMIUtilString strContent;
+ strContent.reserve( (m_nAddrNumBytesToRead << 1) + 1 );
+ for( MIuint64 i = 0; i < m_nAddrNumBytesToRead; i ++ )
+ {
+ strContent += CMIUtilString::Format( "%02x", m_pBufferMemory[ i ] );
+ }
+ const CMICmnMIValueConst miValueConst4( strContent );
+ const CMICmnMIValueResult miValueResult4( "contents", miValueConst4 );
+ miValueTuple.Add( miValueResult4 );
+ const CMICmnMIValueList miValueList( miValueTuple );
+ const CMICmnMIValueResult miValueResult5( "memory", miValueList );
+
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult5 );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdDataReadMemoryBytes::CreateSelf( void )
+{
+ return new CMICmdCmdDataReadMemoryBytes();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataReadMemory constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory( void )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "data-read-memory";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdDataReadMemory::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataReadMemory destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataReadMemory::Execute( void )
+{
+ // Do nothing - command deprecated use "data-read-memory-bytes" command
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataReadMemory::Acknowledge( void )
+{
+ // Command CMICmdCmdSupportListFeatures sends "data-read-memory-bytes" which causes this command not to be called
+ const CMICmnMIValueConst miValueConst( MIRSRC( IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED ) );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdDataReadMemory::CreateSelf( void )
+{
+ return new CMICmdCmdDataReadMemory();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataListRegisterNames constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames( void )
+: m_constStrArgThreadGroup( "thread-group" )
+, m_constStrArgRegNo( "regno" )
+, m_miValueList( true )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "data-list-register-names";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdDataListRegisterNames::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataReadMemoryBytes destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataListRegisterNames::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThreadGroup, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgRegNo, false, false, CMICmdArgValListBase::eArgValType_Number ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataListRegisterNames::Execute( void )
+{
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+ if( !rProcess.IsValid() )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_PROCESS ), m_cmdData.strMiCmd.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ lldb::SBThread thread = rProcess.GetSelectedThread();
+ lldb::SBFrame frame = thread.GetSelectedFrame();
+ lldb::SBValueList registers = frame.GetRegisters();
+ const MIuint nRegisters = registers.GetSize();
+ for( MIuint i = 0; i < nRegisters; i++ )
+ {
+ lldb::SBValue value = registers.GetValueAtIndex( i );
+ const MIuint nRegChildren = value.GetNumChildren();
+ for( MIuint j = 0; j < nRegChildren; j++ )
+ {
+ lldb::SBValue value2 = value.GetChildAtIndex( j );
+ if( value2.IsValid() )
+ {
+ const CMICmnMIValueConst miValueConst( CMICmnLLDBUtilSBValue( value2 ).GetName() );
+ m_miValueList.Add( miValueConst );
+ }
+ }
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataListRegisterNames::Acknowledge( void )
+{
+ const CMICmnMIValueResult miValueResult( "register-names", m_miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdDataListRegisterNames::CreateSelf( void )
+{
+ return new CMICmdCmdDataListRegisterNames();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataListRegisterValues constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues( void )
+: m_constStrArgThread( "thread" )
+, m_constStrArgSkip( "skip-unavailable" )
+, m_constStrArgFormat( "fmt" )
+, m_constStrArgRegNo( "regno" )
+, m_miValueList( true )
+, m_pProcess( nullptr )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "data-list-register-values";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdDataListRegisterValues::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataListRegisterValues destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataListRegisterValues::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgSkip, false, false ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgFormat, true, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgRegNo, false, true, CMICmdArgValListBase::eArgValType_Number ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataListRegisterValues::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgFormat, String, m_constStrArgFormat );
+ CMICMDBASE_GETOPTION( pArgRegNo, ListOfN, m_constStrArgRegNo );
+
+ const CMIUtilString & rStrFormat( pArgFormat->GetValue() );
+ if( rStrFormat.length() != 1 )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_FORMAT_TYPE ), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str() ) );
+ return MIstatus::failure;
+ }
+ const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e eFormat = CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar( rStrFormat[ 0 ] );
+ if( eFormat == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_FORMAT_TYPE ), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+ if( !rProcess.IsValid() )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_PROCESS ), m_cmdData.strMiCmd.c_str() ) );
+ return MIstatus::failure;
+ }
+ m_pProcess = &rProcess;
+
+ const CMICmdArgValListBase::VecArgObjPtr_t & rVecRegNo( pArgRegNo->GetExpectedOptions() );
+ CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin();
+ while( it != rVecRegNo.end() )
+ {
+ const CMICmdArgValNumber * pRegNo = static_cast< CMICmdArgValNumber * >( *it );
+ const MIuint nReg = pRegNo->GetValue();
+ lldb::SBValue regValue = GetRegister( nReg );
+ const CMIUtilString strRegValue( CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted( regValue, eFormat ) );
+
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%u", nReg ) );
+ const CMICmnMIValueResult miValueResult( "number", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueConst miValueConst2( strRegValue );
+ const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
+ miValueTuple.Add( miValueResult2 );
+ m_miValueList.Add( miValueTuple );
+
+ // Next
+ ++it;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataListRegisterValues::Acknowledge( void )
+{
+ const CMICmnMIValueResult miValueResult( "register-values", m_miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdDataListRegisterValues::CreateSelf( void )
+{
+ return new CMICmdCmdDataListRegisterValues();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Method.
+// Args: None.
+// Return: lldb::SBValue - LLDB SBValue object.
+// Throws: None.
+//--
+lldb::SBValue CMICmdCmdDataListRegisterValues::GetRegister( const MIuint vRegisterIndex ) const
+{
+ lldb::SBThread thread = m_pProcess->GetSelectedThread();
+ lldb::SBFrame frame = thread.GetSelectedFrame();
+ lldb::SBValueList registers = frame.GetRegisters();
+ const MIuint nRegisters = registers.GetSize();
+ for( MIuint i = 0; i < nRegisters; i++ )
+ {
+ lldb::SBValue value = registers.GetValueAtIndex( i );
+ const MIuint nRegChildren = value.GetNumChildren();
+ if( nRegChildren > 0 )
+ {
+ lldb::SBValue value2 = value.GetChildAtIndex( vRegisterIndex );
+ if( value2.IsValid() )
+ {
+ return value2;
+ }
+ }
+ }
+
+ return lldb::SBValue();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataListRegisterChanged constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged( void )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "data-list-changed-registers";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdDataListRegisterChanged::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataListRegisterChanged destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataListRegisterChanged::Execute( void )
+{
+ // Do nothing
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataListRegisterChanged::Acknowledge( void )
+{
+ const CMICmnMIValueConst miValueConst( MIRSRC( IDS_WORD_NOT_IMPLEMENTED ) );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdDataListRegisterChanged::CreateSelf( void )
+{
+ return new CMICmdCmdDataListRegisterChanged();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataWriteMemoryBytes constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes( void )
+: m_constStrArgThread( "thread" )
+, m_constStrArgAddr( "address" )
+, m_constStrArgContents( "contents" )
+, m_constStrArgCount( "count" )
+, m_nAddr( 0 )
+, m_nCount( 0 )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "data-write-memory-bytes";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdDataWriteMemoryBytes::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataWriteMemoryBytes destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataWriteMemoryBytes::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgAddr, true, true, false, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgContents, true, true, true, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgCount, false, true, false, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataWriteMemoryBytes::Execute( void )
+{
+ // Do nothing - not reproduceable (yet) in Eclipse
+ //CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset );
+ //CMICMDBASE_GETOPTION( pArgAddr, String, m_constStrArgAddr );
+ //CMICMDBASE_GETOPTION( pArgNumber, String, m_constStrArgNumber );
+ //CMICMDBASE_GETOPTION( pArgContents, String, m_constStrArgContents );
+ //
+ // Numbers extracts as string types as they could be hex numbers
+ // '&' is not recognised and so has to be removed
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataWriteMemoryBytes::Acknowledge( void )
+{
+ const CMICmnMIValueConst miValueConst( MIRSRC( IDS_WORD_NOT_IMPLEMENTED ) );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdDataWriteMemoryBytes::CreateSelf( void )
+{
+ return new CMICmdCmdDataWriteMemoryBytes();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataWriteMemory constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory( void )
+: m_constStrArgThread( "thread" )
+, m_constStrArgOffset( "o" )
+, m_constStrArgAddr( "address" )
+, m_constStrArgD( "d" )
+, m_constStrArgNumber( "a number" )
+, m_constStrArgContents( "contents" )
+, m_nAddr( 0 )
+, m_nCount( 0 )
+, m_pBufferMemory( nullptr )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "data-write-memory";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdDataWriteMemory::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdDataWriteMemory destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory( void )
+{
+ if( m_pBufferMemory != nullptr )
+ {
+ delete [] m_pBufferMemory;
+ m_pBufferMemory = nullptr;
+ }
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataWriteMemory::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgAddr, true, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgD, true, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNumber, true, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgContents, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataWriteMemory::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset );
+ CMICMDBASE_GETOPTION( pArgAddr, Number, m_constStrArgAddr );
+ CMICMDBASE_GETOPTION( pArgNumber, Number, m_constStrArgNumber );
+ CMICMDBASE_GETOPTION( pArgContents, Number, m_constStrArgContents );
+
+ MIuint nAddrOffset = 0;
+ if( pArgOffset->GetFound() && !pArgOffset->GetExpectedOption< CMICmdArgValNumber, MIuint>( nAddrOffset ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgAddr.c_str() ) );
+ return MIstatus::failure;
+ }
+ m_nAddr = pArgAddr->GetValue();
+ m_nCount = pArgNumber->GetValue();
+ const MIuint64 nValue = pArgContents->GetValue();
+
+ m_pBufferMemory = new MIuchar [ m_nCount ];
+ if( m_pBufferMemory == nullptr )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_MEMORY_ALLOC_FAILURE ), m_cmdData.strMiCmd.c_str(), m_nCount ) );
+ return MIstatus::failure;
+ }
+ *m_pBufferMemory = static_cast< MIchar >( nValue );
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+ lldb::SBError error;
+ lldb::addr_t addr = static_cast< lldb::addr_t >( m_nAddr + nAddrOffset );
+ const size_t nBytesWritten = rProcess.WriteMemory( addr, (const void *) m_pBufferMemory, (size_t) m_nCount, error );
+ if( nBytesWritten != static_cast< size_t >( m_nCount ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK ), m_cmdData.strMiCmd.c_str(), m_nCount, addr ) );
+ return MIstatus::failure;
+ }
+ if( error.Fail() )
+ {
+ lldb::SBStream err;
+ const bool bOk = error.GetDescription( err ); MIunused( bOk );
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES ), m_cmdData.strMiCmd.c_str(), m_nCount, addr, err.GetData() ) );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdDataWriteMemory::Acknowledge( void )
+{
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdDataWriteMemory::CreateSelf( void )
+{
+ return new CMICmdCmdDataWriteMemory();
+}
diff --git a/tools/lldb-mi/MICmdCmdData.h b/tools/lldb-mi/MICmdCmdData.h
new file mode 100644
index 000000000000..c1501de3918f
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdData.h
@@ -0,0 +1,374 @@
+//===-- MICmdCmdData.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdData.h
+//
+// Overview: CMICmdCmdDataEvaluateExpression interface.
+// CMICmdCmdDataDisassemble interface.
+// CMICmdCmdDataReadMemoryBytes interface.
+// CMICmdCmdDataReadMemory interface.
+// CMICmdCmdDataListRegisterNames interface.
+// CMICmdCmdDataListRegisterValues interface.
+// CMICmdCmdDataListRegisterChanged interface.
+// CMICmdCmdDataWriteMemoryBytes interface.
+// CMICmdCmdDataWriteMemory interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdBase.h"
+#include "MICmnMIValueTuple.h"
+#include "MICmnMIValueList.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "data-evaluate-expression".
+// Gotchas: None.
+// Authors: Illya Rudkin 26/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdDataEvaluateExpression : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdDataEvaluateExpression( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdDataEvaluateExpression( void );
+
+// Methods:
+private:
+ bool HaveInvalidCharacterInExpression( const CMIUtilString & vrExpr, MIchar & vrwInvalidChar );
+
+// Attributes:
+private:
+ bool m_bExpressionValid; // True = yes is valid, false = not valid
+ bool m_bEvaluatedExpression; // True = yes is expression evaluated, false = failed
+ CMIUtilString m_strValue;
+ CMICmnMIValueTuple m_miValueTuple;
+ bool m_bCompositeVarType; // True = yes composite type, false = internal type
+ bool m_bFoundInvalidChar; // True = yes found unexpected character in the expression, false = all ok
+ MIchar m_cExpressionInvalidChar;
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command.
+ const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option. Not handled by command.
+ const CMIUtilString m_constStrArgExpr;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "data-disassemble".
+// Gotchas: None.
+// Authors: Illya Rudkin 19/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdDataDisassemble : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdDataDisassemble( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdDataDisassemble( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command.
+ const CMIUtilString m_constStrArgAddrStart; // MI spec non mandatory, *this command mandatory
+ const CMIUtilString m_constStrArgAddrEnd; // MI spec non mandatory, *this command mandatory
+ const CMIUtilString m_constStrArgConsume;
+ const CMIUtilString m_constStrArgMode;
+ CMICmnMIValueList m_miValueList;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "data-read-memory-bytes".
+// Gotchas: None.
+// Authors: Illya Rudkin 20/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdDataReadMemoryBytes : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdDataReadMemoryBytes( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdDataReadMemoryBytes( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command.
+ const CMIUtilString m_constStrArgByteOffset;
+ const CMIUtilString m_constStrArgAddrStart;
+ const CMIUtilString m_constStrArgNumBytes;
+ MIuchar * m_pBufferMemory;
+ MIuint64 m_nAddrStart;
+ MIuint64 m_nAddrNumBytesToRead;
+ MIuint64 m_nAddrOffset;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "data-read-memory".
+// Gotchas: None.
+// Authors: Illya Rudkin 21/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdDataReadMemory : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdDataReadMemory( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdDataReadMemory( void );
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "data-list-register-names".
+// Gotchas: None.
+// Authors: Illya Rudkin 21/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdDataListRegisterNames : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdDataListRegisterNames( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdDataListRegisterNames( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgThreadGroup; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgRegNo; // Not handled by *this command
+ CMICmnMIValueList m_miValueList;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "data-list-register-values".
+// Gotchas: None.
+// Authors: Illya Rudkin 21/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdDataListRegisterValues : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdDataListRegisterValues( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdDataListRegisterValues( void );
+
+// Methods:
+private:
+ lldb::SBValue GetRegister( const MIuint vRegisterIndex ) const;
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgSkip; // Not handled by *this command
+ const CMIUtilString m_constStrArgFormat;
+ const CMIUtilString m_constStrArgRegNo;
+ CMICmnMIValueList m_miValueList;
+ lldb::SBProcess * m_pProcess;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "data-list-changed-registers".
+// Gotchas: None.
+// Authors: Illya Rudkin 22/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdDataListRegisterChanged : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdDataListRegisterChanged( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdDataListRegisterChanged( void );
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "data-read-memory-bytes".
+// Gotchas: None.
+// Authors: Illya Rudkin 30/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdDataWriteMemoryBytes : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdDataWriteMemoryBytes( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdDataWriteMemoryBytes( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command.
+ const CMIUtilString m_constStrArgAddr;
+ const CMIUtilString m_constStrArgContents;
+ const CMIUtilString m_constStrArgCount;
+ MIuint64 m_nAddr;
+ CMIUtilString m_strContents;
+ MIuint64 m_nCount;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "data-read-memory".
+// Not specified in MI spec but Eclipse gives *this command.
+// Gotchas: None.
+// Authors: Illya Rudkin 02/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdDataWriteMemory : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdDataWriteMemory( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdDataWriteMemory( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command.
+ const CMIUtilString m_constStrArgOffset; // Not specified in MI spec but Eclipse gives this option.
+ const CMIUtilString m_constStrArgAddr; // Not specified in MI spec but Eclipse gives this option.
+ const CMIUtilString m_constStrArgD; // Not specified in MI spec but Eclipse gives this option.
+ const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option.
+ const CMIUtilString m_constStrArgContents; // Not specified in MI spec but Eclipse gives this option.
+ MIuint64 m_nAddr;
+ CMIUtilString m_strContents;
+ MIuint64 m_nCount;
+ MIuchar * m_pBufferMemory;
+}; \ No newline at end of file
diff --git a/tools/lldb-mi/MICmdCmdEnviro.cpp b/tools/lldb-mi/MICmdCmdEnviro.cpp
new file mode 100644
index 000000000000..b47327af9406
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdEnviro.cpp
@@ -0,0 +1,143 @@
+//===-- MICmdCmdEnviro.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdEnviro.cpp
+//
+// Overview: CMICmdCmdEnvironmentCd implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdCmdEnviro.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnLLDBDebugger.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MICmdArgValFile.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdEnvironmentCd constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdEnvironmentCd::CMICmdCmdEnvironmentCd( void )
+: m_constStrArgNamePathDir( "pathdir" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "environment-cd";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdEnvironmentCd::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdEnvironmentCd destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdEnvironmentCd::~CMICmdCmdEnvironmentCd( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdEnvironmentCd::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValFile( m_constStrArgNamePathDir, true, true ) ) );
+ CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdEnvironmentCd::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgPathDir, File, m_constStrArgNamePathDir );
+ const CMIUtilString & strWkDir( pArgPathDir->GetValue() );
+ CMICmnLLDBDebugger & rDbg( CMICmnLLDBDebugger::Instance() );
+ lldb::SBDebugger & rLldbDbg = rDbg.GetTheDebugger();
+ bool bOk = rLldbDbg.SetCurrentPlatformSDKRoot( strWkDir.c_str() );
+ if( bOk )
+ {
+ const CMIUtilString & rStrKeyWkDir( m_rLLDBDebugSessionInfo.m_constStrSharedDataKeyWkDir );
+ if( !m_rLLDBDebugSessionInfo.SharedDataAdd< CMIUtilString >( rStrKeyWkDir, strWkDir ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_DBGSESSION_ERR_SHARED_DATA_ADD ), m_cmdData.strMiCmd.c_str(), rStrKeyWkDir.c_str() ) );
+ bOk = MIstatus::failure;
+ }
+ }
+ else
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_FNFAILED ), m_cmdData.strMiCmd.c_str(), "SetCurrentPlatformSDKRoot()" ) );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdEnvironmentCd::Acknowledge( void )
+{
+ const CMIUtilString & rStrKeyWkDir( m_rLLDBDebugSessionInfo.m_constStrSharedDataKeyWkDir );
+ CMIUtilString strWkDir;
+ const bool bOk = m_rLLDBDebugSessionInfo.SharedDataRetrieve< CMIUtilString >( rStrKeyWkDir, strWkDir );
+ if( bOk )
+ {
+ const CMICmnMIValueConst miValueConst( strWkDir );
+ const CMICmnMIValueResult miValueResult( "path", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_SHARED_DATA_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), rStrKeyWkDir.c_str() ) );
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdEnvironmentCd::CreateSelf( void )
+{
+ return new CMICmdCmdEnvironmentCd();
+}
diff --git a/tools/lldb-mi/MICmdCmdEnviro.h b/tools/lldb-mi/MICmdCmdEnviro.h
new file mode 100644
index 000000000000..efbe89238218
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdEnviro.h
@@ -0,0 +1,69 @@
+//===-- MICmdCmdEnviro.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdEnviro.h
+//
+// Overview: CMICmdCmdEnvironmentCd interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdBase.h"
+#include "MICmnMIValueTuple.h"
+#include "MICmnMIValueList.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "environment-cd".
+// Gotchas: None.
+// Authors: Illya Rudkin 03/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdEnvironmentCd : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdEnvironmentCd( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdEnvironmentCd( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgNamePathDir;
+};
+
diff --git a/tools/lldb-mi/MICmdCmdExec.cpp b/tools/lldb-mi/MICmdCmdExec.cpp
new file mode 100644
index 000000000000..c0ec25d701b7
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdExec.cpp
@@ -0,0 +1,982 @@
+//===-- MICmdCmdExec.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdExec.cpp
+//
+// Overview: CMICmdCmdExecRun implementation.
+// CMICmdCmdExecContinue implementation.
+// CMICmdCmdExecNext implementation.
+// CMICmdCmdExecStep implementation.
+// CMICmdCmdExecNextInstruction implementation.
+// CMICmdCmdExecStepInstruction implementation.
+// CMICmdCmdExecFinish implementation.
+// CMICmdCmdExecInterrupt implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third Party Headers:
+#include <lldb/API/SBCommandInterpreter.h>
+#include <lldb/API/SBProcess.h>
+#include <lldb/API/SBStream.h>
+#include "lldb/lldb-enumerations.h"
+
+// In-house headers:
+#include "MICmdCmdExec.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnLLDBDebugger.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MIDriver.h"
+#include "MICmdArgValNumber.h"
+#include "MICmdArgValString.h"
+#include "MICmdArgValThreadGrp.h"
+#include "MICmdArgValOptionLong.h"
+#include "MICmdArgValOptionShort.h"
+#include "MICmdArgValListOfN.h"
+#include "MICmnStreamStdout.h"
+#include "MICmnMIOutOfBandRecord.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecRun constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecRun::CMICmdCmdExecRun( void )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "exec-run";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdExecRun::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecRun destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecRun::~CMICmdCmdExecRun( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecRun::Execute( void )
+{
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBError error;
+ lldb::SBStream errMsg;
+ uint32_t launch_flags = lldb::LaunchFlags::eLaunchFlagDebug;
+ lldb::SBProcess process = rSessionInfo.m_lldbTarget.Launch (rSessionInfo.m_rLlldbListener,
+ nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, launch_flags, false, error);
+
+ if( (!process.IsValid()) || (error.Fail()) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_PROCESS ), m_cmdData.strMiCmd.c_str(), errMsg.GetData() ) );
+ return MIstatus::failure;
+ }
+
+ // Save the process in the session info
+ rSessionInfo.m_lldbProcess = process;
+
+ if( !CMIDriver::Instance().SetDriverStateRunningDebugging() )
+ {
+ const CMIUtilString & rErrMsg( CMIDriver::Instance().GetErrorDescription() );
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_SET_NEW_DRIVER_STATE ), m_cmdData.strMiCmd.c_str(), rErrMsg.c_str() ) );
+ return MIstatus::failure;
+ }
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecRun::Acknowledge( void )
+{
+ if( m_lldbResult.GetErrorSize() > 0 )
+ {
+ const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() );
+ const CMICmnMIValueResult miValueResult( "message", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ }
+ else
+ {
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running );
+ m_miResultRecord = miRecordResult;
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID();
+ // Give the client '=thread-group-started,id="i1" pid="xyz"'
+ m_bHasResultRecordExtra = true;
+ const CMICmnMIValueConst miValueConst2( "i1" );
+ const CMICmnMIValueResult miValueResult2( "id", miValueConst2 );
+ const CMIUtilString strPid( CMIUtilString::Format( "%lld", pid ) );
+ const CMICmnMIValueConst miValueConst( strPid );
+ const CMICmnMIValueResult miValueResult( "pid", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2 );
+ miOutOfBand.Add( miValueResult );
+ m_miResultRecordExtra = miOutOfBand.GetString();
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdExecRun::CreateSelf( void )
+{
+ return new CMICmdCmdExecRun();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecContinue constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecContinue::CMICmdCmdExecContinue( void )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "exec-continue";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdExecContinue::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecContinue destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecContinue::~CMICmdCmdExecContinue( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecContinue::Execute( void )
+{
+ const MIchar * pCmd = "continue";
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ const lldb::ReturnStatus rtn = rSessionInfo.m_rLldbDebugger.GetCommandInterpreter().HandleCommand( pCmd, m_lldbResult ); MIunused( rtn );
+
+
+ if( m_lldbResult.GetErrorSize() == 0 )
+ {
+ // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+ if( !CMIDriver::Instance().SetDriverStateRunningDebugging() )
+ {
+ const CMIUtilString & rErrMsg( CMIDriver::Instance().GetErrorDescription() );
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_SET_NEW_DRIVER_STATE ), m_cmdData.strMiCmd.c_str(), rErrMsg.c_str() ) );
+ return MIstatus::failure;
+ }
+ }
+ else
+ {
+ // ToDo: Re-evaluate if this is required when application near finished as this is parsing LLDB error message
+ // which seems a hack and is code brittle
+ const MIchar * pLldbErr = m_lldbResult.GetError();
+ const CMIUtilString strLldbMsg( CMIUtilString( pLldbErr ).StripCREndOfLine() );
+ if( strLldbMsg == "error: Process must be launched." )
+ {
+ CMIDriver::Instance().SetExitApplicationFlag( true );
+ }
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecContinue::Acknowledge( void )
+{
+ if( m_lldbResult.GetErrorSize() > 0 )
+ {
+ const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() );
+ const CMICmnMIValueResult miValueResult( "message", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ }
+ else
+ {
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running );
+ m_miResultRecord = miRecordResult;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdExecContinue::CreateSelf( void )
+{
+ return new CMICmdCmdExecContinue();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecNext constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecNext::CMICmdCmdExecNext( void )
+: m_constStrArgThread( "thread" )
+, m_constStrArgNumber( "number" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "exec-next";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdExecNext::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecNext destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecNext::~CMICmdCmdExecNext( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecNext::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNumber, false, false ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecNext::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
+
+ // Retrieve the --thread option's thread ID (only 1)
+ MIuint64 nThreadId = UINT64_MAX;
+ if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_THREAD_INVALID ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBDebugger & rDebugger = rSessionInfo.m_rLldbDebugger;
+ CMIUtilString strCmd( "thread step-over" );
+ if( nThreadId != UINT64_MAX )
+ strCmd += CMIUtilString::Format( " %llu", nThreadId );
+ rDebugger.GetCommandInterpreter().HandleCommand( strCmd.c_str(), m_lldbResult, false );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecNext::Acknowledge( void )
+{
+ if( m_lldbResult.GetErrorSize() > 0 )
+ {
+ const MIchar * pLldbErr = m_lldbResult.GetError(); MIunused( pLldbErr );
+ const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() );
+ const CMICmnMIValueResult miValueResult( "message", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ }
+ else
+ {
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running );
+ m_miResultRecord = miRecordResult;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdExecNext::CreateSelf( void )
+{
+ return new CMICmdCmdExecNext();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecStep constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecStep::CMICmdCmdExecStep( void )
+: m_constStrArgThread( "thread" )
+, m_constStrArgNumber( "number" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "exec-step";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdExecStep::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecStep destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecStep::~CMICmdCmdExecStep( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecStep::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNumber, false, false ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecStep::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
+
+ // Retrieve the --thread option's thread ID (only 1)
+ MIuint64 nThreadId = UINT64_MAX;
+ if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBDebugger & rDebugger = rSessionInfo.m_rLldbDebugger;
+ CMIUtilString strCmd( "thread step-in" );
+ if( nThreadId != UINT64_MAX )
+ strCmd += CMIUtilString::Format( " %llu", nThreadId );
+ rDebugger.GetCommandInterpreter().HandleCommand( strCmd.c_str(), m_lldbResult, false );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecStep::Acknowledge( void )
+{
+ if( m_lldbResult.GetErrorSize() > 0 )
+ {
+ const MIchar * pLldbErr = m_lldbResult.GetError(); MIunused( pLldbErr );
+ const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() );
+ const CMICmnMIValueResult miValueResult( "message", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ }
+ else
+ {
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running );
+ m_miResultRecord = miRecordResult;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdExecStep::CreateSelf( void )
+{
+ return new CMICmdCmdExecStep();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecNextInstruction constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecNextInstruction::CMICmdCmdExecNextInstruction( void )
+: m_constStrArgThread( "thread" )
+, m_constStrArgNumber( "number" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "exec-next-instruction";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdExecNextInstruction::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecNextInstruction destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecNextInstruction::~CMICmdCmdExecNextInstruction( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecNextInstruction::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNumber, false, false ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecNextInstruction::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
+
+ // Retrieve the --thread option's thread ID (only 1)
+ MIuint64 nThreadId = UINT64_MAX;
+ if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBDebugger & rDebugger = rSessionInfo.m_rLldbDebugger;
+ CMIUtilString strCmd( "thread step-inst-over" );
+ if( nThreadId != UINT64_MAX )
+ strCmd += CMIUtilString::Format( " %llu", nThreadId );
+ rDebugger.GetCommandInterpreter().HandleCommand( strCmd.c_str(), m_lldbResult, false );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecNextInstruction::Acknowledge( void )
+{
+ if( m_lldbResult.GetErrorSize() > 0 )
+ {
+ const MIchar * pLldbErr = m_lldbResult.GetError(); MIunused( pLldbErr );
+ const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() );
+ const CMICmnMIValueResult miValueResult( "message", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ }
+ else
+ {
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running );
+ m_miResultRecord = miRecordResult;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdExecNextInstruction::CreateSelf( void )
+{
+ return new CMICmdCmdExecNextInstruction();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecStepInstruction constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecStepInstruction::CMICmdCmdExecStepInstruction( void )
+: m_constStrArgThread( "thread" )
+, m_constStrArgNumber( "number" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "exec-step-instruction";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdExecStepInstruction::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecStepInstruction destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecStepInstruction::~CMICmdCmdExecStepInstruction( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecStepInstruction::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNumber, false, false ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecStepInstruction::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
+
+ // Retrieve the --thread option's thread ID (only 1)
+ MIuint64 nThreadId = UINT64_MAX;
+ if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBDebugger & rDebugger = rSessionInfo.m_rLldbDebugger;
+ CMIUtilString strCmd( "thread step-inst" );
+ if( nThreadId != UINT64_MAX )
+ strCmd += CMIUtilString::Format( " %llu", nThreadId );
+ rDebugger.GetCommandInterpreter().HandleCommand( strCmd.c_str(), m_lldbResult, false );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecStepInstruction::Acknowledge( void )
+{
+ if( m_lldbResult.GetErrorSize() > 0 )
+ {
+ const MIchar * pLldbErr = m_lldbResult.GetError(); MIunused( pLldbErr );
+ const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() );
+ const CMICmnMIValueResult miValueResult( "message", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ }
+ else
+ {
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running );
+ m_miResultRecord = miRecordResult;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdExecStepInstruction::CreateSelf( void )
+{
+ return new CMICmdCmdExecStepInstruction();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecFinish constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecFinish::CMICmdCmdExecFinish( void )
+: m_constStrArgThread( "thread" )
+, m_constStrArgFrame( "frame" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "exec-finish";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdExecFinish::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecFinish destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecFinish::~CMICmdCmdExecFinish( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecFinish::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgFrame, false, false, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecFinish::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
+
+ // Retrieve the --thread option's thread ID (only 1)
+ MIuint64 nThreadId = UINT64_MAX;
+ if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBDebugger & rDebugger = rSessionInfo.m_rLldbDebugger;
+ CMIUtilString strCmd( "thread step-out" );
+ if( nThreadId != UINT64_MAX )
+ strCmd += CMIUtilString::Format( " %llu", nThreadId );
+ rDebugger.GetCommandInterpreter().HandleCommand( strCmd.c_str(), m_lldbResult, false );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecFinish::Acknowledge( void )
+{
+ if( m_lldbResult.GetErrorSize() > 0 )
+ {
+ const MIchar * pLldbErr = m_lldbResult.GetError(); MIunused( pLldbErr );
+ const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() );
+ const CMICmnMIValueResult miValueResult( "message", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ }
+ else
+ {
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running );
+ m_miResultRecord = miRecordResult;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdExecFinish::CreateSelf( void )
+{
+ return new CMICmdCmdExecFinish();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecInterrupt constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecInterrupt::CMICmdCmdExecInterrupt( void )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "exec-interrupt";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdExecInterrupt::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdExecInterrupt destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdExecInterrupt::~CMICmdCmdExecInterrupt( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecInterrupt::Execute( void )
+{
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBDebugger & rDebugger = rSessionInfo.m_rLldbDebugger;
+ CMIUtilString strCmd( "process interrupt" );
+ const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand( strCmd.c_str(), m_lldbResult, false ); MIunused( status );
+
+ // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+ if( !CMIDriver::Instance().SetDriverStateRunningNotDebugging() )
+ {
+ const CMIUtilString & rErrMsg( CMIDriver::Instance().GetErrorDescription() );
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_SET_NEW_DRIVER_STATE ), strCmd.c_str(), rErrMsg.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdExecInterrupt::Acknowledge( void )
+{
+ if( m_lldbResult.GetErrorSize() > 0 )
+ {
+ const CMICmnMIValueConst miValueConst( m_lldbResult.GetError() );
+ const CMICmnMIValueResult miValueResult( "message", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ }
+ else
+ {
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdExecInterrupt::CreateSelf( void )
+{
+ return new CMICmdCmdExecInterrupt();
+}
+
diff --git a/tools/lldb-mi/MICmdCmdExec.h b/tools/lldb-mi/MICmdCmdExec.h
new file mode 100644
index 000000000000..a712b23ca5e0
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdExec.h
@@ -0,0 +1,310 @@
+//===-- MICmdCmdExec.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdExec.h
+//
+// Overview: CMICmdCmdExecRun interface.
+// CMICmdCmdExecContinue interface.
+// CMICmdCmdExecNext interface.
+// CMICmdCmdExecStep interface.
+// CMICmdCmdExecNextInstruction interface.
+// CMICmdCmdExecStepInstruction interface.
+// CMICmdCmdExecFinish interface.
+// CMICmdCmdExecInterrupt interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <lldb/API/SBCommandReturnObject.h>
+
+// In-house headers:
+#include "MICmdBase.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "exec-run".
+// Gotchas: None.
+// Authors: Illya Rudkin 07/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdExecRun : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdExecRun( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdExecRun( void );
+
+// Attributes:
+private:
+ lldb::SBCommandReturnObject m_lldbResult;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "exec-continue".
+// Gotchas: None.
+// Authors: Illya Rudkin 07/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdExecContinue : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdExecContinue( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdExecContinue( void );
+
+// Attributes:
+private:
+ lldb::SBCommandReturnObject m_lldbResult;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "exec-next".
+// Gotchas: None.
+// Authors: Illya Rudkin 25/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdExecNext : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdExecNext( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdExecNext( void );
+
+// Attributes:
+private:
+ lldb::SBCommandReturnObject m_lldbResult;
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "exec-step".
+// Gotchas: None.
+// Authors: Illya Rudkin 25/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdExecStep : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdExecStep( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdExecStep( void );
+
+// Attributes:
+private:
+ lldb::SBCommandReturnObject m_lldbResult;
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "exec-next-instruction".
+// Gotchas: None.
+// Authors: Illya Rudkin 25/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdExecNextInstruction : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdExecNextInstruction( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdExecNextInstruction( void );
+
+// Attributes:
+private:
+ lldb::SBCommandReturnObject m_lldbResult;
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "exec-step-instruction".
+// Gotchas: None.
+// Authors: Illya Rudkin 25/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdExecStepInstruction : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdExecStepInstruction( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdExecStepInstruction( void );
+
+// Attributes:
+private:
+ lldb::SBCommandReturnObject m_lldbResult;
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "exec-finish".
+// Gotchas: None.
+// Authors: Illya Rudkin 25/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdExecFinish : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdExecFinish( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdExecFinish( void );
+
+// Attributes:
+private:
+ lldb::SBCommandReturnObject m_lldbResult;
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option
+};
+
+// CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "exec-interrupt".
+// Gotchas: Using Eclipse this command is injected into the command system when a
+// SIGINT signal is received while running an inferior program.
+// Authors: Illya Rudkin 03/06/2014.
+// Changes: None.
+//--
+class CMICmdCmdExecInterrupt : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdExecInterrupt( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdExecInterrupt( void );
+
+// Attributes:
+private:
+ lldb::SBCommandReturnObject m_lldbResult;
+};
+
diff --git a/tools/lldb-mi/MICmdCmdFile.cpp b/tools/lldb-mi/MICmdCmdFile.cpp
new file mode 100644
index 000000000000..1d0b494362ce
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdFile.cpp
@@ -0,0 +1,184 @@
+//===-- MICmdCmdFile.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdFile.cpp
+//
+// Overview: CMICmdCmdFileExecAndSymbols implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third Party Headers:
+#include <lldb/API/SBStream.h>
+
+// In-house headers:
+#include "MICmdCmdFile.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnLLDBDebugger.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MIUtilFileStd.h"
+#include "MICmdArgValFile.h"
+#include "MICmdArgValOptionLong.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdFileExecAndSymbols constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdFileExecAndSymbols::CMICmdCmdFileExecAndSymbols( void )
+: m_constStrArgNameFile( "file" )
+, m_constStrArgThreadGrp( "thread-group" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "file-exec-and-symbols";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdFileExecAndSymbols::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdFileExecAndSymbols destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdFileExecAndSymbols::~CMICmdCmdFileExecAndSymbols( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdFileExecAndSymbols::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValFile( m_constStrArgNameFile, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Synopsis: -file-exec-and-symbols file
+// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-File-Commands.html#GDB_002fMI-File-Commands
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdFileExecAndSymbols::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgNamedFile, File, m_constStrArgNameFile );
+ CMICmdArgValFile * pArgFile = static_cast< CMICmdArgValFile * >( pArgNamedFile );
+ const CMIUtilString & strExeFilePath( pArgFile->GetValue() );
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBDebugger & rDbgr = rSessionInfo.m_rLldbDebugger;
+ lldb::SBError error;
+ const MIchar * pTargetTriple = nullptr; // Let LLDB discover the triple required
+ const MIchar * pTargetPlatformName = "";
+ const bool bAddDepModules = false;
+ lldb::SBTarget target = rDbgr.CreateTarget( strExeFilePath.c_str(), pTargetTriple, pTargetPlatformName, bAddDepModules, error );
+ CMIUtilString strWkDir;
+ const CMIUtilString & rStrKeyWkDir( rSessionInfo.m_constStrSharedDataKeyWkDir );
+ if( !rSessionInfo.SharedDataRetrieve< CMIUtilString >( rStrKeyWkDir, strWkDir ) )
+ {
+ strWkDir = CMIUtilFileStd().StripOffFileName( strExeFilePath );
+ if( !rSessionInfo.SharedDataAdd< CMIUtilString >( rStrKeyWkDir, strWkDir ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_DBGSESSION_ERR_SHARED_DATA_ADD ), m_cmdData.strMiCmd.c_str(), rStrKeyWkDir.c_str() ) );
+ return MIstatus::failure;
+ }
+ }
+ if( !rDbgr.SetCurrentPlatformSDKRoot( strWkDir.c_str() ) )
+ {
+
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_FNFAILED ), m_cmdData.strMiCmd.c_str(), "SetCurrentPlatformSDKRoot()" ) );
+ return MIstatus::failure;
+ }
+ lldb::SBStream err;
+ if( error.Fail() )
+ {
+ const bool bOk = error.GetDescription( err ); MIunused( bOk );
+ }
+ if( !target.IsValid() )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_TARGET ), m_cmdData.strMiCmd.c_str(), strExeFilePath.c_str(), err.GetData() ) );
+ return MIstatus::failure;
+ }
+ if( error.Fail() )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_CREATE_TARGET ), m_cmdData.strMiCmd.c_str(), err.GetData() ) );
+ return MIstatus::failure;
+ }
+
+ rSessionInfo.m_lldbTarget = target;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdFileExecAndSymbols::Acknowledge( void )
+{
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdFileExecAndSymbols::CreateSelf( void )
+{
+ return new CMICmdCmdFileExecAndSymbols();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: If the MI Driver is not operating via a client i.e. Eclipse but say operating
+// on a executable passed in as a argument to the drive then what should the driver
+// do on a command failing? Either continue operating or exit the application.
+// Override this function where a command failure cannot allow the driver to
+// continue operating.
+// Type: Overridden.
+// Args: None.
+// Return: bool - True = Fatal if command fails, false = can continue if command fails.
+// Throws: None.
+//--
+bool CMICmdCmdFileExecAndSymbols::GetExitAppOnCommandFailure( void ) const
+{
+ return true;
+} \ No newline at end of file
diff --git a/tools/lldb-mi/MICmdCmdFile.h b/tools/lldb-mi/MICmdCmdFile.h
new file mode 100644
index 000000000000..a80a313ea7b5
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdFile.h
@@ -0,0 +1,71 @@
+//===-- MICmdCmdFile.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdFile.h
+//
+// Overview: CMICmdCmdFileExecAndSymbols interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdBase.h"
+#include "MICmnMIValueTuple.h"
+#include "MICmnMIValueList.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "file-exec-and-symbols".
+// This command does not follow the MI documentation exactly.
+// Gotchas: None.
+// Authors: Illya Rudkin 25/02/2014.
+// Changes: None.
+//--
+class CMICmdCmdFileExecAndSymbols : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdFileExecAndSymbols( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdFileExecAndSymbols( void );
+ virtual bool GetExitAppOnCommandFailure( void ) const;
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgNameFile;
+ const CMIUtilString m_constStrArgThreadGrp; // Not handled by *this command. Not specified in MI spec but Eclipse gives this option sometimes
+};
diff --git a/tools/lldb-mi/MICmdCmdGdbInfo.cpp b/tools/lldb-mi/MICmdCmdGdbInfo.cpp
new file mode 100644
index 000000000000..62bb1f280bc3
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdGdbInfo.cpp
@@ -0,0 +1,232 @@
+//===-- MICmdCmdGdbInfo.cpp ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdGdbInfo.cpp
+//
+// Overview: CMICmdCmdGdbInfo implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers:
+#include <lldb/API/SBCommandReturnObject.h>
+
+// In-house headers:
+#include "MICmdCmdGdbInfo.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmdArgValString.h"
+#include "MICmnStreamStdout.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+
+// Instantiations:
+const CMICmdCmdGdbInfo::MapPrintFnNameToPrintFn_t CMICmdCmdGdbInfo::ms_mapPrintFnNameToPrintFn =
+{
+ { "sharedlibrary", &CMICmdCmdGdbInfo::PrintFnSharedLibrary }
+};
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdGdbInfo constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdGdbInfo::CMICmdCmdGdbInfo( void )
+: m_constStrArgNamedPrint( "print" )
+, m_bPrintFnRecognised( true )
+, m_bPrintFnSuccessful( false )
+, m_strPrintFnError( MIRSRC( IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS ) )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "info";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdGdbInfo::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdGdbInfo destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdGdbInfo::~CMICmdCmdGdbInfo( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbInfo::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedPrint, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbInfo::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgPrint, String, m_constStrArgNamedPrint );
+ const CMIUtilString & rPrintRequest( pArgPrint->GetValue() );
+
+ FnPrintPtr pPrintRequestFn = nullptr;
+ if( !GetPrintFn( rPrintRequest, pPrintRequestFn ) )
+ {
+ m_strPrintFnName = rPrintRequest;
+ m_bPrintFnRecognised = false;
+ return MIstatus::success;
+ }
+
+ m_bPrintFnSuccessful = (this->*(pPrintRequestFn))();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbInfo::Acknowledge( void )
+{
+ if( !m_bPrintFnRecognised )
+ {
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND ), m_strPrintFnName.c_str() ) );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ if( m_bPrintFnSuccessful )
+ {
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INFO_PRINTFN_FAILED ), m_strPrintFnError.c_str() ) );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdGdbInfo::CreateSelf( void )
+{
+ return new CMICmdCmdGdbInfo();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the print function's pointer for the matching print request.
+// Type: Method.
+// Args: vrPrintFnName - (R) The info requested.
+// vrwpFn - (W) The print function's pointer of the function to carry out
+// Return: bool - True = Print request is implemented, false = not found.
+// Throws: None.
+//--
+bool CMICmdCmdGdbInfo::GetPrintFn( const CMIUtilString & vrPrintFnName, FnPrintPtr & vrwpFn ) const
+{
+ vrwpFn = nullptr;
+
+ const MapPrintFnNameToPrintFn_t::const_iterator it = ms_mapPrintFnNameToPrintFn.find( vrPrintFnName );
+ if( it != ms_mapPrintFnNameToPrintFn.end() )
+ {
+ vrwpFn = (*it).second;
+ return true;
+ }
+
+ return false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Carry out work to complete the request to prepare and send back information
+// asked for.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbInfo::PrintFnSharedLibrary( void )
+{
+ CMICmnStreamStdout & rStdout = CMICmnStreamStdout::Instance();
+ bool bOk = rStdout.TextToStdout( "~\"From To Syms Read Shared Object Library\"" );
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBTarget & rTarget = rSessionInfo.m_lldbTarget;
+ const MIuint nModules = rTarget.GetNumModules();
+ for( MIuint i = 0; bOk && (i < nModules); i++ )
+ {
+ lldb::SBModule module = rTarget.GetModuleAtIndex( i );
+ if( module.IsValid() )
+ {
+ const CMIUtilString strModuleFilePath( module.GetFileSpec().GetDirectory() );
+ const CMIUtilString strModuleFileName( module.GetFileSpec().GetFilename() );
+ const CMIUtilString strModuleFullPath( CMIUtilString::Format( "%s/%s", strModuleFilePath.c_str(), strModuleFileName.c_str() ) );
+ const CMIUtilString strHasSymbols = (module.GetNumSymbols() > 0) ? "Yes" : "No";
+ lldb::addr_t addrLoadS = 0xffffffff;
+ lldb::addr_t addrLoadSize = 0;
+ bool bHaveAddrLoad = false;
+ const MIuint nSections = module.GetNumSections();
+ for( MIuint j = 0; j < nSections; j++ )
+ {
+ lldb::SBSection section = module.GetSectionAtIndex( j );
+ lldb::addr_t addrLoad = section.GetLoadAddress( rTarget );
+ if( addrLoad != (lldb::addr_t) -1 )
+ {
+ if( !bHaveAddrLoad )
+ {
+ bHaveAddrLoad = true;
+ addrLoadS = addrLoad;
+ }
+
+ addrLoadSize += section.GetByteSize();
+ }
+ }
+ bOk = bOk && rStdout.TextToStdout( CMIUtilString::Format( "~\"0x%08x\t0x%08x\t%s\t\t%s\"", addrLoadS, addrLoadS + addrLoadSize, strHasSymbols.c_str(), strModuleFullPath.c_str() ) );
+ }
+ }
+
+ return bOk;
+}
diff --git a/tools/lldb-mi/MICmdCmdGdbInfo.h b/tools/lldb-mi/MICmdCmdGdbInfo.h
new file mode 100644
index 000000000000..3fa920669416
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdGdbInfo.h
@@ -0,0 +1,93 @@
+//===-- MICmdCmdGdbInfo.h --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdGdbInfo.h
+//
+// Overview: CMICmdCmdGdbInfo interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <map>
+
+// In-house headers:
+#include "MICmdBase.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements GDB command "info".
+// The design of matching the info request to a request action (or
+// command) is very simple. The request function which carries out
+// the task of information gathering and printing to stdout is part of
+// *this class. Should the request function become more complicated then
+// that request should really reside in a command type class. Then this
+// class instantiates a request info command for a matching request. The
+// design/code of *this class then does not then become bloated. Use a
+// lightweight version of the current MI command system.
+// Gotchas: None.
+// Authors: Illya Rudkin 05/06/2014.
+// Changes: None.
+//--
+class CMICmdCmdGdbInfo : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdGdbInfo( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdGdbInfo( void );
+
+// Typedefs:
+private:
+ typedef bool (CMICmdCmdGdbInfo::*FnPrintPtr)();
+ typedef std::map< CMIUtilString, FnPrintPtr > MapPrintFnNameToPrintFn_t;
+
+// Methods:
+private:
+ bool GetPrintFn( const CMIUtilString & vrPrintFnName, FnPrintPtr & vrwpFn ) const;
+ bool PrintFnSharedLibrary( void );
+
+// Attributes:
+private:
+ const static MapPrintFnNameToPrintFn_t ms_mapPrintFnNameToPrintFn;
+ //
+ const CMIUtilString m_constStrArgNamedPrint;
+ bool m_bPrintFnRecognised; // True = This command has a function with a name that matches the Print argument, false = not found
+ bool m_bPrintFnSuccessful; // True = The print function completed its task ok, false = function failed for some reason
+ CMIUtilString m_strPrintFnName;
+ CMIUtilString m_strPrintFnError;
+}; \ No newline at end of file
diff --git a/tools/lldb-mi/MICmdCmdGdbSet.cpp b/tools/lldb-mi/MICmdCmdGdbSet.cpp
new file mode 100644
index 000000000000..a256ee2e2ca1
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdGdbSet.cpp
@@ -0,0 +1,260 @@
+//===-- MICmdCmdGdbSet.cpp ------- -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdGdbSet.cpp
+//
+// Overview: CMICmdCmdGdbSet implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdCmdGdbSet.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmdArgValString.h"
+#include "MICmdArgValListOfN.h"
+#include "MICmdArgValOptionLong.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+
+// Instantiations:
+const CMICmdCmdGdbSet::MapGdbOptionNameToFnGdbOptionPtr_t CMICmdCmdGdbSet::ms_mapGdbOptionNameToFnGdbOptionPtr =
+{
+ // { "target-async", &CMICmdCmdGdbSet::OptionFnTargetAsync }, // Example code if need to implement GDB set other options
+ // { "auto-solib-add", &CMICmdCmdGdbSet::OptionFnAutoSolibAdd }, // Example code if need to implement GDB set other options
+ { "solib-search-path", &CMICmdCmdGdbSet::OptionFnSolibSearchPath },
+ { "fallback", &CMICmdCmdGdbSet::OptionFnFallback }
+};
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdGdbSet constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdGdbSet::CMICmdCmdGdbSet( void )
+: m_constStrArgNamedThreadGrp( "thread-group" )
+, m_constStrArgNamedGdbOption( "option" )
+, m_bGdbOptionRecognised( true )
+, m_bGdbOptionFnSuccessful( false )
+, m_bGbbOptionFnHasError( false )
+, m_strGdbOptionFnError( MIRSRC( IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS ) )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "gdb-set";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdGdbSet::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdGdbSet destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdGdbSet::~CMICmdCmdGdbSet( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbSet::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgNamedGdbOption, true, true, CMICmdArgValListBase::eArgValType_StringAnything ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbSet::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgGdbOption, ListOfN, m_constStrArgNamedGdbOption );
+ const CMICmdArgValListBase::VecArgObjPtr_t & rVecWords( pArgGdbOption->GetExpectedOptions() );
+
+ // Get the gdb-set option to carry out
+ CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecWords.begin();
+ const CMICmdArgValString * pOption = static_cast< const CMICmdArgValString * >( *it );
+ const CMIUtilString strOption( pOption->GetValue() );
+ ++it;
+
+ // Retrieve the parameter(s) for the option
+ CMIUtilString::VecString_t vecWords;
+ while( it != rVecWords.end() )
+ {
+ const CMICmdArgValString * pWord = static_cast< const CMICmdArgValString * >( *it );
+ vecWords.push_back( pWord->GetValue() );
+
+ // Next
+ ++it;
+ }
+
+ FnGdbOptionPtr pPrintRequestFn = nullptr;
+ if( !GetOptionFn( strOption, pPrintRequestFn ) )
+ {
+ // For unimplemented option handlers, fallback on a generic handler
+ // ToDo: Remove this when ALL options have been implemented
+ if( !GetOptionFn( "fallback", pPrintRequestFn ) )
+ {
+ m_bGdbOptionRecognised = false;
+ m_strGdbOptionName = "fallback"; // This would be the strOption name
+ return MIstatus::success;
+ }
+ }
+
+ m_bGdbOptionFnSuccessful = (this->*(pPrintRequestFn))( vecWords );
+ if( !m_bGdbOptionFnSuccessful && !m_bGbbOptionFnHasError )
+ return MIstatus::failure;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbSet::Acknowledge( void )
+{
+ if( !m_bGdbOptionRecognised )
+ {
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND ), m_strGdbOptionName.c_str() ) );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ if( m_bGdbOptionFnSuccessful )
+ {
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INFO_PRINTFN_FAILED ), m_strGdbOptionFnError.c_str() ) );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdGdbSet::CreateSelf( void )
+{
+ return new CMICmdCmdGdbSet();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the print function's pointer for the matching print request.
+// Type: Method.
+// Args: vrPrintFnName - (R) The info requested.
+// vrwpFn - (W) The print function's pointer of the function to carry out
+// Return: bool - True = Print request is implemented, false = not found.
+// Throws: None.
+//--
+bool CMICmdCmdGdbSet::GetOptionFn( const CMIUtilString & vrPrintFnName, FnGdbOptionPtr & vrwpFn ) const
+{
+ vrwpFn = nullptr;
+
+ const MapGdbOptionNameToFnGdbOptionPtr_t::const_iterator it = ms_mapGdbOptionNameToFnGdbOptionPtr.find( vrPrintFnName );
+ if( it != ms_mapGdbOptionNameToFnGdbOptionPtr.end() )
+ {
+ vrwpFn = (*it).second;
+ return true;
+ }
+
+ return false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Carry out work to complete the GDB set option 'solib-search-path' to prepare
+// and send back information asked for.
+// Type: Method.
+// Args: vrWords - (R) List of additional parameters used by this option.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbSet::OptionFnSolibSearchPath( const CMIUtilString::VecString_t & vrWords )
+{
+ // Check we have at least one argument
+ if( vrWords.size() < 1 )
+ {
+ m_bGbbOptionFnHasError = true;
+ m_strGdbOptionFnError = MIRSRC( IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH );
+ return MIstatus::failure;
+ }
+ const CMIUtilString & rStrValSolibPath( vrWords[ 0 ] );
+
+ // Add 'solib-search-path' to the shared data list
+ const CMIUtilString & rStrKeySolibPath( m_rLLDBDebugSessionInfo.m_constStrSharedDataSolibPath );
+ if( !m_rLLDBDebugSessionInfo.SharedDataAdd< CMIUtilString >( rStrKeySolibPath, rStrValSolibPath ) )
+ {
+ m_bGbbOptionFnHasError = false;
+ SetError( CMIUtilString::Format( MIRSRC( IDS_DBGSESSION_ERR_SHARED_DATA_ADD ), m_cmdData.strMiCmd.c_str(), rStrKeySolibPath.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Carry out work to complete the GDB set option to prepare and send back information
+// asked for.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbSet::OptionFnFallback( const CMIUtilString::VecString_t & vrWords )
+{
+ MIunused( vrWords );
+
+ // Do nothing - intentional. This is a fallback temporary action function to do nothing.
+ // This allows the search for gdb-set options to always suceed when the option is not
+ // found (implemented).
+
+ return MIstatus::success;
+}
diff --git a/tools/lldb-mi/MICmdCmdGdbSet.h b/tools/lldb-mi/MICmdCmdGdbSet.h
new file mode 100644
index 000000000000..24b54557bf37
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdGdbSet.h
@@ -0,0 +1,96 @@
+//===-- MICmdCmdGdbSet.h ------------- ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdGdbSet.h
+//
+// Overview: CMICmdCmdGdbSet interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdBase.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "gdb-set".
+// This command does not follow the MI documentation exactly. While *this
+// command is implemented it does not do anything with the gdb-set
+// variable past in.
+// The design of matching the info request to a request action (or
+// command) is very simple. The request function which carries out
+// the task of information gathering and printing to stdout is part of
+// *this class. Should the request function become more complicated then
+// that request should really reside in a command type class. Then this
+// class instantiates a request info command for a matching request. The
+// design/code of *this class then does not then become bloated. Use a
+// lightweight version of the current MI command system.
+// Gotchas: None.
+// Authors: Illya Rudkin 03/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdGdbSet : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdGdbSet( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdGdbSet( void );
+
+// Typedefs:
+private:
+ typedef bool (CMICmdCmdGdbSet::*FnGdbOptionPtr)( const CMIUtilString::VecString_t & vrWords );
+ typedef std::map< CMIUtilString, FnGdbOptionPtr > MapGdbOptionNameToFnGdbOptionPtr_t;
+
+// Methods:
+private:
+ bool GetOptionFn( const CMIUtilString & vrGdbOptionName, FnGdbOptionPtr & vrwpFn ) const;
+ bool OptionFnSolibSearchPath( const CMIUtilString::VecString_t & vrWords );
+ bool OptionFnFallback( const CMIUtilString::VecString_t & vrWords );
+
+// Attributes:
+private:
+ const static MapGdbOptionNameToFnGdbOptionPtr_t ms_mapGdbOptionNameToFnGdbOptionPtr;
+ //
+ const CMIUtilString m_constStrArgNamedThreadGrp;
+ const CMIUtilString m_constStrArgNamedGdbOption;
+ bool m_bGdbOptionRecognised; // True = This command has a function with a name that matches the Print argument, false = not found
+ bool m_bGdbOptionFnSuccessful; // True = The print function completed its task ok, false = function failed for some reason
+ bool m_bGbbOptionFnHasError; // True = The option function has an error condition (not the command!), false = option function ok.
+ CMIUtilString m_strGdbOptionName;
+ CMIUtilString m_strGdbOptionFnError;
+}; \ No newline at end of file
diff --git a/tools/lldb-mi/MICmdCmdGdbThread.cpp b/tools/lldb-mi/MICmdCmdGdbThread.cpp
new file mode 100644
index 000000000000..09bd053a65e1
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdGdbThread.cpp
@@ -0,0 +1,100 @@
+//===-- MICmdCmdGdbThread.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdGdbThread.cpp
+//
+// Overview: CMICmdCmdGdbThread implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdCmdGdbThread.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdGdbThread constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdGdbThread::CMICmdCmdGdbThread( void )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "thread";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdGdbThread::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdThread destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdGdbThread::~CMICmdCmdGdbThread( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbThread::Execute( void )
+{
+ // Do nothing
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbThread::Acknowledge( void )
+{
+ const CMICmnMIValueConst miValueConst( MIRSRC( IDS_WORD_NOT_IMPLEMENTED ) );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdGdbThread::CreateSelf( void )
+{
+ return new CMICmdCmdGdbThread();
+} \ No newline at end of file
diff --git a/tools/lldb-mi/MICmdCmdGdbThread.h b/tools/lldb-mi/MICmdCmdGdbThread.h
new file mode 100644
index 000000000000..29c1361b4cf4
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdGdbThread.h
@@ -0,0 +1,61 @@
+//===-- MICmdCmdGdbThread.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdGdbThread.h
+//
+// Overview: CMICmdCmdGdbThread interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdBase.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements GDB command "thread".
+// Gotchas: None.
+// Authors: Illya Rudkin 25/02/2014.
+// Changes: None.
+//--
+class CMICmdCmdGdbThread : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdGdbThread( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdGdbThread( void );
+}; \ No newline at end of file
diff --git a/tools/lldb-mi/MICmdCmdMiscellanous.cpp b/tools/lldb-mi/MICmdCmdMiscellanous.cpp
new file mode 100644
index 000000000000..b09f585598a4
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdMiscellanous.cpp
@@ -0,0 +1,588 @@
+//===-- MICmdCmdMiscellanous.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdMiscellanous.cpp
+//
+// Overview: CMICmdCmdGdbExit implementation.
+// CMICmdCmdListThreadGroups implementation.
+// CMICmdCmdInterpreterExec implementation.
+// CMICmdCmdInferiorTtySet implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third Party Headers:
+#include <lldb/API/SBCommandInterpreter.h>
+#include <lldb/API/SBThread.h>
+
+// In-house headers:
+#include "MICmdCmdMiscellanous.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnMIOutOfBandRecord.h"
+#include "MICmnLLDBDebugger.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MIDriverBase.h"
+#include "MICmdArgValFile.h"
+#include "MICmdArgValNumber.h"
+#include "MICmdArgValString.h"
+#include "MICmdArgValThreadGrp.h"
+#include "MICmdArgValOptionLong.h"
+#include "MICmdArgValOptionShort.h"
+#include "MICmdArgValListOfN.h"
+#include "MICmnStreamStdout.h"
+#include "MICmnStreamStderr.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdGdbExit constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdGdbExit::CMICmdCmdGdbExit( void )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "gdb-exit";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdGdbExit::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdGdbExit destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdGdbExit::~CMICmdCmdGdbExit( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbExit::Execute( void )
+{
+ CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag( true );
+ const lldb::SBError sbErr = m_rLLDBDebugSessionInfo.m_lldbProcess.Detach();
+ // Do not check for sbErr.Fail() here, m_lldbProcess is likely !IsValid()
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbExit::Acknowledge( void )
+{
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Exit );
+ m_miResultRecord = miRecordResult;
+
+ // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' because it is using LLDB debugger
+ // Give the client '=thread-group-exited,id="i1"'
+ m_bHasResultRecordExtra = true;
+ const CMICmnMIValueConst miValueConst2( "i1" );
+ const CMICmnMIValueResult miValueResult2( "id", miValueConst2 );
+ const CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult2 );
+ m_miResultRecordExtra = miOutOfBand.GetString();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdGdbExit::CreateSelf( void )
+{
+ return new CMICmdCmdGdbExit();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdListThreadGroups constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdListThreadGroups::CMICmdCmdListThreadGroups( void )
+: m_bIsI1( false )
+, m_bHaveArgOption( false )
+, m_bHaveArgRecurse( false )
+, m_constStrArgNamedAvailable( "available" )
+, m_constStrArgNamedRecurse( "recurse" )
+, m_constStrArgNamedGroup( "group" )
+, m_constStrArgNamedThreadGroup( "i1" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "list-thread-groups";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdListThreadGroups::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdListThreadGroups destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdListThreadGroups::~CMICmdCmdListThreadGroups( void )
+{
+ m_vecMIValueTuple.clear();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdListThreadGroups::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedAvailable, false, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgNamedRecurse, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValListOfN( m_constStrArgNamedGroup, false, true, CMICmdArgValListBase::eArgValType_Number ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValThreadGrp( m_constStrArgNamedThreadGroup, false, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Synopis: -list-thread-groups [ --available ] [ --recurse 1 ] [ group ... ]
+// This command does not follow the MI documentation exactly. Has an extra
+// argument "i1" to handle.
+// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html#GDB_002fMI-Miscellaneous-Commands
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdListThreadGroups::Execute( void )
+{
+ if( m_setCmdArgs.IsArgContextEmpty() )
+ // No options so "top level thread groups"
+ return MIstatus::success;
+
+ CMICMDBASE_GETOPTION( pArgAvailable, OptionLong, m_constStrArgNamedAvailable );
+ CMICMDBASE_GETOPTION( pArgRecurse, OptionLong, m_constStrArgNamedRecurse );
+ CMICMDBASE_GETOPTION( pArgThreadGroup, ThreadGrp, m_constStrArgNamedThreadGroup );
+
+ // Got some options so "threads"
+ if( pArgAvailable->GetFound() )
+ {
+ if( pArgRecurse->GetFound() )
+ {
+ m_bHaveArgRecurse = true;
+ return MIstatus::success;
+ }
+
+ m_bHaveArgOption = true;
+ return MIstatus::success;
+ }
+ // "i1" as first argument (pos 0 of possible arg)
+ if( !pArgThreadGroup->GetFound() )
+ return MIstatus::success;
+ m_bIsI1 = true;
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+
+ // Note do not check for rProcess is IsValid(), continue
+
+ m_vecMIValueTuple.clear();
+ const MIuint nThreads = rProcess.GetNumThreads();
+ for( MIuint i = 0; i < nThreads; i++ )
+ {
+ // GetThreadAtIndex() uses a base 0 index
+ // GetThreadByIndexID() uses a base 1 index
+ lldb::SBThread thread = rProcess.GetThreadAtIndex( i );
+
+ if( thread.IsValid() )
+ {
+ CMICmnMIValueTuple miTuple;
+ if( !rSessionInfo.MIResponseFormThreadInfo2( m_cmdData, thread, miTuple ) )
+ return MIstatus::failure;
+
+ m_vecMIValueTuple.push_back( miTuple );
+ }
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdListThreadGroups::Acknowledge( void )
+{
+ if( m_bHaveArgOption )
+ {
+ if( m_bHaveArgRecurse )
+ {
+ const CMICmnMIValueConst miValueConst( MIRSRC( IDS_WORD_NOT_IMPLEMENTED_BRKTS ) );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+ }
+
+ const CMICmnMIValueConst miValueConst1( "i1" );
+ const CMICmnMIValueResult miValueResult1( "id", miValueConst1 );
+ CMICmnMIValueTuple miTuple( miValueResult1 );
+
+ const CMICmnMIValueConst miValueConst2( "process" );
+ const CMICmnMIValueResult miValueResult2( "type", miValueConst2 );
+ miTuple.Add( miValueResult2 );
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ if (rSessionInfo.m_lldbProcess.IsValid ())
+ {
+ const lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID();
+ const CMIUtilString strPid( CMIUtilString::Format( "%lld", pid ) );
+ const CMICmnMIValueConst miValueConst3( strPid );
+ const CMICmnMIValueResult miValueResult3( "pid", miValueConst3 );
+ miTuple.Add( miValueResult3 );
+ }
+
+ const CMICmnMIValueConst miValueConst4( MIRSRC( IDS_WORD_NOT_IMPLEMENTED_BRKTS ) );
+ const CMICmnMIValueResult miValueResult4( "num_children", miValueConst4 );
+ miTuple.Add( miValueResult4 );
+
+ const CMICmnMIValueConst miValueConst5( MIRSRC( IDS_WORD_NOT_IMPLEMENTED_BRKTS ) );
+ const CMICmnMIValueResult miValueResult5( "cores", miValueConst5 );
+ miTuple.Add( miValueResult5 );
+
+ const CMICmnMIValueList miValueList( miTuple );
+ const CMICmnMIValueResult miValueResult6( "groups", miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+ }
+
+ if( !m_bIsI1 )
+ {
+ const CMICmnMIValueConst miValueConst1( "i1" );
+ const CMICmnMIValueResult miValueResult1( "id", miValueConst1 );
+ CMICmnMIValueTuple miTuple( miValueResult1 );
+
+ const CMICmnMIValueConst miValueConst2( "process" );
+ const CMICmnMIValueResult miValueResult2( "type", miValueConst2 );
+ miTuple.Add( miValueResult2 );
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ if (rSessionInfo.m_lldbProcess.IsValid ())
+ {
+ const lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID();
+ const CMIUtilString strPid( CMIUtilString::Format( "%lld", pid ) );
+ const CMICmnMIValueConst miValueConst3( strPid );
+ const CMICmnMIValueResult miValueResult3( "pid", miValueConst3 );
+ miTuple.Add( miValueResult3 );
+ }
+
+ if (rSessionInfo.m_lldbTarget.IsValid ())
+ {
+ lldb::SBTarget & rTrgt = rSessionInfo.m_lldbTarget;
+ const MIchar * pDir = rTrgt.GetExecutable().GetDirectory();
+ const MIchar * pFileName = rTrgt.GetExecutable().GetFilename();
+ const CMIUtilString strFile( CMIUtilString::Format( "%s/%s", pDir, pFileName ) );
+ const CMICmnMIValueConst miValueConst4( strFile );
+ const CMICmnMIValueResult miValueResult4( "executable", miValueConst4 );
+ miTuple.Add( miValueResult4 );
+ }
+
+ const CMICmnMIValueList miValueList( miTuple );
+ const CMICmnMIValueResult miValueResult5( "groups", miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult5 );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ // Build up a list of thread information from tuples
+ VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin();
+ if( it == m_vecMIValueTuple.end() )
+ {
+ const CMICmnMIValueConst miValueConst( "[]" );
+ const CMICmnMIValueResult miValueResult( "threads", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+ CMICmnMIValueList miValueList( *it );
+ ++it;
+ while( it != m_vecMIValueTuple.end() )
+ {
+ const CMICmnMIValueTuple & rTuple( *it );
+ miValueList.Add( rTuple );
+
+ // Next
+ ++it;
+ }
+
+ const CMICmnMIValueResult miValueResult( "threads", miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdListThreadGroups::CreateSelf( void )
+{
+ return new CMICmdCmdListThreadGroups();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdInterpreterExec constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdInterpreterExec::CMICmdCmdInterpreterExec( void )
+: m_constStrArgNamedInterpreter( "intepreter" )
+, m_constStrArgNamedCommand( "command" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "interpreter-exec";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdInterpreterExec::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdInterpreterExec destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdInterpreterExec::~CMICmdCmdInterpreterExec( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdInterpreterExec::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedInterpreter, true, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedCommand, true, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdInterpreterExec::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgInterpreter, String, m_constStrArgNamedInterpreter );
+ CMICMDBASE_GETOPTION( pArgCommand, String, m_constStrArgNamedCommand );
+
+ // Handle the interpreter parameter by do nothing on purpose (set to 'handled' in
+ // the arg definition above)
+ const CMIUtilString & rStrInterpreter( pArgInterpreter->GetValue() ); MIunused( rStrInterpreter );
+
+ const CMIUtilString & rStrCommand( pArgCommand->GetValue() );
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ const lldb::ReturnStatus rtn = rSessionInfo.m_rLldbDebugger.GetCommandInterpreter().HandleCommand( rStrCommand.c_str(), m_lldbResult, true ); MIunused( rtn );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdInterpreterExec::Acknowledge( void )
+{
+ if( m_lldbResult.GetOutputSize() > 0 )
+ {
+ CMIUtilString strMsg( m_lldbResult.GetOutput() );
+ strMsg = strMsg.StripCREndOfLine();
+ CMICmnStreamStdout::TextToStdout( strMsg );
+
+ // Send the LLDB result message to console so the user can see the result of the
+ // command they typed. It is not necessary an error message.
+ CMICmnStreamStderr::LLDBMsgToConsole( strMsg );
+ }
+ if( m_lldbResult.GetErrorSize() > 0 )
+ {
+ CMIUtilString strMsg( m_lldbResult.GetError() );
+ strMsg = strMsg.StripCREndOfLine();
+ CMICmnStreamStderr::LLDBMsgToConsole( strMsg );
+
+ // Send LLDB's error message to the MI Driver's Log file
+ CMICmnStreamStdout::TextToStdout( strMsg );
+ }
+
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdInterpreterExec::CreateSelf( void )
+{
+ return new CMICmdCmdInterpreterExec();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdInferiorTtySet constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdInferiorTtySet::CMICmdCmdInferiorTtySet( void )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "inferior-tty-set";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdInferiorTtySet::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdInferiorTtySet destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdInferiorTtySet::~CMICmdCmdInferiorTtySet( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdInferiorTtySet::Execute( void )
+{
+ // Do nothing
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdInferiorTtySet::Acknowledge( void )
+{
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdInferiorTtySet::CreateSelf( void )
+{
+ return new CMICmdCmdInferiorTtySet();
+}
diff --git a/tools/lldb-mi/MICmdCmdMiscellanous.h b/tools/lldb-mi/MICmdCmdMiscellanous.h
new file mode 100644
index 000000000000..ea71f1233418
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdMiscellanous.h
@@ -0,0 +1,175 @@
+//===-- MICmdCmdMiscellanous.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdMiscellanous.h
+//
+// Overview: CMICmdCmdGdbExit interface.
+// CMICmdCmdListThreadGroups interface.
+// CMICmdCmdInterpreterExec interface.
+// CMICmdCmdInferiorTtySet interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <lldb/API/SBCommandReturnObject.h>
+
+// In-house headers:
+#include "MICmdBase.h"
+#include "MICmnMIValueTuple.h"
+#include "MICmnMIValueList.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "gdb-exit".
+// Gotchas: None.
+// Authors: Illya Rudkin 04/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdGdbExit : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdGdbExit( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdGdbExit( void );
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "list-thread-groups".
+// This command does not follow the MI documentation exactly.
+// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html#GDB_002fMI-Miscellaneous-Commands
+// Gotchas: None.
+// Authors: Illya Rudkin 06/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdListThreadGroups : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdListThreadGroups( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdListThreadGroups( void );
+
+// Typedefs:
+private:
+ typedef std::vector< CMICmnMIValueTuple > VecMIValueTuple_t;
+
+// Attributes:
+private:
+ bool m_bIsI1; // True = Yes command argument equal "i1", false = no match
+ bool m_bHaveArgOption; // True = Yes "--available" present, false = not found
+ bool m_bHaveArgRecurse; // True = Yes command argument "--recurse", false = no found
+ VecMIValueTuple_t m_vecMIValueTuple;
+ const CMIUtilString m_constStrArgNamedAvailable;
+ const CMIUtilString m_constStrArgNamedRecurse;
+ const CMIUtilString m_constStrArgNamedGroup;
+ const CMIUtilString m_constStrArgNamedThreadGroup;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "interpreter-exec".
+// Gotchas: None.
+// Authors: Illya Rudkin 16/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdInterpreterExec : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdInterpreterExec( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdInterpreterExec( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgNamedInterpreter;
+ const CMIUtilString m_constStrArgNamedCommand;
+ lldb::SBCommandReturnObject m_lldbResult;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "inferior-tty-set".
+// Gotchas: None.
+// Authors: Illya Rudkin 22/07/2014.
+// Changes: None.
+//--
+class CMICmdCmdInferiorTtySet : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdInferiorTtySet( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdInferiorTtySet( void );
+}; \ No newline at end of file
diff --git a/tools/lldb-mi/MICmdCmdStack.cpp b/tools/lldb-mi/MICmdCmdStack.cpp
new file mode 100644
index 000000000000..5f5b355758c4
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdStack.cpp
@@ -0,0 +1,634 @@
+//===-- MICmdCmdStack.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdStack.cpp
+//
+// Overview: CMICmdCmdStackInfoDepth implementation.
+// CMICmdCmdStackListFrames implementation.
+// CMICmdCmdStackListArguments implementation.
+// CMICmdCmdStackListLocals implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third Party Headers:
+#include <lldb/API/SBThread.h>
+
+// In-house headers:
+#include "MICmdCmdStack.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnMIOutOfBandRecord.h"
+#include "MICmnLLDBDebugger.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MICmdArgValNumber.h"
+#include "MICmdArgValString.h"
+#include "MICmdArgValThreadGrp.h"
+#include "MICmdArgValOptionLong.h"
+#include "MICmdArgValOptionShort.h"
+#include "MICmdArgValListOfN.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdStackInfoDepth constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdStackInfoDepth::CMICmdCmdStackInfoDepth( void )
+: m_nThreadFrames( 0 )
+, m_constStrArgThread( "thread" )
+, m_constStrArgMaxDepth( "max-depth" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "stack-info-depth";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdStackInfoDepth::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdStackInfoDepth destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdStackInfoDepth::~CMICmdCmdStackInfoDepth( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdStackInfoDepth::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgMaxDepth, false, false ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdStackInfoDepth::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
+ CMICMDBASE_GETOPTION( pArgMaxDepth, Number, m_constStrArgMaxDepth );
+
+ // Retrieve the --thread option's thread ID (only 1)
+ MIuint64 nThreadId = UINT64_MAX;
+ if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+ lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread();
+ m_nThreadFrames = thread.GetNumFrames();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdStackInfoDepth::Acknowledge( void )
+{
+ const CMIUtilString strDepth( CMIUtilString::Format( "%d", m_nThreadFrames ) );
+ const CMICmnMIValueConst miValueConst( strDepth );
+ const CMICmnMIValueResult miValueResult( "depth", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdStackInfoDepth::CreateSelf( void )
+{
+ return new CMICmdCmdStackInfoDepth();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdStackListFrames constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdStackListFrames::CMICmdCmdStackListFrames( void )
+: m_nThreadFrames( 0 )
+, m_constStrArgThread( "thread" )
+, m_constStrArgFrameLow( "low-frame" )
+, m_constStrArgFrameHigh( "high-frame" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "stack-list-frames";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdStackListFrames::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdStackListFrames destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdStackListFrames::~CMICmdCmdStackListFrames( void )
+{
+ m_vecMIValueResult.clear();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdStackListFrames::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgFrameLow, false, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgFrameHigh, false, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdStackListFrames::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
+ CMICMDBASE_GETOPTION( pArgFrameLow, Number, m_constStrArgFrameLow );
+ CMICMDBASE_GETOPTION( pArgFrameHigh, Number, m_constStrArgFrameHigh );
+
+ // Retrieve the --thread option's thread ID (only 1)
+ MIuint64 nThreadId = UINT64_MAX;
+ if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ // Frame low and high options are not mandatory
+ MIuint nFrameHigh = pArgFrameHigh->GetFound() ? pArgFrameHigh->GetValue() : UINT64_MAX;
+ const MIuint nFrameLow = pArgFrameLow->GetFound() ? pArgFrameLow->GetValue() : 0;
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+ lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread();
+ MIuint nThreadFrames = thread.GetNumFrames();
+
+ // Adjust nThreadFrames for the nFrameHigh argument as we use nFrameHigh+1 in the min calc as the arg
+ // is not an index, but a frame id value.
+ if( nFrameHigh < UINT32_MAX )
+ {
+ nFrameHigh++;
+ nThreadFrames = (nFrameHigh < nThreadFrames) ? nFrameHigh : nThreadFrames;
+ }
+
+ m_nThreadFrames = nThreadFrames;
+ if( nThreadFrames == 0 )
+ return MIstatus::success;
+
+ m_vecMIValueResult.clear();
+ for( MIuint nLevel = nFrameLow; nLevel < nThreadFrames; nLevel++ )
+ {
+ CMICmnMIValueTuple miValueTuple;
+ if( !rSessionInfo.MIResponseFormFrameInfo( thread, nLevel, miValueTuple ) )
+ return MIstatus::failure;
+
+ const CMICmnMIValueResult miValueResult8( "frame", miValueTuple );
+ m_vecMIValueResult.push_back( miValueResult8 );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdStackListFrames::Acknowledge( void )
+{
+ if( m_nThreadFrames == 0 )
+ {
+ // MI print "3^done,stack=[{}]"
+ const CMICmnMIValueTuple miValueTuple;
+ const CMICmnMIValueList miValueList( miValueTuple );
+ const CMICmnMIValueResult miValueResult( "stack", miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+ }
+
+ // Build up a list of thread information from tuples
+ VecMIValueResult_t::const_iterator it = m_vecMIValueResult.begin();
+ if( it == m_vecMIValueResult.end() )
+ {
+ // MI print "3^done,stack=[{}]"
+ const CMICmnMIValueTuple miValueTuple;
+ const CMICmnMIValueList miValueList( miValueTuple );
+ const CMICmnMIValueResult miValueResult( "stack", miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+ CMICmnMIValueList miValueList( *it );
+ ++it;
+ while( it != m_vecMIValueResult.end() )
+ {
+ const CMICmnMIValueResult & rTuple( *it );
+ miValueList.Add( rTuple );
+
+ // Next
+ ++it;
+ }
+ const CMICmnMIValueResult miValueResult( "stack", miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdStackListFrames::CreateSelf( void )
+{
+ return new CMICmdCmdStackListFrames();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdStackListArguments constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdStackListArguments::CMICmdCmdStackListArguments( void )
+: m_bThreadInvalid( false )
+, m_miValueList( true )
+, m_constStrArgThread( "thread" )
+, m_constStrArgPrintValues( "print-values" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "stack-list-arguments";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdStackListArguments::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdStackListArguments destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdStackListArguments::~CMICmdCmdStackListArguments( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdStackListArguments::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgPrintValues, true, false ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdStackListArguments::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
+ CMICMDBASE_GETOPTION( pArgPrintValues, Number, m_constStrArgPrintValues );
+
+ // Retrieve the --thread option's thread ID (only 1)
+ MIuint64 nThreadId = UINT64_MAX;
+ if( pArgThread->GetFound() )
+ {
+ if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
+ return MIstatus::failure;
+ }
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+ lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread();
+ m_bThreadInvalid = !thread.IsValid();
+ if( m_bThreadInvalid )
+ return MIstatus::success;
+
+ const lldb::StopReason eStopReason = thread.GetStopReason();
+ if( (eStopReason == lldb::eStopReasonNone) || (eStopReason == lldb::eStopReasonInvalid) )
+ {
+ m_bThreadInvalid = true;
+ return MIstatus::success;
+ }
+
+
+ const MIuint nFrames = thread.GetNumFrames();
+ for( MIuint i = 0; i < nFrames; i++ )
+ {
+ lldb::SBFrame frame = thread.GetFrameAtIndex( i );
+ CMICmnMIValueList miValueList( true );
+ const MIuint maskVarTypes = 0x1000;
+ if( !rSessionInfo.MIResponseFormVariableInfo3( frame, maskVarTypes, miValueList ) )
+ return MIstatus::failure;
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", i ) );
+ const CMICmnMIValueResult miValueResult( "level", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueResult miValueResult2( "args", miValueList );
+ miValueTuple.Add( miValueResult2 );
+ const CMICmnMIValueResult miValueResult3( "frame", miValueTuple );
+ m_miValueList.Add( miValueResult3 );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdStackListArguments::Acknowledge( void )
+{
+ if( m_bThreadInvalid )
+ {
+ // MI print "%s^done,stack-args=[]"
+ const CMICmnMIValueList miValueList( true );
+ const CMICmnMIValueResult miValueResult( "stack-args", miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ // MI print "%s^done,stack-args=[frame={level=\"0\",args=[%s]},frame={level=\"1\",args=[%s]}]"
+ const CMICmnMIValueResult miValueResult4( "stack-args", m_miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult4 );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdStackListArguments::CreateSelf( void )
+{
+ return new CMICmdCmdStackListArguments();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdStackListLocals constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdStackListLocals::CMICmdCmdStackListLocals( void )
+: m_bThreadInvalid( false )
+, m_miValueList( true )
+, m_constStrArgThread( "thread" )
+, m_constStrArgFrame( "frame" )
+, m_constStrArgPrintValues( "print-values" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "stack-list-locals";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdStackListLocals::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdStackListLocals destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdStackListLocals::~CMICmdCmdStackListLocals( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdStackListLocals::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgPrintValues, true, false ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdStackListLocals::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
+ CMICMDBASE_GETOPTION( pArgFrame, OptionLong, m_constStrArgFrame );
+
+ // Retrieve the --thread option's thread ID (only 1)
+ MIuint64 nThreadId = UINT64_MAX;
+ if( pArgThread->GetFound() )
+ {
+ if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
+ return MIstatus::failure;
+ }
+ }
+ MIuint64 nFrame = UINT64_MAX;
+ if( pArgFrame->GetFound() )
+ {
+ if( !pArgFrame->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nFrame ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str() ) );
+ return MIstatus::failure;
+ }
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+ lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread();
+ m_bThreadInvalid = !thread.IsValid();
+ if( m_bThreadInvalid )
+ return MIstatus::success;
+
+ const lldb::StopReason eStopReason = thread.GetStopReason();
+ if( (eStopReason == lldb::eStopReasonNone) || (eStopReason == lldb::eStopReasonInvalid) )
+ {
+ m_bThreadInvalid = true;
+ return MIstatus::success;
+ }
+
+ const MIuint nFrames = thread.GetNumFrames(); MIunused( nFrames );
+ lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex( nFrame ) : thread.GetSelectedFrame();
+ CMICmnMIValueList miValueList( true );
+ const MIuint maskVarTypes = 0x0110;
+ if( !rSessionInfo.MIResponseFormVariableInfo( frame, maskVarTypes, miValueList ) )
+ return MIstatus::failure;
+
+ m_miValueList = miValueList;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdStackListLocals::Acknowledge( void )
+{
+ if( m_bThreadInvalid )
+ {
+ // MI print "%s^done,locals=[]"
+ const CMICmnMIValueList miValueList( true );
+ const CMICmnMIValueResult miValueResult( "locals", miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ // MI print "%s^done,locals=[%s]"
+ const CMICmnMIValueResult miValueResult( "locals", m_miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdStackListLocals::CreateSelf( void )
+{
+ return new CMICmdCmdStackListLocals();
+}
+
diff --git a/tools/lldb-mi/MICmdCmdStack.h b/tools/lldb-mi/MICmdCmdStack.h
new file mode 100644
index 000000000000..0c3a291d5870
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdStack.h
@@ -0,0 +1,184 @@
+//===-- MICmdCmdStack.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdStack.h
+//
+// Overview: CMICmdCmdStackInfoDepth interface.
+// CMICmdCmdStackListFrames interface.
+// CMICmdCmdStackListArguments interface.
+// CMICmdCmdStackListLocals interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdBase.h"
+#include "MICmnMIValueList.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "stack-info-depth".
+// Gotchas: None.
+// Authors: Illya Rudkin 21/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdStackInfoDepth : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdStackInfoDepth( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdStackInfoDepth( void );
+
+// Attributes:
+private:
+ MIuint m_nThreadFrames;
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgMaxDepth; // Not handled by *this command
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "stack-list-frames".
+// Gotchas: None.
+// Authors: Illya Rudkin 21/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdStackListFrames : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdStackListFrames( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdStackListFrames( void );
+
+// Typedefs:
+private:
+ typedef std::vector< CMICmnMIValueResult > VecMIValueResult_t;
+
+// Attributes:
+private:
+ MIuint m_nThreadFrames;
+ VecMIValueResult_t m_vecMIValueResult;
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgFrameLow;
+ const CMIUtilString m_constStrArgFrameHigh;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "stack-list-arguments".
+// Gotchas: None.
+// Authors: Illya Rudkin 24/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdStackListArguments : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdStackListArguments( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdStackListArguments( void );
+
+// Attributes:
+private:
+ bool m_bThreadInvalid; // True = yes invalid thread, false = thread object valid
+ CMICmnMIValueList m_miValueList;
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "stack-list-locals".
+// Gotchas: None.
+// Authors: Illya Rudkin 24/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdStackListLocals : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdStackListLocals( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdStackListLocals( void );
+
+// Attributes:
+private:
+ bool m_bThreadInvalid; // True = yes invalid thread, false = thread object valid
+ CMICmnMIValueList m_miValueList;
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command
+};
+
diff --git a/tools/lldb-mi/MICmdCmdSupportInfo.cpp b/tools/lldb-mi/MICmdCmdSupportInfo.cpp
new file mode 100644
index 000000000000..e6f96f094e58
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdSupportInfo.cpp
@@ -0,0 +1,129 @@
+//===-- MICmdCmdSupportListInfo.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdSupportListInfo.cpp
+//
+// Overview: CMICmdCmdSupportInfoMiCmdQuery implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdCmdSupportInfo.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnMIValueTuple.h"
+#include "MICmdArgValString.h"
+#include "MICmdFactory.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdSupportInfoMiCmdQuery constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdSupportInfoMiCmdQuery::CMICmdCmdSupportInfoMiCmdQuery( void )
+: m_bCmdFound( false )
+, m_constStrArgCmdName( "cmd_name" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "info-gdb-mi-command";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdSupportInfoMiCmdQuery::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdSupportInfoMiCmdQuery destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdSupportInfoMiCmdQuery::~CMICmdCmdSupportInfoMiCmdQuery( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdSupportInfoMiCmdQuery::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgCmdName, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdSupportInfoMiCmdQuery::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgNamedCmdName, String, m_constStrArgCmdName );
+ const CMIUtilString & rCmdToQuery( pArgNamedCmdName->GetValue() );
+ const MIuint nLen = rCmdToQuery.length();
+ const CMICmdFactory & rCmdFactory = CMICmdFactory::Instance();
+ if( (nLen > 1) && (rCmdToQuery[ 0 ] == '-') )
+ m_bCmdFound = rCmdFactory.CmdExist( rCmdToQuery.substr( 1, nLen - 1 ).c_str() );
+ else
+ m_bCmdFound = rCmdFactory.CmdExist( rCmdToQuery );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdSupportInfoMiCmdQuery::Acknowledge( void )
+{
+ const CMICmnMIValueConst miValueConst( m_bCmdFound ? "true" : "false" );
+ const CMICmnMIValueResult miValueResult( "exists", miValueConst );
+ const CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueResult miValueResult2( "command", miValueTuple );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult2 );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdSupportInfoMiCmdQuery::CreateSelf( void )
+{
+ return new CMICmdCmdSupportInfoMiCmdQuery();
+}
diff --git a/tools/lldb-mi/MICmdCmdSupportInfo.h b/tools/lldb-mi/MICmdCmdSupportInfo.h
new file mode 100644
index 000000000000..2633e99ce10e
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdSupportInfo.h
@@ -0,0 +1,69 @@
+//===-- MICmdCmdSupportInfo.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdSupportInfo.h
+//
+// Overview: CMICmdCmdSupportInfoMiCmdQuery interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdBase.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "info-gdb-mi-command".
+// This command does not follow the MI documentation exactly.
+// Gotchas: None.
+// Authors: Illya Rudkin 06/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdSupportInfoMiCmdQuery : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdSupportInfoMiCmdQuery( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdSupportInfoMiCmdQuery( void );
+
+// Attributes:
+private:
+ bool m_bCmdFound; // True = query for the command in command factory found, false = not found not recognised
+ const CMIUtilString m_constStrArgCmdName;
+};
+
diff --git a/tools/lldb-mi/MICmdCmdSupportList.cpp b/tools/lldb-mi/MICmdCmdSupportList.cpp
new file mode 100644
index 000000000000..2e4beb3edc85
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdSupportList.cpp
@@ -0,0 +1,102 @@
+//===-- MICmdCmdSupportList.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdSupportList.cpp
+//
+// Overview: CMICmdCmdSupportListFeatures implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdCmdSupportList.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnMIValueList.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdSupportListFeatures constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdSupportListFeatures::CMICmdCmdSupportListFeatures( void )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "list-features";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdSupportListFeatures::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdSupportListFeatures destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdSupportListFeatures::~CMICmdCmdSupportListFeatures( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdSupportListFeatures::Execute( void )
+{
+ // Do nothing
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdSupportListFeatures::Acknowledge( void )
+{
+ const CMICmnMIValueConst miValueConst( "data-read-memory-bytes" );
+ const CMICmnMIValueList miValueList( miValueConst );
+ const CMICmnMIValueResult miValueResult( "features", miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdSupportListFeatures::CreateSelf( void )
+{
+ return new CMICmdCmdSupportListFeatures();
+}
diff --git a/tools/lldb-mi/MICmdCmdSupportList.h b/tools/lldb-mi/MICmdCmdSupportList.h
new file mode 100644
index 000000000000..d9909a88997f
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdSupportList.h
@@ -0,0 +1,63 @@
+//===-- MICmdCmdSupportList.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdSupportList.h
+//
+// Overview: CMICmdCmdSupportListFeatures interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdBase.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "list-features".
+// This command does not follow the MI documentation exactly.
+// Gotchas: None.
+// Authors: Illya Rudkin 03/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdSupportListFeatures : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdSupportListFeatures( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdSupportListFeatures( void );
+};
+
diff --git a/tools/lldb-mi/MICmdCmdTarget.cpp b/tools/lldb-mi/MICmdCmdTarget.cpp
new file mode 100644
index 000000000000..60c1c5e4bba2
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdTarget.cpp
@@ -0,0 +1,217 @@
+//===-- MICmdCmdTarget.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdTarget.cpp
+//
+// Overview: CMICmdCmdTargetSelect implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third Party Headers:
+#include <lldb/API/SBStream.h>
+#include <lldb/API/SBCommandInterpreter.h>
+#include <lldb/API/SBCommandReturnObject.h>
+
+// In-house headers:
+#include "MICmdCmdTarget.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnMIOutOfBandRecord.h"
+#include "MICmnLLDBDebugger.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MICmdArgValString.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdTargetSelect constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdTargetSelect::CMICmdCmdTargetSelect( void )
+: m_constStrArgNamedType( "type" )
+, m_constStrArgNamedParameters( "parameters" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "target-select";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdTargetSelect::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdTargetSelect destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdTargetSelect::~CMICmdCmdTargetSelect( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdTargetSelect::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedType, true, true )) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgNamedParameters, true, true )) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Synopsis: -target-select type parameters ...
+// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdTargetSelect::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgType, String, m_constStrArgNamedType );
+ CMICMDBASE_GETOPTION( pArgParameters, String, m_constStrArgNamedParameters );
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+
+ // Check we have a valid target
+ // Note: target created via 'file-exec-and-symbols' command
+ if( !rSessionInfo.m_lldbTarget.IsValid() )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_TARGET_CURRENT ), m_cmdData.strMiCmd.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ // Verify that we are executing remotely
+ const CMIUtilString & rRemoteType( pArgType->GetValue() );
+ if( rRemoteType != "remote" )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_TARGET_TYPE ), m_cmdData.strMiCmd.c_str(), rRemoteType.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ // Create a URL pointing to the remote gdb stub
+ const CMIUtilString strUrl = CMIUtilString::Format( "connect://%s", pArgParameters->GetValue().c_str() );
+
+ // Ask LLDB to collect to the target port
+ const MIchar * pPlugin( "gdb-remote" );
+ lldb::SBError error;
+ lldb::SBProcess process = rSessionInfo.m_lldbTarget.ConnectRemote( rSessionInfo.m_rLlldbListener, strUrl.c_str(), pPlugin, error );
+
+ // Verify that we have managed to connect successfully
+ lldb::SBStream errMsg;
+ if( !process.IsValid() )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_INVALID_TARGET_PLUGIN ), m_cmdData.strMiCmd.c_str(), errMsg.GetData() ) );
+ return MIstatus::failure;
+ }
+ if( error.Fail() )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_CONNECT_TO_TARGET ), m_cmdData.strMiCmd.c_str(), errMsg.GetData() ) );
+ return MIstatus::failure;
+ }
+
+ // Save the process in the session info
+ // Note: Order is important here since this process handle may be used by CMICmnLLDBDebugHandleEvents
+ // which can fire when interpreting via HandleCommand() below.
+ rSessionInfo.m_lldbProcess = process;
+
+ // Set the environment path if we were given one
+ CMIUtilString strWkDir;
+ if( rSessionInfo.SharedDataRetrieve< CMIUtilString >( rSessionInfo.m_constStrSharedDataKeyWkDir, strWkDir ) )
+ {
+ lldb::SBDebugger & rDbgr = rSessionInfo.m_rLldbDebugger;
+ if( !rDbgr.SetCurrentPlatformSDKRoot( strWkDir.c_str() ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_FNFAILED ), m_cmdData.strMiCmd.c_str(), "target-select" ) );
+ return MIstatus::failure;
+ }
+ }
+
+ // Set the shared object path if we were given one
+ CMIUtilString strSolibPath;
+ if( rSessionInfo.SharedDataRetrieve< CMIUtilString >( rSessionInfo.m_constStrSharedDataSolibPath, strSolibPath ) )
+ {
+ lldb::SBDebugger & rDbgr = rSessionInfo.m_rLldbDebugger;
+ lldb::SBCommandInterpreter cmdIterpreter = rDbgr.GetCommandInterpreter();
+
+ CMIUtilString strCmdString = CMIUtilString::Format( "target modules search-paths add . %s", strSolibPath.c_str() );
+
+ lldb::SBCommandReturnObject retObj;
+ cmdIterpreter.HandleCommand( strCmdString.c_str(), retObj, false );
+
+ if( !retObj.Succeeded() )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_FNFAILED ), m_cmdData.strMiCmd.c_str(), "target-select" ) );
+ return MIstatus::failure;
+ }
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdTargetSelect::Acknowledge( void )
+{
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Connected );
+ m_miResultRecord = miRecordResult;
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID();
+ // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' because it is using LLDB debugger
+ // Give the client '=thread-group-started,id="i1"'
+ m_bHasResultRecordExtra = true;
+ const CMICmnMIValueConst miValueConst2( "i1" );
+ const CMICmnMIValueResult miValueResult2( "id", miValueConst2 );
+ const CMIUtilString strPid( CMIUtilString::Format( "%lld", pid ) );
+ const CMICmnMIValueConst miValueConst( strPid );
+ const CMICmnMIValueResult miValueResult( "pid", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2 );
+ miOutOfBand.Add( miValueResult );
+ m_miResultRecordExtra = miOutOfBand.GetString();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdTargetSelect::CreateSelf( void )
+{
+ return new CMICmdCmdTargetSelect();
+}
diff --git a/tools/lldb-mi/MICmdCmdTarget.h b/tools/lldb-mi/MICmdCmdTarget.h
new file mode 100644
index 000000000000..f904f20ee4f6
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdTarget.h
@@ -0,0 +1,70 @@
+//===-- MICmdCmdTarget.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdTarget.h
+//
+// Overview: CMICmdCmdTargetSelect interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdBase.h"
+#include "MICmnMIValueTuple.h"
+#include "MICmnMIValueList.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "target-select".
+// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation
+// Gotchas: None.
+// Authors: Illya Rudkin 05/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdTargetSelect : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdTargetSelect( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdTargetSelect( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgNamedType;
+ const CMIUtilString m_constStrArgNamedParameters;
+};
diff --git a/tools/lldb-mi/MICmdCmdThread.cpp b/tools/lldb-mi/MICmdCmdThread.cpp
new file mode 100644
index 000000000000..8cfaae804931
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdThread.cpp
@@ -0,0 +1,207 @@
+//===-- MICmdCmdThread.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdThread.cpp
+//
+// Overview: CMICmdCmdThreadInfo implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third Party Headers:
+#include <lldb/API/SBBreakpointLocation.h>
+#include <lldb/API/SBThread.h>
+
+// In-house headers:
+#include "MICmdCmdThread.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnLLDBDebugger.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MICmdArgValNumber.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdThreadInfo constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdThreadInfo::CMICmdCmdThreadInfo( void )
+: m_bSingleThread( false )
+, m_bThreadInvalid( true )
+, m_constStrArgNamedThreadId( "thread-id" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "thread-info";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdThreadInfo::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdThreadInfo destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdThreadInfo::~CMICmdCmdThreadInfo( void )
+{
+ m_vecMIValueTuple.clear();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdThreadInfo::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNamedThreadId, false, true )) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdThreadInfo::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgThreadId, Number, m_constStrArgNamedThreadId );
+ MIuint nThreadId = 0;
+ if( pArgThreadId->GetFound() && pArgThreadId->GetValid() )
+ {
+ m_bSingleThread = true;
+ nThreadId = static_cast< MIuint >( pArgThreadId->GetValue() );
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+ lldb::SBThread thread = rProcess.GetSelectedThread();
+
+ if( m_bSingleThread )
+ {
+ thread = rProcess.GetThreadByIndexID( nThreadId );
+ m_bThreadInvalid = thread.IsValid();
+ if( !m_bThreadInvalid )
+ return MIstatus::success;
+
+ CMICmnMIValueTuple miTuple;
+ if( !rSessionInfo.MIResponseFormThreadInfo3( m_cmdData, thread, miTuple ) )
+ return MIstatus::failure;
+
+ m_miValueTupleThread = miTuple;
+
+ return MIstatus::success;
+ }
+
+ // Multiple threads
+ m_vecMIValueTuple.clear();
+ const MIuint nThreads = rProcess.GetNumThreads();
+ for( MIuint i = 0; i < nThreads; i++ )
+ {
+ lldb::SBThread thread = rProcess.GetThreadAtIndex( i );
+ if( thread.IsValid() )
+ {
+ CMICmnMIValueTuple miTuple;
+ if( !rSessionInfo.MIResponseFormThreadInfo3( m_cmdData, thread, miTuple ) )
+ return MIstatus::failure;
+
+ m_vecMIValueTuple.push_back( miTuple );
+ }
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdThreadInfo::Acknowledge( void )
+{
+ if( m_bSingleThread )
+ {
+ if( !m_bThreadInvalid )
+ {
+ const CMICmnMIValueConst miValueConst( "invalid thread id" );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ // MI print "%s^done,threads=[{id=\"%d\",target-id=\"%s\",frame={},state=\"%s\"}]
+ const CMICmnMIValueList miValueList( m_miValueTupleThread );
+ const CMICmnMIValueResult miValueResult( "threads", miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ // Build up a list of thread information from tuples
+ VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin();
+ if( it == m_vecMIValueTuple.end() )
+ {
+ const CMICmnMIValueConst miValueConst( "[]" );
+ const CMICmnMIValueResult miValueResult( "threads", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+ CMICmnMIValueList miValueList( *it );
+ ++it;
+ while( it != m_vecMIValueTuple.end() )
+ {
+ const CMICmnMIValueTuple & rTuple( *it );
+ miValueList.Add( rTuple );
+
+ // Next
+ ++it;
+ }
+
+ const CMICmnMIValueResult miValueResult( "threads", miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdThreadInfo::CreateSelf( void )
+{
+ return new CMICmdCmdThreadInfo();
+}
diff --git a/tools/lldb-mi/MICmdCmdThread.h b/tools/lldb-mi/MICmdCmdThread.h
new file mode 100644
index 000000000000..33cd786a8cac
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdThread.h
@@ -0,0 +1,76 @@
+//===-- MICmdCmdThread.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdThread.h
+//
+// Overview: CMICmdCmdThreadInfo interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdBase.h"
+#include "MICmnMIValueTuple.h"
+#include "MICmnMIValueList.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "thread-info".
+// Gotchas: None.
+// Authors: Illya Rudkin 07/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdThreadInfo : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdThreadInfo( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdThreadInfo( void );
+
+// Typedefs:
+private:
+ typedef std::vector< CMICmnMIValueTuple > VecMIValueTuple_t;
+
+// Attributes:
+private:
+ CMICmnMIValueTuple m_miValueTupleThread;
+ bool m_bSingleThread; // True = yes single thread, false = multiple threads
+ bool m_bThreadInvalid; // True = invalid, false = ok
+ VecMIValueTuple_t m_vecMIValueTuple;
+ const CMIUtilString m_constStrArgNamedThreadId;
+};
diff --git a/tools/lldb-mi/MICmdCmdTrace.cpp b/tools/lldb-mi/MICmdCmdTrace.cpp
new file mode 100644
index 000000000000..8623db9eb151
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdTrace.cpp
@@ -0,0 +1,99 @@
+//===-- MICmdCmdTrace.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdTrace.cpp
+//
+// Overview: CMICmdCmdTraceStatus implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdCmdTrace.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdTraceStatus constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdTraceStatus::CMICmdCmdTraceStatus( void )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "trace-status";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdTraceStatus::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdTraceStatus destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdTraceStatus::~CMICmdCmdTraceStatus( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdTraceStatus::Execute( void )
+{
+ // Do nothing
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdTraceStatus::Acknowledge( void )
+{
+ const CMICmnMIValueConst miValueConst( MIRSRC( IDS_CMD_ERR_NOT_IMPLEMENTED ) );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdTraceStatus::CreateSelf( void )
+{
+ return new CMICmdCmdTraceStatus();
+}
diff --git a/tools/lldb-mi/MICmdCmdTrace.h b/tools/lldb-mi/MICmdCmdTrace.h
new file mode 100644
index 000000000000..2192d007a599
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdTrace.h
@@ -0,0 +1,61 @@
+//===-- MICmdCmdTrace.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdTrace.h
+//
+// Overview: CMICmdCmdTraceStatus interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdBase.h"
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "trace-status".
+// Gotchas: None.
+// Authors: Illya Rudkin 07/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdTraceStatus : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdTraceStatus( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdTraceStatus( void );
+};
diff --git a/tools/lldb-mi/MICmdCmdVar.cpp b/tools/lldb-mi/MICmdCmdVar.cpp
new file mode 100644
index 000000000000..346d69600760
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdVar.cpp
@@ -0,0 +1,1492 @@
+//===-- MICmdCmdVar.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdVar.cpp
+//
+// Overview: CMICmdCmdVarCreate implementation.
+// CMICmdCmdVarUpdate implementation.
+// CMICmdCmdVarDelete implementation.
+// CMICmdCmdVarAssign implementation.
+// CMICmdCmdVarSetFormat implementation.
+// CMICmdCmdVarListChildren implementation.
+// CMICmdCmdVarEvaluateExpression implementation.
+// CMICmdCmdVarInfoPathExpression implementation.
+// CMICmdCmdVarShowAttributes implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third Party Headers:
+#include <lldb/API/SBStream.h>
+#include <lldb/API/SBThread.h>
+
+// In-house headers:
+#include "MICmdCmdVar.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnLLDBDebugger.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MICmdArgValNumber.h"
+#include "MICmdArgValString.h"
+#include "MICmdArgValThreadGrp.h"
+#include "MICmdArgValOptionLong.h"
+#include "MICmdArgValOptionShort.h"
+#include "MICmdArgValListOfN.h"
+#include "MICmnLLDBProxySBValue.h"
+#include "MICmnLLDBUtilSBValue.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarCreate constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarCreate::CMICmdCmdVarCreate( void )
+: m_nChildren( 0 )
+, m_nMore( 0 )
+, m_nThreadId( 0 )
+, m_strType( "??" )
+, m_bValid( false )
+, m_strValue( "??" )
+, m_constStrArgThread( "thread" )
+, m_constStrArgThreadGroup( "thread-group" )
+, m_constStrArgFrame( "frame" )
+, m_constStrArgName( "name" )
+, m_constStrArgFrameAddr( "frame-addr" )
+, m_constStrArgExpression( "expression" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "var-create";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdVarCreate::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarCreate destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarCreate::~CMICmdCmdVarCreate( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarCreate::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgThreadGroup, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong( m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, false, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgFrameAddr, false, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgExpression, true, true, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarCreate::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread );
+ CMICMDBASE_GETOPTION( pArgFrame, OptionLong, m_constStrArgFrame );
+ CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
+ CMICMDBASE_GETOPTION( pArgFrameAddr, String, m_constStrArgFrameAddr );
+ CMICMDBASE_GETOPTION( pArgExpression, String, m_constStrArgExpression );
+
+ // Retrieve the --thread option's thread ID (only 1)
+ MIuint64 nThreadId = UINT64_MAX;
+ if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) );
+ return MIstatus::failure;
+ }
+ m_nThreadId = nThreadId;
+
+ // Retrieve the --frame option's number
+ MIuint64 nFrame = UINT64_MAX;
+ if( !pArgFrame->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nFrame ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ const CMICmdArgValOptionLong::VecArgObjPtr_t & rVecFrameId( pArgFrame->GetExpectedOptions() );
+ CMICmdArgValOptionLong::VecArgObjPtr_t::const_iterator it2 = rVecFrameId.begin();
+ if( it2 != rVecFrameId.end() )
+ {
+ const CMICmdArgValNumber * pOption = static_cast< CMICmdArgValNumber * >( *it2 );
+ nFrame = pOption->GetValue();
+ }
+
+ bool bAutoName = false;
+ const CMIUtilString strArgName;
+ if( pArgName->GetFound() )
+ {
+ const CMIUtilString & rArg = pArgName->GetValue();
+ bAutoName = (rArg == "-");
+ }
+
+ const CMIUtilString & rStrExpression( pArgExpression->GetValue() );
+ m_strExpression = rStrExpression;
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ m_strVarName = "<unnamedvariable>";
+ if( bAutoName )
+ {
+ m_strVarName = CMIUtilString::Format( "var%u", CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet() );
+ CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc();
+ }
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+ lldb::SBThread thread = rProcess.GetThreadByIndexID( nThreadId );
+ lldb::SBFrame frame = thread.GetFrameAtIndex( nFrame );
+ lldb::SBValue value = frame.FindVariable( rStrExpression.c_str() );
+ if( !value.IsValid() )
+ value = frame.EvaluateExpression( rStrExpression.c_str() );
+ if( value.IsValid() )
+ {
+ m_bValid = true;
+ m_nChildren = value.GetNumChildren();
+ m_strType = CMICmnLLDBUtilSBValue( value ).GetTypeNameDisplay();
+
+ // This gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs
+ CMICmnLLDBDebugSessionInfoVarObj varObj( rStrExpression, m_strVarName, value );
+ m_strValue = varObj.GetValueFormatted();
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarCreate::Acknowledge( void )
+{
+ if( m_bValid )
+ {
+ // MI print "%s^done,name=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%llu\",has_more=\"%u\""
+ const CMICmnMIValueConst miValueConst( m_strVarName );
+ CMICmnMIValueResult miValueResultAll( "name", miValueConst );
+ const CMIUtilString strNumChild( CMIUtilString::Format( "%d", m_nChildren ) );
+ const CMICmnMIValueConst miValueConst2( strNumChild );
+ miValueResultAll.Add( "numchild", miValueConst2 );
+ const CMICmnMIValueConst miValueConst3( m_strValue );
+ miValueResultAll.Add( "value", miValueConst3 );
+ const CMICmnMIValueConst miValueConst4( m_strType );
+ miValueResultAll.Add( "type", miValueConst4 );
+ const CMIUtilString strThreadId( CMIUtilString::Format( "%llu", m_nThreadId ) );
+ const CMICmnMIValueConst miValueConst5( strThreadId );
+ miValueResultAll.Add( "thread-id", miValueConst5 );
+ const CMICmnMIValueConst miValueConst6( "0" );
+ miValueResultAll.Add( "has_more", miValueConst6 );
+
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResultAll );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+ }
+
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_CREATION_FAILED ), m_strExpression.c_str() ) );
+ CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdVarCreate::CreateSelf( void )
+{
+ return new CMICmdCmdVarCreate();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarUpdate constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarUpdate::CMICmdCmdVarUpdate( void )
+: m_constStrArgPrintValues( "print-values" )
+, m_constStrArgName( "name" )
+, m_bValueChangedArrayType( false )
+, m_bValueChangedCompositeType( false )
+, m_bValueChangedNormalType( false )
+, m_miValueList( true )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "var-update";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdVarUpdate::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarUpdate destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarUpdate::~CMICmdCmdVarUpdate( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarUpdate::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgPrintValues, false, false ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarUpdate::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
+
+ const CMIUtilString & rVarObjName( pArgName->GetValue() );
+ CMICmnLLDBDebugSessionInfoVarObj varObj;
+ if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ const CMIUtilString & rVarRealName( varObj.GetNameReal() ); MIunused( rVarRealName );
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
+ const bool bValid = rValue.IsValid();
+ if( bValid && rValue.GetValueDidChange() )
+ {
+ m_bValueChangedNormalType = true;
+ varObj.UpdateValue();
+ m_strValueName = rVarObjName;
+ return MIstatus::success;
+ }
+
+ // Examine an array type variable
+ if( !ExamineSBValueForChange( varObj, false, m_bValueChangedArrayType ) )
+ return MIstatus::failure;
+
+ // Handle composite types i.e. struct or arrays
+ const MIuint nChildren = rValue.GetNumChildren();
+ for( MIuint i = 0; i < nChildren; i++ )
+ {
+ lldb::SBValue member = rValue.GetChildAtIndex( i );
+ if( !member.IsValid() )
+ continue;
+
+ const CMIUtilString varName( CMIUtilString::Format( "%s.%s", rVarObjName.c_str(), member.GetName() ) );
+ if( member.GetValueDidChange() )
+ {
+ // Handle composite
+ const CMIUtilString strValue( CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted( member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural ) );
+ const CMIUtilString strInScope( member.IsInScope() ? "true" : "false" );
+ MIFormResponse( varName, strValue, strInScope );
+
+ m_bValueChangedCompositeType = true;
+ }
+ else
+ {
+ // Handle array of composites
+ CMICmnLLDBDebugSessionInfoVarObj varObj;
+ if( CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( varName, varObj ) )
+ {
+ bool bValueChanged = false;
+ if( ExamineSBValueForChange( varObj, true, bValueChanged ) )
+ {
+ if( bValueChanged && CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( varName, varObj ) )
+ {
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
+ const bool bValid = rValue.IsValid();
+ const CMIUtilString strValue( bValid ? varObj.GetValueFormatted() : "<unknown>" );
+ const CMIUtilString strInScope( (bValid && rValue.IsInScope()) ? "true" : "false" );
+ MIFormResponse( varName, strValue, strInScope );
+
+ m_bValueChangedCompositeType = true;
+ }
+ }
+ else
+ return MIstatus::failure;
+ }
+ }
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarUpdate::Acknowledge( void )
+{
+ if( m_bValueChangedArrayType || m_bValueChangedNormalType )
+ {
+ CMICmnLLDBDebugSessionInfoVarObj varObj;
+ CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( m_strValueName, varObj );
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
+ const bool bValid = rValue.IsValid();
+ const CMIUtilString strValue( bValid ? varObj.GetValueFormatted() : "<unknown>" );
+ const CMIUtilString strInScope( (bValid && rValue.IsInScope()) ? "true" : "false" );
+
+ // MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]"
+ const CMICmnMIValueConst miValueConst( m_strValueName );
+ CMICmnMIValueResult miValueResult( "name", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueConst miValueConst2( strValue );
+ CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
+ miValueTuple.Add( miValueResult2 );
+ const CMICmnMIValueConst miValueConst3( strInScope );
+ CMICmnMIValueResult miValueResult3( "in_scope", miValueConst3 );
+ miValueTuple.Add( miValueResult3 );
+ const CMICmnMIValueConst miValueConst4( "false" );
+ CMICmnMIValueResult miValueResult4( "type_changed", miValueConst4 );
+ miValueTuple.Add( miValueResult4 );
+ const CMICmnMIValueConst miValueConst5( "0" );
+ CMICmnMIValueResult miValueResult5( "has_more", miValueConst5 );
+ miValueTuple.Add( miValueResult5 );
+ const CMICmnMIValueList miValueList( miValueTuple );
+ CMICmnMIValueResult miValueResult6( "changelist", miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+ }
+ else if( m_bValueChangedCompositeType )
+ {
+ // MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"},{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]"
+ CMICmnMIValueResult miValueResult6( "changelist", m_miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 );
+ m_miResultRecord = miRecordResult;
+ }
+ else
+ {
+ // MI: "%s^done,changelist=[]"
+ const CMICmnMIValueList miValueList( true );
+ CMICmnMIValueResult miValueResult6( "changelist", miValueList );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdVarUpdate::CreateSelf( void )
+{
+ return new CMICmdCmdVarUpdate();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Form the MI response for multiple variables.
+// Type: Method.
+// Args: vrStrVarName - (R) Session var object's name.
+// vrStrValue - (R) Text version of the value held in the variable.
+// vrStrScope - (R) In scope "yes" or "no".
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarUpdate::MIFormResponse( const CMIUtilString & vrStrVarName, const CMIUtilString & vrStrValue, const CMIUtilString & vrStrScope )
+{
+ // MI print "[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]"
+ const CMICmnMIValueConst miValueConst( vrStrVarName );
+ CMICmnMIValueResult miValueResult( "name", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueConst miValueConst2( vrStrValue );
+ CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
+ bool bOk = miValueTuple.Add( miValueResult2 );
+ const CMICmnMIValueConst miValueConst3( vrStrScope );
+ CMICmnMIValueResult miValueResult3( "in_scope", miValueConst3 );
+ bOk = bOk && miValueTuple.Add( miValueResult3 );
+ const CMICmnMIValueConst miValueConst4( "false" );
+ CMICmnMIValueResult miValueResult4( "type_changed", miValueConst4 );
+ bOk = bOk && miValueTuple.Add( miValueResult4 );
+ const CMICmnMIValueConst miValueConst5( "0" );
+ CMICmnMIValueResult miValueResult5( "has_more", miValueConst5 );
+ bOk = bOk && miValueTuple.Add( miValueResult5 );
+ bOk = bOk && m_miValueList.Add( miValueTuple );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine if the var object is a array type variable. LLDB does not 'detect'
+// a value change for some types like elements in an array so have to re-evaluate
+// the expression again.
+// Type: Method.
+// Args: vrVarObj - (R) Session var object to examine.
+// vrwbChanged - (W) True = Is an array type and it changed,
+// False = Not an array type or not changed.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarUpdate::ExamineSBValueForChange( const CMICmnLLDBDebugSessionInfoVarObj & vrVarObj, const bool vbIgnoreVarType, bool & vrwbChanged )
+{
+ vrwbChanged = false;
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+ lldb::SBThread thread = rProcess.GetSelectedThread();
+ if( thread.GetNumFrames() == 0 )
+ {
+ return MIstatus::success;
+ }
+
+ const CMIUtilString & strVarObjParentName = vrVarObj.GetVarParentName();
+ lldb::SBFrame frame = thread.GetSelectedFrame();
+ const CMIUtilString & rExpression( vrVarObj.GetNameReal() );
+ CMIUtilString varExpression;
+ if( strVarObjParentName.empty() )
+ {
+ varExpression = rExpression;
+ }
+ else
+ {
+ CMICmnLLDBDebugSessionInfoVarObj varObjParent;
+ if( CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( strVarObjParentName, varObjParent ) )
+ varExpression = CMIUtilString::Format( "%s.%s", varObjParent.GetNameReal().c_str(), rExpression.c_str() );
+ else
+ {
+ // The parent is only assigned in the CMICmdCmdVarListChildren command, we have a problem, need to investigate
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), strVarObjParentName.c_str() ) );
+ return MIstatus::failure;
+ }
+ }
+
+ lldb::SBValue value = frame.EvaluateExpression( varExpression.c_str() );
+ if( !value.IsValid() )
+ value = frame.FindVariable( rExpression.c_str() );
+ if( value.IsValid() )
+ {
+ lldb::SBType valueType = value.GetType();
+ const lldb::BasicType eValueType = valueType.GetBasicType();
+ if( vbIgnoreVarType || (eValueType != lldb::BasicType::eBasicTypeInvalid) )
+ {
+ MIuint64 nPrevValue = 0;
+ MIuint64 nRevaluateValue = 0;
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrVarObj.GetValue() );
+ if( CMICmnLLDBProxySBValue::GetValueAsUnsigned( rValue, nPrevValue ) &&
+ CMICmnLLDBProxySBValue::GetValueAsUnsigned( value, nRevaluateValue ) &&
+ (nPrevValue != nRevaluateValue) )
+ {
+ // Have a value change so update the var object
+ vrwbChanged = true;
+ const CMICmnLLDBDebugSessionInfoVarObj varObj( rExpression, vrVarObj.GetName(), value, strVarObjParentName );
+ }
+ }
+ }
+
+ return MIstatus::success;
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarDelete constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarDelete::CMICmdCmdVarDelete( void )
+: m_constStrArgName( "name" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "var-delete";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdVarDelete::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarDelete::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarDelete destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarDelete::~CMICmdCmdVarDelete( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarDelete::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
+
+ const CMIUtilString & rVarObjName( pArgName->GetValue() );
+ CMICmnLLDBDebugSessionInfoVarObj::VarObjDelete( rVarObjName );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarDelete::Acknowledge( void )
+{
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdVarDelete::CreateSelf( void )
+{
+ return new CMICmdCmdVarDelete();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarAssign constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarAssign::CMICmdCmdVarAssign( void )
+: m_bOk( true )
+, m_constStrArgName( "name" )
+, m_constStrArgExpression( "expression" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "var-assign";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdVarAssign::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarAssign destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarAssign::~CMICmdCmdVarAssign( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarAssign::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgExpression, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarAssign::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
+ CMICMDBASE_GETOPTION( pArgExpression, String, m_constStrArgExpression );
+
+ const CMIUtilString & rVarObjName( pArgName->GetValue() );
+ const CMIUtilString & rExpression( pArgExpression->GetValue() );
+
+ CMICmnLLDBDebugSessionInfoVarObj varObj;
+ if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
+ return MIstatus::failure;
+ }
+ m_varObjName = rVarObjName;
+
+ CMIUtilString strExpression( rExpression.Trim() );
+ strExpression = strExpression.Trim( '"' );
+ lldb::SBValue & rValue( const_cast< lldb::SBValue & >( varObj.GetValue() ) );
+ m_bOk = rValue.SetValueFromCString( strExpression.c_str() );
+ if( m_bOk )
+ varObj.UpdateValue();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarAssign::Acknowledge( void )
+{
+ if( m_bOk )
+ {
+ // MI print "%s^done,value=\"%s\""
+ CMICmnLLDBDebugSessionInfoVarObj varObj;
+ CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( m_varObjName, varObj );
+ const CMICmnMIValueConst miValueConst( varObj.GetValueFormatted() );
+ const CMICmnMIValueResult miValueResult( "value", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+ }
+
+ const CMICmnMIValueConst miValueConst( "expression could not be evaluated" );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdVarAssign::CreateSelf( void )
+{
+ return new CMICmdCmdVarAssign();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarSetFormat constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarSetFormat::CMICmdCmdVarSetFormat( void )
+: m_constStrArgName( "name" )
+, m_constStrArgFormatSpec( "format-spec" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "var-set-format";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdVarSetFormat::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarSetFormat destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarSetFormat::~CMICmdCmdVarSetFormat( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarSetFormat::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgFormatSpec, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarSetFormat::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
+ CMICMDBASE_GETOPTION( pArgFormatSpec, String, m_constStrArgFormatSpec );
+
+ const CMIUtilString & rVarObjName( pArgName->GetValue() );
+ const CMIUtilString & rExpression( pArgFormatSpec->GetValue() );
+
+ CMICmnLLDBDebugSessionInfoVarObj varObj;
+ if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
+ return MIstatus::failure;
+ }
+ if( !varObj.SetVarFormat( CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForString( rExpression ) ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_ENUM_INVALID ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str(), rExpression.c_str() ) );
+ return MIstatus::failure;
+ }
+ varObj.UpdateValue();
+
+ m_varObjName = rVarObjName;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarSetFormat::Acknowledge( void )
+{
+ // MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]"
+ CMICmnLLDBDebugSessionInfoVarObj varObj;
+ CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( m_varObjName, varObj );
+ const CMICmnMIValueConst miValueConst( m_varObjName );
+ const CMICmnMIValueResult miValueResult( "name", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueConst miValueConst2( varObj.GetValueFormatted() );
+ const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
+ miValueTuple.Add( miValueResult2 );
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
+ const CMICmnMIValueConst miValueConst3( rValue.IsInScope() ? "true" : "false" );
+ const CMICmnMIValueResult miValueResult3( "in_scope", miValueConst3 );
+ miValueTuple.Add( miValueResult3 );
+ const CMICmnMIValueConst miValueConst4( "false" );
+ const CMICmnMIValueResult miValueResult4( "type_changed", miValueConst4 );
+ miValueTuple.Add( miValueResult4 );
+ const CMICmnMIValueConst miValueConst5( "0" );
+ const CMICmnMIValueResult miValueResult5( "type_changed", miValueConst5 );
+ miValueTuple.Add( miValueResult5 );
+ const CMICmnMIValueList miValueList( miValueTuple );
+ const CMICmnMIValueResult miValueResult6( "changelist", miValueList );
+
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdVarSetFormat::CreateSelf( void )
+{
+ return new CMICmdCmdVarSetFormat();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarListChildren constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarListChildren::CMICmdCmdVarListChildren( void )
+: m_bValueValid( false )
+, m_nChildren( 0 )
+, m_constStrArgPrintValues( "print-values" )
+, m_constStrArgName( "name" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "var-list-children";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdVarListChildren::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarListChildren destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarListChildren::~CMICmdCmdVarListChildren( void )
+{
+ m_vecMiValueResult.clear();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarListChildren::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgPrintValues, false, false ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarListChildren::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
+
+ const CMIUtilString & rVarObjName( pArgName->GetValue() );
+ CMICmnLLDBDebugSessionInfoVarObj varObj;
+ if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
+ m_bValueValid = rValue.IsValid();
+ if( !m_bValueValid )
+ return MIstatus::success;
+
+ m_vecMiValueResult.clear();
+ m_nChildren = rValue.GetNumChildren();
+ for( MIuint i = 0; i < m_nChildren; i++ )
+ {
+ lldb::SBValue member = rValue.GetChildAtIndex( i );
+ if( !member.IsValid() )
+ continue;
+ const CMICmnLLDBUtilSBValue utilValue( member );
+ const CMIUtilString strExp = utilValue.GetName();
+ const CMIUtilString name( CMIUtilString::Format( "%s.%s", rVarObjName.c_str(), strExp.c_str() ) );
+ const MIuint nChildren = member.GetNumChildren();
+ const CMIUtilString strThreadId( CMIUtilString::Format( "%u", member.GetThread().GetIndexID() ) );
+
+ // Varobj gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs
+ CMICmnLLDBDebugSessionInfoVarObj var( strExp, name, member, rVarObjName );
+
+ // MI print "child={name=\"%s\",exp=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%u\",has_more=\"%u\"}"
+ const CMICmnMIValueConst miValueConst( name );
+ const CMICmnMIValueResult miValueResult( "name", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueConst miValueConst2( strExp );
+ const CMICmnMIValueResult miValueResult2( "exp", miValueConst2 );
+ miValueTuple.Add( miValueResult2 );
+ const CMIUtilString strNumChild( CMIUtilString::Format( "%d", nChildren ) );
+ const CMICmnMIValueConst miValueConst3( strNumChild );
+ const CMICmnMIValueResult miValueResult3( "numchild", miValueConst3 );
+ miValueTuple.Add( miValueResult3 );
+ const CMICmnMIValueConst miValueConst5( utilValue.GetTypeNameDisplay() );
+ const CMICmnMIValueResult miValueResult5( "type", miValueConst5 );
+ miValueTuple.Add( miValueResult5 );
+ const CMICmnMIValueConst miValueConst6( strThreadId );
+ const CMICmnMIValueResult miValueResult6( "thread-id", miValueConst6 );
+ miValueTuple.Add( miValueResult6 );
+ const CMICmnMIValueConst miValueConst7( "0" );
+ const CMICmnMIValueResult miValueResult7( "has_more", miValueConst7 );
+ miValueTuple.Add( miValueResult7 );
+ const CMICmnMIValueResult miValueResult8( "child", miValueTuple );
+ m_vecMiValueResult.push_back( miValueResult8 );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarListChildren::Acknowledge( void )
+{
+ if( m_bValueValid )
+ {
+ // MI print "%s^done,numchild=\"%u\",children=[]""
+ const CMIUtilString strNumChild( CMIUtilString::Format( "%u", m_nChildren ) );
+ const CMICmnMIValueConst miValueConst( strNumChild );
+ CMICmnMIValueResult miValueResult( "numchild", miValueConst );
+
+ VecMIValueResult_t::const_iterator it = m_vecMiValueResult.begin();
+ if( it == m_vecMiValueResult.end() )
+ {
+ const CMICmnMIValueConst miValueConst( "[]" );
+ miValueResult.Add( "children", miValueConst );
+ }
+ else
+ {
+ CMICmnMIValueList miValueList( *it );
+ ++it;
+ while( it != m_vecMiValueResult.end() )
+ {
+ const CMICmnMIValueResult & rResult( *it );
+ miValueList.Add( rResult );
+
+ // Next
+ ++it;
+ }
+ miValueResult.Add( "children", miValueList );
+ }
+
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ // MI print "%s^done,numchild=\"0\""
+ const CMICmnMIValueConst miValueConst( "0" );
+ const CMICmnMIValueResult miValueResult( "numchild", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdVarListChildren::CreateSelf( void )
+{
+ return new CMICmdCmdVarListChildren();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarEvaluateExpression constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarEvaluateExpression::CMICmdCmdVarEvaluateExpression( void )
+: m_bValueValid( true )
+, m_constStrArgFormatSpec( "-f" )
+, m_constStrArgName( "name" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "var-evaluate-expression";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdVarEvaluateExpression::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarEvaluateExpression destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarEvaluateExpression::~CMICmdCmdVarEvaluateExpression( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarEvaluateExpression::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgFormatSpec, false, false, CMICmdArgValListBase::eArgValType_String, 1 ) ) );
+ bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarEvaluateExpression::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
+
+ const CMIUtilString & rVarObjName( pArgName->GetValue() );
+ CMICmnLLDBDebugSessionInfoVarObj varObj;
+ if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
+ m_bValueValid = rValue.IsValid();
+ if( !m_bValueValid )
+ return MIstatus::success;
+
+ m_varObjName = rVarObjName;
+ varObj.UpdateValue();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarEvaluateExpression::Acknowledge( void )
+{
+ if( m_bValueValid )
+ {
+ CMICmnLLDBDebugSessionInfoVarObj varObj;
+ CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( m_varObjName, varObj );
+ const CMICmnMIValueConst miValueConst( varObj.GetValueFormatted() );
+ const CMICmnMIValueResult miValueResult( "value", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ const CMICmnMIValueConst miValueConst( "variable invalid" );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdVarEvaluateExpression::CreateSelf( void )
+{
+ return new CMICmdCmdVarEvaluateExpression();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarInfoPathExpression constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarInfoPathExpression::CMICmdCmdVarInfoPathExpression( void )
+: m_bValueValid( true )
+, m_constStrArgName( "name" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "var-info-path-expression";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdVarInfoPathExpression::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarInfoPathExpression destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarInfoPathExpression::~CMICmdCmdVarInfoPathExpression( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarInfoPathExpression::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarInfoPathExpression::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
+
+ const CMIUtilString & rVarObjName( pArgName->GetValue() );
+ CMICmnLLDBDebugSessionInfoVarObj varObj;
+ if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( varObj.GetValue() );
+ m_bValueValid = rValue.IsValid();
+ if( !m_bValueValid )
+ return MIstatus::success;
+
+ lldb::SBStream stream;
+ if( !rValue.GetExpressionPath( stream, true ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ const MIchar * pPathExpression = stream.GetData();
+ if( pPathExpression == nullptr )
+ {
+ // Build expression from what we do know
+ m_strPathExpression = varObj.GetNameReal();
+ return MIstatus::success;
+ }
+
+ // Has LLDB returned a var signature of it's own
+ if( pPathExpression[ 0 ] != '$' )
+ {
+ m_strPathExpression = pPathExpression;
+ return MIstatus::success;
+ }
+
+ // Build expression from what we do know
+ const CMIUtilString & rVarParentName( varObj.GetVarParentName() );
+ if( rVarParentName.empty() )
+ {
+ m_strPathExpression = varObj.GetNameReal();
+ }
+ else
+ {
+ CMICmnLLDBDebugSessionInfoVarObj varObjParent;
+ if( !CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarParentName, varObjParent ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarParentName.c_str() ) );
+ return MIstatus::failure;
+ }
+ m_strPathExpression = CMIUtilString::Format( "%s.%s", varObjParent.GetNameReal().c_str(), varObj.GetNameReal().c_str() );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarInfoPathExpression::Acknowledge( void )
+{
+ if( m_bValueValid )
+ {
+ const CMICmnMIValueConst miValueConst( m_strPathExpression );
+ const CMICmnMIValueResult miValueResult( "path_expr", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+ return MIstatus::success;
+ }
+
+ const CMICmnMIValueConst miValueConst( "variable invalid" );
+ const CMICmnMIValueResult miValueResult( "msg", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdVarInfoPathExpression::CreateSelf( void )
+{
+ return new CMICmdCmdVarInfoPathExpression();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarShowAttributes constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarShowAttributes::CMICmdCmdVarShowAttributes( void )
+: m_constStrArgName( "name" )
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "var-show-attributes";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdVarShowAttributes::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdVarShowAttributes destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdVarShowAttributes::~CMICmdCmdVarShowAttributes( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarShowAttributes::ParseArgs( void )
+{
+ bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValString( m_constStrArgName, true, true ) ) );
+ return (bOk && ParseValidateCmdOptions() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarShowAttributes::Execute( void )
+{
+ CMICMDBASE_GETOPTION( pArgName, String, m_constStrArgName );
+
+ const CMIUtilString & rVarObjName( pArgName->GetValue() );
+ CMICmnLLDBDebugSessionInfoVarObj varObj;
+ if( CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( rVarObjName, varObj ) )
+ {
+ SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdCmdVarShowAttributes::Acknowledge( void )
+{
+ // MI output: "%s^done,status=\"editable\"]"
+ const CMICmnMIValueConst miValueConst( "editable" );
+ const CMICmnMIValueResult miValueResult( "status", miValueConst );
+ const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult );
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase * CMICmdCmdVarShowAttributes::CreateSelf( void )
+{
+ return new CMICmdCmdVarShowAttributes();
+}
diff --git a/tools/lldb-mi/MICmdCmdVar.h b/tools/lldb-mi/MICmdCmdVar.h
new file mode 100644
index 000000000000..387cfc4ada83
--- /dev/null
+++ b/tools/lldb-mi/MICmdCmdVar.h
@@ -0,0 +1,382 @@
+//===-- MICmdCmdVar.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCmdVar.h
+//
+// Overview: CMICmdCmdVarCreate interface.
+// CMICmdCmdVarUpdate interface.
+// CMICmdCmdVarDelete interface.
+// CMICmdCmdVarAssign interface.
+// CMICmdCmdVarSetFormat interface.
+// CMICmdCmdVarListChildren interface.
+// CMICmdCmdVarEvaluateExpression interface.
+// CMICmdCmdVarInfoPathExpression interface.
+// CMICmdCmdVarShowAttributes interface.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
+// command class as an example.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmdBase.h"
+#include "MICmnMIValueTuple.h"
+#include "MICmnMIValueList.h"
+#include "MICmnLLDBDebugSessionInfoVarObj.h"
+
+// Declarations:
+class CMICmnLLDBDebugSessionInfoVarObj;
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "var-create".
+// Gotchas: None.
+// Authors: Illya Rudkin 24/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdVarCreate : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdVarCreate( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdVarCreate( void );
+
+// Attribute:
+private:
+ CMIUtilString m_strVarName;
+ MIuint m_nChildren;
+ MIuint m_nMore;
+ MIuint64 m_nThreadId;
+ CMIUtilString m_strType;
+ bool m_bValid; // True = Variable is valid, false = not valid
+ CMIUtilString m_strExpression;
+ CMIUtilString m_strValue;
+ const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgThreadGroup; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option
+ const CMIUtilString m_constStrArgName;
+ const CMIUtilString m_constStrArgFrameAddr;
+ const CMIUtilString m_constStrArgExpression;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "var-update".
+// Gotchas: None.
+// Authors: Illya Rudkin 25/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdVarUpdate : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdVarUpdate( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdVarUpdate( void );
+
+// Methods:
+private:
+ bool ExamineSBValueForChange( const CMICmnLLDBDebugSessionInfoVarObj & vrVarObj, const bool vbIgnoreVarType, bool & vrwbChanged );
+ bool MIFormResponse( const CMIUtilString & vrStrVarName, const CMIUtilString & vrStrValue, const CMIUtilString & vrStrScope );
+
+// Attribute:
+private:
+ CMIUtilString m_strValueName;
+ const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command
+ const CMIUtilString m_constStrArgName;
+ bool m_bValueChangedArrayType; // True = yes value changed, false = no change
+ bool m_bValueChangedCompositeType; // True = yes value changed, false = no change
+ bool m_bValueChangedNormalType; // True = yes value changed, false = no change
+ CMICmnMIValueList m_miValueList;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "var-delete".
+// Gotchas: None.
+// Authors: Illya Rudkin 25/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdVarDelete : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdVarDelete( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdVarDelete( void );
+
+// Attribute:
+private:
+ const CMIUtilString m_constStrArgName;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "var-assign".
+// Gotchas: None.
+// Authors: Illya Rudkin 25/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdVarAssign : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdVarAssign( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdVarAssign( void );
+
+// Attributes:
+private:
+ bool m_bOk; // True = success, false = failure
+ CMIUtilString m_varObjName;
+ const CMIUtilString m_constStrArgName;
+ const CMIUtilString m_constStrArgExpression;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "var-set-format".
+// Gotchas: None.
+// Authors: Illya Rudkin 26/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdVarSetFormat : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdVarSetFormat( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdVarSetFormat( void );
+
+// Attributes:
+private:
+ CMIUtilString m_varObjName;
+ const CMIUtilString m_constStrArgName;
+ const CMIUtilString m_constStrArgFormatSpec;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "var-list-children".
+// Gotchas: None.
+// Authors: Illya Rudkin 26/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdVarListChildren : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdVarListChildren( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdVarListChildren( void );
+
+// Typedefs:
+private:
+ typedef std::vector< CMICmnMIValueResult > VecMIValueResult_t;
+
+// Attributes:
+private:
+ bool m_bValueValid; // True = yes SBValue object is valid, false = not valid
+ VecMIValueResult_t m_vecMiValueResult;
+ MIuint m_nChildren;
+ const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command
+ const CMIUtilString m_constStrArgName;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "var-evaluate-expression".
+// Gotchas: None.
+// Authors: Illya Rudkin 26/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdVarEvaluateExpression : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdVarEvaluateExpression( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdVarEvaluateExpression( void );
+
+// Attributes:
+private:
+ bool m_bValueValid; // True = yes SBValue object is valid, false = not valid
+ CMIUtilString m_varObjName;
+ const CMIUtilString m_constStrArgFormatSpec; // Not handled by *this command
+ const CMIUtilString m_constStrArgName;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "var-info-path-expression".
+// Gotchas: None.
+// Authors: Illya Rudkin 26/03/2014.
+// Changes: None.
+//--
+class CMICmdCmdVarInfoPathExpression : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdVarInfoPathExpression( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdVarInfoPathExpression( void );
+
+// Attributes:
+private:
+ bool m_bValueValid; // True = yes SBValue object is valid, false = not valid
+ CMIUtilString m_strPathExpression;
+ const CMIUtilString m_constStrArgName;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "var-show-attributes".
+// Gotchas: None.
+// Authors: Illya Rudkin 19/05/2014.
+// Changes: None.
+//--
+class CMICmdCmdVarShowAttributes : public CMICmdBase
+{
+// Statics:
+public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase * CreateSelf( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmdCmdVarShowAttributes( void );
+
+// Overridden:
+public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute( void );
+ virtual bool Acknowledge( void );
+ virtual bool ParseArgs( void );
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdVarShowAttributes( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrArgName;
+};
+
diff --git a/tools/lldb-mi/MICmdCommands.cpp b/tools/lldb-mi/MICmdCommands.cpp
new file mode 100644
index 000000000000..4187b059b395
--- /dev/null
+++ b/tools/lldb-mi/MICmdCommands.cpp
@@ -0,0 +1,135 @@
+//===-- MICmdCommands.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCommands.cpp
+//
+// Overview: MI command are registered with the MI command factory.
+//
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdCommands.h"
+#include "MICmdFactory.h"
+#include "MICmdCmd.h"
+#include "MICmdCmdBreak.h"
+#include "MICmdCmdData.h"
+#include "MICmdCmdEnviro.h"
+#include "MICmdCmdExec.h"
+#include "MICmdCmdFile.h"
+#include "MICmdCmdGdbInfo.h"
+#include "MICmdCmdGdbSet.h"
+#include "MICmdCmdGdbThread.h"
+#include "MICmdCmdMiscellanous.h"
+#include "MICmdCmdStack.h"
+#include "MICmdCmdSupportInfo.h"
+#include "MICmdCmdSupportList.h"
+#include "MICmdCmdTarget.h"
+#include "MICmdCmdThread.h"
+#include "MICmdCmdTrace.h"
+#include "MICmdCmdVar.h"
+
+namespace MICmnCommands
+{
+ template< typename T >
+ static bool Register( void );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Command to command factory registration function.
+// Type: Template function.
+// Args: typename T - A command type class.
+// Return: bool - True = yes command is registered, false = command failed to register.
+// Throws: None.
+//--
+template< typename T >
+static bool MICmnCommands::Register( void )
+{
+ static CMICmdFactory & rCmdFactory = CMICmdFactory::Instance();
+ const CMIUtilString strMiCmd = T().GetMiCmd();
+ CMICmdFactory::CmdCreatorFnPtr fn = T().GetCmdCreatorFn();
+ return rCmdFactory.CmdRegister( strMiCmd, fn );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Register commands with MI command factory
+// Type: Function.
+// Args: None.
+// Return: bool - True = yes all commands are registered,
+// false = one or more commands failed to register.
+// Throws: None.
+//--
+bool MICmnCommands::RegisterAll( void )
+{
+ bool bOk = MIstatus::success;
+
+ bOk &= Register< CMICmdCmdSupportInfoMiCmdQuery >();
+ bOk &= Register< CMICmdCmdBreakAfter >();
+ bOk &= Register< CMICmdCmdBreakCondition >();
+ bOk &= Register< CMICmdCmdBreakDelete >();
+ bOk &= Register< CMICmdCmdBreakDisable >();
+ bOk &= Register< CMICmdCmdBreakEnable >();
+ bOk &= Register< CMICmdCmdBreakInsert >();
+ bOk &= Register< CMICmdCmdDataDisassemble >();
+ bOk &= Register< CMICmdCmdDataEvaluateExpression >();
+ bOk &= Register< CMICmdCmdDataReadMemoryBytes >();
+ bOk &= Register< CMICmdCmdDataReadMemory >();
+ bOk &= Register< CMICmdCmdDataListRegisterNames >();
+ bOk &= Register< CMICmdCmdDataListRegisterValues >();
+ bOk &= Register< CMICmdCmdDataWriteMemory >();
+ bOk &= Register< CMICmdCmdEnablePrettyPrinting >();
+ bOk &= Register< CMICmdCmdEnvironmentCd >();
+ bOk &= Register< CMICmdCmdExecContinue >();
+ bOk &= Register< CMICmdCmdExecInterrupt >();
+ bOk &= Register< CMICmdCmdExecFinish >();
+ bOk &= Register< CMICmdCmdExecNext >();
+ bOk &= Register< CMICmdCmdExecNextInstruction >();
+ bOk &= Register< CMICmdCmdExecRun >();
+ bOk &= Register< CMICmdCmdExecStep >();
+ bOk &= Register< CMICmdCmdExecStepInstruction >();
+ bOk &= Register< CMICmdCmdFileExecAndSymbols >();
+ bOk &= Register< CMICmdCmdGdbExit >();
+ bOk &= Register< CMICmdCmdGdbInfo >();
+ bOk &= Register< CMICmdCmdGdbSet >();
+ bOk &= Register< CMICmdCmdGdbThread >();
+ bOk &= Register< CMICmdCmdInferiorTtySet >();
+ bOk &= Register< CMICmdCmdInterpreterExec >();
+ bOk &= Register< CMICmdCmdListThreadGroups >();
+ bOk &= Register< CMICmdCmdSource >();
+ bOk &= Register< CMICmdCmdStackInfoDepth >();
+ bOk &= Register< CMICmdCmdStackListFrames >();
+ bOk &= Register< CMICmdCmdStackListArguments >();
+ bOk &= Register< CMICmdCmdStackListLocals >();
+ bOk &= Register< CMICmdCmdSupportListFeatures >();
+ bOk &= Register< CMICmdCmdTargetSelect >();
+ bOk &= Register< CMICmdCmdThreadInfo >();
+ bOk &= Register< CMICmdCmdVarAssign >();
+ bOk &= Register< CMICmdCmdVarCreate >();
+ bOk &= Register< CMICmdCmdVarDelete >();
+ bOk &= Register< CMICmdCmdVarEvaluateExpression >();
+ bOk &= Register< CMICmdCmdVarInfoPathExpression >();
+ bOk &= Register< CMICmdCmdVarListChildren >();
+ bOk &= Register< CMICmdCmdVarSetFormat >();
+ bOk &= Register< CMICmdCmdVarShowAttributes >();
+ bOk &= Register< CMICmdCmdVarUpdate >();
+
+ return bOk;
+}
diff --git a/tools/lldb-mi/MICmdCommands.h b/tools/lldb-mi/MICmdCommands.h
new file mode 100644
index 000000000000..7bfc8aef6867
--- /dev/null
+++ b/tools/lldb-mi/MICmdCommands.h
@@ -0,0 +1,36 @@
+//===-- MICmdCommands.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdCommands.h
+//
+// Overview: CMICmdCommands instantiated.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+namespace MICmnCommands
+{
+
+//++ ============================================================================
+// Details: MI Command are instantiated and registered automatically with the
+// Command Factory
+// Gotchas: None.
+// Authors: Illya Rudkin 18/02/2014.
+// Changes: None.
+//--
+bool RegisterAll( void );
+
+}
diff --git a/tools/lldb-mi/MICmdData.cpp b/tools/lldb-mi/MICmdData.cpp
new file mode 100644
index 000000000000..8eb84f32000a
--- /dev/null
+++ b/tools/lldb-mi/MICmdData.cpp
@@ -0,0 +1,24 @@
+//===-- MICmdData.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdData.cpp
+//
+// Overview: SMICmdData implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdData.h"
+
diff --git a/tools/lldb-mi/MICmdData.h b/tools/lldb-mi/MICmdData.h
new file mode 100644
index 000000000000..d54a21663581
--- /dev/null
+++ b/tools/lldb-mi/MICmdData.h
@@ -0,0 +1,74 @@
+//===-- MICmdData.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdData.h
+//
+// Overview: SMICmdData interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmnResources.h"
+
+//++ ============================================================================
+// Details: MI command metadata. Holds the command's name, MI number and options
+// as found on stdin. Holds the command's MI output (written to stdout).
+// Gotchas: None.
+// Authors: Illya Rudkin 18/02/2014.
+// Changes: None.
+//--
+struct SMICmdData
+{
+ SMICmdData( void )
+ : id( 0 )
+ , bCmdValid( false )
+ , bCmdExecutedSuccessfully( false )
+ , bMIOldStyle( false )
+ , bHasResultRecordExtra( false )
+ {
+ };
+
+ MIuint id; // A command's unique ID i.e. GUID
+ CMIUtilString strMiCmdToken; // The command's MI token (a number)
+ CMIUtilString strMiCmd; // The command's name
+ CMIUtilString strMiCmdOption; // The command's arguments or options
+ CMIUtilString strMiCmdAll; // The text as received from the client
+ CMIUtilString strMiCmdResultRecord; // Each command forms 1 response to its input
+ CMIUtilString strMiCmdResultRecordExtra; // Hack command produce more response text to help the client because of using LLDB
+ bool bCmdValid; // True = Valid MI format command, false = invalid
+ bool bCmdExecutedSuccessfully; // True = Command finished successfully, false = Did not start/did not complete
+ CMIUtilString strErrorDescription; // Command failed this is why
+ bool bMIOldStyle; // True = format "3thread", false = format "3-thread"
+ bool bHasResultRecordExtra; // True = Yes command produced additional MI output to its 1 line response, false = no extra MI output formed
+
+ void Clear( void )
+ {
+ id = 0;
+ strMiCmdToken.clear();
+ strMiCmd = MIRSRC( IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION );
+ strMiCmdOption.clear();
+ strMiCmdAll.clear();
+ strMiCmdResultRecord.clear();
+ strMiCmdResultRecordExtra.clear();
+ bCmdValid = false;
+ bCmdExecutedSuccessfully = false;
+ strErrorDescription.clear();
+ bMIOldStyle = false;
+ bHasResultRecordExtra = false;
+ }
+};
+
diff --git a/tools/lldb-mi/MICmdFactory.cpp b/tools/lldb-mi/MICmdFactory.cpp
new file mode 100644
index 000000000000..4897c60e4d66
--- /dev/null
+++ b/tools/lldb-mi/MICmdFactory.cpp
@@ -0,0 +1,229 @@
+//===-- MICmdFactory.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdFactory.cpp
+//
+// Overview: CMICmdFactory implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdFactory.h"
+#include "MICmnResources.h"
+#include "MICmdData.h"
+#include "MICmdBase.h"
+#include "MICmdCommands.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdFactory constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdFactory::CMICmdFactory( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdFactory destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdFactory::~CMICmdFactory( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this Command factory.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmdFactory::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = true;
+
+ MICmnCommands::RegisterAll();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this Command Factory.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmdFactory::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ m_mapMiCmdToCmdCreatorFn.clear();
+
+ m_bInitialized = false;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Register a command's creator function with the command identitier the MI
+// command name i.e. 'file-exec-and-symbols'.
+// Type: Method.
+// Args: vMiCmd - (R) Command's name, the MI command.
+// vCmdCreateFn - (R) Command's creator function pointer.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmdFactory::CmdRegister( const CMIUtilString & vMiCmd, CmdCreatorFnPtr vCmdCreateFn )
+{
+ if( !IsValid( vMiCmd ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_INVALID_CMD_NAME ), vMiCmd.c_str() ) );
+ return MIstatus::failure;
+ }
+ if( vCmdCreateFn == nullptr )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN ), vMiCmd.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ if( HaveAlready( vMiCmd ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED ), vMiCmd.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ MapPairMiCmdToCmdCreatorFn_t pr( vMiCmd, vCmdCreateFn );
+ m_mapMiCmdToCmdCreatorFn.insert( pr );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Check a command is already registered.
+// Type: Method.
+// Args: vMiCmd - (R) Command's name, the MI command.
+// Return: True - registered.
+// False - not found.
+// Throws: None.
+//--
+bool CMICmdFactory::HaveAlready( const CMIUtilString & vMiCmd ) const
+{
+ const MapMiCmdToCmdCreatorFn_t::const_iterator it = m_mapMiCmdToCmdCreatorFn.find( vMiCmd );
+ if( it != m_mapMiCmdToCmdCreatorFn.end() )
+ return true;
+
+ return false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Check a command's name is valid:
+// - name is not empty
+// - name does not have spaces
+// Type: Method.
+// Args: vMiCmd - (R) Command's name, the MI command.
+// Return: True - valid.
+// False - not valid.
+// Throws: None.
+//--
+bool CMICmdFactory::IsValid( const CMIUtilString & vMiCmd ) const
+{
+ bool bValid = true;
+
+ if( vMiCmd.empty() )
+ {
+ bValid = false;
+ return false;
+ }
+
+ const MIint nPos = vMiCmd.find( " " );
+ if( nPos != (MIint) std::string::npos )
+ bValid = false;
+
+ return bValid;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Check a command is already registered.
+// Type: Method.
+// Args: vMiCmd - (R) Command's name, the MI command.
+// Return: True - registered.
+// False - not found.
+// Throws: None.
+//--
+bool CMICmdFactory::CmdExist( const CMIUtilString & vMiCmd ) const
+{
+ return HaveAlready( vMiCmd );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Create a command given the specified MI command name. The command data object
+// contains the options for the command.
+// Type: Method.
+// Args: vMiCmd - (R) Command's name, the MI command.
+// vCmdData - (RW) Command's metadata status/information/result object.
+// vpNewCmd - (W) New command instance.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmdFactory::CmdCreate( const CMIUtilString & vMiCmd, const SMICmdData & vCmdData, CMICmdBase *& vpNewCmd )
+{
+ bool bOk = MIstatus::success;
+
+ vpNewCmd = nullptr;
+
+ if( !IsValid( vMiCmd ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_INVALID_CMD_NAME ), vMiCmd.c_str() ) );
+ return MIstatus::failure;
+ }
+ if( !HaveAlready( vMiCmd ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED ), vMiCmd.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ const MapMiCmdToCmdCreatorFn_t::const_iterator it = m_mapMiCmdToCmdCreatorFn.find( vMiCmd );
+ const CMIUtilString & rMiCmd( (*it).first ); MIunused( rMiCmd );
+ CmdCreatorFnPtr pFn = (*it).second;
+ CMICmdBase * pCmd = (*pFn)();
+
+ SMICmdData cmdData( vCmdData );
+ cmdData.id = pCmd->GetGUID();
+ bOk = pCmd->SetCmdData( cmdData );
+ if( bOk )
+ vpNewCmd = pCmd;
+
+ return bOk;
+}
diff --git a/tools/lldb-mi/MICmdFactory.h b/tools/lldb-mi/MICmdFactory.h
new file mode 100644
index 000000000000..52281d1e7d1d
--- /dev/null
+++ b/tools/lldb-mi/MICmdFactory.h
@@ -0,0 +1,99 @@
+//===-- MICmdFactory.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdFactory.h
+//
+// Overview: CMICmdFactory interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers
+#include <map>
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MIUtilSingletonBase.h"
+
+// Declarations:
+class CMICmdBase;
+struct SMICmdData;
+
+//++ ============================================================================
+// Details: MI Command Factory. Holds a list of registered MI commands that
+// MI application understands to interpret. Creates commands objects.
+// The Command Factory is carried out in the main thread.
+// A singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 19/02/2014.
+// Changes: None.
+//--
+class CMICmdFactory
+: public CMICmnBase
+, public MI::ISingleton< CMICmdFactory >
+{
+ friend class MI::ISingleton< CMICmdFactory >;
+
+// Typedefs:
+public:
+ typedef CMICmdBase * (*CmdCreatorFnPtr)( void );
+
+// Class:
+public:
+ //++
+ // Description: Command's factory's interface for commands to implement.
+ //--
+ class ICmd
+ {
+ public:
+ virtual const CMIUtilString & GetMiCmd( void ) const = 0;
+ virtual CmdCreatorFnPtr GetCmdCreatorFn( void ) const = 0;
+ //virtual CMICmdBase * CreateSelf( void ) = 0; // Not possible as require a static creator function in the command class, here for awareness
+
+ /* dtor */ virtual ~ICmd( void ) {};
+ };
+
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+ bool CmdRegister( const CMIUtilString & vMiCmd, CmdCreatorFnPtr vCmdCreateFn );
+ bool CmdCreate( const CMIUtilString & vMiCmd, const SMICmdData & vCmdData, CMICmdBase *& vpNewCmd );
+ bool CmdExist( const CMIUtilString & vMiCmd ) const;
+
+// Methods:
+private:
+ /* ctor */ CMICmdFactory( void );
+ /* ctor */ CMICmdFactory( const CMICmdFactory & );
+ void operator=( const CMICmdFactory & );
+
+ bool HaveAlready( const CMIUtilString & vMiCmd ) const;
+ bool IsValid( const CMIUtilString & vMiCmd ) const;
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdFactory( void );
+
+// Typedefs:
+private:
+ typedef std::map< CMIUtilString, CmdCreatorFnPtr > MapMiCmdToCmdCreatorFn_t;
+ typedef std::pair< CMIUtilString, CmdCreatorFnPtr > MapPairMiCmdToCmdCreatorFn_t;
+
+// Attributes:
+private:
+ MapMiCmdToCmdCreatorFn_t m_mapMiCmdToCmdCreatorFn;
+};
diff --git a/tools/lldb-mi/MICmdInterpreter.cpp b/tools/lldb-mi/MICmdInterpreter.cpp
new file mode 100644
index 000000000000..dd5b2818705c
--- /dev/null
+++ b/tools/lldb-mi/MICmdInterpreter.cpp
@@ -0,0 +1,301 @@
+//===-- MICmdInterpreter.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdInterpreter.cpp
+//
+// Overview: CMICmdInterpreter implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdInterpreter.h"
+#include "MICmdFactory.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdInterpreter constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdInterpreter::CMICmdInterpreter( void )
+: m_rCmdFactory( CMICmdFactory::Instance() )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdInterpreter destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdInterpreter::~CMICmdInterpreter( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this Command Interpreter.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdInterpreter::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = true;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this Command Interpreter.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdInterpreter::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = false;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Establish whether the text data is an MI format type command.
+// Type: Method.
+// Args: vTextLine - (R) Text data to interpret.
+// vwbYesValid - (W) True = MI type command, false = not recognised.
+// vwbCmdNotInCmdFactor - (W) True = MI command not found in the command factory, false = recognised.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdInterpreter::ValidateIsMi( const CMIUtilString & vTextLine, bool & vwbYesValid, bool & vwbCmdNotInCmdFactor, SMICmdData & rwCmdData )
+{
+ vwbYesValid = false;
+ vwbCmdNotInCmdFactor = false;
+ rwCmdData.Clear();
+
+ if( vTextLine.empty() )
+ return MIstatus::success;
+
+ // MI format is [cmd #]-[command name]<space>[command arg(s)]
+ // i.e. 1-file-exec-and-symbols --thread-group i1 DEVICE_EXECUTABLE
+ // 5-data-evaluate-expression --thread 1 --frame 0 *(argv)
+
+ m_miCmdData.Clear();
+ m_miCmdData.strMiCmd = vTextLine;
+
+ // The following change m_miCmdData as valid parts are indentified
+ vwbYesValid = (MiHasCmdTokenEndingHypthen( vTextLine ) || MiHasCmdTokenEndingAlpha( vTextLine ));
+ vwbYesValid = vwbYesValid && MiHasCmd( vTextLine );
+ if( vwbYesValid )
+ {
+ vwbCmdNotInCmdFactor = !HasCmdFactoryGotMiCmd( MiGetCmdData() );
+ vwbYesValid = !vwbCmdNotInCmdFactor;
+ }
+
+ // Update command's meta data valid state
+ m_miCmdData.bCmdValid = vwbYesValid;
+
+ // Ok to return new updated command information
+ rwCmdData = MiGetCmdData();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Establish whether the command name entered on the stdin stream is recognised by
+// the MI driver.
+// Type: Method.
+// Args: vCmd - (R) Command information structure.
+// Return: bool - True = yes command is recognised, false = command not recognised.
+// Throws: None.
+//--
+bool CMICmdInterpreter::HasCmdFactoryGotMiCmd( const SMICmdData & vCmd ) const
+{
+ return m_rCmdFactory.CmdExist( vCmd.strMiCmd );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Does the command entered match the criteria for a MI command format.
+// The format to validate against is 'nn-' where there can be 1 to n digits.
+// I.e. '2-gdb-exit'.
+// Is the execution token present? The command token is entered into the
+// command meta data structure whether correct or not for reporting or later
+// command execution purposes.
+// Type: Method.
+// Args: vTextLine - (R) Text data to interpret.
+// Return: bool - True = yes command token present, false = command not recognised.
+// Throws: None.
+//--
+bool CMICmdInterpreter::MiHasCmdTokenEndingHypthen( const CMIUtilString & vTextLine )
+{
+ // The hythen is mandatory
+ const MIint nPos = vTextLine.find( "-", 0 );
+ if( (nPos == (MIint) std::string::npos) )
+ return false;
+
+ if( MiHasCmdTokenPresent( vTextLine ) )
+ {
+ const std::string strNum = vTextLine.substr( 0, nPos );
+ if( !CMIUtilString( strNum.c_str() ).IsNumber() )
+ return false;
+
+ m_miCmdData.strMiCmdToken = strNum.c_str();
+ }
+
+ m_miCmdData.bMIOldStyle = false;
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Does the command entered match the criteria for a MI command format.
+// The format to validate against is 'nnA' where there can be 1 to n digits.
+// 'A' represents any non numeric token. I.e. '1source .gdbinit'.
+// Is the execution token present? The command token is entered into the
+// command meta data structure whether correct or not for reporting or later
+// command execution purposes.
+// Type: Method.
+// Args: vTextLine - (R) Text data to interpret.
+// Return: bool - True = yes command token present, false = command not recognised.
+// Throws: None.
+//--
+bool CMICmdInterpreter::MiHasCmdTokenEndingAlpha( const CMIUtilString & vTextLine )
+{
+ MIchar cChar = vTextLine[ 0 ];
+ MIuint i = 0;
+ while( ::isdigit( cChar ) != 0 )
+ {
+ cChar = vTextLine[ ++i ];
+ }
+ if( ::isalpha( cChar ) == 0 )
+ return false;
+ if( i == 0 )
+ return false;
+
+ const std::string strNum = vTextLine.substr( 0, i );
+ m_miCmdData.strMiCmdToken = strNum.c_str();
+ m_miCmdData.bMIOldStyle = true;
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Does the command entered match the criteria for a MI command format.
+// Is the command token present before the hypen?
+// Type: Method.
+// Args: vTextLine - (R) Text data to interpret.
+// Return: bool - True = yes command token present, false = token not present.
+// Throws: None.
+//--
+bool CMICmdInterpreter::MiHasCmdTokenPresent( const CMIUtilString & vTextLine )
+{
+ const MIint nPos = vTextLine.find( "-", 0 );
+ return (nPos > 0);
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Does the command name entered match the criteria for a MI command format.
+// Is a recogised command present? The command name is entered into the
+// command meta data structure whether correct or not for reporting or later
+// command execution purposes. Command options is present are also put into the
+// command meta data structure.
+// Type: Method.
+// Args: vTextLine - (R) Command information structure.
+// Return: bool - True = yes command name present, false = command not recognised.
+// Throws: None.
+//--
+bool CMICmdInterpreter::MiHasCmd( const CMIUtilString & vTextLine )
+{
+ MIint nPos = 0;
+ if( m_miCmdData.bMIOldStyle )
+ {
+ char cChar = vTextLine[ 0 ];
+ MIuint i = 0;
+ while( ::isdigit( cChar ) != 0 )
+ {
+ cChar = vTextLine[ ++i ];
+ }
+ nPos = --i;
+ }
+ else
+ {
+ nPos = vTextLine.find( "-", 0 );
+ }
+
+ bool bFoundCmd = false;
+ const MIint nLen = vTextLine.length();
+ const MIint nPos2 = vTextLine.find( " ", nPos );
+ if( nPos2 != (MIint) std::string::npos )
+ {
+ if( nPos2 == nLen )
+ return false;
+ const CMIUtilString cmd = CMIUtilString( vTextLine.substr( nPos + 1, nPos2 - nPos - 1 ).c_str() );
+ if( cmd.empty() )
+ return false;
+
+ m_miCmdData.strMiCmd = cmd;
+
+ if( nPos2 < nLen )
+ m_miCmdData.strMiCmdOption = CMIUtilString( vTextLine.substr( nPos2 + 1, nLen - nPos2 - 1 ).c_str() );
+
+ bFoundCmd = true;
+ }
+ else
+ {
+ const CMIUtilString cmd = CMIUtilString( vTextLine.substr( nPos + 1, nLen - nPos - 1 ).c_str() );
+ if( cmd.empty() )
+ return false;
+ m_miCmdData.strMiCmd = cmd;
+ bFoundCmd = true;
+ }
+
+ if( bFoundCmd )
+ m_miCmdData.strMiCmdAll = vTextLine;
+
+ return bFoundCmd;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the just entered new command from stdin. It contains the command
+// name, number and any options.
+// Type: Method.
+// Args: vTextLine - (R) Command information structure.
+// Return: SMICmdData & - Command meta data information/result/status.
+// Throws: None.
+//--
+const SMICmdData & CMICmdInterpreter::MiGetCmdData( void ) const
+{
+ return m_miCmdData;
+}
+
diff --git a/tools/lldb-mi/MICmdInterpreter.h b/tools/lldb-mi/MICmdInterpreter.h
new file mode 100644
index 000000000000..d924a1f77af2
--- /dev/null
+++ b/tools/lldb-mi/MICmdInterpreter.h
@@ -0,0 +1,78 @@
+//===-- MICmdInterpreter.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdInterpreter.h
+//
+// Overview: CMICmdInterpreter interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MICmdData.h"
+#include "MIUtilSingletonBase.h"
+
+// Declarations:
+class CMICmdFactory;
+
+//++ ============================================================================
+// Details: MI command interpreter. It takes text data from the MI driver
+// (which got it from Stdin singleton) and validate the text to see if
+// matches Machine Interface (MI) format and commands defined in the
+// MI application.
+// A singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 18/02/2014.
+// Changes: None.
+//--
+class CMICmdInterpreter
+: public CMICmnBase
+, public MI::ISingleton< CMICmdInterpreter >
+{
+ friend MI::ISingleton< CMICmdInterpreter >;
+
+// Methods:
+public:
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+ bool ValidateIsMi( const CMIUtilString & vTextLine, bool & vwbYesValid, bool & vwbCmdNotInCmdFactor, SMICmdData & rwCmdData );
+
+// Methods:
+private:
+ /* ctor */ CMICmdInterpreter( void );
+ /* ctor */ CMICmdInterpreter( const CMICmdInterpreter & );
+ void operator=( const CMICmdInterpreter & );
+
+ bool HasCmdFactoryGotMiCmd( const SMICmdData & vCmdData ) const;
+ bool MiHasCmdTokenEndingHypthen( const CMIUtilString & vTextLine );
+ bool MiHasCmdTokenEndingAlpha( const CMIUtilString & vTextLine );
+ bool MiHasCmd( const CMIUtilString & vTextLine );
+ bool MiHasCmdTokenPresent( const CMIUtilString & vTextLine );
+ const SMICmdData & MiGetCmdData() const;
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdInterpreter( void );
+
+// Attributes:
+private:
+ SMICmdData m_miCmdData; // Filled in on each new line being interpreted
+ CMICmdFactory & m_rCmdFactory;
+};
diff --git a/tools/lldb-mi/MICmdInvoker.cpp b/tools/lldb-mi/MICmdInvoker.cpp
new file mode 100644
index 000000000000..41f9f77542a3
--- /dev/null
+++ b/tools/lldb-mi/MICmdInvoker.cpp
@@ -0,0 +1,333 @@
+//===-- MICmdInvoker.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdInvoker.cpp
+//
+// Overview: CMICmdInvoker implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdInvoker.h"
+#include "MICmdBase.h"
+#include "MICmdMgr.h"
+#include "MICmnLog.h"
+#include "MICmnStreamStdout.h"
+#include "MIDriver.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdInvoker constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdInvoker::CMICmdInvoker( void )
+: m_rStreamOut( CMICmnStreamStdout::Instance() )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdInvoker destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdInvoker::~CMICmdInvoker( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this Command Invoker.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdInvoker::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = true;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this Stdin stream.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdInvoker::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ CmdDeleteAll();
+
+ m_bInitialized = false;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Empty the map of invoked commands doing work. Command objects are deleted too.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMICmdInvoker::CmdDeleteAll( void )
+{
+ CMICmdMgr & rMgr = CMICmdMgr::Instance();
+ MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.begin();
+ while( it != m_mapCmdIdToCmd.end() )
+ {
+ const MIuint cmdId( (*it).first ); MIunused( cmdId );
+ CMICmdBase * pCmd = (*it).second;
+ const CMIUtilString & rCmdName( pCmd->GetCmdData().strMiCmd ); MIunused( rCmdName );
+ rMgr.CmdDelete( pCmd->GetCmdData() );
+
+ // Next
+ ++it;
+ }
+ m_mapCmdIdToCmd.clear();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Remove from the map of invoked commands doing work a command that has finished
+// its work. The command object is deleted too.
+// Type: Method.
+// Args: vId - (R) Command object's unique ID.
+// vbYesDeleteCmd - (R) True = Delete command object, false = delete via the Command Manager.
+// Return: None.
+// Throws: None.
+//--
+bool CMICmdInvoker::CmdDelete( const MIuint vId, const bool vbYesDeleteCmd /*= false*/ )
+{
+ CMICmdMgr & rMgr = CMICmdMgr::Instance();
+ MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find( vId );
+ if( it != m_mapCmdIdToCmd.end() )
+ {
+ CMICmdBase * pCmd = (*it).second;
+ if( vbYesDeleteCmd )
+ {
+ // Via registered interest command manager callback *this object to delete the command
+ m_mapCmdIdToCmd.erase( it );
+ delete pCmd;
+ }
+ else
+ // Notify other interested object of this command's pending deletion
+ rMgr.CmdDelete( pCmd->GetCmdData() );
+ }
+
+ if( m_mapCmdIdToCmd.empty() )
+ rMgr.CmdUnregisterForDeleteNotification( *this );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add to the map of invoked commands doing work a command that is about to
+// start to do work.
+// Type: Method.
+// Args: vCmd - (R) Command object.
+// Return: None.
+// Throws: None.
+//--
+bool CMICmdInvoker::CmdAdd( const CMICmdBase & vCmd )
+{
+ if( m_mapCmdIdToCmd.empty() )
+ {
+ CMICmdMgr & rMgr = CMICmdMgr::Instance();
+ rMgr.CmdRegisterForDeleteNotification( *this );
+ }
+
+ const MIuint & cmdId( vCmd.GetCmdData().id );
+ MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find( cmdId );
+ if( it != m_mapCmdIdToCmd.end() )
+ return MIstatus::success;
+
+ MapPairCmdIdToCmd_t pr( cmdId, const_cast< CMICmdBase *>( &vCmd ));
+ m_mapCmdIdToCmd.insert( pr );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Having previously had the potential command validated and found valid now
+// get the command executed.
+// If the Functionalityity returns MIstatus::failure call GetErrorDescription().
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: vCmd - (RW) Command object.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmdInvoker::CmdExecute( CMICmdBase & vCmd )
+{
+ bool bOk = CmdAdd( vCmd );
+
+ if( bOk && !vCmd.ParseArgs() )
+ {
+ // Report command execution failed
+ const SMICmdData cmdData( vCmd.GetCmdData() );
+ CmdStdout( cmdData );
+ CmdCauseAppExit( vCmd );
+ CmdDelete( cmdData.id );
+
+ // Proceed to wait or execute next command
+ return MIstatus::success;
+ }
+
+ if( bOk && !vCmd.Execute() )
+ {
+ // Report command execution failed
+ const SMICmdData cmdData( vCmd.GetCmdData() );
+ CmdStdout( cmdData );
+ CmdCauseAppExit( vCmd );
+ CmdDelete( cmdData.id );
+
+ // Proceed to wait or execute next command
+ return MIstatus::success;
+ }
+
+ bOk = CmdExecuteFinished( vCmd );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Called when a command has finished its Execution() work either synchronously
+// because the command executed was the type a non event type or asynchronoulsy
+// via the command's callback (because of an SB Listener event). Needs to be called
+// so that *this invoker call do some house keeping and then proceed to call
+// the command's Acknowledge() function.
+// Type: Method.
+// Args: vCmd - (R) Command object.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmdInvoker::CmdExecuteFinished( CMICmdBase & vCmd )
+{
+ // Command finished now get the command to gather it's information and form the MI
+ // Result record
+ if( !vCmd.Acknowledge() )
+ {
+ // Report command acknowledge functionality failed
+ const SMICmdData cmdData( vCmd.GetCmdData() );
+ CmdStdout( cmdData );
+ CmdCauseAppExit( vCmd );
+ CmdDelete( cmdData.id );
+
+ // Proceed to wait or execute next command
+ return MIstatus::success;
+ }
+
+ // Retrieve the command's latest data/information. Needed for commands of the event type so have
+ // a record of commands pending finishing execution.
+ const CMIUtilString & rMIResultRecord( vCmd.GetMIResultRecord() );
+ SMICmdData cmdData( vCmd.GetCmdData() ); // Make a copy as the command will be deleted soon
+ cmdData.strMiCmdResultRecord = rMIResultRecord; // Precautionary copy as the command might forget to do this
+ if( vCmd.HasMIResultRecordExtra() )
+ {
+ cmdData.bHasResultRecordExtra = true;
+ const CMIUtilString & rMIExtra( vCmd.GetMIResultRecordExtra() );
+ cmdData.strMiCmdResultRecordExtra = rMIExtra; // Precautionary copy as the command might forget to do this
+ }
+
+ // Send command's MI response to the client
+ bool bOk = CmdStdout( cmdData );
+
+ // Delete the command object as do not require anymore
+ bOk = bOk && CmdDelete( vCmd.GetCmdData().id );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: If the MI Driver is not operating via a client i.e. Eclipse check the command
+// on failure suggests the application exits. A command can be such that a
+// failure cannot the allow the application to continue operating.
+// Args: vCmd - (R) Command object.
+// Return: None.
+// Return: None.
+// Throws: None.
+//--
+void CMICmdInvoker::CmdCauseAppExit( const CMICmdBase & vCmd ) const
+{
+ if( vCmd.GetExitAppOnCommandFailure() )
+ {
+ CMIDriver & rDriver( CMIDriver::Instance() );
+ if( rDriver.IsDriverDebuggingArgExecutable() )
+ {
+ rDriver.SetExitApplicationFlag( true );
+ }
+ }
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Write to stdout and the Log file the command's MI formatted result.
+// Type: vCmdData - (R) A command's information.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Return: None.
+// Throws: None.
+//--
+bool CMICmdInvoker::CmdStdout( const SMICmdData & vCmdData ) const
+{
+ bool bOk = m_pLog->WriteLog( vCmdData.strMiCmdAll );
+ const bool bLock = bOk && m_rStreamOut.Lock();
+ bOk = bOk && bLock && m_rStreamOut.WriteMIResponse( vCmdData.strMiCmdResultRecord );
+ if( bOk && vCmdData.bHasResultRecordExtra )
+ {
+ bOk = m_rStreamOut.WriteMIResponse( vCmdData.strMiCmdResultRecordExtra );
+ }
+ bOk = bLock && m_rStreamOut.Unlock();
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdMgr::ICmdDeleteCallback. *this object is registered
+// with the Command Manager to receive callbacks when a command is being deleted.
+// An object, *this invoker, does not delete a command object itself but calls
+// the Command Manager to delete a command object. This function is the Invoker's
+// called.
+// The Invoker owns the command objects and so can delete them but must do it
+// via the manager so other objects can be notified of the deletion.
+// Type: Method.
+// Args: vCmd - (RW) Command.
+// Return: None.
+// Throws: None.
+//--
+void CMICmdInvoker::Delete( SMICmdData & vCmd )
+{
+ CmdDelete( vCmd.id, true );
+}
diff --git a/tools/lldb-mi/MICmdInvoker.h b/tools/lldb-mi/MICmdInvoker.h
new file mode 100644
index 000000000000..b89d506b1f58
--- /dev/null
+++ b/tools/lldb-mi/MICmdInvoker.h
@@ -0,0 +1,118 @@
+//===-- MICmdInvoker.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdInvoker.h
+//
+// Overview: CMICmdInvoker interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers
+#include <map>
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MICmdData.h"
+#include "MICmdMgrSetCmdDeleteCallback.h"
+#include "MIUtilSingletonBase.h"
+
+// Declarations:
+class CMICmdBase;
+class CMICmnStreamStdout;
+
+//++ ============================================================================
+// Details: MI Command Invoker. The Invoker works on the command pattern design.
+// There two main jobs; action command Execute() function, followed by
+// the command's Acknowledge() function. When a command has finished its
+// execute function it returns to the invoker. The invoker then calls the
+// command's Acknowledge() function to do more work, form and give
+// back a MI result. In the meantime the Command Monitor is monitoring
+// the each command doing their Execute() function work so they do not
+// exceed a time limit which if it exceeds informs the command(s) to
+// stop work.
+// The work by the Invoker is carried out in the main thread.
+// The Invoker takes ownersip of any commands created which means it
+// is the only object to delete them when a command is finished working.
+// A singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 19/02/2014.
+// Changes: None.
+//--
+class CMICmdInvoker
+: public CMICmnBase
+, public CMICmdMgrSetCmdDeleteCallback::ICallback
+, public MI::ISingleton< CMICmdInvoker >
+{
+ friend class MI::ISingleton< CMICmdInvoker >;
+
+// Class:
+public:
+ //++
+ // Description: Invoker's interface for commands to implement.
+ //--
+ class ICmd
+ {
+ public:
+ virtual bool Acknowledge( void ) = 0;
+ virtual bool Execute( void ) = 0;
+ virtual bool ParseArgs( void ) = 0;
+ virtual bool SetCmdData( const SMICmdData & vCmdData ) = 0;
+ virtual const SMICmdData & GetCmdData( void ) const = 0;
+ virtual const CMIUtilString & GetErrorDescription( void ) const = 0;
+ virtual void CmdFinishedTellInvoker( void ) const = 0;
+ virtual const CMIUtilString & GetMIResultRecord( void ) const = 0;
+ virtual const CMIUtilString & GetMIResultRecordExtra( void ) const = 0;
+ virtual bool HasMIResultRecordExtra( void ) const = 0;
+
+ /* dtor */ virtual ~ICmd( void ) {};
+ };
+
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+ bool CmdExecute( CMICmdBase & vCmd );
+ bool CmdExecuteFinished( CMICmdBase & vCmd );
+
+// Typedefs:
+private:
+ typedef std::map< MIuint, CMICmdBase * > MapCmdIdToCmd_t;
+ typedef std::pair< MIuint, CMICmdBase * > MapPairCmdIdToCmd_t;
+
+// Methods:
+private:
+ /* ctor */ CMICmdInvoker( void );
+ /* ctor */ CMICmdInvoker( const CMICmdInvoker & );
+ void operator=( const CMICmdInvoker & );
+ void CmdDeleteAll( void );
+ bool CmdDelete( const MIuint vCmdId, const bool vbYesDeleteCmd = false );
+ bool CmdAdd( const CMICmdBase & vCmd );
+ bool CmdStdout( const SMICmdData & vCmdData ) const;
+ void CmdCauseAppExit( const CMICmdBase & vCmd ) const;
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdInvoker( void );
+ // From CMICmdMgrSetCmdDeleteCallback::ICallback
+ virtual void Delete( SMICmdData & vCmd );
+
+// Attributes:
+private:
+ MapCmdIdToCmd_t m_mapCmdIdToCmd;
+ CMICmnStreamStdout & m_rStreamOut;
+};
diff --git a/tools/lldb-mi/MICmdMgr.cpp b/tools/lldb-mi/MICmdMgr.cpp
new file mode 100644
index 000000000000..4abcbad3f48d
--- /dev/null
+++ b/tools/lldb-mi/MICmdMgr.cpp
@@ -0,0 +1,257 @@
+//===-- MICmdMgr.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdMgr.cpp
+//
+// Overview: CMICmdMgr implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdMgr.h"
+#include "MICmnResources.h"
+#include "MICmnLog.h"
+#include "MICmdInterpreter.h"
+#include "MICmdFactory.h"
+#include "MICmdInvoker.h"
+#include "MICmdBase.h"
+#include "MIUtilSingletonBase.h"
+#include "MIUtilSingletonHelper.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdMgr constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdMgr::CMICmdMgr( void )
+: m_interpretor( CMICmdInterpreter::Instance() )
+, m_factory( CMICmdFactory::Instance() )
+, m_invoker( CMICmdInvoker::Instance() )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdMgr destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdMgr::~CMICmdMgr( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this Command Manager.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmdMgr::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Note initialization order is important here as some resources depend on previous
+ MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+ MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg );
+ if( bOk && !m_interpretor.Initialize() )
+ {
+ bOk = false;
+ errMsg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_CMDINTERPRETER ), m_interpretor.GetErrorDescription().c_str() );
+ }
+ if( bOk && !m_factory.Initialize() )
+ {
+ bOk = false;
+ errMsg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_CMDFACTORY ), m_factory.GetErrorDescription().c_str() );
+ }
+ if( bOk && !m_invoker.Initialize() )
+ {
+ bOk = false;
+ errMsg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_CMDINVOKER ), m_invoker.GetErrorDescription().c_str() );
+ }
+ m_bInitialized = bOk;
+
+ if( !bOk )
+ {
+ CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_CMDMGR ), errMsg.c_str() ) );
+ SetErrorDescription( strInitError );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this Command Manager.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmdMgr::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = false;
+
+ ClrErrorDescription();
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Tidy up
+ m_setCmdDeleteCallback.clear();
+
+ // Note shutdown order is important here
+ if( !m_invoker.Shutdown() )
+ {
+ bOk = false;
+ errMsg += CMIUtilString::Format( MIRSRC( IDS_MI_SHTDWN_ERR_CMDINVOKER ), m_invoker.GetErrorDescription().c_str() );
+ }
+ if( !m_factory.Shutdown() )
+ {
+ bOk = false;
+ if( !errMsg.empty() ) errMsg += ", ";
+ errMsg += CMIUtilString::Format( MIRSRC( IDS_MI_SHTDWN_ERR_CMDFACTORY ), m_factory.GetErrorDescription().c_str() );
+ }
+ if( !m_interpretor.Shutdown() )
+ {
+ bOk = false;
+ if( !errMsg.empty() ) errMsg += ", ";
+ errMsg += CMIUtilString::Format( MIRSRC( IDS_MI_SHTDWN_ERR_CMDINTERPRETER ), m_interpretor.GetErrorDescription().c_str() );
+ }
+ MI::ModuleShutdown< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg );
+ MI::ModuleShutdown< CMICmnLog >( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+
+ if( !bOk )
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_MI_SHUTDOWN_ERR ), errMsg.c_str() );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Establish whether the text data is an MI format type command.
+// Type: Method.
+// Args: vTextLine - (R) Text data to interpret.
+// vwbYesValid - (W) True = MI type command, false = not recognised.
+// vwbCmdNotInCmdFactor - (W) True = MI command not found in the command factor, false = recognised.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmdMgr::CmdInterpret( const CMIUtilString & vTextLine, bool & vwbYesValid, bool & vwbCmdNotInCmdFactor, SMICmdData & rwCmdData )
+{
+ return m_interpretor.ValidateIsMi( vTextLine, vwbYesValid, vwbCmdNotInCmdFactor, rwCmdData );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Having previously had the potential command validated and found valid now
+// get the command executed.
+// If the Functionalityity returns MIstatus::failure call GetErrorDescription().
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: vCmdData - (RW) Command meta data.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmdMgr::CmdExecute( const SMICmdData & vCmdData )
+{
+ bool bOk = MIstatus::success;
+
+ // Pass the command's meta data structure to the command
+ // so it can update it if required. (Need to copy it out of the
+ // command before the command is deleted)
+ CMICmdBase * pCmd = nullptr;
+ bOk = m_factory.CmdCreate( vCmdData.strMiCmd, vCmdData, pCmd );
+ if( !bOk )
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_CMDMGR_ERR_CMD_FAILED_CREATE ), m_factory.GetErrorDescription().c_str() ) );
+ SetErrorDescription( errMsg );
+ return MIstatus::failure;
+ }
+
+ bOk = m_invoker.CmdExecute( *pCmd );
+ if( !bOk )
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_CMDMGR_ERR_CMD_INVOKER ), m_invoker.GetErrorDescription().c_str() ) );
+ SetErrorDescription( errMsg );
+ return MIstatus::failure;
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Iterate all interested clients and tell them a command is being deleted.
+// Type: Method.
+// Args: vCmdData - (RW) The command to be deleted.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdMgr::CmdDelete( SMICmdData vCmdData )
+{
+ // Note vCmdData is a copy! The command holding its copy will be deleted soon
+ // we still need to iterate callback clients after a command object is deleted
+
+ m_setCmdDeleteCallback.Delete( vCmdData );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Register an object to be called when a command object is deleted.
+// Type: Method.
+// Args: vObject - (R) A new interested client.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdMgr::CmdRegisterForDeleteNotification( CMICmdMgrSetCmdDeleteCallback::ICallback & vObject )
+{
+ return m_setCmdDeleteCallback.Register( vObject );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Unregister an object from being called when a command object is deleted.
+// Type: Method.
+// Args: vObject - (R) The was interested client.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmdMgr::CmdUnregisterForDeleteNotification( CMICmdMgrSetCmdDeleteCallback::ICallback & vObject )
+{
+ return m_setCmdDeleteCallback.Unregister( vObject );
+}
diff --git a/tools/lldb-mi/MICmdMgr.h b/tools/lldb-mi/MICmdMgr.h
new file mode 100644
index 000000000000..2b6a99248b16
--- /dev/null
+++ b/tools/lldb-mi/MICmdMgr.h
@@ -0,0 +1,83 @@
+//===-- MICmdMgr.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdMgr.h
+//
+// Overview: CMICmdMgr interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers
+#include <set>
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MICmdBase.h"
+#include "MICmdMgrSetCmdDeleteCallback.h"
+#include "MIUtilSingletonBase.h"
+
+// Declarations:
+class CMICmdInterpreter;
+class CMICmdFactory;
+class CMICmdInvoker;
+class CMICmdBase;
+
+//++ ============================================================================
+// Details: MI command manager. Oversees command operations, controls command
+// production and the running of commands.
+// Command Invoker, Command Factory and Command Monitor while independant
+// units are overseen/managed by *this manager.
+// A singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 19/02/2014.
+// Changes: None.
+//--
+class CMICmdMgr
+: public CMICmnBase
+, public MI::ISingleton< CMICmdMgr >
+{
+ friend class MI::ISingleton< CMICmdMgr >;
+
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+
+ bool CmdInterpret( const CMIUtilString & vTextLine, bool & vwbYesValid, bool & vwbCmdNotInCmdFactor, SMICmdData & rwCmdData );
+ bool CmdExecute( const SMICmdData & vCmdData );
+ bool CmdDelete( SMICmdData vCmdData );
+ bool CmdRegisterForDeleteNotification( CMICmdMgrSetCmdDeleteCallback::ICallback & vObject );
+ bool CmdUnregisterForDeleteNotification( CMICmdMgrSetCmdDeleteCallback::ICallback & vObject );
+
+// Methods:
+private:
+ /* ctor */ CMICmdMgr( void );
+ /* ctor */ CMICmdMgr( const CMICmdMgr & );
+ void operator=( const CMICmdMgr & );
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdMgr( void );
+
+// Attributes:
+private:
+ CMICmdInterpreter & m_interpretor;
+ CMICmdFactory & m_factory;
+ CMICmdInvoker & m_invoker;
+ CMICmdMgrSetCmdDeleteCallback::CSetClients m_setCmdDeleteCallback;
+}; \ No newline at end of file
diff --git a/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp b/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp
new file mode 100644
index 000000000000..1303a8832f66
--- /dev/null
+++ b/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp
@@ -0,0 +1,110 @@
+//===-- MICmdMgrSetCmdDeleteCallback.cpp ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdMgrSetCmdDeleteCallback.cpp
+//
+// Overview: CSetClients implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmdMgrSetCmdDeleteCallback.h"
+
+namespace CMICmdMgrSetCmdDeleteCallback
+{
+
+//++ ------------------------------------------------------------------------------------
+// Details: CSetClients constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CSetClients::CSetClients( void )
+: m_bClientUnregistered( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CSetClients destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CSetClients::~CSetClients( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Register an object to be called when a command object is deleted.
+// Type: Method.
+// Args: vObject - (R) A new interested client.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CSetClients::Register( ICallback & vObject )
+{
+ insert( &vObject );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Unregister an object from being called when a command object is deleted.
+// Type: Method.
+// Args: vObject - (R) The was interested client.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CSetClients::Unregister( ICallback & vObject )
+{
+ m_bClientUnregistered = true;
+ erase( &vObject );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Iterate all interested clients and tell them a command is being deleted.
+// Type: Method.
+// Args: vCmd - (RW) The command to be deleted.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+void CSetClients::Delete( SMICmdData & vCmd )
+{
+ m_bClientUnregistered = false; // Reset
+ iterator it = begin();
+ while( it != end() )
+ {
+ ICallback * pObj = *it;
+ pObj->Delete( vCmd );
+
+ if( m_bClientUnregistered )
+ {
+ m_bClientUnregistered = false; // Reset
+ it = begin();
+ }
+ else
+ // Next
+ ++it;
+ }
+}
+
+} // namespace CMICmdMgrSetCmdDeleteCallback
diff --git a/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h b/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h
new file mode 100644
index 000000000000..3579d3582615
--- /dev/null
+++ b/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h
@@ -0,0 +1,88 @@
+//===-- MICmdMgrSetCmdDeleteCallback.h --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmdMgrSetCmdDeleteCallback.h
+//
+// Overview: ICallback interface.
+// CSetClients interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <set>
+
+// In-house headers:
+#include "MICmnBase.h"
+
+// Declarations:
+struct SMICmdData;
+
+namespace CMICmdMgrSetCmdDeleteCallback
+{
+
+//++ ============================================================================
+// Details: MI Command Manager interface for client call back.
+// Objects that want to be notified of a command being deleted
+// inherit this interface and register interest in command object
+// deletion. An object deleting a command must not do it itself but call
+// the Command Manager CmdDelete() function to delete a command object.
+// Gotchas: None.
+// Authors: Illya Rudkin 21/02/2014.
+// Changes: None.
+//--
+class ICallback
+{
+public:
+ virtual void Delete( SMICmdData & vCmd ) = 0;
+
+ /* dtor */ virtual ~ICallback( void ) {};
+};
+
+//++ ============================================================================
+// Details: MI Command Manager container for clients registered interest in command
+// objects being deleted. Objects register an interest so when a command
+// is to be deleted that object wanting the delete calls the Command
+// Manager to delete the command object. In so do all other registered
+// objects get called to about the deletion including the object wanting
+// to do the delete in the first place.
+// Gotchas: None.
+// Authors: Illya Rudkin 21/02/2014.
+// Changes: None.
+//--
+class CSetClients
+: public std::set< class ICallback * >
+, public CMICmnBase
+{
+// Methods:
+public:
+ /* ctor */ CSetClients( void );
+
+ bool Register( class ICallback & vObject );
+ bool Unregister( class ICallback & vObject );
+ void Delete( SMICmdData & vCmdData );
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CSetClients( void );
+
+// Attributes:
+private:
+ bool m_bClientUnregistered; // True = yes while deleting a client unregistered, false = no client unregistered during deletion
+};
+
+} // namespace CMICmdMgrSetCmdDeleteCallback
diff --git a/tools/lldb-mi/MICmnBase.cpp b/tools/lldb-mi/MICmnBase.cpp
new file mode 100644
index 000000000000..3da7a41b3336
--- /dev/null
+++ b/tools/lldb-mi/MICmnBase.cpp
@@ -0,0 +1,144 @@
+//===-- MICmnBase.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnBase.cpp
+//
+// Overview: CMICmnBase implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers
+#include <stdarg.h> // va_list, va_start, var_end
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MICmnLog.h"
+#include "MICmnStreamStderr.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnBase constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnBase::CMICmnBase( void )
+: m_strMILastErrorDescription( CMIUtilString() )
+, m_bInitialized( false )
+, m_pLog( &CMICmnLog::Instance() )
+, m_clientUsageRefCnt( 0 )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnBase destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnBase::~CMICmnBase( void )
+{
+ m_pLog = NULL;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve whether *this object has an error description set.
+// Type: Method.
+// Args: None.
+// Return: bool - True = Yes already defined, false = empty discription.
+// Throws: None.
+//--
+bool CMICmnBase::HaveErrorDescription( void ) const
+{
+ return m_strMILastErrorDescription.empty();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve MI's last error condition.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnBase::GetErrorDescription( void ) const
+{
+ return m_strMILastErrorDescription;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set MI's error condition description. This may be accessed by clients and
+// seen by users. Message is available to the client using the server and sent
+// to the Logger.
+// Type: Method.
+// Args: vrTxt - (R) Text description.
+// Return: None.
+// Throws: None.
+//--
+void CMICmnBase::SetErrorDescription( const CMIUtilString & vrTxt ) const
+{
+ m_strMILastErrorDescription = vrTxt;
+ if( !vrTxt.empty() )
+ {
+ const CMIUtilString txt( CMIUtilString::Format( "Error: %s", vrTxt.c_str() ) );
+ CMICmnStreamStderr::Instance().Write( txt );
+ }
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set MI's error condition description. This may be accessed by clients and
+// seen by users. Message is available to the client using the server and sent
+// to the Logger.
+// Type: Method.
+// Args: vrTxt - (R) Text description.
+// Return: None.
+// Throws: None.
+//--
+void CMICmnBase::SetErrorDescriptionNoLog( const CMIUtilString & vrTxt ) const
+{
+ m_strMILastErrorDescription = vrTxt;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Clear MI's error condition description.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMICmnBase::ClrErrorDescription( void ) const
+{
+ m_strMILastErrorDescription.clear();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set MI's error condition description. This may be accessed by clients and
+// seen by users. Message is available to the client using the server and sent
+// to the Logger.
+// Type: Method.
+// Args: vrFormat - (R) Format string.
+// ... - (R) Variable number of CMIUtilString type objects.
+// Return: None.
+// Throws: None.
+//--
+void CMICmnBase::SetErrorDescriptionn( const CMIUtilString & vrFormat, ... ) const
+{
+ va_list args;
+ va_start( args, vrFormat );
+ CMIUtilString strResult = CMIUtilString::FormatValist( vrFormat, args );
+ va_end( args );
+
+ SetErrorDescription( strResult );
+} \ No newline at end of file
diff --git a/tools/lldb-mi/MICmnBase.h b/tools/lldb-mi/MICmnBase.h
new file mode 100644
index 000000000000..db7338c5581f
--- /dev/null
+++ b/tools/lldb-mi/MICmnBase.h
@@ -0,0 +1,60 @@
+//===-- MICmnBase.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnBase.h
+//
+// Overview: CMICmnBase interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MIDataTypes.h"
+#include "MIUtilString.h"
+
+// Declarations:
+class CMICmnLog;
+
+//++ ============================================================================
+// Details: MI common code implementation base class.
+// Gotchas: None.
+// Authors: Illya Rudkin 28/01/2014.
+// Changes: None.
+//--
+class CMICmnBase
+{
+// Methods:
+public:
+ /* ctor */ CMICmnBase( void );
+
+ bool HaveErrorDescription( void ) const;
+ const CMIUtilString & GetErrorDescription( void ) const;
+ void SetErrorDescription( const CMIUtilString & vrTxt ) const;
+ void SetErrorDescriptionn( const CMIUtilString & vrFormat, ... ) const;
+ void SetErrorDescriptionNoLog( const CMIUtilString & vrTxt ) const;
+ void ClrErrorDescription( void ) const;
+
+// Overrideable:
+public:
+ /* dtor */ virtual ~CMICmnBase( void );
+
+// Attributes:
+protected:
+ mutable CMIUtilString m_strMILastErrorDescription;
+ bool m_bInitialized; // True = yes successfully initialized, false = no yet or failed
+ CMICmnLog * m_pLog; // Allow all derived classes to use the logger
+ MIint m_clientUsageRefCnt; // Count of client using *this object so not shutdown() object to early
+}; \ No newline at end of file
diff --git a/tools/lldb-mi/MICmnConfig.h b/tools/lldb-mi/MICmnConfig.h
new file mode 100644
index 000000000000..68093e87998b
--- /dev/null
+++ b/tools/lldb-mi/MICmnConfig.h
@@ -0,0 +1,50 @@
+//===-- MICmnConfig.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnConfig.h
+//
+// Overview: Common defines to guide feature inclusion at compile time.
+//
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+#pragma once
+
+// 1 = Yes compile MI Driver version, 0 = compile original LLDB driver code only.
+// 0 was mainly just for testing purposes and so may be removed at a later time.
+#define MICONFIG_COMPILE_MIDRIVER_VERSION 1
+
+// 1 = Show debug process attach modal dialog, 0 = do not show
+// For windows only ATM, other OS's code is an infinite loop which a debugger must change a value to continue
+#define MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG 0
+
+// 1 = Compile in and init LLDB driver code alongside MI version, 0 = do not compile in
+#define MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER 1
+
+// 1 = Give runtime our own custom buffer, 0 = Use runtime managed buffer
+#define MICONFIG_CREATE_OWN_STDIN_BUFFER 0
+
+// 1 = Use the MI driver regardless of --interpreter, 0 = require --interpreter argument
+// This depends on MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
+#define MICONFIG_DEFAULT_TO_MI_DRIVER 0
+
+// 1 = Check for stdin before we issue blocking read, 0 = issue blocking call always
+#define MICONFIG_POLL_FOR_STD_IN 1
+
+// 1 = Write to MI's Log file warnings about commands that did not handle arguments or
+// options present to them by the driver's client, 0 = no warnings given
+#define MICONFIG_GIVE_WARNING_CMD_ARGS_NOT_HANDLED 1
+
+// 1 = Enable MI Driver in MI mode to create a local debug session, 0 = Report "Not implemented"
+#define MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION 0 \ No newline at end of file
diff --git a/tools/lldb-mi/MICmnLLDBBroadcaster.cpp b/tools/lldb-mi/MICmnLLDBBroadcaster.cpp
new file mode 100644
index 000000000000..743100ae7b0f
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBBroadcaster.cpp
@@ -0,0 +1,89 @@
+//===-- MICmnLLDBBroadcaster.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBBroadcaster.cpp
+//
+// Overview: CMICmnLLDBBroadcaster implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnLLDBBroadcaster.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBBroadcaster constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBBroadcaster::CMICmnLLDBBroadcaster( void )
+: lldb::SBBroadcaster( "MI driver" )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBBroadcaster destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBBroadcaster::~CMICmnLLDBBroadcaster( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this broardcaster object.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBBroadcaster::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = MIstatus::success;
+
+ return m_bInitialized;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this broardcaster object.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBBroadcaster::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = false;
+
+ return MIstatus::success;
+}
+
diff --git a/tools/lldb-mi/MICmnLLDBBroadcaster.h b/tools/lldb-mi/MICmnLLDBBroadcaster.h
new file mode 100644
index 000000000000..6c3300aefcc4
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBBroadcaster.h
@@ -0,0 +1,61 @@
+//===-- MICmnLLDBBroadcaster.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBBroadcaster.h
+//
+// Overview: CMICmnLLDBBroadcaster interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include <lldb/API/SBBroadcaster.h>
+#include "MICmnBase.h"
+#include "MIUtilSingletonBase.h"
+
+//++ ============================================================================
+// Details: MI derived class from LLDB SBBroardcaster API.
+//
+// *** This class (files) is a place holder until we know we need it or
+// *** not
+//
+// A singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 28/02/2014.
+// Changes: None.
+//--
+class CMICmnLLDBBroadcaster
+: public CMICmnBase
+, public lldb::SBBroadcaster
+, public MI::ISingleton< CMICmnLLDBBroadcaster >
+{
+ friend MI::ISingleton< CMICmnLLDBBroadcaster >;
+
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+// Methods:
+private:
+ /* ctor */ CMICmnLLDBBroadcaster( void );
+ /* ctor */ CMICmnLLDBBroadcaster( const CMICmnLLDBBroadcaster & );
+ void operator=( const CMICmnLLDBBroadcaster & );
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnLLDBBroadcaster( void );
+};
diff --git a/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
new file mode 100644
index 000000000000..3b7789ee1d63
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
@@ -0,0 +1,1312 @@
+//===-- MICmnLLDBDebugSessionInfo.cpp ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBDebugSessionInfo.cpp
+//
+// Overview: CMICmnLLDBDebugSessionInfo implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers:
+#include <lldb/API/SBThread.h>
+#ifdef _WIN32
+ #include <io.h> // For the ::_access()
+#else
+ #include <unistd.h> // For the ::access()
+#endif // _WIN32
+#include <lldb/API/SBBreakpointLocation.h>
+
+// In-house headers:
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MICmnLLDBDebugger.h"
+#include "MICmnResources.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnMIValueList.h"
+#include "MICmnMIValueTuple.h"
+#include "MICmdData.h"
+#include "MICmnLLDBUtilSBValue.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebugSessionInfo constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfo::CMICmnLLDBDebugSessionInfo( void )
+: m_rLldbDebugger( CMICmnLLDBDebugger::Instance().GetTheDebugger() )
+, m_rLlldbListener( CMICmnLLDBDebugger::Instance().GetTheListener() )
+, m_nBrkPointCntMax( INT32_MAX )
+, m_currentSelectedThread( LLDB_INVALID_THREAD_ID )
+, m_constStrSharedDataKeyWkDir( "Working Directory" )
+, m_constStrSharedDataSolibPath( "Solib Path" )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebugSessionInfo destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this object.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ m_currentSelectedThread = LLDB_INVALID_THREAD_ID;
+ CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero();
+
+ m_bInitialized = MIstatus::success;
+
+ return m_bInitialized;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this object.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Tidy up
+ bOk = SharedDataDestroy();
+ if( !bOk )
+ {
+ errMsg = CMIUtilString::Format( MIRSRC( IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE ) );
+ errMsg += "\n";
+ }
+ m_vecActiveThreadId.clear();
+ CMICmnLLDBDebugSessionInfoVarObj::VarObjClear();
+
+ m_bInitialized = false;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Command instances can create and share data between other instances of commands.
+// Data can also be assigned by a command and retrieved by LLDB event handler.
+// This function takes down those resources build up over the use of the commands.
+// This function should be called when the creation and running of command has
+// stopped i.e. application shutdown.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::SharedDataDestroy( void )
+{
+ m_mapIdToSessionData.Clear();
+ m_vecVarObj.clear();
+ m_mapBrkPtIdToBrkPtInfo.clear();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Record information about a LLDB break point so that is can be recalled in other
+// commands or LLDB event handling functions.
+// Type: Method.
+// Args: vBrkPtId - (R) LLDB break point ID.
+// vrBrkPtInfo - (R) Break point information object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfo( const MIuint vnBrkPtId, const SBrkPtInfo & vrBrkPtInfo )
+{
+ MapPairBrkPtIdToBrkPtInfo_t pr( vnBrkPtId, vrBrkPtInfo );
+ m_mapBrkPtIdToBrkPtInfo.insert( pr );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve information about a LLDB break point previous recorded either by
+// commands or LLDB event handling functions.
+// Type: Method.
+// Args: vBrkPtId - (R) LLDB break point ID.
+// vrwBrkPtInfo - (W) Break point information object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoGet( const MIuint vnBrkPtId, SBrkPtInfo & vrwBrkPtInfo ) const
+{
+ const MapBrkPtIdToBrkPtInfo_t::const_iterator it = m_mapBrkPtIdToBrkPtInfo.find( vnBrkPtId );
+ if( it != m_mapBrkPtIdToBrkPtInfo.end() )
+ {
+ vrwBrkPtInfo = (*it).second;
+ return MIstatus::success;
+ }
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Delete information about a specific LLDB break point object. This function
+// should be called when a LLDB break point is deleted.
+// Type: Method.
+// Args: vBrkPtId - (R) LLDB break point ID.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoDelete( const MIuint vnBrkPtId )
+{
+ const MapBrkPtIdToBrkPtInfo_t::const_iterator it = m_mapBrkPtIdToBrkPtInfo.find( vnBrkPtId );
+ if( it != m_mapBrkPtIdToBrkPtInfo.end() )
+ {
+ m_mapBrkPtIdToBrkPtInfo.erase( it );
+ return MIstatus::success;
+ }
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the specified thread's frame information.
+// Type: Method.
+// Args: vCmdData - (R) A command's information.
+// vThreadIdx - (R) Thread index.
+// vwrThreadFrames - (W) Frame data.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::GetThreadFrames( const SMICmdData & vCmdData, const MIuint vThreadIdx, CMIUtilString & vwrThreadFrames )
+{
+ lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID( vThreadIdx );
+ const uint32_t nFrames = thread.GetNumFrames();
+ if( nFrames == 0 )
+ {
+ // MI print "frame={}"
+ CMICmnMIValueTuple miValueTuple;
+ CMICmnMIValueResult miValueResult( "frame", miValueTuple );
+ vwrThreadFrames = miValueResult.GetString();
+ return MIstatus::success;
+ }
+
+ // MI print "frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}, ..."
+ CMIUtilString strListCommaSeperated;
+ for( MIuint nLevel = 0; nLevel < nFrames; nLevel++ )
+ {
+ lldb::SBFrame frame = thread.GetFrameAtIndex( nLevel );
+ lldb::addr_t pc = 0;
+ CMIUtilString fnName;
+ CMIUtilString fileName;
+ CMIUtilString path;
+ MIuint nLine = 0;
+ if( !GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
+ return MIstatus::failure;
+
+ // Function args
+ CMICmnMIValueList miValueList( true );
+ const MIuint maskVarTypes = 0x1000;
+ if( !MIResponseFormVariableInfo( frame, maskVarTypes, miValueList ) )
+ return MIstatus::failure;
+
+ const MIchar * pUnknown = "??";
+ if( fnName != pUnknown )
+ {
+ std::replace( fnName.begin(), fnName.end(), ')', ' ' );
+ std::replace( fnName.begin(), fnName.end(), '(', ' ' );
+ std::replace( fnName.begin(), fnName.end(), '\'', ' ' );
+ }
+
+ CMICmnMIValueTuple miValueTuple;
+ const CMIUtilString strLevel( CMIUtilString::Format( "%d", nLevel ) );
+ const CMICmnMIValueConst miValueConst( strLevel );
+ const CMICmnMIValueResult miValueResult( "level", miValueConst );
+ miValueTuple.Add( miValueResult );
+ if( !MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple ) )
+ return MIstatus::failure;
+
+ const CMICmnMIValueResult miValueResult2( "frame", miValueTuple );
+ if( nLevel != 0 )
+ strListCommaSeperated += ",";
+ strListCommaSeperated += miValueResult2.GetString();
+ }
+
+ vwrThreadFrames = strListCommaSeperated;
+
+ return MIstatus::success;
+}
+
+// Todo: Refactor maybe to so only one function with this name, but not just yet
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the specified thread's frame information.
+// Type: Method.
+// Args: vCmdData - (R) A command's information.
+// vThreadIdx - (R) Thread index.
+// vwrThreadFrames - (W) Frame data.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::GetThreadFrames2( const SMICmdData & vCmdData, const MIuint vThreadIdx, CMIUtilString & vwrThreadFrames )
+{
+ lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID( vThreadIdx );
+ const uint32_t nFrames = thread.GetNumFrames();
+ if( nFrames == 0 )
+ {
+ // MI print "frame={}"
+ CMICmnMIValueTuple miValueTuple;
+ CMICmnMIValueResult miValueResult( "frame", miValueTuple );
+ vwrThreadFrames = miValueResult.GetString();
+ return MIstatus::success;
+ }
+
+ // MI print "frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}, ..."
+ CMIUtilString strListCommaSeperated;
+ for( MIuint nLevel = 0; nLevel < nFrames; nLevel++ )
+ {
+ lldb::SBFrame frame = thread.GetFrameAtIndex( nLevel );
+ lldb::addr_t pc = 0;
+ CMIUtilString fnName;
+ CMIUtilString fileName;
+ CMIUtilString path;
+ MIuint nLine = 0;
+ if( !GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
+ return MIstatus::failure;
+
+ // Function args
+ CMICmnMIValueList miValueList( true );
+ const MIuint maskVarTypes = 0x1000;
+ if( !MIResponseFormVariableInfo2( frame, maskVarTypes, miValueList ) )
+ return MIstatus::failure;
+
+ const MIchar * pUnknown = "??";
+ if( fnName != pUnknown )
+ {
+ std::replace( fnName.begin(), fnName.end(), ')', ' ' );
+ std::replace( fnName.begin(), fnName.end(), '(', ' ' );
+ std::replace( fnName.begin(), fnName.end(), '\'', ' ' );
+ }
+
+ CMICmnMIValueTuple miValueTuple;
+ const CMIUtilString strLevel( CMIUtilString::Format( "%d", nLevel ) );
+ const CMICmnMIValueConst miValueConst( strLevel );
+ const CMICmnMIValueResult miValueResult( "level", miValueConst );
+ miValueTuple.Add( miValueResult );
+ if( !MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple ) )
+ return MIstatus::failure;
+
+ const CMICmnMIValueResult miValueResult2( "frame", miValueTuple );
+ if( nLevel != 0 )
+ strListCommaSeperated += ",";
+ strListCommaSeperated += miValueResult2.GetString();
+ }
+
+ vwrThreadFrames = strListCommaSeperated;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return the resolved file's path for the given file.
+// Type: Method.
+// Args: vCmdData - (R) A command's information.
+// vPath - (R) Original path.
+// vwrResolvedPath - (W) Resolved path.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::ResolvePath( const SMICmdData & vCmdData, const CMIUtilString & vPath, CMIUtilString & vwrResolvedPath )
+{
+ // ToDo: Verify this code as it does not work as vPath is always empty
+
+ CMIUtilString strResolvedPath;
+ if( !SharedDataRetrieve< CMIUtilString >( m_constStrSharedDataKeyWkDir, strResolvedPath ) )
+ {
+ vwrResolvedPath = "";
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_SHARED_DATA_NOT_FOUND ), vCmdData.strMiCmd.c_str(), m_constStrSharedDataKeyWkDir.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ vwrResolvedPath = vPath;
+
+ return ResolvePath( strResolvedPath, vwrResolvedPath );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return the resolved file's path for the given file.
+// Type: Method.
+// Args: vstrUnknown - (R) String assigned to path when resolved path is empty.
+// vwrResolvedPath - (RW) The original path overwritten with resolved path.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::ResolvePath( const CMIUtilString & vstrUnknown, CMIUtilString & vwrResolvedPath )
+{
+ if( vwrResolvedPath.size() < 1 )
+ {
+ vwrResolvedPath = vstrUnknown;
+ return MIstatus::success;
+ }
+
+ bool bOk = MIstatus::success;
+
+ CMIUtilString::VecString_t vecPathFolders;
+ const MIuint nSplits = vwrResolvedPath.Split( "/", vecPathFolders ); MIunused( nSplits );
+ MIuint nFoldersBack = 1; // 1 is just the file (last element of vector)
+ while( bOk && (vecPathFolders.size() >= nFoldersBack) )
+ {
+ CMIUtilString strTestPath;
+ MIuint nFoldersToAdd = nFoldersBack;
+ while( nFoldersToAdd > 0 )
+ {
+ strTestPath += "/";
+ strTestPath += vecPathFolders[ vecPathFolders.size() - nFoldersToAdd ];
+ nFoldersToAdd--;
+ }
+ bool bYesAccessible = false;
+ bOk = AccessPath( strTestPath, bYesAccessible );
+ if( bYesAccessible )
+ {
+ vwrResolvedPath = strTestPath;
+ return MIstatus::success;
+ }
+ else
+ nFoldersBack++;
+ }
+
+ // No files exist in the union of working directory and debuginfo path
+ // Simply use the debuginfo path and let the IDE handle it.
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine the given file path exists or not.
+// Type: Method.
+// Args: vPath - (R) File name path.
+// vwbYesAccessible - (W) True - file exists, false = does not exist.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::AccessPath( const CMIUtilString & vPath, bool & vwbYesAccessible )
+{
+#ifdef _WIN32
+ vwbYesAccessible = (::_access( vPath.c_str(), 0 ) == 0);
+#else
+ vwbYesAccessible = (::access( vPath.c_str(), 0 ) == 0);
+#endif // _WIN32
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Form MI partial response by appending more MI value type objects to the
+// tuple type object past in.
+// Type: Method.
+// Args: vCmdData - (R) A command's information.
+// vrThread - (R) LLDB thread object.
+// vwrMIValueTuple - (W) MI value tuple object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple )
+{
+ lldb::SBThread & rThread = const_cast< lldb::SBThread & >( vrThread );
+
+ CMIUtilString strFrames;
+ if( !GetThreadFrames( vCmdData, rThread.GetIndexID(), strFrames ) )
+ return MIstatus::failure;
+
+ const bool bSuspended = rThread.IsSuspended();
+ const lldb::StopReason eReason = rThread.GetStopReason();
+ const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid));
+ const CMIUtilString strState( (bSuspended || bValidReason) ? "stopped" : "running" );
+
+ // Add "id"
+ const CMIUtilString strId( CMIUtilString::Format( "%d", rThread.GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst1( strId );
+ const CMICmnMIValueResult miValueResult1( "id", miValueConst1 );
+ if( !vwrMIValueTuple.Add( miValueResult1 ) )
+ return MIstatus::failure;
+
+ // Add "target-id"
+ const MIchar * pThreadName = rThread.GetName();
+ const MIuint len = (pThreadName != nullptr) ? CMIUtilString( pThreadName ).length() : 0;
+ const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && CMIUtilString::IsAllValidAlphaAndNumeric( *pThreadName ) ); // 32 is arbitary number
+ const MIchar * pThrdFmt = bHaveName ? "%s" : "Thread %d";
+ CMIUtilString strThread;
+ if( bHaveName )
+ strThread = CMIUtilString::Format( pThrdFmt, pThreadName );
+ else
+ strThread = CMIUtilString::Format( pThrdFmt, rThread.GetIndexID() );
+ const CMICmnMIValueConst miValueConst2( strThread );
+ const CMICmnMIValueResult miValueResult2( "target-id", miValueConst2 );
+ if( !vwrMIValueTuple.Add( miValueResult2 ) )
+ return MIstatus::failure;
+
+ // Add "frame"
+ const CMICmnMIValueConst miValueConst3( strFrames, true );
+ if( !vwrMIValueTuple.Add( miValueConst3, false ) )
+ return MIstatus::failure;
+
+ // Add "state"
+ const CMICmnMIValueConst miValueConst4( strState );
+ const CMICmnMIValueResult miValueResult4( "state", miValueConst4 );
+ if( !vwrMIValueTuple.Add( miValueResult4 ) )
+ return MIstatus::failure;
+
+ return MIstatus::success;
+}
+
+// Todo: Refactor maybe to so only one function with this name, but not just yet
+//++ ------------------------------------------------------------------------------------
+// Details: Form MI partial response by appending more MI value type objects to the
+// tuple type object past in.
+// Type: Method.
+// Args: vCmdData - (R) A command's information.
+// vrThread - (R) LLDB thread object.
+// vwrMIValueTuple - (W) MI value tuple object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo3( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple )
+{
+ lldb::SBThread & rThread = const_cast< lldb::SBThread & >( vrThread );
+
+ CMIUtilString strFrames;
+ if( !GetThreadFrames2( vCmdData, rThread.GetIndexID(), strFrames ) )
+ return MIstatus::failure;
+
+ const bool bSuspended = rThread.IsSuspended();
+ const lldb::StopReason eReason = rThread.GetStopReason();
+ const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid));
+ const CMIUtilString strState( (bSuspended || bValidReason) ? "stopped" : "running" );
+
+ // Add "id"
+ const CMIUtilString strId( CMIUtilString::Format( "%d", rThread.GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst1( strId );
+ const CMICmnMIValueResult miValueResult1( "id", miValueConst1 );
+ if( !vwrMIValueTuple.Add( miValueResult1 ) )
+ return MIstatus::failure;
+
+ // Add "target-id"
+ const MIchar * pThreadName = rThread.GetName();
+ const MIuint len = (pThreadName != nullptr) ? CMIUtilString( pThreadName ).length() : 0;
+ const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && CMIUtilString::IsAllValidAlphaAndNumeric( *pThreadName ) ); // 32 is arbitary number
+ const MIchar * pThrdFmt = bHaveName ? "%s" : "Thread %d";
+ CMIUtilString strThread;
+ if( bHaveName )
+ strThread = CMIUtilString::Format( pThrdFmt, pThreadName );
+ else
+ strThread = CMIUtilString::Format( pThrdFmt, rThread.GetIndexID() );
+ const CMICmnMIValueConst miValueConst2( strThread );
+ const CMICmnMIValueResult miValueResult2( "target-id", miValueConst2 );
+ if( !vwrMIValueTuple.Add( miValueResult2 ) )
+ return MIstatus::failure;
+
+ // Add "frame"
+ const CMICmnMIValueConst miValueConst3( strFrames, true );
+ if( !vwrMIValueTuple.Add( miValueConst3, false ) )
+ return MIstatus::failure;
+
+ // Add "state"
+ const CMICmnMIValueConst miValueConst4( strState );
+ const CMICmnMIValueResult miValueResult4( "state", miValueConst4 );
+ if( !vwrMIValueTuple.Add( miValueResult4 ) )
+ return MIstatus::failure;
+
+ return MIstatus::success;
+}
+
+// Todo: Refactor maybe to so only one function with this name, but not just yet
+//++ ------------------------------------------------------------------------------------
+// Details: Form MI partial response by appending more MI value type objects to the
+// tuple type object past in.
+// Type: Method.
+// Args: vCmdData - (R) A command's information.
+// vrThread - (R) LLDB thread object.
+// vwrMIValueTuple - (W) MI value tuple object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple )
+{
+ lldb::SBThread & rThread = const_cast< lldb::SBThread & >( vrThread );
+
+ const bool bSuspended = rThread.IsSuspended();
+ const lldb::StopReason eReason = rThread.GetStopReason();
+ const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid));
+ const CMIUtilString strState( (bSuspended || bValidReason) ? "stopped" : "running" );
+
+ // Add "id"
+ const CMIUtilString strId( CMIUtilString::Format( "%d", rThread.GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst1( strId );
+ const CMICmnMIValueResult miValueResult1( "id", miValueConst1 );
+ if( !vwrMIValueTuple.Add( miValueResult1 ) )
+ return MIstatus::failure;
+
+ // Add "target-id"
+ const MIchar * pThreadName = rThread.GetName();
+ const MIuint len = (pThreadName != nullptr) ? CMIUtilString( pThreadName ).length() : 0;
+ const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && CMIUtilString::IsAllValidAlphaAndNumeric( *pThreadName ) ); // 32 is arbitary number
+ const MIchar * pThrdFmt = bHaveName ? "%s" : "Thread %d";
+ CMIUtilString strThread;
+ if( bHaveName )
+ strThread = CMIUtilString::Format( pThrdFmt, pThreadName );
+ else
+ strThread = CMIUtilString::Format( pThrdFmt, rThread.GetIndexID() );
+ const CMICmnMIValueConst miValueConst2( strThread );
+ const CMICmnMIValueResult miValueResult2( "target-id", miValueConst2 );
+ if( !vwrMIValueTuple.Add( miValueResult2 ) )
+ return MIstatus::failure;
+
+ // Add "state"
+ const CMICmnMIValueConst miValueConst4( strState );
+ const CMICmnMIValueResult miValueResult4( "state", miValueConst4 );
+ if( !vwrMIValueTuple.Add( miValueResult4 ) )
+ return MIstatus::failure;
+
+ return MIstatus::success;
+}
+
+// Todo: Refactor maybe to so only one function with this name, but not just yet
+//++ ------------------------------------------------------------------------------------
+// Details: Form MI partial response by appending more MI value type objects to the
+// tuple type object past in.
+// Type: Method.
+// Args: vrFrame - (R) LLDB thread object.
+// vMaskVarTypes - (R) 0x1000 = arguments,
+// 0x0100 = locals,
+// 0x0010 = statics,
+// 0x0001 = in scope only.
+// vwrMIValueList - (W) MI value list object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo2( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList )
+{
+ bool bOk = MIstatus::success;
+ lldb::SBFrame & rFrame = const_cast< lldb::SBFrame & >( vrFrame );
+
+ const bool bArg = (vMaskVarTypes & 0x1000);
+ const bool bLocals = (vMaskVarTypes & 0x0100);
+ const bool bStatics = (vMaskVarTypes & 0x0010);
+ const bool bInScopeOnly = (vMaskVarTypes & 0x0001);
+ lldb::SBValueList listArg = rFrame.GetVariables( bArg, bLocals, bStatics, bInScopeOnly );
+ const MIuint nArgs = listArg.GetSize();
+ for( MIuint i = 0; bOk && (i < nArgs); i++ )
+ {
+ lldb::SBValue value = listArg.GetValueAtIndex( i );
+ const CMICmnLLDBUtilSBValue utilValue( value );
+ const CMICmnMIValueConst miValueConst( utilValue.GetName() );
+ const CMICmnMIValueResult miValueResult( "name", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueConst miValueConst2( utilValue.GetValue() );
+ const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
+ miValueTuple.Add( miValueResult2 );
+ bOk = vwrMiValueList.Add( miValueTuple );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Form MI partial response by appending more MI value type objects to the
+// tuple type object past in.
+// Type: Method.
+// Args: vrFrame - (R) LLDB thread object.
+// vMaskVarTypes - (R) 0x1000 = arguments,
+// 0x0100 = locals,
+// 0x0010 = statics,
+// 0x0001 = in scope only.
+// vwrMIValueList - (W) MI value list object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList )
+{
+ bool bOk = MIstatus::success;
+ lldb::SBFrame & rFrame = const_cast< lldb::SBFrame & >( vrFrame );
+
+ const bool bArg = (vMaskVarTypes & 0x1000);
+ const bool bLocals = (vMaskVarTypes & 0x0100);
+ const bool bStatics = (vMaskVarTypes & 0x0010);
+ const bool bInScopeOnly = (vMaskVarTypes & 0x0001);
+ const MIuint nMaxRecusiveDepth = 10;
+ MIuint nCurrentRecursiveDepth = 0;
+ lldb::SBValueList listArg = rFrame.GetVariables( bArg, bLocals, bStatics, bInScopeOnly );
+ const MIuint nArgs = listArg.GetSize();
+ for( MIuint i = 0; bOk && (i < nArgs); i++ )
+ {
+ lldb::SBValue value = listArg.GetValueAtIndex( i );
+ bOk = GetVariableInfo( nMaxRecusiveDepth, value, false, vwrMiValueList, nCurrentRecursiveDepth );
+ }
+
+ return bOk;
+}
+
+// *** Do not refactor this function to be one function with same name as it can break more than
+// *** than one stack type command
+//++ ------------------------------------------------------------------------------------
+// Details: Form MI partial response by appending more MI value type objects to the
+// tuple type object past in.
+// Type: Method.
+// Args: vrFrame - (R) LLDB thread object.
+// vMaskVarTypes - (R) 0x1000 = arguments,
+// 0x0100 = locals,
+// 0x0010 = statics,
+// 0x0001 = in scope only.
+// vwrMIValueList - (W) MI value list object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo3( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList )
+{
+ bool bOk = MIstatus::success;
+ lldb::SBFrame & rFrame = const_cast< lldb::SBFrame & >( vrFrame );
+
+ const bool bArg = (vMaskVarTypes & 0x1000);
+ const bool bLocals = (vMaskVarTypes & 0x0100);
+ const bool bStatics = (vMaskVarTypes & 0x0010);
+ const bool bInScopeOnly = (vMaskVarTypes & 0x0001);
+ const MIuint nMaxRecusiveDepth = 10;
+ MIuint nCurrentRecursiveDepth = 0;
+ lldb::SBValueList listArg = rFrame.GetVariables( bArg, bLocals, bStatics, bInScopeOnly );
+ const MIuint nArgs = listArg.GetSize();
+ for( MIuint i = 0; bOk && (i < nArgs); i++ )
+ {
+ lldb::SBValue value = listArg.GetValueAtIndex( i );
+ bOk = GetVariableInfo2( nMaxRecusiveDepth, value, false, vwrMiValueList, nCurrentRecursiveDepth );
+ }
+
+ return bOk;
+}
+
+// *** Do not refactor this function to be one function with same name as it can break more than
+// *** than one stack type command
+//++ ------------------------------------------------------------------------------------
+// Details: Extract the value's name and value or recurse into child value object.
+// Type: Method.
+// Args: vnMaxDepth - (R) The max recursive depth for this function.
+// vrValue - (R) LLDB value object.
+// vbIsChildValue - (R) True = Value object is a child of a higher Value object,
+// - False = Value object not a child.
+// vwrMIValueList - (W) MI value list object.
+// vnDepth - (RW) The current recursive depth of this function.
+// // Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::GetVariableInfo( const MIuint vnMaxDepth, const lldb::SBValue & vrValue, const bool vbIsChildValue, CMICmnMIValueList & vwrMiValueList, MIuint & vrwnDepth )
+{
+ // *** Update GetVariableInfo2() with any code changes here ***
+
+ // Check recursive depth
+ if( vrwnDepth >= vnMaxDepth )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue );
+ const CMICmnLLDBUtilSBValue utilValue( vrValue, true );
+ CMICmnMIValueTuple miValueTuple;
+ const MIchar * pName = rValue.GetName(); MIunused( pName );
+ const bool bIsPointerType = rValue.GetType().IsPointerType();
+ const MIuint nChildren = rValue.GetNumChildren();
+ if( nChildren == 0 )
+ {
+ if( vbIsChildValue )
+ {
+ if( utilValue.IsCharType() )
+ {
+ // For char types and try to form text string
+ const CMICmnMIValueConst miValueConst( utilValue.GetValue().c_str(), true );
+ miValueTuple.Add( miValueConst, true );
+ }
+ else
+ {
+ // For composite types
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str() ), true );
+ miValueTuple.Add( miValueConst, true );
+ }
+ return vwrMiValueList.Add( CMICmnMIValueConst( miValueTuple.ExtractContentNoBrackets(), true ) );
+ }
+ else
+ {
+ // Basic types
+ const CMICmnMIValueConst miValueConst( utilValue.GetName() );
+ const CMICmnMIValueResult miValueResult( "name", miValueConst );
+ miValueTuple.Add( miValueResult );
+ const CMICmnMIValueConst miValueConst2( utilValue.GetValue() );
+ const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
+ miValueTuple.Add( miValueResult2 );
+ return vwrMiValueList.Add( miValueTuple );
+ }
+ }
+ else if( bIsPointerType && utilValue.IsChildCharType() )
+ {
+ // Append string text to the parent value information
+ const CMICmnMIValueConst miValueConst( utilValue.GetName() );
+ const CMICmnMIValueResult miValueResult( "name", miValueConst );
+ miValueTuple.Add( miValueResult );
+
+ const CMIUtilString & rText( utilValue.GetChildValueCString() );
+ if( rText.empty() )
+ {
+ const CMICmnMIValueConst miValueConst( utilValue.GetValue() );
+ const CMICmnMIValueResult miValueResult( "value", miValueConst );
+ miValueTuple.Add( miValueResult );
+ }
+ else
+ {
+ if( utilValue.IsValueUnknown() )
+ {
+ const CMICmnMIValueConst miValueConst( rText );
+ const CMICmnMIValueResult miValueResult( "value", miValueConst );
+ miValueTuple.Add( miValueResult );
+ }
+ else
+ {
+ // Note code that has const in will not show the text suffix to the string pointer
+ // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this
+ // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%s %s", utilValue.GetValue().c_str(), rText.c_str() ) );
+ const CMICmnMIValueResult miValueResult( "value", miValueConst );
+ miValueTuple.Add( miValueResult );
+ }
+ }
+ return vwrMiValueList.Add( miValueTuple );
+ }
+ else if( bIsPointerType )
+ {
+ if( vbIsChildValue )
+ {
+ // For composite types
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str() ), true );
+ miValueTuple.Add( miValueConst, true );
+ return vwrMiValueList.Add( CMICmnMIValueConst( miValueTuple.ExtractContentNoBrackets(), true ) );
+ }
+ else
+ {
+ // Basic types
+ const CMICmnMIValueConst miValueConst( utilValue.GetName() );
+ const CMICmnMIValueResult miValueResult( "name", miValueConst );
+ miValueTuple.Add( miValueResult );
+ const CMICmnMIValueConst miValueConst2( utilValue.GetValue() );
+ const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
+ miValueTuple.Add( miValueResult2 );
+ return vwrMiValueList.Add( miValueTuple );
+ }
+ }
+ else
+ {
+ // Build parent child composite types
+ CMICmnMIValueList miValueList( true );
+ for( MIuint i = 0; bOk && (i < nChildren); i++ )
+ {
+ lldb::SBValue member = rValue.GetChildAtIndex( i );
+ bOk = GetVariableInfo( vnMaxDepth, member, true, miValueList, ++vrwnDepth );
+ }
+ const CMICmnMIValueConst miValueConst( utilValue.GetName() );
+ const CMICmnMIValueResult miValueResult( "name", miValueConst );
+ miValueTuple.Add( miValueResult );
+ const CMICmnMIValueConst miValueConst2( CMIUtilString::Format( "{%s}", miValueList.ExtractContentNoBrackets().c_str() ) );
+ const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
+ miValueTuple.Add( miValueResult2 );
+ return vwrMiValueList.Add( miValueTuple );
+ }
+}
+
+// *** Do not refactor this function to be one function with same name as it can break more than
+// *** than one stack type command
+//++ ------------------------------------------------------------------------------------
+// Details: Extract the value's name and value or recurse into child value object.
+// Type: Method.
+// Args: vnMaxDepth - (R) The max recursive depth for this function.
+// vrValue - (R) LLDB value object.
+// vbIsChildValue - (R) True = Value object is a child of a higher Value object,
+// - False = Value object not a child.
+// vwrMIValueList - (W) MI value list object.
+// vnDepth - (RW) The current recursive depth of this function.
+// // Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::GetVariableInfo2( const MIuint vnMaxDepth, const lldb::SBValue & vrValue, const bool vbIsChildValue, CMICmnMIValueList & vwrMiValueList, MIuint & vrwnDepth )
+{
+ // *** Update GetVariableInfo() with any code changes here ***
+
+ // Check recursive depth
+ if( vrwnDepth >= vnMaxDepth )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue );
+ const CMICmnLLDBUtilSBValue utilValue( vrValue, true );
+ CMICmnMIValueTuple miValueTuple;
+ const MIchar * pName = rValue.GetName(); MIunused( pName );
+ const MIuint nChildren = rValue.GetNumChildren();
+ if( nChildren == 0 )
+ {
+ if( vbIsChildValue && utilValue.IsCharType() )
+ {
+ // For char types and try to form text string
+ const CMICmnMIValueConst miValueConst( utilValue.GetValue().c_str(), true );
+ miValueTuple.Add( miValueConst, true );
+ return vwrMiValueList.Add( CMICmnMIValueConst( miValueTuple.ExtractContentNoBrackets(), true ) );
+ }
+ else
+ {
+ // Basic types
+ const CMICmnMIValueConst miValueConst( utilValue.GetName() );
+ const CMICmnMIValueResult miValueResult( "name", miValueConst );
+ miValueTuple.Add( miValueResult );
+ const CMICmnMIValueConst miValueConst2( utilValue.GetValue() );
+ const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
+ miValueTuple.Add( miValueResult2 );
+ return vwrMiValueList.Add( miValueTuple );
+ }
+ }
+ else if( utilValue.IsChildCharType() )
+ {
+ // Append string text to the parent value information
+ const CMICmnMIValueConst miValueConst( utilValue.GetName() );
+ const CMICmnMIValueResult miValueResult( "name", miValueConst );
+ miValueTuple.Add( miValueResult );
+
+ const CMIUtilString & rText( utilValue.GetChildValueCString() );
+ if( rText.empty() )
+ {
+ const CMICmnMIValueConst miValueConst( utilValue.GetValue() );
+ const CMICmnMIValueResult miValueResult( "value", miValueConst );
+ miValueTuple.Add( miValueResult );
+ }
+ else
+ {
+ if( utilValue.IsValueUnknown() )
+ {
+ const CMICmnMIValueConst miValueConst( rText );
+ const CMICmnMIValueResult miValueResult( "value", miValueConst );
+ miValueTuple.Add( miValueResult );
+ }
+ else
+ {
+ // Note code that has const in will not show the text suffix to the string pointer
+ // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this
+ // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%s %s", utilValue.GetValue().c_str(), rText.c_str() ) );
+ const CMICmnMIValueResult miValueResult( "value", miValueConst );
+ miValueTuple.Add( miValueResult );
+ }
+ }
+ return vwrMiValueList.Add( miValueTuple );
+ }
+ else
+ {
+ // Build parent child composite types
+ CMICmnMIValueList miValueList( true );
+ for( MIuint i = 0; bOk && (i < nChildren); i++ )
+ {
+ lldb::SBValue member = rValue.GetChildAtIndex( i );
+ bOk = GetVariableInfo( vnMaxDepth, member, true, miValueList, ++vrwnDepth );
+ }
+ const CMICmnMIValueConst miValueConst( utilValue.GetName() );
+ const CMICmnMIValueResult miValueResult( "name", miValueConst );
+ miValueTuple.Add( miValueResult );
+ const CMICmnMIValueConst miValueConst2( CMIUtilString::Format( "{%s}", miValueList.ExtractContentNoBrackets().c_str() ) );
+ const CMICmnMIValueResult miValueResult2( "value", miValueConst2 );
+ miValueTuple.Add( miValueResult2 );
+ return vwrMiValueList.Add( miValueTuple );
+ }
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Form MI partial response by appending more MI value type objects to the
+// tuple type object past in.
+// Type: Method.
+// Args: vrThread - (R) LLDB thread object.
+// vwrMIValueTuple - (W) MI value tuple object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo( const lldb::SBThread & vrThread, const MIuint vnLevel, CMICmnMIValueTuple & vwrMiValueTuple )
+{
+ lldb::SBThread & rThread = const_cast< lldb::SBThread & >( vrThread );
+
+ lldb::SBFrame frame = rThread.GetFrameAtIndex( vnLevel );
+ lldb::addr_t pc = 0;
+ CMIUtilString fnName;
+ CMIUtilString fileName;
+ CMIUtilString path;
+ MIuint nLine = 0;
+ if( !GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
+ return MIstatus::failure;
+
+ // MI print "{level=\"0\",addr=\"0x%08llx\",func=\"%s\",file=\"%s\",fullname=\"%s\",line=\"%d\"}"
+ const CMIUtilString strLevel( CMIUtilString::Format( "%d", vnLevel ) );
+ const CMICmnMIValueConst miValueConst( strLevel );
+ const CMICmnMIValueResult miValueResult( "level", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ if( !MIResponseFormFrameInfo( pc, fnName, fileName, path, nLine, miValueTuple ) )
+ return MIstatus::failure;
+
+ vwrMiValueTuple = miValueTuple;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the frame information from LLDB frame object.
+// Type: Method.
+// Args: vrFrame - (R) LLDB thread object.
+// vPc - (W) Address number.
+// vFnName - (W) Function name.
+// vFileName - (W) File name text.
+// vPath - (W) Full file name and path text.
+// vnLine - (W) File line number.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::GetFrameInfo( const lldb::SBFrame & vrFrame, lldb::addr_t & vwPc, CMIUtilString & vwFnName, CMIUtilString & vwFileName, CMIUtilString & vwPath, MIuint & vwnLine )
+{
+ lldb::SBFrame & rFrame = const_cast< lldb::SBFrame & >( vrFrame );
+
+ static char pBuffer[ MAX_PATH ];
+ const MIuint nBytes = rFrame.GetLineEntry().GetFileSpec().GetPath( &pBuffer[ 0 ], sizeof( pBuffer ) ); MIunused( nBytes );
+ CMIUtilString strResolvedPath( &pBuffer[ 0 ] );
+ const MIchar * pUnkwn = "??";
+ if( !ResolvePath( pUnkwn, strResolvedPath ) )
+ return MIstatus::failure;
+ vwPath = strResolvedPath;
+
+ vwPc = rFrame.GetPC();
+
+ const MIchar * pFnName = rFrame.GetFunctionName();
+ vwFnName = (pFnName != nullptr) ? pFnName : pUnkwn;
+
+ const MIchar * pFileName = rFrame.GetLineEntry().GetFileSpec().GetFilename();
+ vwFileName = (pFileName != nullptr) ? pFileName : pUnkwn;
+
+ vwnLine = rFrame.GetLineEntry().GetLine();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Form MI partial response by appending more MI value type objects to the
+// tuple type object past in.
+// Type: Method.
+// Args: vPc - (R) Address number.
+// vFnName - (R) Function name.
+// vFileName - (R) File name text.
+// vPath - (R) Full file name and path text.
+// vnLine - (R) File line number.
+// vwrMIValueTuple - (W) MI value tuple object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo( const lldb::addr_t vPc, const CMIUtilString & vFnName, const CMIUtilString & vFileName, const CMIUtilString & vPath, const MIuint vnLine, CMICmnMIValueTuple & vwrMiValueTuple )
+{
+ const CMIUtilString strAddr( CMIUtilString::Format( "0x%08llx", vPc ) );
+ const CMICmnMIValueConst miValueConst2( strAddr );
+ const CMICmnMIValueResult miValueResult2( "addr", miValueConst2 );
+ if( !vwrMiValueTuple.Add( miValueResult2 ) )
+ return MIstatus::failure;
+ const CMICmnMIValueConst miValueConst3( vFnName );
+ const CMICmnMIValueResult miValueResult3( "func", miValueConst3 );
+ if( !vwrMiValueTuple.Add( miValueResult3 ) )
+ return MIstatus::failure;
+ const CMICmnMIValueConst miValueConst5( vFileName );
+ const CMICmnMIValueResult miValueResult5( "file", miValueConst5 );
+ if( !vwrMiValueTuple.Add( miValueResult5 ) )
+ return MIstatus::failure;
+ const CMICmnMIValueConst miValueConst6( vPath );
+ const CMICmnMIValueResult miValueResult6( "fullname", miValueConst6 );
+ if( !vwrMiValueTuple.Add( miValueResult6 ) )
+ return MIstatus::failure;
+ const CMIUtilString strLine( CMIUtilString::Format( "%d", vnLine ) );
+ const CMICmnMIValueConst miValueConst7( strLine );
+ const CMICmnMIValueResult miValueResult7( "line", miValueConst7 );
+ if( !vwrMiValueTuple.Add( miValueResult7 ) )
+ return MIstatus::failure;
+
+ return MIstatus::success;
+}
+
+// Todo: Refactor maybe to so only one function with this name, but not just yet
+//++ ------------------------------------------------------------------------------------
+// Details: Form MI partial response by appending more MI value type objects to the
+// tuple type object past in.
+// Type: Method.
+// Args: vPc - (R) Address number.
+// vArgInfo - (R) Args information in MI response form.
+// vFnName - (R) Function name.
+// vFileName - (R) File name text.
+// vPath - (R) Full file name and path text.
+// vnLine - (R) File line number.
+// vwrMIValueTuple - (W) MI value tuple object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo2( const lldb::addr_t vPc, const CMIUtilString & vArgInfo, const CMIUtilString & vFnName, const CMIUtilString & vFileName, const CMIUtilString & vPath, const MIuint vnLine, CMICmnMIValueTuple & vwrMiValueTuple )
+{
+ const CMIUtilString strAddr( CMIUtilString::Format( "0x%08llx", vPc ) );
+ const CMICmnMIValueConst miValueConst2( strAddr );
+ const CMICmnMIValueResult miValueResult2( "addr", miValueConst2 );
+ if( !vwrMiValueTuple.Add( miValueResult2 ) )
+ return MIstatus::failure;
+ const CMICmnMIValueConst miValueConst3( vFnName );
+ const CMICmnMIValueResult miValueResult3( "func", miValueConst3 );
+ if( !vwrMiValueTuple.Add( miValueResult3 ) )
+ return MIstatus::failure;
+ const CMICmnMIValueConst miValueConst4( vArgInfo, true );
+ const CMICmnMIValueResult miValueResult4( "args", miValueConst4 );
+ if( !vwrMiValueTuple.Add( miValueResult4 ) )
+ return MIstatus::failure;
+ const CMICmnMIValueConst miValueConst5( vFileName );
+ const CMICmnMIValueResult miValueResult5( "file", miValueConst5 );
+ if( !vwrMiValueTuple.Add( miValueResult5 ) )
+ return MIstatus::failure;
+ const CMICmnMIValueConst miValueConst6( vPath );
+ const CMICmnMIValueResult miValueResult6( "fullname", miValueConst6 );
+ if( !vwrMiValueTuple.Add( miValueResult6 ) )
+ return MIstatus::failure;
+ const CMIUtilString strLine( CMIUtilString::Format( "%d", vnLine ) );
+ const CMICmnMIValueConst miValueConst7( strLine );
+ const CMICmnMIValueResult miValueResult7( "line", miValueConst7 );
+ if( !vwrMiValueTuple.Add( miValueResult7 ) )
+ return MIstatus::failure;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Form MI partial response by appending more MI value type objects to the
+// tuple type object past in.
+// Type: Method.
+// Args: vrBrkPtInfo - (R) Break point information object.
+// vwrMIValueTuple - (W) MI value tuple object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtFrameInfo( const SBrkPtInfo & vrBrkPtInfo, CMICmnMIValueTuple & vwrMiValueTuple )
+{
+ const CMIUtilString strAddr( CMIUtilString::Format( "0x%08llx", vrBrkPtInfo.m_pc ) );
+ const CMICmnMIValueConst miValueConst2( strAddr );
+ const CMICmnMIValueResult miValueResult2( "addr", miValueConst2 );
+ if( !vwrMiValueTuple.Add( miValueResult2 ) )
+ return MIstatus::failure;
+ const CMICmnMIValueConst miValueConst3( vrBrkPtInfo.m_fnName );
+ const CMICmnMIValueResult miValueResult3( "func", miValueConst3 );
+ if( !vwrMiValueTuple.Add( miValueResult3 ) )
+ return MIstatus::failure;
+ const CMICmnMIValueConst miValueConst5( vrBrkPtInfo.m_fileName );
+ const CMICmnMIValueResult miValueResult5( "file", miValueConst5 );
+ if( !vwrMiValueTuple.Add( miValueResult5 ) )
+ return MIstatus::failure;
+ const CMIUtilString strN5 = CMIUtilString::Format( "%s/%s", vrBrkPtInfo.m_path.c_str(), vrBrkPtInfo.m_fileName.c_str() );
+ const CMICmnMIValueConst miValueConst6( strN5 );
+ const CMICmnMIValueResult miValueResult6( "fullname", miValueConst6 );
+ if( !vwrMiValueTuple.Add( miValueResult6 ) )
+ return MIstatus::failure;
+ const CMIUtilString strLine( CMIUtilString::Format( "%d", vrBrkPtInfo.m_nLine ) );
+ const CMICmnMIValueConst miValueConst7( strLine );
+ const CMICmnMIValueResult miValueResult7( "line", miValueConst7 );
+ if( !vwrMiValueTuple.Add( miValueResult7 ) )
+ return MIstatus::failure;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Form MI partial response by appending more MI value type objects to the
+// tuple type object past in.
+// Type: Method.
+// Args: vrBrkPtInfo - (R) Break point information object.
+// vwrMIValueTuple - (W) MI value tuple object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtInfo( const SBrkPtInfo & vrBrkPtInfo, CMICmnMIValueTuple & vwrMiValueTuple )
+{
+ // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\", func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
+
+ // "number="
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", vrBrkPtInfo.m_id ) );
+ const CMICmnMIValueResult miValueResult( "number", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ // "type="
+ const CMICmnMIValueConst miValueConst2( vrBrkPtInfo.m_strType );
+ const CMICmnMIValueResult miValueResult2( "type", miValueConst2 );
+ bool bOk = miValueTuple.Add( miValueResult2 );
+ // "disp="
+ const CMICmnMIValueConst miValueConst3( vrBrkPtInfo.m_bDisp ? "del" : "keep" );
+ const CMICmnMIValueResult miValueResult3( "disp", miValueConst3 );
+ bOk = bOk && miValueTuple.Add( miValueResult3 );
+ // "enabled="
+ const CMICmnMIValueConst miValueConst4( vrBrkPtInfo.m_bEnabled ? "y" : "n" );
+ const CMICmnMIValueResult miValueResult4( "enabled", miValueConst4 );
+ bOk = bOk && miValueTuple.Add( miValueResult4 );
+ // "addr="
+ // "func="
+ // "file="
+ // "fullname="
+ // "line="
+ bOk = bOk && MIResponseFormBrkPtFrameInfo( vrBrkPtInfo, miValueTuple );
+ // "pending="
+ if( vrBrkPtInfo.m_bPending )
+ {
+ const CMICmnMIValueConst miValueConst( vrBrkPtInfo.m_strOrigLoc );
+ const CMICmnMIValueList miValueList( miValueConst );
+ const CMICmnMIValueResult miValueResult( "pending", miValueList );
+ bOk = bOk && miValueTuple.Add( miValueResult );
+ }
+ if( vrBrkPtInfo.m_bHaveArgOptionThreadGrp )
+ {
+ const CMICmnMIValueConst miValueConst( vrBrkPtInfo.m_strOptThrdGrp );
+ const CMICmnMIValueList miValueList( miValueConst );
+ const CMICmnMIValueResult miValueResult( "thread-groups", miValueList );
+ bOk = bOk && miValueTuple.Add( miValueResult );
+ }
+ // "times="
+ const CMICmnMIValueConst miValueConstB( CMIUtilString::Format( "%d", vrBrkPtInfo.m_nTimes ) );
+ const CMICmnMIValueResult miValueResultB( "times", miValueConstB );
+ bOk = bOk && miValueTuple.Add( miValueResultB );
+ // "thread="
+ if( vrBrkPtInfo.m_bBrkPtThreadId )
+ {
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", vrBrkPtInfo.m_nBrkPtThreadId ) );
+ const CMICmnMIValueResult miValueResult( "thread", miValueConst );
+ bOk = bOk && miValueTuple.Add( miValueResult );
+ }
+ // "cond="
+ if( vrBrkPtInfo.m_bCondition )
+ {
+ const CMICmnMIValueConst miValueConst( vrBrkPtInfo.m_strCondition );
+ const CMICmnMIValueResult miValueResult( "cond", miValueConst );
+ bOk = bOk && miValueTuple.Add( miValueResult );
+ }
+ // "ignore="
+ if( vrBrkPtInfo.m_nIgnore != 0 )
+ {
+ const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", vrBrkPtInfo.m_nIgnore ) );
+ const CMICmnMIValueResult miValueResult( "ignore", miValueConst );
+ bOk = bOk && miValueTuple.Add( miValueResult );
+ }
+ // "original-location="
+ const CMICmnMIValueConst miValueConstC( vrBrkPtInfo.m_strOrigLoc );
+ const CMICmnMIValueResult miValueResultC( "original-location", miValueConstC );
+ bOk = bOk && miValueTuple.Add( miValueResultC );
+
+ vwrMiValueTuple = miValueTuple;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve breakpoint information and write into the given breakpoint information
+// object. Note not all possible information is retrieved and so the information
+// object may need to be filled in with more information after calling this
+// function. Mainly breakpoint location information of information that is
+// unlikely to change.
+// Type: Method.
+// Args: vBrkPt - (R) LLDB break point object.
+// vrBrkPtInfo - (W) Break point information object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfo::GetBrkPtInfo( const lldb::SBBreakpoint & vBrkPt, SBrkPtInfo & vrwBrkPtInfo ) const
+{
+ lldb::SBBreakpoint & rBrkPt = const_cast< lldb::SBBreakpoint & >( vBrkPt );
+ lldb::SBBreakpointLocation brkPtLoc = rBrkPt.GetLocationAtIndex( 0 );
+ lldb::SBAddress brkPtAddr = brkPtLoc.GetAddress();
+ lldb::SBSymbolContext symbolCntxt = brkPtAddr.GetSymbolContext( lldb::eSymbolContextEverything );
+ const MIchar * pUnkwn = "??";
+ lldb::SBModule rModule = symbolCntxt.GetModule();
+ const MIchar * pModule = rModule.IsValid() ? rModule.GetFileSpec().GetFilename() : pUnkwn; MIunused( pModule );
+ const MIchar * pFile = pUnkwn;
+ const MIchar * pFn = pUnkwn;
+ const MIchar * pFilePath = pUnkwn;
+ size_t nLine = 0;
+ const size_t nAddr = brkPtAddr.GetLoadAddress( m_lldbTarget );
+
+ lldb::SBCompileUnit rCmplUnit = symbolCntxt.GetCompileUnit();
+ if( rCmplUnit.IsValid() )
+ {
+ lldb::SBFileSpec rFileSpec = rCmplUnit.GetFileSpec();
+ pFile = rFileSpec.GetFilename();
+ pFilePath = rFileSpec.GetDirectory();
+ lldb::SBFunction rFn = symbolCntxt.GetFunction();
+ if( rFn.IsValid() )
+ pFn = rFn.GetName();
+ lldb::SBLineEntry rLnEntry = symbolCntxt.GetLineEntry();
+ if( rLnEntry.GetLine() > 0 )
+ nLine = rLnEntry.GetLine();
+ }
+
+ vrwBrkPtInfo.m_id = vBrkPt.GetID();
+ vrwBrkPtInfo.m_strType = "breakpoint";
+ vrwBrkPtInfo.m_pc = nAddr;
+ vrwBrkPtInfo.m_fnName = pFn;
+ vrwBrkPtInfo.m_fileName = pFile;
+ vrwBrkPtInfo.m_path = pFilePath;
+ vrwBrkPtInfo.m_nLine = nLine;
+ vrwBrkPtInfo.m_nTimes = vBrkPt.GetHitCount();
+
+ return MIstatus::success;
+}
diff --git a/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h
new file mode 100644
index 000000000000..ca7ea27f5611
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h
@@ -0,0 +1,236 @@
+//===-- MICmnLLDBDebugSessionInfo.h -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBDebugSessionInfo.h
+//
+// Overview: CMICmnLLDBDebugSessionInfo interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <map>
+#include <vector>
+#include <lldb/API/SBDebugger.h>
+#include <lldb/API/SBListener.h>
+#include <lldb/API/SBProcess.h>
+#include <lldb/API/SBTarget.h>
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MIUtilSingletonBase.h"
+#include "MICmnLLDBDebugSessionInfoVarObj.h"
+#include "MICmnMIValueTuple.h"
+#include "MIUtilMapIdToVariant.h"
+
+// Declarations:
+class CMICmnLLDBDebugger;
+struct SMICmdData;
+class CMICmnMIValueTuple;
+class CMICmnMIValueList;
+
+//++ ============================================================================
+// Details: MI debug session object that holds debugging information between
+// instances of MI commands executing their work and producing MI
+// result records. Information/data is set by one or many commands then
+// retrieved by the same or other sebsequent commands.
+// It primarily to hold LLDB type objects.
+// A singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 04/03/2014.
+// Changes: None.
+//--
+class CMICmnLLDBDebugSessionInfo
+: public CMICmnBase
+, public MI::ISingleton< CMICmnLLDBDebugSessionInfo >
+{
+ friend class MI::ISingleton< CMICmnLLDBDebugSessionInfo >;
+
+// Structs:
+public:
+ //++ ============================================================================
+ // Details: Break point information object. Used to easily pass information about
+ // a break around and record break point information to be recalled by
+ // other commands or LLDB event handling functions.
+ //--
+ struct SBrkPtInfo
+ {
+ SBrkPtInfo( void )
+ : m_id( 0 )
+ , m_bDisp( false )
+ , m_bEnabled( false )
+ , m_pc( 0 )
+ , m_nLine( 0 )
+ , m_bHaveArgOptionThreadGrp( false )
+ , m_nTimes( 0 )
+ , m_bPending( false )
+ , m_nIgnore( 0 )
+ , m_bCondition( false )
+ , m_bBrkPtThreadId( false )
+ , m_nBrkPtThreadId( 0 )
+ {
+ }
+
+ MIuint m_id; // LLDB break point ID.
+ CMIUtilString m_strType; // Break point type.
+ bool m_bDisp ; // True = "del", false = "keep".
+ bool m_bEnabled; // True = enabled, false = disabled break point.
+ MIuint m_pc; // Address number.
+ CMIUtilString m_fnName; // Function name.
+ CMIUtilString m_fileName; // File name text.
+ CMIUtilString m_path; // Full file name and path text.
+ MIuint m_nLine; // File line number.
+ bool m_bHaveArgOptionThreadGrp; // True = include MI field, false = do not include "thread-groups".
+ CMIUtilString m_strOptThrdGrp; // Thread group number.
+ MIuint m_nTimes; // The count of the breakpoint existence.
+ CMIUtilString m_strOrigLoc; // The name of the break point.
+ bool m_bPending; // True = the breakpoint has not been established yet, false = location found
+ MIuint m_nIgnore; // The number of time the breakpoint is run over before it is stopped on a hit
+ bool m_bCondition; // True = break point is conditional, use condition expression, false = no condition
+ CMIUtilString m_strCondition; // Break point condition expression
+ bool m_bBrkPtThreadId; // True = break point is specified to work with a specific thread, false = no specified thread given
+ MIuint m_nBrkPtThreadId; // Restrict the breakpoint to the specified thread-id
+ };
+
+// Typedefs:
+public:
+ typedef std::vector< uint32_t > VecActiveThreadId_t;
+
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+
+ // Variant type data which can be assigned and retrieved across all command instances
+ template< typename T >
+ bool SharedDataAdd( const CMIUtilString & vKey, const T & vData );
+ template< typename T >
+ bool SharedDataRetrieve( const CMIUtilString & vKey, T & vwData );
+ bool SharedDataDestroy( void );
+
+ // Common command required functionality
+ bool AccessPath( const CMIUtilString & vPath, bool & vwbYesAccessible );
+ bool GetFrameInfo( const lldb::SBFrame & vrFrame, lldb::addr_t & vwPc, CMIUtilString & vwFnName, CMIUtilString & vwFileName, CMIUtilString & vwPath, MIuint & vwnLine );
+ bool GetThreadFrames( const SMICmdData & vCmdData, const MIuint vThreadIdx, CMIUtilString & vwrThreadFrames );
+ bool GetThreadFrames2( const SMICmdData & vCmdData, const MIuint vThreadIdx, CMIUtilString & vwrThreadFrames );
+ bool ResolvePath( const SMICmdData & vCmdData, const CMIUtilString & vPath, CMIUtilString & vwrResolvedPath );
+ bool ResolvePath( const CMIUtilString & vstrUnknown, CMIUtilString & vwrResolvedPath );
+ bool MIResponseFormFrameInfo( const lldb::SBThread & vrThread, const MIuint vnLevel, CMICmnMIValueTuple & vwrMiValueTuple );
+ bool MIResponseFormFrameInfo( const lldb::addr_t vPc, const CMIUtilString & vFnName, const CMIUtilString & vFileName, const CMIUtilString & vPath, const MIuint vnLine, CMICmnMIValueTuple & vwrMiValueTuple );
+ bool MIResponseFormFrameInfo2( const lldb::addr_t vPc, const CMIUtilString & vArgInfo, const CMIUtilString & vFnName, const CMIUtilString & vFileName, const CMIUtilString & vPath, const MIuint vnLine, CMICmnMIValueTuple & vwrMiValueTuple );
+ bool MIResponseFormThreadInfo( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple );
+ bool MIResponseFormThreadInfo2( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple );
+ bool MIResponseFormThreadInfo3( const SMICmdData & vCmdData, const lldb::SBThread & vrThread, CMICmnMIValueTuple & vwrMIValueTuple );
+ bool MIResponseFormVariableInfo( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList );
+ bool MIResponseFormVariableInfo2( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList );
+ bool MIResponseFormVariableInfo3( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList );
+ bool MIResponseFormBrkPtFrameInfo( const SBrkPtInfo & vrBrkPtInfo, CMICmnMIValueTuple & vwrMiValueTuple );
+ bool MIResponseFormBrkPtInfo( const SBrkPtInfo & vrBrkPtInfo, CMICmnMIValueTuple & vwrMiValueTuple );
+ bool GetBrkPtInfo( const lldb::SBBreakpoint & vBrkPt, SBrkPtInfo & vrwBrkPtInfo ) const;
+ bool RecordBrkPtInfo( const MIuint vnBrkPtId, const SBrkPtInfo & vrBrkPtInfo );
+ bool RecordBrkPtInfoGet( const MIuint vnBrkPtId, SBrkPtInfo & vrwBrkPtInfo ) const;
+ bool RecordBrkPtInfoDelete( const MIuint vnBrkPtId );
+
+// Attributes:
+public:
+ // The following are available to all command instances
+ lldb::SBDebugger & m_rLldbDebugger;
+ lldb::SBListener & m_rLlldbListener;
+ lldb::SBTarget m_lldbTarget;
+ lldb::SBProcess m_lldbProcess;
+ const MIuint m_nBrkPointCntMax;
+ VecActiveThreadId_t m_vecActiveThreadId;
+ lldb::tid_t m_currentSelectedThread;
+
+ // These are keys that can be used to access the shared data map
+ // Note: This list is expected to grow and will be moved and abstracted in the future.
+ const CMIUtilString m_constStrSharedDataKeyWkDir;
+ const CMIUtilString m_constStrSharedDataSolibPath;
+
+// Typedefs:
+private:
+ typedef std::vector< CMICmnLLDBDebugSessionInfoVarObj > VecVarObj_t;
+ typedef std::map< MIuint, SBrkPtInfo > MapBrkPtIdToBrkPtInfo_t;
+ typedef std::pair< MIuint, SBrkPtInfo > MapPairBrkPtIdToBrkPtInfo_t;
+
+// Methods:
+private:
+ /* ctor */ CMICmnLLDBDebugSessionInfo( void );
+ /* ctor */ CMICmnLLDBDebugSessionInfo( const CMICmnLLDBDebugSessionInfo & );
+ void operator=( const CMICmnLLDBDebugSessionInfo & );
+ //
+ bool GetVariableInfo( const MIuint vnMaxDepth, const lldb::SBValue & vrValue, const bool vbIsChildValue, CMICmnMIValueList & vwrMiValueList, MIuint & vrwnDepth );
+ bool GetVariableInfo2( const MIuint vnMaxDepth, const lldb::SBValue & vrValue, const bool vbIsChildValue, CMICmnMIValueList & vwrMiValueList, MIuint & vrwnDepth );
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnLLDBDebugSessionInfo( void );
+
+// Attributes:
+private:
+ CMIUtilMapIdToVariant m_mapIdToSessionData; // Hold and retrieve key to value data available across all commands
+ VecVarObj_t m_vecVarObj; // Vector of session variable objects
+ MapBrkPtIdToBrkPtInfo_t m_mapBrkPtIdToBrkPtInfo;
+};
+
+//++ ------------------------------------------------------------------------------------
+// Details: Command instances can create and share data between other instances of commands.
+// This function adds new data to the shared data. Using the same ID more than
+// once replaces any previous matching data keys.
+// Type: Template method.
+// Args: T - The type of the object to be stored.
+// vKey - (R) A non empty unique data key to retrieve the data by.
+// vData - (R) Data to be added to the share.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+template< typename T >
+bool CMICmnLLDBDebugSessionInfo::SharedDataAdd( const CMIUtilString & vKey, const T & vData )
+{
+ if( !m_mapIdToSessionData.Add< T >( vKey, vData ) )
+ {
+ SetErrorDescription( m_mapIdToSessionData.GetErrorDescription() );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Command instances can create and share data between other instances of commands.
+// This function retrieves data from the shared data container.
+// Type: Method.
+// Args: T - The type of the object being retrieved.
+// vKey - (R) A non empty unique data key to retrieve the data by.
+// vData - (W) The data.
+// Return: bool - True = data found, false = data not found or an error occurred trying to fetch.
+// Throws: None.
+//--
+template< typename T >
+bool CMICmnLLDBDebugSessionInfo::SharedDataRetrieve( const CMIUtilString & vKey, T & vwData )
+{
+ bool bDataFound = false;
+
+ if( !m_mapIdToSessionData.Get< T >( vKey, vwData, bDataFound ) )
+ {
+ SetErrorDescription( m_mapIdToSessionData.GetErrorDescription() );
+ return MIstatus::failure;
+ }
+
+ return bDataFound;
+} \ No newline at end of file
diff --git a/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp b/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp
new file mode 100644
index 000000000000..d519875993fe
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp
@@ -0,0 +1,570 @@
+//===-- MICmnLLDBDebugSessionInfoVarObj.cpp ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBDebugSessionInfoVarObj.cpp
+//
+// Overview: CMICmnLLDBDebugSessionInfoVarObj implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnLLDBDebugSessionInfoVarObj.h"
+#include "MICmnLLDBProxySBValue.h"
+#include "MICmnLLDBUtilSBValue.h"
+
+// Instantiations:
+const MIchar * CMICmnLLDBDebugSessionInfoVarObj::ms_aVarFormatStrings[] =
+{
+ // CODETAG_SESSIONINFO_VARFORMAT_ENUM
+ // *** Order is import here.
+ "<Invalid var format>",
+ "binary",
+ "octal",
+ "decimal",
+ "hexadecimal",
+ "natural"
+};
+const MIchar * CMICmnLLDBDebugSessionInfoVarObj::ms_aVarFormatChars[] =
+{
+ // CODETAG_SESSIONINFO_VARFORMAT_ENUM
+ // *** Order is import here.
+ "<Invalid var format>",
+ "t",
+ "o",
+ "d",
+ "x",
+ "N"
+};
+CMICmnLLDBDebugSessionInfoVarObj::MapKeyToVarObj_t CMICmnLLDBDebugSessionInfoVarObj::ms_mapVarIdToVarObj;
+MIuint CMICmnLLDBDebugSessionInfoVarObj::ms_nVarUniqueId = 0; // Index from 0
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebugSessionInfoVarObj constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( void )
+: m_eVarFormat( eVarFormat_Natural )
+, m_eVarType( eVarType_Internal )
+{
+ // Do not call UpdateValue() in here as not necessary
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebugSessionInfoVarObj constructor.
+// Type: Method.
+// Args: vrStrNameReal - (R) The actual name of the variable, the expression.
+// vrStrName - (R) The name given for *this var object.
+// vrValue - (R) The LLDB SBValue object represented by *this object.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( const CMIUtilString & vrStrNameReal, const CMIUtilString & vrStrName, const lldb::SBValue & vrValue )
+: m_eVarFormat( eVarFormat_Natural )
+, m_eVarType( eVarType_Internal )
+, m_strName( vrStrName )
+, m_SBValue( vrValue )
+, m_strNameReal( vrStrNameReal )
+{
+ UpdateValue();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebugSessionInfoVarObj constructor.
+// Type: Method.
+// Args: vrStrNameReal - (R) The actual name of the variable, the expression.
+// vrStrName - (R) The name given for *this var object.
+// vrValue - (R) The LLDB SBValue object represented by *this object.
+// vrStrVarObjParentName - (R) The var object parent to *this var object (LLDB SBValue equivalent).
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( const CMIUtilString & vrStrNameReal, const CMIUtilString & vrStrName, const lldb::SBValue & vrValue, const CMIUtilString & vrStrVarObjParentName )
+: m_eVarFormat( eVarFormat_Natural )
+, m_eVarType( eVarType_Internal )
+, m_strName( vrStrName )
+, m_SBValue( vrValue )
+, m_strNameReal( vrStrNameReal )
+, m_strVarObjParentName( vrStrVarObjParentName )
+{
+ UpdateValue();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebugSessionInfoVarObj copy constructor.
+// Type: Method.
+// Args: vrOther - (R) The object to copy from.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( const CMICmnLLDBDebugSessionInfoVarObj & vrOther )
+{
+ CopyOther( vrOther );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebugSessionInfoVarObj copy constructor.
+// Type: Method.
+// Args: vrOther - (R) The object to copy from.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( CMICmnLLDBDebugSessionInfoVarObj & vrOther )
+{
+ CopyOther( vrOther );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebugSessionInfoVarObj move constructor.
+// Type: Method.
+// Args: vrwOther - (R) The object to copy from.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( CMICmnLLDBDebugSessionInfoVarObj && vrwOther )
+{
+ MoveOther( vrwOther );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebugSessionInfoVarObj assignment operator.
+// Type: Method.
+// Args: vrOther - (R) The object to copy from.
+// Return: CMICmnLLDBDebugSessionInfoVarObj & - Updated *this object.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfoVarObj & CMICmnLLDBDebugSessionInfoVarObj::operator= ( const CMICmnLLDBDebugSessionInfoVarObj & vrOther )
+{
+ CopyOther( vrOther );
+
+ return *this;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebugSessionInfoVarObj assignment operator.
+// Type: Method.
+// Args: vrwOther - (R) The object to copy from.
+// Return: CMICmnLLDBDebugSessionInfoVarObj & - Updated *this object.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfoVarObj & CMICmnLLDBDebugSessionInfoVarObj::operator= ( CMICmnLLDBDebugSessionInfoVarObj && vrwOther )
+{
+ MoveOther( vrwOther );
+
+ return *this;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Copy the other instance of that object to *this object.
+// Type: Method.
+// Args: vrOther - (R) The object to copy from.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfoVarObj::CopyOther( const CMICmnLLDBDebugSessionInfoVarObj & vrOther )
+{
+ // Check for self-assignment
+ if( this == &vrOther )
+ return MIstatus::success;
+
+ m_eVarFormat = vrOther.m_eVarFormat;
+ m_eVarType = vrOther.m_eVarType;
+ m_strName = vrOther.m_strName;
+ m_SBValue = vrOther.m_SBValue;
+ m_strNameReal = vrOther.m_strNameReal;
+ m_strFormattedValue = vrOther.m_strFormattedValue;
+ m_strVarObjParentName = vrOther.m_strVarObjParentName;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Move that object to *this object.
+// Type: Method.
+// Args: vrwOther - (RW) The object to copy from.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfoVarObj::MoveOther( CMICmnLLDBDebugSessionInfoVarObj & vrwOther )
+{
+ // Check for self-assignment
+ if( this == &vrwOther )
+ return MIstatus::success;
+
+ CopyOther( vrwOther );
+ vrwOther.m_eVarFormat = eVarFormat_Natural;
+ vrwOther.m_eVarType = eVarType_Internal;
+ vrwOther.m_strName.clear();
+ vrwOther.m_SBValue.Clear();
+ vrwOther.m_strNameReal.clear();
+ vrwOther.m_strFormattedValue.clear();
+ vrwOther.m_strVarObjParentName.clear();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebugSessionInfoVarObj destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfoVarObj::~CMICmnLLDBDebugSessionInfoVarObj( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the var format enumeration for the specified string.
+// Type: Static method.
+// Args: vrStrFormat - (R) Text description of the var format.
+// Return: varFormat_e - Var format enumeration.
+// - No match found return eVarFormat_Invalid.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfoVarObj::varFormat_e CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForString( const CMIUtilString & vrStrFormat )
+{
+ // CODETAG_SESSIONINFO_VARFORMAT_ENUM
+ for( MIuint i = 0; i < eVarFormat_count; i++ )
+ {
+ const MIchar * pVarFormatString = ms_aVarFormatStrings[ i ];
+ if( vrStrFormat == pVarFormatString )
+ return static_cast< varFormat_e >( i );
+ }
+
+ return eVarFormat_Invalid;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the var format enumeration for the specified character.
+// Type: Static method.
+// Args: vrcFormat - (R) Character representing the var format.
+// Return: varFormat_e - Var format enumeration.
+// - No match found return eVarFormat_Invalid.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfoVarObj::varFormat_e CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar( const MIchar & vrcFormat )
+{
+ if( 'r' == vrcFormat )
+ return eVarFormat_Hex;
+
+ // CODETAG_SESSIONINFO_VARFORMAT_ENUM
+ for( MIuint i = 0; i < eVarFormat_count; i++ )
+ {
+ const MIchar * pVarFormatChar = ms_aVarFormatChars[ i ];
+ if( *pVarFormatChar == vrcFormat )
+ return static_cast< varFormat_e >( i );
+ }
+
+ return eVarFormat_Invalid;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return the equivalent var value formatted string for the given value type.
+// The SBValue vrValue parameter is checked by LLDB private code for valid
+// scalar type via MI Driver proxy function as the valued returned can also be
+// an error condition. The proxy function determines if the check was valid
+// otherwise return an error condition state by other means saying so.
+// Type: Static method.
+// Args: vrValue - (R) The var value object.
+// veVarFormat - (R) Var format enumeration.
+// Returns: CMIUtilString - Value formatted string.
+// Throws: None.
+//--
+CMIUtilString CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted( const lldb::SBValue & vrValue, const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat )
+{
+ CMIUtilString strFormattedValue;
+
+ MIuint64 nValue = 0;
+ if( CMICmnLLDBProxySBValue::GetValueAsUnsigned( vrValue, nValue ) == MIstatus::success )
+ {
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue );
+ strFormattedValue = GetStringFormatted( nValue, rValue.GetValue(), veVarFormat );
+ }
+ else
+ {
+ // Composite variable type i.e. struct
+ strFormattedValue = "{...}";
+ }
+
+ return strFormattedValue;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return nuber formatted string according to the given value type.
+// Type: Static method.
+// Args: vnValue - (R) The number value to get formatted.
+// vpStrValueNatural - (R) The natural representation of the number value.
+// veVarFormat - (R) Var format enumeration.
+// Returns: CMIUtilString - Numerical formatted string.
+// Throws: None.
+//--
+CMIUtilString CMICmnLLDBDebugSessionInfoVarObj::GetStringFormatted( const MIuint64 vnValue, const MIchar * vpStrValueNatural, const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat )
+{
+ CMIUtilString strFormattedValue;
+
+ switch( veVarFormat )
+ {
+ case eVarFormat_Binary:
+ strFormattedValue = CMIUtilString::FormatBinary( vnValue );
+ break;
+ case eVarFormat_Octal:
+ strFormattedValue = CMIUtilString::Format( "0%llo", vnValue );
+ break;
+ case eVarFormat_Decimal:
+ strFormattedValue = CMIUtilString::Format( "%lld", vnValue );
+ break;
+ case eVarFormat_Hex:
+ strFormattedValue = CMIUtilString::Format( "0x%llx", vnValue );
+ break;
+ case eVarFormat_Natural:
+ default:
+ {
+ strFormattedValue = (vpStrValueNatural != nullptr) ? vpStrValueNatural : "";
+ }
+ }
+
+ return strFormattedValue;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Delete internal container contents.
+// Type: Static method.
+// Args: None.
+// Returns: None.
+// Throws: None.
+//--
+void CMICmnLLDBDebugSessionInfoVarObj::VarObjClear( void )
+{
+ ms_mapVarIdToVarObj.clear();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add a var object to the internal container.
+// Type: Static method.
+// Args: vrVarObj - (R) The var value object.
+// Returns: None.
+// Throws: None.
+//--
+void CMICmnLLDBDebugSessionInfoVarObj::VarObjAdd( const CMICmnLLDBDebugSessionInfoVarObj & vrVarObj )
+{
+ VarObjDelete( vrVarObj.GetName() );
+ MapPairKeyToVarObj_t pr( vrVarObj.GetName(), vrVarObj );
+ ms_mapVarIdToVarObj.insert( pr );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Delete the var object from the internal container matching the specified name.
+// Type: Static method.
+// Args: vrVarName - (R) The var value name.
+// Returns: None.
+// Throws: None.
+//--
+void CMICmnLLDBDebugSessionInfoVarObj::VarObjDelete( const CMIUtilString & vrVarName )
+{
+ const MapKeyToVarObj_t::const_iterator it = ms_mapVarIdToVarObj.find( vrVarName );
+ if( it != ms_mapVarIdToVarObj.end() )
+ {
+ ms_mapVarIdToVarObj.erase( it );
+ }
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Update an existing var object in the internal container.
+// Type: Static method.
+// Args: vrVarObj - (R) The var value object.
+// Returns: None.
+// Throws: None.
+//--
+void CMICmnLLDBDebugSessionInfoVarObj::VarObjUpdate( const CMICmnLLDBDebugSessionInfoVarObj & vrVarObj )
+{
+ VarObjAdd( vrVarObj );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the var object matching the specified name.
+// Type: Static method.
+// Args: vrVarName - (R) The var value name.
+// vrwVarObj - (W) A var object.
+// Returns: bool - True = object found, false = object not found.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( const CMIUtilString & vrVarName, CMICmnLLDBDebugSessionInfoVarObj & vrwVarObj )
+{
+ const MapKeyToVarObj_t::const_iterator it = ms_mapVarIdToVarObj.find( vrVarName );
+ if( it != ms_mapVarIdToVarObj.end() )
+ {
+ const CMICmnLLDBDebugSessionInfoVarObj & rVarObj = (*it).second;
+ vrwVarObj = rVarObj;
+ return true;
+ }
+
+ return false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: A count is kept of the number of var value objects created. This is count is
+// used to ID the var value object. Reset the count to 0.
+// Type: Static method.
+// Args: None.
+// Returns: None.
+// Throws: None.
+//--
+void CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero( void )
+{
+ ms_nVarUniqueId = 0;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: A count is kept of the number of var value objects created. This is count is
+// used to ID the var value object. Increment the count by 1.
+// Type: Static method.
+// Args: None.
+// Returns: None.
+// Throws: None.
+//--
+void CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc( void )
+{
+ ms_nVarUniqueId++;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: A count is kept of the number of var value objects created. This is count is
+// used to ID the var value object. Retrieve ID.
+// Type: Static method.
+// Args: None.
+// Returns: None.
+// Throws: None.
+//--
+MIuint CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet( void )
+{
+ return ms_nVarUniqueId;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the value formatted object's name.
+// Type: Method.
+// Args: None.
+// Returns: CMIUtilString & - Value's var%u name text.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnLLDBDebugSessionInfoVarObj::GetName( void ) const
+{
+ return m_strName;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the value formatted object's variable name as given in the MI command
+// to create the var object.
+// Type: Method.
+// Args: None.
+// Returns: CMIUtilString & - Value's real name text.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnLLDBDebugSessionInfoVarObj::GetNameReal( void ) const
+{
+ return m_strNameReal;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the value formatted string.
+// Type: Method.
+// Args: None.
+// Returns: CMIUtilString & - Value formatted string.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnLLDBDebugSessionInfoVarObj::GetValueFormatted( void ) const
+{
+ return m_strFormattedValue;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the LLDB Value object.
+// Type: Method.
+// Args: None.
+// Returns: lldb::SBValue & - LLDB Value object.
+// Throws: None.
+//--
+const lldb::SBValue & CMICmnLLDBDebugSessionInfoVarObj::GetValue( void ) const
+{
+ return m_SBValue;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the var format type for *this object and upate the formatting.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugSessionInfoVarObj::SetVarFormat( const varFormat_e veVarFormat )
+{
+ if( veVarFormat >= eVarFormat_count )
+ return MIstatus::failure;
+
+ m_eVarFormat = veVarFormat;
+ UpdateValue();
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Update *this var obj. Update it's value and type.
+// Type: Method.
+// Args: None.
+// Returns: None.
+// Throws: None.
+//--
+void CMICmnLLDBDebugSessionInfoVarObj::UpdateValue( void )
+{
+ m_strFormattedValue = CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted( m_SBValue, m_eVarFormat );
+
+ MIuint64 nValue = 0;
+ if( CMICmnLLDBProxySBValue::GetValueAsUnsigned( m_SBValue, nValue ) == MIstatus::failure )
+ m_eVarType = eVarType_Composite;
+
+ CMICmnLLDBDebugSessionInfoVarObj::VarObjUpdate( *this );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the enumeration type of the var object.
+// Type: Method.
+// Args: None.
+// Returns: varType_e - Enumeration value.
+// Throws: None.
+//--
+CMICmnLLDBDebugSessionInfoVarObj::varType_e CMICmnLLDBDebugSessionInfoVarObj::GetType( void ) const
+{
+ return m_eVarType;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the parent var object's name, the parent var object to *this var
+// object (if assigned). The parent is equivalent to LLDB SBValue variable's
+// parent.
+// Type: Method.
+// Args: None.
+// Returns: CMIUtilString & - Pointer to var object, NULL = no parent.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnLLDBDebugSessionInfoVarObj::GetVarParentName( void ) const
+{
+ return m_strVarObjParentName;
+}
+ \ No newline at end of file
diff --git a/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h b/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h
new file mode 100644
index 000000000000..1db7bd8daa05
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h
@@ -0,0 +1,139 @@
+//===-- MICmnLLDBDebugSessionInfoVarObj.h -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBDebugSessionInfoVarObj.h
+//
+// Overview: CMICmnLLDBDebugSessionInfoVarObj interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third Party Headers:
+#include <map>
+#include <lldb/API/SBValue.h>
+
+// In-house headers:
+#include "MIUtilString.h"
+
+//++ ============================================================================
+// Details: MI debug session variable object. The static functionality in *this
+// class manages a map container of *these variable objects.
+// Gotchas: None.
+// Authors: Illya Rudkin 24/03/2014.
+// Changes: None.
+//--
+class CMICmnLLDBDebugSessionInfoVarObj
+{
+// Enums:
+public:
+ //++ ----------------------------------------------------------------------
+ // Details: Enumeration of a variable type that is not a composite type
+ //--
+ enum varFormat_e
+ {
+ // CODETAG_SESSIONINFO_VARFORMAT_ENUM
+ // *** Order is import here ***
+ eVarFormat_Invalid = 0,
+ eVarFormat_Binary,
+ eVarFormat_Octal,
+ eVarFormat_Decimal,
+ eVarFormat_Hex,
+ eVarFormat_Natural,
+ eVarFormat_count // Always last one
+ };
+
+ //++ ----------------------------------------------------------------------
+ // Details: Enumeration of a variable type by composite or internal type
+ //--
+ enum varType_e
+ {
+ eVarType_InValid = 0,
+ eVarType_Composite, // i.e. struct
+ eVarType_Internal, // i.e. int
+ eVarType_count // Always last one
+ };
+
+// Statics:
+public:
+ static varFormat_e GetVarFormatForString( const CMIUtilString & vrStrFormat );
+ static varFormat_e GetVarFormatForChar( const MIchar & vrcFormat );
+ static CMIUtilString GetValueStringFormatted( const lldb::SBValue & vrValue, const varFormat_e veVarFormat );
+ static void VarObjAdd( const CMICmnLLDBDebugSessionInfoVarObj & vrVarObj );
+ static void VarObjDelete( const CMIUtilString & vrVarName );
+ static bool VarObjGet( const CMIUtilString & vrVarName, CMICmnLLDBDebugSessionInfoVarObj & vrwVarObj );
+ static void VarObjUpdate( const CMICmnLLDBDebugSessionInfoVarObj & vrVarObj );
+ static void VarObjIdInc( void );
+ static MIuint VarObjIdGet( void );
+ static void VarObjIdResetToZero( void );
+ static void VarObjClear( void );
+
+// Methods:
+public:
+ /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( void );
+ /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( const CMIUtilString & vrStrNameReal, const CMIUtilString & vrStrName, const lldb::SBValue & vrValue );
+ /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( const CMIUtilString & vrStrNameReal, const CMIUtilString & vrStrName, const lldb::SBValue & vrValue, const CMIUtilString & vrStrVarObjParentName );
+ /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( const CMICmnLLDBDebugSessionInfoVarObj & vrOther );
+ /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( CMICmnLLDBDebugSessionInfoVarObj & vrOther );
+ /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( CMICmnLLDBDebugSessionInfoVarObj && vrOther );
+ //
+ CMICmnLLDBDebugSessionInfoVarObj & operator= ( const CMICmnLLDBDebugSessionInfoVarObj & vrOther );
+ CMICmnLLDBDebugSessionInfoVarObj & operator= ( CMICmnLLDBDebugSessionInfoVarObj && vrwOther );
+ //
+ const CMIUtilString & GetName( void ) const;
+ const CMIUtilString & GetNameReal( void ) const;
+ const CMIUtilString & GetValueFormatted( void ) const;
+ const lldb::SBValue & GetValue( void ) const;
+ varType_e GetType( void ) const;
+ bool SetVarFormat( const varFormat_e veVarFormat );
+ const CMIUtilString & GetVarParentName( void ) const;
+ void UpdateValue( void );
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnLLDBDebugSessionInfoVarObj( void );
+
+// Typedefs:
+private:
+ typedef std::map< CMIUtilString, CMICmnLLDBDebugSessionInfoVarObj > MapKeyToVarObj_t;
+ typedef std::pair< CMIUtilString, CMICmnLLDBDebugSessionInfoVarObj > MapPairKeyToVarObj_t;
+
+// Statics:
+private:
+ static CMIUtilString GetStringFormatted( const MIuint64 vnValue, const MIchar * vpStrValueNatural, varFormat_e veVarFormat );
+
+// Methods:
+private:
+ bool CopyOther( const CMICmnLLDBDebugSessionInfoVarObj & vrOther );
+ bool MoveOther( CMICmnLLDBDebugSessionInfoVarObj & vrwOther );
+
+// Attributes:
+private:
+ static const MIchar * ms_aVarFormatStrings[];
+ static const MIchar * ms_aVarFormatChars[];
+ static MapKeyToVarObj_t ms_mapVarIdToVarObj;
+ static MIuint ms_nVarUniqueId;
+ //
+ // *** Upate the copy move constructors and assignment operator ***
+ varFormat_e m_eVarFormat;
+ varType_e m_eVarType;
+ CMIUtilString m_strName;
+ lldb::SBValue m_SBValue;
+ CMIUtilString m_strNameReal;
+ CMIUtilString m_strFormattedValue;
+ CMIUtilString m_strVarObjParentName;
+ // *** Upate the copy move constructors and assignment operator ***
+};
diff --git a/tools/lldb-mi/MICmnLLDBDebugger.cpp b/tools/lldb-mi/MICmnLLDBDebugger.cpp
new file mode 100644
index 000000000000..f68f5083054b
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBDebugger.cpp
@@ -0,0 +1,707 @@
+//===-- MICmnLLDBDebugger.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBDebugger.cpp
+//
+// Overview: CMICmnLLDBDebugger implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers:
+#include <lldb/API/SBTarget.h>
+#include <lldb/API/SBThread.h>
+#include <lldb/API/SBProcess.h>
+#include <lldb/API/SBCommandInterpreter.h>
+
+// In-house headers:
+#include "MICmnLLDBDebugger.h"
+#include "MICmnResources.h"
+#include "MICmnLog.h"
+#include "MIDriverBase.h"
+#include "MICmnThreadMgrStd.h"
+#include "MICmnLLDBDebuggerHandleEvents.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MIUtilSingletonHelper.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebugger constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebugger::CMICmnLLDBDebugger( void )
+: m_constStrThisThreadId( "MI debugger event" )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebugger destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebugger::~CMICmnLLDBDebugger( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this debugger object.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+ ClrErrorDescription();
+
+ if( m_pClientDriver == nullptr )
+ {
+ bOk = false;
+ errMsg = MIRSRC( IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER );
+ }
+
+ // Note initialization order is important here as some resources depend on previous
+ MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+ MI::ModuleInit< CMICmnResources > ( IDS_MI_INIT_ERR_RESOURCES , bOk, errMsg );
+ MI::ModuleInit< CMICmnThreadMgrStd > ( IDS_MI_INIT_ERR_THREADMGR , bOk, errMsg );
+ MI::ModuleInit< CMICmnLLDBDebuggerHandleEvents >( IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg );
+ MI::ModuleInit< CMICmnLLDBDebugSessionInfo > ( IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg );
+
+ // Note order is important here!
+ if( bOk )
+ lldb::SBDebugger::Initialize();
+ if( bOk && !InitSBDebugger() )
+ {
+ bOk = false;
+ if( !errMsg.empty() ) errMsg += ", ";
+ errMsg += GetErrorDescription().c_str();
+ }
+ if( bOk && !InitSBListener() )
+ {
+ bOk = false;
+ if( !errMsg.empty() ) errMsg += ", ";
+ errMsg += GetErrorDescription().c_str();
+ }
+ bOk = bOk && InitStdStreams();
+
+ m_bInitialized = bOk;
+
+ if( !bOk && !HaveErrorDescription() )
+ {
+ CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_LLDBDEBUGGER ), errMsg.c_str() ) );
+ SetErrorDescription( strInitError );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this debugger object.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = false;
+
+ ClrErrorDescription();
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Explicitly delete the remote target in case MI needs to exit prematurely otherwise
+ // LLDB debugger may hang in its Destroy() fn waiting on events
+ m_lldbDebugger.DeleteTarget( CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget );
+
+ // Debug: May need this but does seem to work without it so commented out the fudge 19/06/2014
+ // It appears we need to wait as hang does not occur when hitting a debug breakpoint here
+ //const std::chrono::milliseconds time( 1000 );
+ //std::this_thread::sleep_for( time );
+
+ lldb::SBDebugger::Destroy( m_lldbDebugger );
+ lldb::SBDebugger::Terminate();
+ m_pClientDriver = nullptr;
+ m_mapBroadcastClassNameToEventMask.clear();
+ m_mapIdToEventMask.clear();
+
+ // Note shutdown order is important here
+ MI::ModuleShutdown< CMICmnLLDBDebugSessionInfo > ( IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg );
+ MI::ModuleShutdown< CMICmnLLDBDebuggerHandleEvents >( IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg );
+ MI::ModuleShutdown< CMICmnThreadMgrStd > ( IDS_MI_INIT_ERR_THREADMGR , bOk, errMsg );
+ MI::ModuleShutdown< CMICmnResources > ( IDS_MI_INIT_ERR_RESOURCES , bOk, errMsg );
+ MI::ModuleShutdown< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+
+ if( !bOk )
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_MI_SHTDWN_ERR_LLDBDEBUGGER ), errMsg.c_str() );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return the LLDB debugger instance created for this debug session.
+// Type: Method.
+// Args: None.
+// Return: lldb::SBDebugger & - LLDB debugger object reference.
+// Throws: None.
+//--
+lldb::SBDebugger & CMICmnLLDBDebugger::GetTheDebugger( void )
+{
+ return m_lldbDebugger;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return the LLDB listener instance created for this debug session.
+// Type: Method.
+// Args: None.
+// Return: lldb::SBListener & - LLDB listener object reference.
+// Throws: None.
+//--
+lldb::SBListener & CMICmnLLDBDebugger::GetTheListener( void )
+{
+ return m_lldbListener;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the client driver that wants to use *this LLDB debugger. Call this function
+// prior to Initialize().
+// Type: Method.
+// Args: vClientDriver - (R) A driver.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::SetDriver( const CMIDriverBase & vClientDriver )
+{
+ m_pClientDriver = const_cast< CMIDriverBase * >( &vClientDriver );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the client driver that is use *this LLDB debugger.
+// Type: Method.
+// Args: vClientDriver - (R) A driver.
+// Return: CMIDriverBase & - A driver instance.
+// Throws: None.
+//--
+CMIDriverBase & CMICmnLLDBDebugger::GetDriver( void ) const
+{
+ return *m_pClientDriver;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize the LLDB Debugger object.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::InitSBDebugger( void )
+{
+ m_lldbDebugger = lldb::SBDebugger::Create( false );
+ if( m_lldbDebugger.IsValid() )
+ return MIstatus::success;
+
+ SetErrorDescription( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER ) );
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the LLDB Debugger's std in, err and out streams. (Not implemented left
+// here for reference. Was called in the CMICmnLLDBDebugger::Initialize() )
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::InitStdStreams( void )
+{
+ // This is not required when operating the MI driver's code as it has its own
+ // streams. Setting the Stdin for the lldbDebugger especially on LINUX will cause
+ // another thread to run and partially consume stdin data meant for MI stdin handler
+ //m_lldbDebugger.SetErrorFileHandle( m_pClientDriver->GetStderr(), false );
+ //m_lldbDebugger.SetOutputFileHandle( m_pClientDriver->GetStdout(), false );
+ //m_lldbDebugger.SetInputFileHandle( m_pClientDriver->GetStdin(), false );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set up the events from the SBDebugger's we would to listent to.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::InitSBListener( void )
+{
+ m_lldbListener = m_lldbDebugger.GetListener();
+ if( !m_lldbListener.IsValid() )
+ {
+ SetErrorDescription( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER ) );
+ return MIstatus::failure;
+ }
+
+ const CMIUtilString strDbgId( "CMICmnLLDBDebugger1" );
+ MIuint eventMask = lldb::SBTarget::eBroadcastBitBreakpointChanged;
+ bool bOk = RegisterForEvent( strDbgId, CMIUtilString( lldb::SBTarget::GetBroadcasterClassName() ), eventMask );
+
+ eventMask = lldb::SBThread::eBroadcastBitStackChanged;
+ bOk = bOk && RegisterForEvent( strDbgId, CMIUtilString( lldb::SBThread::GetBroadcasterClassName() ), eventMask );
+
+ eventMask = lldb::SBProcess::eBroadcastBitStateChanged |
+ lldb::SBProcess::eBroadcastBitInterrupt |
+ lldb::SBProcess::eBroadcastBitSTDOUT |
+ lldb::SBProcess::eBroadcastBitSTDERR |
+ lldb::SBProcess::eBroadcastBitProfileData;
+ bOk = bOk && RegisterForEvent( strDbgId, CMIUtilString( lldb::SBProcess::GetBroadcasterClassName() ), eventMask );
+
+ eventMask = lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
+ lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit |
+ lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
+ lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData;
+ bOk = bOk && RegisterForEvent( strDbgId, CMIUtilString( lldb::SBCommandInterpreter::GetBroadcasterClass() ), eventMask );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Register with the debugger, the SBListener, the type of events you are interested
+// in. Others, like commands, may have already set the mask.
+// Type: Method.
+// Args: vClientName - (R) ID of the client who wants these events set.
+// vBroadcasterClass - (R) The SBBroadcaster's class name.
+// vEventMask - (R) The mask of events to listen for.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::RegisterForEvent( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass, const MIuint vEventMask )
+{
+ MIuint existingMask = 0;
+ if( !BroadcasterGetMask( vBroadcasterClass, existingMask ) )
+ return MIstatus::failure;
+
+ if( !ClientSaveMask( vClientName, vBroadcasterClass, vEventMask ) )
+ return MIstatus::failure;
+
+ const MIchar * pBroadCasterName = vBroadcasterClass.c_str();
+ MIuint eventMask = vEventMask;
+ eventMask += existingMask;
+ const MIuint result = m_lldbListener.StartListeningForEventClass( m_lldbDebugger, pBroadCasterName, eventMask );
+ if( result == 0 )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_STARTLISTENER ), pBroadCasterName ) );
+ return MIstatus::failure;
+ }
+
+ return BroadcasterSaveMask( vBroadcasterClass, eventMask );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Register with the debugger, the SBListener, the type of events you are interested
+// in. Others, like commands, may have already set the mask.
+// Type: Method.
+// Args: vClientName - (R) ID of the client who wants these events set.
+// vBroadcaster - (R) An SBBroadcaster's derived class.
+// vEventMask - (R) The mask of events to listen for.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::RegisterForEvent( const CMIUtilString & vClientName, const lldb::SBBroadcaster & vBroadcaster, const MIuint vEventMask )
+{
+ const MIchar * pBroadcasterName = vBroadcaster.GetName();
+ if( pBroadcasterName == nullptr )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME ), MIRSRC( IDS_WORD_INVALIDNULLPTR ) ) );
+ return MIstatus::failure;
+ }
+ CMIUtilString broadcasterName( pBroadcasterName );
+ if( broadcasterName.length() == 0 )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME ), MIRSRC( IDS_WORD_INVALIDEMPTY ) ) );
+ return MIstatus::failure;
+ }
+
+ MIuint existingMask = 0;
+ if( !BroadcasterGetMask( broadcasterName, existingMask ) )
+ return MIstatus::failure;
+
+ if( !ClientSaveMask( vClientName, broadcasterName, vEventMask ) )
+ return MIstatus::failure;
+
+ MIuint eventMask = vEventMask;
+ eventMask += existingMask;
+ const MIuint result = m_lldbListener.StartListeningForEvents( vBroadcaster, eventMask );
+ if( result == 0 )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_STARTLISTENER ), pBroadcasterName ) );
+ return MIstatus::failure;
+ }
+
+ return BroadcasterSaveMask( broadcasterName, eventMask );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Unregister with the debugger, the SBListener, the type of events you are no
+// longer interested in. Others, like commands, may still remain interested so
+// an event may not necessarily be stopped.
+// Type: Method.
+// Args: vClientName - (R) ID of the client who no longer requires these events.
+// vBroadcasterClass - (R) The SBBroadcaster's class name.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::UnregisterForEvent( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass )
+{
+ MIuint clientsEventMask = 0;
+ if( !ClientGetTheirMask( vClientName, vBroadcasterClass, clientsEventMask ) )
+ return MIstatus::failure;
+ if( !ClientRemoveTheirMask( vClientName, vBroadcasterClass ) )
+ return MIstatus::failure;
+
+ const MIuint otherClientsEventMask = ClientGetMaskForAllClients( vBroadcasterClass );
+ MIuint newEventMask = 0;
+ for( MIuint i = 0; i < 32; i++ )
+ {
+ const MIuint bit = 1 << i;
+ const MIuint clientBit = bit & clientsEventMask;
+ const MIuint othersBit = bit & otherClientsEventMask;
+ if( (clientBit != 0) && (othersBit == 0) )
+ {
+ newEventMask += clientBit;
+ }
+ }
+
+ const MIchar * pBroadCasterName = vBroadcasterClass.c_str();
+ if( !m_lldbListener.StopListeningForEventClass( m_lldbDebugger, pBroadCasterName, newEventMask ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_STOPLISTENER ), vClientName.c_str(), pBroadCasterName ) );
+ return MIstatus::failure;
+ }
+
+ return BroadcasterSaveMask( vBroadcasterClass, otherClientsEventMask );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Given the SBBroadcaster class name retrieve it's current event mask.
+// Type: Method.
+// Args: vBroadcasterClass - (R) The SBBroadcaster's class name.
+// vEventMask - (W) The mask of events to listen for.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::BroadcasterGetMask( const CMIUtilString & vBroadcasterClass, MIuint & vwEventMask ) const
+{
+ vwEventMask = 0;
+
+ if( vBroadcasterClass.empty() )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER ), vBroadcasterClass.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ const MapBroadcastClassNameToEventMask_t::const_iterator it = m_mapBroadcastClassNameToEventMask.find( vBroadcasterClass );
+ if( it != m_mapBroadcastClassNameToEventMask.end() )
+ {
+ vwEventMask = (*it).second;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Remove the event mask for the specified SBBroadcaster class name.
+// Type: Method.
+// Args: vBroadcasterClass - (R) The SBBroadcaster's class name.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::BroadcasterRemoveMask( const CMIUtilString & vBroadcasterClass )
+{
+ MapBroadcastClassNameToEventMask_t::const_iterator it = m_mapBroadcastClassNameToEventMask.find( vBroadcasterClass );
+ if( it != m_mapBroadcastClassNameToEventMask.end() )
+ {
+ m_mapBroadcastClassNameToEventMask.erase( it );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Given the SBBroadcaster class name save it's current event mask.
+// Type: Method.
+// Args: vBroadcasterClass - (R) The SBBroadcaster's class name.
+// vEventMask - (R) The mask of events to listen for.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::BroadcasterSaveMask( const CMIUtilString & vBroadcasterClass, const MIuint vEventMask )
+{
+ if( vBroadcasterClass.empty() )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER ), vBroadcasterClass.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ BroadcasterRemoveMask( vBroadcasterClass );
+ MapPairBroadcastClassNameToEventMask_t pr( vBroadcasterClass, vEventMask );
+ m_mapBroadcastClassNameToEventMask.insert( pr );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Iterate all the clients who have registered event masks against particular
+// SBBroadcasters and build up the mask that is for all of them.
+// Type: Method.
+// Args: vBroadcasterClass - (R) The broadcaster to retrieve the mask for.
+// Return: MIuint - Event mask.
+// Throws: None.
+//--
+MIuint CMICmnLLDBDebugger::ClientGetMaskForAllClients( const CMIUtilString & vBroadcasterClass ) const
+{
+ MIuint mask = 0;
+ MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.begin();
+ while( it != m_mapIdToEventMask.end() )
+ {
+ const CMIUtilString & rId( (*it).first );
+ if( rId.find( vBroadcasterClass.c_str() ) != std::string::npos )
+ {
+ const MIuint clientsMask = (*it).second;
+ mask |= clientsMask;
+ }
+
+ // Next
+ ++it;
+ }
+
+ return mask;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Given the client save its particular event requirements.
+// Type: Method.
+// Args: vClientName - (R) The Client's unique ID.
+// vBroadcasterClass - (R) The SBBroadcaster's class name targeted for the events.
+// vEventMask - (R) The mask of events to listen for.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::ClientSaveMask( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass, const MIuint vEventMask )
+{
+ if( vClientName.empty() )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME ), vClientName.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMIUtilString strId( vBroadcasterClass );
+ strId += vClientName;
+
+ ClientRemoveTheirMask( vClientName, vBroadcasterClass );
+ MapPairIdToEventMask_t pr( strId, vEventMask );
+ m_mapIdToEventMask.insert( pr );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Given the client remove it's particular event requirements.
+// Type: Method.
+// Args: vClientName - (R) The Client's unique ID.
+// vBroadcasterClass - (R) The SBBroadcaster's class name.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::ClientRemoveTheirMask( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass )
+{
+ if( vClientName.empty() )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME ), vClientName.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMIUtilString strId( vBroadcasterClass );
+ strId += vClientName;
+
+ const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find( strId );
+ if( it != m_mapIdToEventMask.end() )
+ {
+ m_mapIdToEventMask.erase( it );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the client's event mask used for on a particular SBBroadcaster.
+// Type: Method.
+// Args: vClientName - (R) The Client's unique ID.
+// vBroadcasterClass - (R) The SBBroadcaster's class name.
+// vwEventMask - (W) The client's mask.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::ClientGetTheirMask( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass, MIuint & vwEventMask )
+{
+ vwEventMask = 0;
+
+ if( vClientName.empty() )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME ), vClientName.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ CMIUtilString strId( vBroadcasterClass.c_str() );
+ strId += vClientName;
+
+ const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find( strId );
+ if( it != m_mapIdToEventMask.end() )
+ {
+ vwEventMask = (*it).second;
+ }
+
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERD ), vClientName.c_str() ) );
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Momentarily wait for an events being broadcast and inspect those that do
+// come this way. Check if the target should exit event if so start shutting
+// down this thread and the application. Any other events pass on to the
+// Out-of-band handler to futher determine what kind of event arrived.
+// This function runs in the thread "MI debugger event".
+// Type: Method.
+// Args: vrbIsAlive - (W) False = yes exit event monitoring thread, true = continue.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::MonitorSBListenerEvents( bool & vrbIsAlive )
+{
+ vrbIsAlive = true;
+
+ lldb::SBEvent event;
+ const bool bGotEvent = m_lldbListener.GetNextEvent( event );
+ if ( !bGotEvent || !event.IsValid() )
+ {
+ const std::chrono::milliseconds time( 1 );
+ std::this_thread::sleep_for( time );
+ return MIstatus::success;
+ }
+ if( !event.GetBroadcaster().IsValid() )
+ return MIstatus::success;
+
+ // Debugging
+ m_pLog->WriteLog( CMIUtilString::Format( "##### An event occurred: %s", event.GetBroadcasterClass() ) );
+
+ bool bHandledEvent = false;
+ bool bExitAppEvent = false;
+ const bool bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent( event, bHandledEvent, bExitAppEvent );
+ if( !bHandledEvent )
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT ), event.GetBroadcasterClass() ) );
+ m_pLog->WriteLog( msg );
+ }
+ if( !bOk )
+ {
+ m_pLog->WriteLog( CMICmnLLDBDebuggerHandleEvents::Instance().GetErrorDescription() );
+ }
+
+ if( bExitAppEvent )
+ {
+ // Set the application to shutdown
+ m_pClientDriver->SetExitApplicationFlag( true );
+
+ // Kill *this thread
+ vrbIsAlive = false;
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The main worker method for this thread.
+// Type: Method.
+// Args: vrbIsAlive = (W) True = *this thread is working, false = thread has exited.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::ThreadRun( bool & vrbIsAlive )
+{
+ return MonitorSBListenerEvents( vrbIsAlive );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Let this thread clean up after itself.
+// Type: Method.
+// Args:
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebugger::ThreadFinish( void )
+{
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve *this thread object's name.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Text.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnLLDBDebugger::ThreadGetName( void ) const
+{
+ return m_constStrThisThreadId;
+}
diff --git a/tools/lldb-mi/MICmnLLDBDebugger.h b/tools/lldb-mi/MICmnLLDBDebugger.h
new file mode 100644
index 000000000000..0d608997d959
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBDebugger.h
@@ -0,0 +1,125 @@
+//===-- MICmnLLDBDebugger.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBDebugger.h
+//
+// Overview: CMICmnLLDBDebugger interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers
+#include <queue>
+#include <map>
+#include <lldb/API/SBDebugger.h>
+#include <lldb/API/SBListener.h>
+#include <lldb/API/SBEvent.h>
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MIUtilThreadBaseStd.h"
+#include "MIUtilSingletonBase.h"
+
+// Declarations:
+class CMIDriverBase;
+class CMICmnLLDBDebuggerHandleEvents;
+
+//++ ============================================================================
+// Details: MI proxy/adapter for the LLDB public SBDebugger API. The CMIDriver
+// requires *this object. Command classes make calls on *this object
+// to facilitate their work effort. The instance runs in its own worker
+// thread.
+// A singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 26/02/2014.
+// Changes: None.
+//--
+class CMICmnLLDBDebugger
+: public CMICmnBase
+, public CMIUtilThreadActiveObjBase
+, public MI::ISingleton< CMICmnLLDBDebugger >
+{
+ friend class MI::ISingleton< CMICmnLLDBDebugger >;
+
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+
+ bool SetDriver( const CMIDriverBase & vClientDriver );
+ CMIDriverBase & GetDriver( void ) const;
+ lldb::SBDebugger & GetTheDebugger( void );
+ lldb::SBListener & GetTheListener( void );
+
+ // MI Commands can use these functions to listen for events they require
+ bool RegisterForEvent( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass, const MIuint vEventMask );
+ bool UnregisterForEvent( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass );
+ bool RegisterForEvent( const CMIUtilString & vClientName, const lldb::SBBroadcaster & vBroadcaster, const MIuint vEventMask );
+ bool UnregisterForEvent( const CMIUtilString & vClientName, const lldb::SBBroadcaster & vBroadcaster );
+
+// Overridden:
+public:
+ // From CMIUtilThreadActiveObjBase
+ virtual const CMIUtilString & ThreadGetName( void ) const;
+
+// Overridden:
+protected:
+ // From CMIUtilThreadActiveObjBase
+ virtual bool ThreadRun( bool & vrIsAlive );
+ virtual bool ThreadFinish( void );
+
+// Typedefs:
+private:
+ typedef std::map< CMIUtilString, MIuint > MapBroadcastClassNameToEventMask_t;
+ typedef std::pair< CMIUtilString, MIuint > MapPairBroadcastClassNameToEventMask_t;
+ typedef std::map< CMIUtilString, MIuint > MapIdToEventMask_t;
+ typedef std::pair< CMIUtilString, MIuint > MapPairIdToEventMask_t;
+
+// Methods:
+private:
+ /* ctor */ CMICmnLLDBDebugger( void );
+ /* ctor */ CMICmnLLDBDebugger( const CMICmnLLDBDebugger & );
+ void operator=( const CMICmnLLDBDebugger & );
+
+ bool InitSBDebugger( void );
+ bool InitSBListener( void );
+ bool InitStdStreams( void );
+ bool MonitorSBListenerEvents( bool & vrbYesExit );
+
+ bool BroadcasterGetMask( const CMIUtilString & vBroadcasterClass, MIuint & vEventMask ) const;
+ bool BroadcasterRemoveMask( const CMIUtilString & vBroadcasterClass );
+ bool BroadcasterSaveMask( const CMIUtilString & vBroadcasterClass, const MIuint vEventMask );
+
+ MIuint ClientGetMaskForAllClients( const CMIUtilString & vBroadcasterClass ) const;
+ bool ClientSaveMask( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass, const MIuint vEventMask );
+ bool ClientRemoveTheirMask( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass );
+ bool ClientGetTheirMask( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass, MIuint & vwEventMask );
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnLLDBDebugger( void );
+
+// Attributes:
+private:
+ CMIDriverBase * m_pClientDriver; // The driver that wants to use *this LLDB debugger
+ lldb::SBDebugger m_lldbDebugger; // SBDebugger is the primordial object that creates SBTargets and provides access to them
+ lldb::SBListener m_lldbListener; // API clients can register its own listener to debugger events
+ const CMIUtilString m_constStrThisThreadId;
+ MapBroadcastClassNameToEventMask_t m_mapBroadcastClassNameToEventMask;
+ MapIdToEventMask_t m_mapIdToEventMask;
+};
+
diff --git a/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
new file mode 100644
index 000000000000..08218a2e87e4
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
@@ -0,0 +1,1566 @@
+//===-- MICmnLLDBDebuggerHandleEvents.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBDebuggerHandleEvents.cpp
+//
+// Overview: CMICmnLLDBDebuggerHandleEvents implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers:
+#include <lldb/API/SBEvent.h>
+#include <lldb/API/SBProcess.h>
+#include <lldb/API/SBBreakpoint.h>
+#include <lldb/API/SBStream.h>
+#include <lldb/API/SBThread.h>
+#include <lldb/API/SBCommandInterpreter.h>
+#include <lldb/API/SBCommandReturnObject.h>
+#ifdef _WIN32
+ #include <io.h> // For the ::_access()
+#else
+ #include <unistd.h> // For the ::access()
+#endif // _WIN32
+#include <limits.h>
+
+// In-house headers:
+#include "MICmnLLDBDebuggerHandleEvents.h"
+#include "MICmnResources.h"
+#include "MICmnLog.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnMIValueList.h"
+#include "MICmnMIOutOfBandRecord.h"
+#include "MICmnStreamStdout.h"
+#include "MICmnStreamStderr.h"
+#include "MIUtilDebug.h"
+#include "MIDriver.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebuggerHandleEvents constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebuggerHandleEvents destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this broardcaster object.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = MIstatus::success;
+
+ return m_bInitialized;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this broardcaster object.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = false;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Interpret the event object to asscertain the action to take or information to
+// to form and put in a MI Out-of-band record object which is given to stdout.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// vrbHandledEvent - (W) True - event handled, false = not handled.
+// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEvent( const lldb::SBEvent & vEvent, bool & vrbHandledEvent, bool & vrbExitAppEvent )
+{
+ bool bOk = MIstatus::success;
+ vrbHandledEvent = false;
+ vrbExitAppEvent = false;
+
+ if( lldb::SBProcess::EventIsProcessEvent( vEvent ) )
+ {
+ vrbHandledEvent = true;
+ bOk = HandleEventSBProcess( vEvent, vrbExitAppEvent );
+ }
+ else if( lldb::SBBreakpoint::EventIsBreakpointEvent( vEvent ) )
+ {
+ vrbHandledEvent = true;
+ bOk = HandleEventSBBreakPoint( vEvent );
+ }
+ else if( lldb::SBThread::EventIsThreadEvent( vEvent ) )
+ {
+ vrbHandledEvent = true;
+ bOk = HandleEventSBThread( vEvent );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBProcess event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent )
+{
+ bool bOk = MIstatus::success;
+
+ const MIchar * pEventType = "";
+ const MIuint nEventType = vEvent.GetType();
+ switch( nEventType )
+ {
+ case lldb::SBProcess::eBroadcastBitInterrupt:
+ pEventType = "eBroadcastBitInterrupt";
+ break;
+ case lldb::SBProcess::eBroadcastBitProfileData:
+ pEventType = "eBroadcastBitProfileData";
+ break;
+ case lldb::SBProcess::eBroadcastBitStateChanged:
+ pEventType = "eBroadcastBitStateChanged";
+ bOk = HandleProcessEventBroadcastBitStateChanged( vEvent, vrbExitAppEvent );
+ break;
+ case lldb::SBProcess::eBroadcastBitSTDERR:
+ pEventType = "eBroadcastBitSTDERR";
+ bOk = GetProcessStderr();
+ break;
+ case lldb::SBProcess::eBroadcastBitSTDOUT:
+ pEventType = "eBroadcastBitSTDOUT";
+ bOk = GetProcessStdout();
+ break;
+ default:
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBProcess", (MIuint) nEventType ) );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+ }
+ m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event occurred: %s", pEventType ) );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBBreakpoint event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint( const lldb::SBEvent & vEvent )
+{
+ bool bOk = MIstatus::success;
+
+ const MIchar * pEventType ="";
+ const lldb::BreakpointEventType eEvent = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent( vEvent );
+ switch( eEvent )
+ {
+ case lldb::eBreakpointEventTypeThreadChanged:
+ pEventType = "eBreakpointEventTypeThreadChanged";
+ break;
+ case lldb::eBreakpointEventTypeLocationsRemoved:
+ pEventType = "eBreakpointEventTypeLocationsRemoved";
+ break;
+ case lldb::eBreakpointEventTypeInvalidType:
+ pEventType = "eBreakpointEventTypeInvalidType";
+ break;
+ case lldb::eBreakpointEventTypeLocationsAdded:
+ pEventType = "eBreakpointEventTypeLocationsAdded";
+ bOk = HandleEventSBBreakpointLocationsAdded( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeAdded:
+ pEventType = "eBreakpointEventTypeAdded";
+ bOk = HandleEventSBBreakpointAdded( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeRemoved:
+ pEventType = "eBreakpointEventTypeRemoved";
+ bOk = HandleEventSBBreakpointCmn( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeLocationsResolved:
+ pEventType = "eBreakpointEventTypeLocationsResolved";
+ break;
+ case lldb::eBreakpointEventTypeEnabled:
+ pEventType ="eBreakpointEventTypeEnabled";
+ bOk = HandleEventSBBreakpointCmn( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeDisabled:
+ pEventType = "eBreakpointEventTypeDisabled";
+ bOk = HandleEventSBBreakpointCmn( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeCommandChanged:
+ pEventType = "eBreakpointEventTypeCommandChanged";
+ bOk = HandleEventSBBreakpointCmn( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeConditionChanged:
+ pEventType ="eBreakpointEventTypeConditionChanged";
+ bOk = HandleEventSBBreakpointCmn( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeIgnoreChanged:
+ pEventType = "eBreakpointEventTypeIgnoreChanged";
+ bOk = HandleEventSBBreakpointCmn( vEvent );
+ break;
+ default:
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBBreakPoint", (MIuint) eEvent ) );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+ }
+ m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Breakpoint event occurred: %s", pEventType ) );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBBreakpoint event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded( const lldb::SBEvent & vEvent )
+{
+ const MIuint nLoc = lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent( vEvent );
+ if( nLoc == 0 )
+ return MIstatus::success;
+
+ lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent );
+ const CMIUtilString plural( (nLoc == 1) ? "" : "s" );
+ const CMIUtilString msg( CMIUtilString::Format( "%d location%s added to breakpoint %d", nLoc, plural.c_str(), brkPt.GetID() ) );
+
+ return TextToStdout( msg );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBBreakpoint event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn( const lldb::SBEvent & vEvent )
+{
+ lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent );
+ if( !brkPt.IsValid() )
+ return MIstatus::success;
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
+ if( !rSessionInfo.GetBrkPtInfo( brkPt, sBrkPtInfo ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET ), "HandleEventSBBreakpointCmn()", brkPt.GetID() ) );
+ return MIstatus::failure;
+ }
+
+ // CODETAG_LLDB_BREAKPOINT_CREATION
+ // This is in a worker thread
+ // Add more breakpoint information or overwrite existing information
+ CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
+ if( !rSessionInfo.RecordBrkPtInfoGet( brkPt.GetID(), sBrkPtInfoRec ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND ), "HandleEventSBBreakpointCmn()", brkPt.GetID() ) );
+ return MIstatus::failure;
+ }
+ sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
+ sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
+ sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
+ sBrkPtInfo.m_strOptThrdGrp = "";
+ sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
+ sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
+ sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
+ sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
+ sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
+ sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
+ sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
+ sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
+
+ // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\", func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
+ CMICmnMIValueTuple miValueTuple;
+ if( !rSessionInfo.MIResponseFormBrkPtInfo( sBrkPtInfo, miValueTuple ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "HandleEventSBBreakpointCmn()" ) );
+ return MIstatus::failure;
+ }
+
+ const CMICmnMIValueResult miValueResultC( "bkpt", miValueTuple );
+ const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC );
+ const bool bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBBreakpoint added event.
+// Add more breakpoint information or overwrite existing information.
+// Normally a break point session info objects exists by now when an MI command
+// was issued to insert a break so the retrieval would normally always succeed
+// however should a user type "b main" into a console then LLDB will create a
+// breakpoint directly, hence no MI command, hence no previous record of the
+// breakpoint so RecordBrkPtInfoGet() will fail. We still get the event though
+// so need to create a breakpoint info object here and send appropriate MI
+// response.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded( const lldb::SBEvent & vEvent )
+{
+ lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent );
+ if( !brkPt.IsValid() )
+ return MIstatus::success;
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
+ if( !rSessionInfo.GetBrkPtInfo( brkPt, sBrkPtInfo ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET ), "HandleEventSBBreakpointAdded()", brkPt.GetID() ) );
+ return MIstatus::failure;
+ }
+
+ // CODETAG_LLDB_BREAKPOINT_CREATION
+ // This is in a worker thread
+ CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
+ const bool bBrkPtExistAlready = rSessionInfo.RecordBrkPtInfoGet( brkPt.GetID(), sBrkPtInfoRec );
+ if( bBrkPtExistAlready )
+ {
+ // Update breakpoint information object
+ sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
+ sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
+ sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
+ sBrkPtInfo.m_strOptThrdGrp.clear();
+ sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
+ sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
+ sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
+ sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
+ sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
+ sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
+ sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
+ sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
+ }
+ else
+ {
+ // Create a breakpoint information object
+ sBrkPtInfo.m_bDisp = brkPt.IsOneShot();
+ sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
+ sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
+ sBrkPtInfo.m_strOptThrdGrp.clear();
+ sBrkPtInfo.m_strOrigLoc = CMIUtilString::Format( "%s:%d", sBrkPtInfo.m_fileName.c_str(), sBrkPtInfo.m_nLine );
+ sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount();
+ sBrkPtInfo.m_bPending = false;
+ const MIchar * pStrCondition = brkPt.GetCondition();
+ sBrkPtInfo.m_bCondition = (pStrCondition != nullptr) ? true : false;
+ sBrkPtInfo.m_strCondition = (pStrCondition != nullptr) ? pStrCondition : "??";
+ sBrkPtInfo.m_bBrkPtThreadId = (brkPt.GetThreadID() != 0) ? true : false;
+ sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID();
+ }
+
+ CMICmnMIValueTuple miValueTuple;
+ if( !rSessionInfo.MIResponseFormBrkPtInfo( sBrkPtInfo, miValueTuple ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "HandleEventSBBreakpointAdded()" ) );
+ return MIstatus::failure;
+ }
+
+ bool bOk = MIstatus::success;
+ if( bBrkPtExistAlready )
+ {
+ // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
+ const CMICmnMIValueResult miValueResult( "bkpt", miValueTuple );
+ const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult );
+ bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ }
+ else
+ {
+ // CODETAG_LLDB_BRKPT_ID_MAX
+ if( brkPt.GetID() > (lldb::break_id_t) rSessionInfo.m_nBrkPointCntMax )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_CNT_EXCEEDED ), "HandleEventSBBreakpointAdded()", rSessionInfo.m_nBrkPointCntMax, sBrkPtInfo.m_id ) );
+ return MIstatus::failure;
+ }
+ if( !rSessionInfo.RecordBrkPtInfo( brkPt.GetID(), sBrkPtInfo ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET ), "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id ) );
+ return MIstatus::failure;
+ }
+
+ // MI print "=breakpoint-created,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
+ const CMICmnMIValueResult miValueResult( "bkpt", miValueTuple );
+ const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult );
+ bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBThread event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread( const lldb::SBEvent & vEvent )
+{
+ if( !ChkForStateChanges() )
+ return MIstatus::failure;
+
+ bool bOk = MIstatus::success;
+ const MIchar * pEventType = "";
+ const MIuint nEventType = vEvent.GetType();
+ switch( nEventType )
+ {
+ case lldb::SBThread::eBroadcastBitStackChanged:
+ pEventType = "eBroadcastBitStackChanged";
+ bOk = HandleEventSBThreadBitStackChanged( vEvent );
+ break;
+ case lldb::SBThread::eBroadcastBitThreadSuspended:
+ pEventType = "eBroadcastBitThreadSuspended";
+ bOk = HandleEventSBThreadSuspended( vEvent );
+ break;
+ case lldb::SBThread::eBroadcastBitThreadResumed:
+ pEventType = "eBroadcastBitThreadResumed";
+ break;
+ case lldb::SBThread::eBroadcastBitSelectedFrameChanged:
+ pEventType = "eBroadcastBitSelectedFrameChanged";
+ break;
+ case lldb::SBThread::eBroadcastBitThreadSelected:
+ pEventType = "eBroadcastBitThreadSelected";
+ break;
+ default:
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBThread", (MIuint) nEventType ) );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+ }
+ m_pLog->WriteLog( CMIUtilString::Format( "##### An SBThread event occurred: %s", pEventType ) );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBThread event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended( const lldb::SBEvent & vEvent )
+{
+ lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent( vEvent );
+ if( !thread.IsValid() )
+ return MIstatus::success;
+
+ const lldb::StopReason eStopReason = thread.GetStopReason();
+ if( eStopReason != lldb::eStopReasonSignal )
+ return MIstatus::success;
+
+ // MI print "@thread=%d,signal=%lld"
+ const MIuint64 nId = thread.GetStopReasonDataAtIndex( 0 );
+ const CMIUtilString strThread( CMIUtilString::Format( "%d", thread.GetThreadID() ) );
+ const CMICmnMIValueConst miValueConst( strThread );
+ const CMICmnMIValueResult miValueResult( "thread", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Thread, miValueResult );
+ const CMIUtilString strSignal( CMIUtilString::Format( "%lld", nId ) );
+ const CMICmnMIValueConst miValueConst2( strSignal );
+ const CMICmnMIValueResult miValueResult2( "signal", miValueConst2 );
+ bool bOk = miOutOfBandRecord.Add( miValueResult2 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBThread event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged( const lldb::SBEvent & vEvent )
+{
+ lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent( vEvent );
+ if( !thread.IsValid() )
+ return MIstatus::success;
+
+ lldb::SBStream streamOut;
+ const bool bOk = thread.GetStatus( streamOut );
+ return bOk && TextToStdout( streamOut.GetData() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBCommandInterpreter event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB command interpreter event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter( const lldb::SBEvent & vEvent )
+{
+ // This function is not used
+ // *** This function is under development
+
+ const MIchar * pEventType = "";
+ const MIuint nEventType = vEvent.GetType();
+ switch( nEventType )
+ {
+ case lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit:
+ pEventType ="eBroadcastBitThreadShouldExit";
+ // ToDo: IOR: Reminder to maybe handle this here
+ //const MIuint nEventType = event.GetType();
+ //if( nEventType & lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit )
+ //{
+ // m_pClientDriver->SetExitApplicationFlag();
+ // vrbYesExit = true;
+ // return MIstatus::success;
+ //} break;
+ case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt:
+ pEventType = "eBroadcastBitResetPrompt";
+ break;
+ case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
+ pEventType = "eBroadcastBitQuitCommandReceived";
+ break;
+ case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData:
+ pEventType = "eBroadcastBitAsynchronousOutputData";
+ break;
+ case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData:
+ pEventType = "eBroadcastBitAsynchronousErrorData";
+ break;
+ default:
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBCommandInterpreter", (MIuint) nEventType ) );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+ }
+ m_pLog->WriteLog( CMIUtilString::Format( "##### An SBCommandInterpreter event occurred: %s", pEventType ) );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle SBProcess event eBroadcastBitStateChanged.
+// Type: Method.
+// Args: vEvent - (R) An LLDB event object.
+// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent )
+{
+ bool bOk = ChkForStateChanges();
+ bOk = bOk && GetProcessStdout();
+ bOk = bOk && GetProcessStderr();
+ if( !bOk )
+ return MIstatus::failure;
+
+ // Something changed in the process; get the event and report the process's current
+ // status and location
+ const lldb::StateType eEventState = lldb::SBProcess::GetStateFromEvent( vEvent );
+ if( eEventState == lldb::eStateInvalid )
+ return MIstatus::success;
+
+ lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent( vEvent );
+ if( !process.IsValid() )
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID ), "SBProcess", "HandleProcessEventBroadcastBitStateChanged()" ) );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+
+ bool bShouldBrk = true;
+ const MIchar * pEventType = "";
+ switch( eEventState )
+ {
+ case lldb::eStateUnloaded:
+ pEventType = "eStateUnloaded";
+ break;
+ case lldb::eStateConnected:
+ pEventType = "eStateConnected";
+ break;
+ case lldb::eStateAttaching:
+ pEventType = "eStateAttaching";
+ break;
+ case lldb::eStateLaunching:
+ pEventType ="eStateLaunching";
+ break;
+ case lldb::eStateStopped:
+ pEventType = "eStateStopped";
+ bOk = HandleProcessEventStateStopped( bShouldBrk );
+ if( bShouldBrk )
+ break;
+ case lldb::eStateCrashed:
+ case lldb::eStateSuspended:
+ pEventType = "eStateSuspended";
+ bOk = HandleProcessEventStateSuspended( vEvent );
+ break;
+ case lldb::eStateRunning:
+ pEventType = "eStateRunning";
+ bOk = HandleProcessEventStateRunning();
+ break;
+ case lldb::eStateStepping:
+ pEventType = "eStateStepping";
+ break;
+ case lldb::eStateDetached:
+ pEventType = "eStateDetached";
+ break;
+ case lldb::eStateExited:
+ pEventType = "eStateExited";
+ vrbExitAppEvent = true;
+ bOk = HandleProcessEventStateExited();
+ break;
+ default:
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBProcess BroadcastBitStateChanged", (MIuint) eEventState ) );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+ }
+
+ // ToDo: Remove when finished coding application
+ m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event BroadcastBitStateChanged occurred: %s", pEventType ) );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Asynchronous event handler for LLDB Process state suspended.
+// Type: Method.
+// Args: vEvent - (R) An LLDB event object.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended( const lldb::SBEvent & vEvent )
+{
+ // Make sure the program hasn't been auto-restarted:
+ if( lldb::SBProcess::GetRestartedFromEvent( vEvent ) )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ lldb::SBDebugger & rDebugger = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger;
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ lldb::SBTarget target = rProcess.GetTarget();
+ if( rDebugger.GetSelectedTarget() == target )
+ {
+ if( !UpdateSelectedThread() )
+ return MIstatus::failure;
+
+ lldb::SBCommandReturnObject result;
+ const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand( "process status", result, false ); MIunused( status );
+ bOk = TextToStderr( result.GetError() );
+ bOk = bOk && TextToStdout( result.GetOutput() );
+ }
+ else
+ {
+ lldb::SBStream streamOut;
+ const MIuint nTargetIndex = rDebugger.GetIndexOfTarget( target );
+ if( nTargetIndex != UINT_MAX )
+ streamOut.Printf( "Target %d: (", nTargetIndex );
+ else
+ streamOut.Printf( "Target <unknown index>: (" );
+ target.GetDescription( streamOut, lldb::eDescriptionLevelBrief );
+ streamOut.Printf( ") stopped.\n" );
+ bOk = TextToStdout( streamOut.GetData() );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Print to stdout MI formatted text to indicate process stopped.
+// Type: Method.
+// Args: vwrbShouldBrk - (W) True = Yes break, false = do not.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped( bool & vwrbShouldBrk )
+{
+ if( !UpdateSelectedThread() )
+ return MIstatus::failure;
+
+ const MIchar * pEventType = "";
+ bool bOk = MIstatus::success;
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ const lldb::StopReason eStoppedReason = rProcess.GetSelectedThread().GetStopReason();
+ switch( eStoppedReason )
+ {
+ case lldb::eStopReasonInvalid:
+ pEventType = "eStopReasonInvalid";
+ vwrbShouldBrk = false;
+ break;
+ case lldb::eStopReasonNone:
+ pEventType = "eStopReasonNone";
+ break;
+ case lldb::eStopReasonTrace:
+ pEventType = "eStopReasonTrace";
+ bOk = HandleProcessEventStopReasonTrace();
+ break;
+ case lldb::eStopReasonBreakpoint:
+ pEventType = "eStopReasonBreakpoint";
+ bOk = HandleProcessEventStopReasonBreakpoint();
+ break;
+ case lldb::eStopReasonWatchpoint:
+ pEventType = "eStopReasonWatchpoint";
+ break;
+ case lldb::eStopReasonSignal:
+ pEventType = "eStopReasonSignal";
+ bOk = HandleProcessEventStopSignal( vwrbShouldBrk );
+ break;
+ case lldb::eStopReasonException:
+ pEventType ="eStopReasonException";
+ break;
+ case lldb::eStopReasonExec:
+ pEventType = "eStopReasonExec";
+ break;
+ case lldb::eStopReasonPlanComplete:
+ pEventType = "eStopReasonPlanComplete";
+ bOk = HandleProcessEventStopReasonTrace();
+ break;
+ case lldb::eStopReasonThreadExiting:
+ pEventType = "eStopReasonThreadExiting";
+ break;
+ default:
+ {
+ vwrbShouldBrk = false;
+
+ // MI print "*stopped,reason=\"%d\",stopped-threads=\"all\",from-thread=\"%u\""
+ const CMIUtilString strReason( CMIUtilString::Format( "%d", eStoppedReason ) );
+ const CMICmnMIValueConst miValueConst( strReason );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "all" );
+ const CMICmnMIValueResult miValueResult2( "stopped-threads", miValueConst2 );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+ const CMIUtilString strFromThread( CMIUtilString::Format( "%u", rProcess.GetSelectedThread().GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst3( strFromThread );
+ const CMICmnMIValueResult miValueResult3( "from-thread", miValueConst3 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ }
+ }
+
+ // ToDo: Remove when finished coding application
+ m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event stop state occurred: %s", pEventType ) );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Asynchronous event handler for LLDB Process stop signal.
+// Type: Method.
+// Args: vwrbShouldBrk - (W) True = Yes break, false = do not.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal( bool & vwrbShouldBrk )
+{
+ bool bOk = MIstatus::success;
+
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ const MIuint64 nStopReason = rProcess.GetSelectedThread().GetStopReasonDataAtIndex( 0 );
+ switch( nStopReason )
+ {
+ case 2: // Terminal interrupt signal. SIGINT
+ {
+ // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGNINT\",signal-meaning=\"Interrupt\",frame={%s}"
+ const CMICmnMIValueConst miValueConst( "signal-received" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "SIGINT" );
+ const CMICmnMIValueResult miValueResult2( "signal-name", miValueConst2 );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+ const CMICmnMIValueConst miValueConst3( "Interrupt" );
+ const CMICmnMIValueResult miValueResult3( "signal-meaning", miValueConst3 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
+ CMICmnMIValueTuple miValueTuple;
+ bOk = bOk && MiHelpGetCurrentThreadFrame( miValueTuple );
+ const CMICmnMIValueResult miValueResult5( "frame", miValueTuple );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult5 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ }
+ break;
+ case 11: // Invalid memory reference. SIGSEGV
+ {
+ // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSEGV\",signal-meaning=\"Segmentation fault\",thread-id=\"%d\",frame={%s}"
+ const CMICmnMIValueConst miValueConst( "signal-received" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "SIGSEGV" );
+ const CMICmnMIValueResult miValueResult2( "signal-name", miValueConst2 );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+ const CMICmnMIValueConst miValueConst3( "Segmentation fault" );
+ const CMICmnMIValueResult miValueResult3( "signal-meaning", miValueConst3 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
+ const CMIUtilString strThreadId( CMIUtilString::Format( "%d", rProcess.GetSelectedThread().GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst4( strThreadId );
+ const CMICmnMIValueResult miValueResult4( "thread-id", miValueConst4 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult4 );
+ CMICmnMIValueTuple miValueTuple;
+ bOk = bOk && MiHelpGetCurrentThreadFrame( miValueTuple );
+ const CMICmnMIValueResult miValueResult5( "frame", miValueTuple );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult5 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ // Note no "(gdb)" output here
+ }
+ break;
+ case 19:
+ if( rProcess.IsValid() )
+ rProcess.Continue();
+ break;
+ case 5: // Trace/breakpoint trap. SIGTRAP
+ {
+ lldb::SBThread thread = rProcess.GetSelectedThread();
+ const MIuint nFrames = thread.GetNumFrames();
+ if( nFrames > 0 )
+ {
+ lldb::SBFrame frame = thread.GetFrameAtIndex( 0 );
+ const char * pFnName = frame.GetFunctionName();
+ if( pFnName != nullptr )
+ {
+ const CMIUtilString fnName = CMIUtilString( pFnName );
+ static const CMIUtilString threadCloneFn = CMIUtilString( "__pthread_clone" );
+
+ if( CMIUtilString::Compare( threadCloneFn, fnName ) )
+ {
+ if( rProcess.IsValid() )
+ {
+ rProcess.Continue();
+ vwrbShouldBrk = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ default:
+ {
+ // MI print "*stopped,reason=\"signal-received\",signal=\"%lld\",stopped-threads=\"all\""
+ const CMICmnMIValueConst miValueConst( "signal-received" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMIUtilString strReason( CMIUtilString::Format( "%lld", nStopReason ) );
+ const CMICmnMIValueConst miValueConst2( strReason );
+ const CMICmnMIValueResult miValueResult2( "signal", miValueConst2 );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+ const CMICmnMIValueConst miValueConst3( "all" );
+ const CMICmnMIValueResult miValueResult3( "stopped-threads", miValueConst3 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ }
+ } // switch( nStopReason )
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Form partial MI response in a MI value tuple object.
+// Type: Method.
+// Args: vwrMiValueTuple - (W) MI value tuple object.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame( CMICmnMIValueTuple & vwrMiValueTuple )
+{
+ CMIUtilString strThreadFrame;
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ lldb::SBThread thread = rProcess.GetSelectedThread();
+ const MIuint nFrame = thread.GetNumFrames();
+ if( nFrame == 0 )
+ {
+ // MI print "addr=\"??\",func=\"??\",file=\"??\",fullname=\"??\",line=\"??\""
+ const CMICmnMIValueConst miValueConst( "??" );
+ const CMICmnMIValueResult miValueResult( "addr", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueResult miValueResult2( "func", miValueConst );
+ miValueTuple.Add( miValueResult2 );
+ const CMICmnMIValueResult miValueResult4( "file", miValueConst );
+ miValueTuple.Add( miValueResult4 );
+ const CMICmnMIValueResult miValueResult5( "fullname", miValueConst );
+ miValueTuple.Add( miValueResult5 );
+ const CMICmnMIValueResult miValueResult6( "line", miValueConst );
+ miValueTuple.Add( miValueResult6 );
+
+ vwrMiValueTuple = miValueTuple;
+
+ return MIstatus::success;
+ }
+
+ CMICmnMIValueTuple miValueTuple;
+ if( !CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo( thread, 0, miValueTuple ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "MiHelpGetCurrentThreadFrame()" ) );
+ return MIstatus::failure;
+ }
+
+ vwrMiValueTuple = miValueTuple;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Asynchronous event handler for LLDB Process stop reason breakpoint.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint( void )
+{
+ // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+ if( !CMIDriver::Instance().SetDriverStateRunningNotDebugging() )
+ {
+ const CMIUtilString & rErrMsg( CMIDriver::Instance().GetErrorDescription() );
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE ), "HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ const MIuint64 brkPtId = rProcess.GetSelectedThread().GetStopReasonDataAtIndex( 0 );
+ lldb::SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget.GetBreakpointAtIndex( (MIuint) brkPtId );
+
+ return MiStoppedAtBreakPoint( brkPtId, brkPt );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Form the MI Out-of-band response for stopped reason on hitting a break point.
+// Type: Method.
+// Args: vBrkPtId - (R) The LLDB break point's ID
+// vBrkPt - (R) THe LLDB break point object.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint( const MIuint64 vBrkPtId, const lldb::SBBreakpoint & vBrkPt )
+{
+ bool bOk = MIstatus::success;
+
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ lldb::SBThread thread = rProcess.GetSelectedThread();
+ const MIuint nFrame = thread.GetNumFrames();
+ if( nFrame == 0 )
+ {
+ // MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={},thread-id=\"%d\",stopped-threads=\"all\""
+ const CMICmnMIValueConst miValueConst( "breakpoint-hit" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "del" );
+ const CMICmnMIValueResult miValueResult2( "disp", miValueConst2 );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+ const CMIUtilString strBkp( CMIUtilString::Format( "%d", vBrkPtId ) );
+ const CMICmnMIValueConst miValueConst3( strBkp );
+ CMICmnMIValueResult miValueResult3( "bkptno", miValueConst3 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
+ const CMICmnMIValueConst miValueConst4( "{}" );
+ const CMICmnMIValueResult miValueResult4( "frame", miValueConst4 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult4 );
+ const CMIUtilString strThreadId( CMIUtilString::Format( "%d", vBrkPt.GetThreadIndex() ) );
+ const CMICmnMIValueConst miValueConst5( strThreadId );
+ const CMICmnMIValueResult miValueResult5( "thread-id", miValueConst5 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult5 );
+ const CMICmnMIValueConst miValueConst6( "all" );
+ const CMICmnMIValueResult miValueResult6( "stopped-threads", miValueConst6 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult6 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ return bOk;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSession = CMICmnLLDBDebugSessionInfo::Instance();
+
+ lldb::SBFrame frame = thread.GetFrameAtIndex( 0 );
+ lldb::addr_t pc = 0;
+ CMIUtilString fnName;
+ CMIUtilString fileName;
+ CMIUtilString path;
+ MIuint nLine = 0;
+ if( !rSession.GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET ), "MiStoppedAtBreakPoint()" ) );
+ return MIstatus::failure;
+ }
+
+ // MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
+ const CMICmnMIValueConst miValueConst( "breakpoint-hit" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueConst miValueConstA( "del" );
+ const CMICmnMIValueResult miValueResultA( "disp", miValueConstA );
+ bOk = miOutOfBandRecord.Add( miValueResultA );
+ const CMIUtilString strBkp( CMIUtilString::Format( "%d", vBrkPtId ) );
+ const CMICmnMIValueConst miValueConstB( strBkp );
+ CMICmnMIValueResult miValueResultB( "bkptno", miValueConstB );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResultB );
+
+ // frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
+ if( bOk )
+ {
+ CMICmnMIValueList miValueList( true );
+ const MIuint maskVarTypes = 0x1000;
+ bOk = rSession.MIResponseFormVariableInfo2( frame, maskVarTypes, miValueList );
+
+ CMICmnMIValueTuple miValueTuple;
+ bOk = bOk && rSession.MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple );
+ const CMICmnMIValueResult miValueResult8( "frame", miValueTuple );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult8 );
+ }
+
+ // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
+ if( bOk )
+ {
+ const CMIUtilString strThreadId( CMIUtilString::Format( "%d", thread.GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst8( strThreadId );
+ const CMICmnMIValueResult miValueResult8( "thread-id", miValueConst8 );
+ bOk = miOutOfBandRecord.Add( miValueResult8 );
+ }
+ if( bOk )
+ {
+ const CMICmnMIValueConst miValueConst9( "all" );
+ const CMICmnMIValueResult miValueResult9( "stopped-threads", miValueConst9 );
+ bOk = miOutOfBandRecord.Add( miValueResult9 );
+ bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Asynchronous event handler for LLDB Process stop reason trace.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace( void )
+{
+ bool bOk = true;
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ lldb::SBThread thread = rProcess.GetSelectedThread();
+ const MIuint nFrame = thread.GetNumFrames();
+ if( nFrame == 0 )
+ {
+ // MI print "*stopped,reason=\"trace\",stopped-threads=\"all\""
+ const CMICmnMIValueConst miValueConst( "trace" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "all" );
+ const CMICmnMIValueResult miValueResult2( "stopped-threads", miValueConst2 );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+ bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ return bOk;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSession = CMICmnLLDBDebugSessionInfo::Instance();
+
+ // MI print "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%08x\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
+ lldb::SBFrame frame = thread.GetFrameAtIndex( 0 );
+ lldb::addr_t pc = 0;
+ CMIUtilString fnName;
+ CMIUtilString fileName;
+ CMIUtilString path;
+ MIuint nLine = 0;
+ if( !rSession.GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET ), "HandleProcessEventStopReasonTrace()" ) );
+ return MIstatus::failure;
+ }
+
+ // Function args
+ CMICmnMIValueList miValueList( true );
+ const MIuint maskVarTypes = 0x1000;
+ if( !rSession.MIResponseFormVariableInfo2( frame, maskVarTypes, miValueList ) )
+ return MIstatus::failure;
+ CMICmnMIValueTuple miValueTuple;
+ if( !rSession.MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple ) )
+ return MIstatus::failure;
+
+ const CMICmnMIValueConst miValueConst( "end-stepping-range" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueResult miValueResult2( "frame", miValueTuple );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+
+ // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
+ if( bOk )
+ {
+ const CMIUtilString strThreadId( CMIUtilString::Format( "%d", thread.GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst8( strThreadId );
+ const CMICmnMIValueResult miValueResult8( "thread-id", miValueConst8 );
+ bOk = miOutOfBandRecord.Add( miValueResult8 );
+ }
+ if( bOk )
+ {
+ const CMICmnMIValueConst miValueConst9( "all" );
+ const CMICmnMIValueResult miValueResult9( "stopped-threads", miValueConst9 );
+ bOk = miOutOfBandRecord.Add( miValueResult9 );
+ bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Asynchronous function update selected thread.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread( void )
+{
+ lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
+ if( !process.IsValid() )
+ return MIstatus::success;
+
+ lldb::SBThread currentThread = process.GetSelectedThread();
+ lldb::SBThread thread;
+ const lldb::StopReason eCurrentThreadStoppedReason = currentThread.GetStopReason();
+ if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason == lldb::eStopReasonNone) )
+ {
+ // Prefer a thread that has just completed its plan over another thread as current thread
+ lldb::SBThread planThread;
+ lldb::SBThread otherThread;
+ const size_t nThread = process.GetNumThreads();
+ for( MIuint i = 0; i < nThread; i++ )
+ {
+ // GetThreadAtIndex() uses a base 0 index
+ // GetThreadByIndexID() uses a base 1 index
+ thread = process.GetThreadAtIndex( i );
+ const lldb::StopReason eThreadStopReason = thread.GetStopReason();
+ switch( eThreadStopReason )
+ {
+ case lldb::eStopReasonTrace:
+ case lldb::eStopReasonBreakpoint:
+ case lldb::eStopReasonWatchpoint:
+ case lldb::eStopReasonSignal:
+ case lldb::eStopReasonException:
+ if( !otherThread.IsValid() )
+ otherThread = thread;
+ break;
+ case lldb::eStopReasonPlanComplete:
+ if( !planThread.IsValid() )
+ planThread = thread;
+ break;
+ case lldb::eStopReasonInvalid:
+ case lldb::eStopReasonNone:
+ default:
+ break;
+ }
+ }
+ if( planThread.IsValid() )
+ process.SetSelectedThread( planThread );
+ else if( otherThread.IsValid() )
+ process.SetSelectedThread( otherThread );
+ else
+ {
+ if( currentThread.IsValid() )
+ thread = currentThread;
+ else
+ thread = process.GetThreadAtIndex( 0 );
+
+ if( thread.IsValid() )
+ process.SetSelectedThread( thread );
+ }
+ } // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason == lldb::eStopReasonNone) )
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Print to stdout "*running,thread-id=\"all\"", "(gdb)".
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning( void )
+{
+ CMICmnMIValueConst miValueConst( "all" );
+ CMICmnMIValueResult miValueResult( "thread-id", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult );
+ bool bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Print to stdout "=thread-exited,id=\"%ld\",group-id=\"i1\"",
+// "=thread-group-exited,id=\"i1\",exit-code=\"0\""),
+// "*stopped,reason=\"exited-normally\"",
+// "(gdb)"
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited( void )
+{
+ const CMIUtilString strId( CMIUtilString::Format( "%ld", 1 ) );
+ CMICmnMIValueConst miValueConst( strId );
+ CMICmnMIValueResult miValueResult( "id", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult );
+ CMICmnMIValueConst miValueConst2( "i1" );
+ CMICmnMIValueResult miValueResult2( "group-id", miValueConst2 );
+ bool bOk = miOutOfBandRecord.Add( miValueResult2 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ if( bOk )
+ {
+ CMICmnMIValueConst miValueConst3( "i1" );
+ CMICmnMIValueResult miValueResult3( "id", miValueConst3 );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord2( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3 );
+ CMICmnMIValueConst miValueConst2( "0" );
+ CMICmnMIValueResult miValueResult2( "exit-code", miValueConst2 );
+ bOk = miOutOfBandRecord2.Add( miValueResult2 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord2 );
+ }
+ if( bOk )
+ {
+ CMICmnMIValueConst miValueConst4( "exited-normally" );
+ CMICmnMIValueResult miValueResult4( "reason", miValueConst4 );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord3( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4 );
+ bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord3 );
+ }
+ bOk = bOk && TextToStdout( "(gdb)" );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Drain all stdout so we don't see any output come after we print our prompts.
+// The process has stuff waiting for stdout; get it and write it out to the
+// appropriate place.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::GetProcessStdout( void )
+{
+ bool bOk = MIstatus::success;
+
+ char c;
+ size_t nBytes = 0;
+ CMIUtilString text;
+ lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
+ while( process.GetSTDOUT( &c, 1 ) > 0 )
+ {
+ CMIUtilString str;
+ if( ConvertPrintfCtrlCodeToString( c, str ) )
+ text += str;
+ nBytes++;
+ }
+ if( nBytes > 0 )
+ {
+ const CMIUtilString t( CMIUtilString::Format( "~\"%s\"", text.c_str() ) );
+ bOk = TextToStdout( t );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Drain all stderr so we don't see any output come after we print our prompts.
+// The process has stuff waiting for stderr; get it and write it out to the
+// appropriate place.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::GetProcessStderr( void )
+{
+ bool bOk = MIstatus::success;
+
+ char c;
+ size_t nBytes = 0;
+ CMIUtilString text;
+ lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
+ while( process.GetSTDERR( &c, 1 ) > 0 )
+ {
+ CMIUtilString str;
+ if( ConvertPrintfCtrlCodeToString( c, str ) )
+ text += str;
+ nBytes++;
+ }
+ if( nBytes > 0 )
+ {
+ const CMIUtilString t( CMIUtilString::Format( "~\"%s\"", text.c_str() ) );
+ bOk = TextToStdout( t );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Convert text stream control codes to text equivalent.
+// Type: Method.
+// Args: vCtrl - (R) The control code.
+// vwrStrEquivalent - (W) The text equivalent.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString( const MIchar vCtrl, CMIUtilString & vwrStrEquivalent )
+{
+ switch( vCtrl )
+ {
+ case '\033': vwrStrEquivalent = "\\e"; break;
+ case '\a': vwrStrEquivalent = "\\a"; break;
+ case '\b': vwrStrEquivalent = "\\b"; break;
+ case '\f': vwrStrEquivalent = "\\f"; break;
+ case '\n': vwrStrEquivalent = "\\n"; break;
+ case '\r': vwrStrEquivalent = "\\r"; break;
+ case '\t': vwrStrEquivalent = "\\t"; break;
+ case '\v': vwrStrEquivalent = "\\v"; break;
+ default:
+ vwrStrEquivalent = CMIUtilString::Format( "%c", vCtrl );
+ break;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Asynchronous event function check for state changes.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges( void )
+{
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ if( !rProcess.IsValid() )
+ return MIstatus::success;
+ lldb::SBTarget & rTarget = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget;
+ if( !rTarget.IsValid() )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+
+ // Check for created threads
+ const MIuint nThread = rProcess.GetNumThreads();
+ for( MIuint i = 0; i < nThread; i++ )
+ {
+ // GetThreadAtIndex() uses a base 0 index
+ // GetThreadByIndexID() uses a base 1 index
+ lldb::SBThread thread = rProcess.GetThreadAtIndex( i );
+ if( !thread.IsValid() )
+ continue;
+
+ CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin();
+ bool bFound = false;
+ while( it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end() )
+ {
+ const MIuint nThreadId = *it;
+ if( nThreadId == i )
+ {
+ bFound = true;
+ break;
+ }
+
+ // Next
+ ++it;
+ }
+ if( !bFound )
+ {
+ CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.push_back( i );
+
+ // Form MI "=thread-created,id=\"%d\",group-id=\"i1\""
+ const CMIUtilString strValue( CMIUtilString::Format( "%d", thread.GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst( strValue );
+ const CMICmnMIValueResult miValueResult( "id", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "i1" );
+ const CMICmnMIValueResult miValueResult2( "group-id", miValueConst2 );
+ bOk = miOutOfBand.Add( miValueResult2 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBand );
+ if( !bOk )
+ return MIstatus::failure;
+ }
+ }
+
+ lldb::SBThread currentThread = rProcess.GetSelectedThread();
+ if( currentThread.IsValid() )
+ {
+ const MIuint threadId = currentThread.GetIndexID();
+ if( CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread != threadId )
+ {
+ CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread = threadId;
+
+ // Form MI "=thread-selected,id=\"%d\""
+ const CMIUtilString strValue( CMIUtilString::Format( "%d", currentThread.GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst( strValue );
+ const CMICmnMIValueResult miValueResult( "id", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, miValueResult );
+ if( !MiOutOfBandRecordToStdout( miOutOfBand ) )
+ return MIstatus::failure;
+ }
+ }
+
+ // Check for invalid (removed) threads
+ CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin();
+ while( it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end() )
+ {
+ const MIuint nThreadId = *it;
+ lldb::SBThread thread = rProcess.GetThreadAtIndex( nThreadId );
+ if( !thread.IsValid() )
+ {
+ // Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\""
+ const CMIUtilString strValue( CMIUtilString::Format( "%ld", thread.GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst( strValue );
+ const CMICmnMIValueResult miValueResult( "id", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "i1" );
+ const CMICmnMIValueResult miValueResult2( "group-id", miValueConst2 );
+ bOk = miOutOfBand.Add( miValueResult2 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBand );
+ if( !bOk )
+ return MIstatus::failure;
+ }
+
+ // Next
+ ++it;
+ }
+
+ return TextToStdout( "(gdb)" );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Take a fully formed MI result record and send to the stdout stream.
+// Also output to the MI Log file.
+// Type: Method.
+// Args: vrMiResultRecord - (R) MI result record object.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout( const CMICmnMIResultRecord & vrMiResultRecord )
+{
+ return TextToStdout( vrMiResultRecord.GetString() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Take a fully formed MI Out-of-band record and send to the stdout stream.
+// Also output to the MI Log file.
+// Type: Method.
+// Args: vrMiOutOfBandRecord - (R) MI Out-of-band record object.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout( const CMICmnMIOutOfBandRecord & vrMiOutOfBandRecord )
+{
+ return TextToStdout( vrMiOutOfBandRecord.GetString() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Take a text data and send to the stdout stream. Also output to the MI Log
+// file.
+// Type: Method.
+// Args: vrTxt - (R) Text.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::TextToStdout( const CMIUtilString & vrTxt )
+{
+ return CMICmnStreamStdout::TextToStdout( vrTxt );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Take a text data and send to the stderr stream. Also output to the MI Log
+// file.
+// Type: Method.
+// Args: vrTxt - (R) Text.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::TextToStderr( const CMIUtilString & vrTxt )
+{
+ return CMICmnStreamStderr::TextToStderr( vrTxt );
+}
diff --git a/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h
new file mode 100644
index 000000000000..fdcb2ea4e147
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h
@@ -0,0 +1,97 @@
+//===-- MICmnLLDBDebuggerHandleEvents.h -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBDebuggerHandleEvents.h
+//
+// Overview: CMICmnLLDBDebuggerHandleEvents interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MICmnMIValueTuple.h"
+#include "MIUtilSingletonBase.h"
+
+// Declarations:
+class CMICmnLLDBDebugSessionInfo;
+class CMICmnMIResultRecord;
+class CMICmnStreamStdout;
+class CMICmnMIOutOfBandRecord;
+
+//++ ============================================================================
+// Details: MI class to take LLDB SBEvent objects, filter them and form
+// MI Out-of-band records from the information inside the event object.
+// These records are then pushed to stdout.
+// A singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 02/03/2014.
+// Changes: None.
+//--
+class CMICmnLLDBDebuggerHandleEvents
+: public CMICmnBase
+, public MI::ISingleton< CMICmnLLDBDebuggerHandleEvents >
+{
+ friend class MI::ISingleton< CMICmnLLDBDebuggerHandleEvents >;
+
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+ //
+ bool HandleEvent( const lldb::SBEvent & vEvent, bool & vrbHandledEvent, bool & vrbExitAppEvent );
+
+// Methods:
+private:
+ /* ctor */ CMICmnLLDBDebuggerHandleEvents( void );
+ /* ctor */ CMICmnLLDBDebuggerHandleEvents( const CMICmnLLDBDebuggerHandleEvents & );
+ void operator=( const CMICmnLLDBDebuggerHandleEvents & );
+ //
+ bool ChkForStateChanges( void );
+ bool GetProcessStdout( void );
+ bool GetProcessStderr( void );
+ bool HandleEventSBBreakPoint( const lldb::SBEvent & vEvent );
+ bool HandleEventSBBreakpointCmn( const lldb::SBEvent & vEvent );
+ bool HandleEventSBBreakpointAdded( const lldb::SBEvent & vEvent );
+ bool HandleEventSBBreakpointLocationsAdded( const lldb::SBEvent & vEvent );
+ bool HandleEventSBProcess( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent );
+ bool HandleEventSBThread( const lldb::SBEvent & vEvent );
+ bool HandleEventSBThreadBitStackChanged( const lldb::SBEvent & vEvent );
+ bool HandleEventSBThreadSuspended( const lldb::SBEvent & vEvent );
+ bool HandleEventSBCommandInterpreter( const lldb::SBEvent & vEvent );
+ bool HandleProcessEventBroadcastBitStateChanged( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent );
+ bool HandleProcessEventStateRunning( void );
+ bool HandleProcessEventStateExited( void );
+ bool HandleProcessEventStateStopped( bool & vwrbShouldBrk );
+ bool HandleProcessEventStopReasonTrace( void );
+ bool HandleProcessEventStopReasonBreakpoint( void );
+ bool HandleProcessEventStopSignal( bool & vwrbShouldBrk );
+ bool HandleProcessEventStateSuspended( const lldb::SBEvent & vEvent );
+ bool MiHelpGetCurrentThreadFrame( CMICmnMIValueTuple & vwrMiValueTuple );
+ bool MiResultRecordToStdout( const CMICmnMIResultRecord & vrMiResultRecord );
+ bool MiOutOfBandRecordToStdout( const CMICmnMIOutOfBandRecord & vrMiResultRecord );
+ bool MiStoppedAtBreakPoint( const MIuint64 vBrkPtId, const lldb::SBBreakpoint & vBrkPt );
+ bool TextToStdout( const CMIUtilString & vrTxt );
+ bool TextToStderr( const CMIUtilString & vrTxt );
+ bool UpdateSelectedThread( void );
+ bool ConvertPrintfCtrlCodeToString( const MIchar vCtrl, CMIUtilString & vwrStrEquivalent );
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnLLDBDebuggerHandleEvents( void );
+};
+
diff --git a/tools/lldb-mi/MICmnLLDBProxySBValue.cpp b/tools/lldb-mi/MICmnLLDBProxySBValue.cpp
new file mode 100644
index 000000000000..78ef76bf698f
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBProxySBValue.cpp
@@ -0,0 +1,153 @@
+//===-- MICmnLLDBProxySBValue.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBProxySBValue.cpp
+//
+// Overview: CMICmnLLDBProxySBValue implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#include <stdlib.h>
+
+// Third Party Headers:
+#include <lldb/API/SBError.h>
+
+// In-house headers:
+#include "MICmnLLDBProxySBValue.h"
+#include "MIUtilString.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the numerical value from the SBValue object. If the function fails
+// it could indicate the SBValue object does not represent an internal type.
+// Type: Static method.
+// Args: vrValue - (R) The SBValue object to get a value from.
+// vwValue - (W) The numerical value.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBProxySBValue::GetValueAsUnsigned( const lldb::SBValue & vrValue, MIuint64 & vwValue )
+{
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue );
+ bool bCompositeType = true;
+ MIuint64 nFailValue = 0;
+ MIuint64 nValue = rValue.GetValueAsUnsigned( nFailValue );
+ if( nValue == nFailValue )
+ {
+ nFailValue = 5; // Some arbitary number
+ nValue = rValue.GetValueAsUnsigned( nFailValue );
+ if( nValue != nFailValue )
+ {
+ bCompositeType = false;
+ vwValue = nValue;
+ }
+ }
+ else
+ {
+ bCompositeType = false;
+ vwValue = nValue;
+ }
+
+ return (bCompositeType ? MIstatus::failure : MIstatus::success);
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the numerical value from the SBValue object. If the function fails
+// it could indicate the SBValue object does not represent an internal type.
+// Type: Static method.
+// Args: vrValue - (R) The SBValue object to get a value from.
+// vwValue - (W) The numerical value.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBProxySBValue::GetValueAsSigned( const lldb::SBValue & vrValue, MIint64 & vwValue )
+{
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue );
+ bool bCompositeType = true;
+ MIuint64 nFailValue = 0;
+ MIuint64 nValue = rValue.GetValueAsSigned( nFailValue );
+ if( nValue == nFailValue )
+ {
+ nFailValue = 5; // Some arbitary number
+ nValue = rValue.GetValueAsSigned( nFailValue );
+ if( nValue != nFailValue )
+ {
+ bCompositeType = false;
+ vwValue = nValue;
+ }
+ }
+ else
+ {
+ bCompositeType = false;
+ vwValue = nValue;
+ }
+
+ return (bCompositeType ? MIstatus::failure : MIstatus::success);
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the NUL terminated string from the SBValue object if it of the type
+// unsigned char *.
+// Type: Static method.
+// Args: vrValue - (R) The SBValue object to get a value from.
+// vwCString - (W) The text data '\0' terminated.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed, not suitable type.
+// Throws: None.
+//--
+bool CMICmnLLDBProxySBValue::GetCString( const lldb::SBValue & vrValue, CMIUtilString & vwCString )
+{
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValue );
+ const MIchar * pCType = rValue.GetTypeName();
+ if( pCType == nullptr )
+ return MIstatus::failure;
+
+ const MIchar * pType = "unsigned char *";
+ if( !CMIUtilString::Compare( pCType, pType ) )
+ return MIstatus::failure;
+
+ const CMIUtilString strAddr( rValue.GetValue() );
+ MIint64 nNum = 0;
+ if( !strAddr.ExtractNumber( nNum ) )
+ return MIstatus::failure;
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess;
+ MIuint nBufferSize = 64;
+ bool bNeedResize = false;
+ MIchar * pBuffer = static_cast< MIchar * >( ::malloc( nBufferSize ) );
+ do
+ {
+ lldb::SBError error;
+ const size_t nReadSize = rProcess.ReadCStringFromMemory( (lldb::addr_t) nNum, pBuffer, nBufferSize, error );
+ if( nReadSize == (nBufferSize - 1) )
+ {
+ bNeedResize = true;
+ nBufferSize = nBufferSize << 1;
+ pBuffer = static_cast< MIchar * >( ::realloc( pBuffer, nBufferSize ) );
+ }
+ else
+ bNeedResize = false;
+ }
+ while( bNeedResize );
+
+ vwCString = pBuffer;
+ free( (void *) pBuffer );
+
+ return MIstatus::success;
+}
+
diff --git a/tools/lldb-mi/MICmnLLDBProxySBValue.h b/tools/lldb-mi/MICmnLLDBProxySBValue.h
new file mode 100644
index 000000000000..7e743cdb7eaf
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBProxySBValue.h
@@ -0,0 +1,47 @@
+//===-- MICmnLLDBProxySBValue.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBProxySBValue.h
+//
+// Overview: CMICmnLLDBProxySBValue interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third Party Headers:
+#include <lldb/API/SBValue.h>
+
+// In-house headers:
+#include "MIDataTypes.h"
+
+// Declerations:
+class CMIUtilString;
+
+//++ ============================================================================
+// Details: MI proxy wrapper class to lldb::SBValue. The class provides functionality
+// to assist in the use of SBValue's parculiar function usage.
+// Gotchas: None.
+// Authors: Illya Rudkin 03/04/2014.
+// Changes: None.
+//--
+class CMICmnLLDBProxySBValue
+{
+// Statics:
+public:
+ static bool GetValueAsSigned( const lldb::SBValue & vrValue, MIint64 & vwValue );
+ static bool GetValueAsUnsigned( const lldb::SBValue & vrValue, MIuint64 & vwValue );
+ static bool GetCString( const lldb::SBValue & vrValue, CMIUtilString & vwCString );
+};
diff --git a/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp b/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp
new file mode 100644
index 000000000000..004be071260a
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp
@@ -0,0 +1,324 @@
+//===-- MICmnLLDBUtilSBValue.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBUtilSBValue.cpp
+//
+// Overview: CMICmnLLDBUtilSBValue implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnLLDBUtilSBValue.h"
+#include "MIUtilString.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBUtilSBValue constructor.
+// Type: Method.
+// Args: vrValue - (R) The LLDb value object.
+// vbHandleCharType - (R) True = Yes return text molding to char type,
+// False = just return data.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBUtilSBValue::CMICmnLLDBUtilSBValue( const lldb::SBValue & vrValue, const bool vbHandleCharType /* = false */ )
+: m_rValue( const_cast< lldb::SBValue & >( vrValue ) )
+, m_pUnkwn( "??" )
+, m_bHandleCharType( vbHandleCharType )
+{
+ m_bValidSBValue = m_rValue.IsValid();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBUtilSBValue destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBUtilSBValue::~CMICmnLLDBUtilSBValue( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve from the LLDB SB Value object the name of the variable. If the name
+// is invalid (or the SBValue object invalid) then "??" is returned.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Name of the variable or "??" for unknown.
+// Throws: None.
+//--
+CMIUtilString CMICmnLLDBUtilSBValue::GetName( void ) const
+{
+ const MIchar * pName = m_bValidSBValue ? m_rValue.GetName() : nullptr;
+ const CMIUtilString text( (pName != nullptr) ? pName : m_pUnkwn );
+
+ return text;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve from the LLDB SB Value object the value of the variable described in
+// text. If the value is invalid (or the SBValue object invalid) then "??" is
+// returned.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Text description of the variable's value or "??".
+// Throws: None.
+//--
+CMIUtilString CMICmnLLDBUtilSBValue::GetValue( void ) const
+{
+ CMIUtilString text;
+
+ if( m_bHandleCharType && IsCharType() )
+ {
+ const lldb::addr_t addr = m_rValue.GetLoadAddress();
+ text = CMIUtilString::Format( "0x%08x", addr );
+ const CMIUtilString cString( GetValueCString() );
+ if( !cString.empty() )
+ text += CMIUtilString::Format( " %s", cString.c_str() );
+ }
+ else
+ {
+ const MIchar * pValue = m_bValidSBValue ? m_rValue.GetValue() : nullptr;
+ text = (pValue != nullptr) ? pValue : m_pUnkwn;
+ }
+
+ return text;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: If the LLDB SB Value object is a char type then form the text data string
+// otherwise return nothing. m_bHandleCharType must be true to return text data
+// if any.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Text description of the variable's value.
+// Throws: None.
+//--
+CMIUtilString CMICmnLLDBUtilSBValue::GetValueCString( void ) const
+{
+ CMIUtilString text;
+
+ if( m_bHandleCharType && IsCharType() )
+ {
+ text = ReadCStringFromHostMemory( m_rValue );
+ }
+
+ return text;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the flag stating whether this value object is a char type or some
+// other type. Char type can be signed or unsigned.
+// Type: Method.
+// Args: None.
+// Return: bool - True = Yes is a char type, false = some other type.
+// Throws: None.
+//--
+bool CMICmnLLDBUtilSBValue::IsCharType( void ) const
+{
+ const MIchar * pName = m_rValue.GetName(); MIunused( pName );
+ const lldb::BasicType eType = m_rValue.GetType().GetBasicType();
+ return ((eType == lldb::eBasicTypeChar) ||
+ (eType == lldb::eBasicTypeSignedChar) ||
+ (eType == lldb::eBasicTypeUnsignedChar) );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the flag stating whether any child value object of *this object is a
+// char type or some other type. Returns false if there are not children. Char
+// type can be signed or unsigned.
+// Type: Method.
+// Args: None.
+// Return: bool - True = Yes is a char type, false = some other type.
+// Throws: None.
+//--
+bool CMICmnLLDBUtilSBValue::IsChildCharType( void ) const
+{
+ const MIuint nChildren = m_rValue.GetNumChildren();
+
+ // Is it a basic type
+ if( nChildren == 0 )
+ return false;
+
+ // Is it a composite type
+ if( nChildren > 1 )
+ return false;
+
+ lldb::SBValue member = m_rValue.GetChildAtIndex( 0 );
+ const CMICmnLLDBUtilSBValue utilValue( member );
+ return utilValue.IsCharType();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the C string data for a child of char type (one and only child) for
+// the parent value object. If the child is not a char type or the parent has
+// more than one child then an empty string is returned. Char type can be
+// signed or unsigned.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Text description of the variable's value.
+// Throws: None.
+//--
+CMIUtilString CMICmnLLDBUtilSBValue::GetChildValueCString( void ) const
+{
+ CMIUtilString text;
+ const MIuint nChildren = m_rValue.GetNumChildren();
+
+ // Is it a basic type
+ if( nChildren == 0 )
+ return text;
+
+ // Is it a composite type
+ if( nChildren > 1 )
+ return text;
+
+ lldb::SBValue member = m_rValue.GetChildAtIndex( 0 );
+ const CMICmnLLDBUtilSBValue utilValue( member );
+ if( m_bHandleCharType && utilValue.IsCharType() )
+ {
+ text = ReadCStringFromHostMemory( member );
+ }
+
+ return text;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the C string data of value object by read the memory where the
+// variable is held.
+// Type: Method.
+// Args: vrValueObj - (R) LLDB SBValue variable object.
+// Return: CMIUtilString - Text description of the variable's value.
+// Throws: None.
+//--
+CMIUtilString CMICmnLLDBUtilSBValue::ReadCStringFromHostMemory( const lldb::SBValue & vrValueObj ) const
+{
+ CMIUtilString text;
+
+ lldb::SBValue & rValue = const_cast< lldb::SBValue & >( vrValueObj );
+ const lldb::addr_t addr = rValue.GetLoadAddress();
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ const MIuint nBytes( 128 );
+ const MIchar * pBufferMemory = new MIchar[ nBytes ];
+ lldb::SBError error;
+ const MIuint64 nReadBytes = rSessionInfo.m_lldbProcess.ReadMemory( addr, (void *) pBufferMemory, nBytes, error ); MIunused( nReadBytes );
+ text = CMIUtilString::Format( "\\\"%s\\\"", pBufferMemory );
+ delete [] pBufferMemory;
+
+ return text;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the state of the value object's name.
+// Type: Method.
+// Args: None.
+// Return: bool - True = yes name is indeterminate, false = name is valid.
+// Throws: None.
+//--
+bool CMICmnLLDBUtilSBValue::IsNameUnknown( void ) const
+{
+ const CMIUtilString name( GetName() );
+ return (name == m_pUnkwn);
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the state of the value object's value data.
+// Type: Method.
+// Args: None.
+// Return: bool - True = yes value is indeterminate, false = value valid.
+// Throws: None.
+//--
+bool CMICmnLLDBUtilSBValue::IsValueUnknown( void ) const
+{
+ const CMIUtilString value( GetValue() );
+ return (value == m_pUnkwn);
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the value object's type name if valid.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - The type name or "??".
+// Throws: None.
+//--
+CMIUtilString CMICmnLLDBUtilSBValue::GetTypeName( void ) const
+{
+ const MIchar * pName = m_bValidSBValue ? m_rValue.GetTypeName() : nullptr;
+ const CMIUtilString text( (pName != nullptr) ? pName : m_pUnkwn );
+
+ return text;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the value object's display type name if valid.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - The type name or "??".
+// Throws: None.
+//--
+CMIUtilString CMICmnLLDBUtilSBValue::GetTypeNameDisplay( void ) const
+{
+ const MIchar * pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr;
+ const CMIUtilString text( (pName != nullptr) ? pName : m_pUnkwn );
+
+ return text;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve whether the value object's is valid or not.
+// Type: Method.
+// Args: None.
+// Return: bool - True = valid, false = not valid.
+// Throws: None.
+//--
+bool CMICmnLLDBUtilSBValue::IsValid( void ) const
+{
+ return m_bValidSBValue;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the value object' has a name. A value object can be valid but still
+// have no name which suggest it is not a variable.
+// Type: Method.
+// Args: None.
+// Return: bool - True = valid, false = not valid.
+// Throws: None.
+//--
+bool CMICmnLLDBUtilSBValue::HasName( void ) const
+{
+ bool bHasAName = false;
+
+ const MIchar * pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr;
+ if( pName != nullptr )
+ {
+ bHasAName = (CMIUtilString( pName ).length() > 0);
+ }
+
+ return bHasAName;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine if the value object' respresents a LLDB variable i.e. "$0".
+// Type: Method.
+// Args: None.
+// Return: bool - True = Yes LLDB variable, false = no.
+// Throws: None.
+//--
+bool CMICmnLLDBUtilSBValue::IsLLDBVariable( void ) const
+{
+ return (GetName().at( 0 ) == '$' );
+}
+
+
diff --git a/tools/lldb-mi/MICmnLLDBUtilSBValue.h b/tools/lldb-mi/MICmnLLDBUtilSBValue.h
new file mode 100644
index 000000000000..d2c1876c44b7
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBUtilSBValue.h
@@ -0,0 +1,71 @@
+//===-- MICmnLLDBUtilSBValue.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBUtilSBValue.h
+//
+// Overview: CMICmnLLDBUtilSBValue interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third Party Headers:
+#include <lldb/API/SBValue.h>
+
+// In-house headers:
+#include "MIDataTypes.h"
+
+// Declerations:
+class CMIUtilString;
+
+//++ ============================================================================
+// Details: Utility helper class to lldb::SBValue. Using a lldb::SBValue extract
+// value object information to help form verbose debug information.
+// Gotchas: None.
+// Authors: Illya Rudkin 08/07/2014.
+// Changes: None.
+//--
+class CMICmnLLDBUtilSBValue
+{
+// Methods:
+public:
+ /* ctor */ CMICmnLLDBUtilSBValue( const lldb::SBValue & vrValue, const bool vbHandleCharType = false );
+ /* dtor */ ~CMICmnLLDBUtilSBValue( void );
+ //
+ CMIUtilString GetName( void ) const;
+ CMIUtilString GetValue( void ) const;
+ CMIUtilString GetValueCString( void ) const;
+ CMIUtilString GetChildValueCString( void ) const;
+ CMIUtilString GetTypeName( void ) const;
+ CMIUtilString GetTypeNameDisplay( void ) const;
+ bool IsCharType( void ) const;
+ bool IsChildCharType( void ) const;
+ bool IsLLDBVariable( void ) const;
+ bool IsNameUnknown( void ) const;
+ bool IsValueUnknown( void ) const;
+ bool IsValid( void ) const;
+ bool HasName( void ) const;
+
+// Methods:
+private:
+ CMIUtilString ReadCStringFromHostMemory( const lldb::SBValue & vrValueObj ) const;
+
+// Attributes:
+private:
+ lldb::SBValue & m_rValue;
+ const MIchar * m_pUnkwn;
+ bool m_bValidSBValue; // True = SBValue is a valid object, false = not valid.
+ bool m_bHandleCharType; // True = Yes return text molding to char type, false = just return data.
+};
diff --git a/tools/lldb-mi/MICmnLog.cpp b/tools/lldb-mi/MICmnLog.cpp
new file mode 100644
index 000000000000..4ccbd3ef992c
--- /dev/null
+++ b/tools/lldb-mi/MICmnLog.cpp
@@ -0,0 +1,355 @@
+//===-- MICmnLog.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLog.cpp
+//
+// Overview: CMICmnLog implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnLog.h"
+#include "MICmnLogMediumFile.h"
+#include "MIDriverMgr.h"
+#include "MICmnResources.h"
+#include "MIUtilDateTimeStd.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLog constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLog::CMICmnLog( void )
+: m_bEnabled( false )
+, m_bInitializingATM( false )
+{
+ // Do not use this constructor, use Initialize()
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLog destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLog::~CMICmnLog( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this Logger.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLog::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ ClrErrorDescription();
+
+ // Mediums set inside because explicitly initing in MIDriverMain.cpp causes compile errors with CAtlFile
+ CMICmnLogMediumFile & rFileLog( CMICmnLogMediumFile::Instance() );
+ bool bOk = RegisterMedium( rFileLog );
+ bOk = bOk && SetEnabled( true );
+ if( bOk )
+ {
+ // Set the Log trace file's header
+ const CMIUtilString & rCR( rFileLog.GetLineReturn() );
+ CMIUtilDateTimeStd date;
+ CMIUtilString msg;
+ msg = CMIUtilString::Format( "%s\n", CMIDriverMgr::Instance().GetAppVersion().c_str() );
+ CMIUtilString logHdr( msg );
+ msg = CMIUtilString::Format( MIRSRC( IDS_LOG_MSG_CREATION_DATE ), date.GetDate().c_str(), date.GetTime().c_str(), rCR.c_str() );
+ logHdr += msg;
+ msg = CMIUtilString::Format( MIRSRC( IDS_LOG_MSG_FILE_LOGGER_PATH ), rFileLog.GetFileNamePath().c_str(), rCR.c_str() );
+ logHdr += msg;
+
+ bOk = rFileLog.SetHeaderTxt( logHdr );
+
+ // Note log file medium's status is not available until we write at least once to the file (so just write the title 1st line)
+ m_bInitializingATM = true;
+ CMICmnLog::WriteLog( "." );
+ if( !rFileLog.IsOk() )
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LOG_ERR_FILE_LOGGER_DISABLED ), rFileLog.GetErrorDescription().c_str() ) );
+ CMICmnLog::WriteLog( msg );
+ }
+ m_bInitializingATM = false;
+ }
+
+ m_bInitialized = bOk;
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this Logger.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLog::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ ClrErrorDescription();
+
+ const bool bOk = UnregisterMediumAll();
+
+ m_bInitialized = bOk;
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Enabled or disable *this Logger from writing any data to registered clients.
+// Type: Method.
+// Args: vbYes - (R) True = Logger enabled, false = disabled.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLog::SetEnabled( const bool vbYes )
+{
+ m_bEnabled = vbYes;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve state whether *this Logger is enabled writing data to registered clients.
+// Type: Method.
+// Args: None.
+// Return: True = Logger enable.
+// False = disabled.
+// Throws: None.
+//--
+bool CMICmnLog::GetEnabled( void ) const
+{
+ return m_bEnabled;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Unregister all the Mediums registered with *this Logger.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLog::UnregisterMediumAll( void )
+{
+ MapMediumToName_t::const_iterator it = m_mapMediumToName.begin();
+ for( ; it != m_mapMediumToName.end( ); it++ )
+ {
+ IMedium * pMedium = (*it).first;
+ pMedium->Shutdown();
+ }
+
+ m_mapMediumToName.clear();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Register a Medium with *this Logger.
+// Type: Method.
+// Args: vrMedium - (R) The medium to register.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLog::RegisterMedium( const IMedium & vrMedium )
+{
+ if( HaveMediumAlready( vrMedium ) )
+ return MIstatus::success;
+
+ IMedium * pMedium = const_cast< IMedium * >( &vrMedium );
+ if( !pMedium->Initialize() )
+ {
+ const CMIUtilString & rStrMedName( pMedium->GetName() );
+ const CMIUtilString & rStrMedErr( pMedium->GetError() );
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LOG_MEDIUM_ERR_INIT ), rStrMedName.c_str(), rStrMedErr.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ MapPairMediumToName_t pr( pMedium, pMedium->GetName() );
+ m_mapMediumToName.insert( pr );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Query the Logger to see if a medium is already registered.
+// Type: Method.
+// Args: vrMedium - (R) The medium to query.
+// Return: True - registered.
+// False - not registered.
+// Throws: None.
+//--
+bool CMICmnLog::HaveMediumAlready( const IMedium & vrMedium ) const
+{
+ IMedium * pMedium = const_cast< IMedium * >( &vrMedium );
+ const MapMediumToName_t::const_iterator it = m_mapMediumToName.find( pMedium );
+ if( it != m_mapMediumToName.end() )
+ return true;
+
+ return false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Unregister a medium from the Logger.
+// Type: Method.
+// Args: vrMedium - (R) The medium to unregister.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLog::UnregisterMedium( const IMedium & vrMedium )
+{
+ IMedium * pMedium = const_cast< IMedium * >( &vrMedium );
+ m_mapMediumToName.erase( pMedium );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The callee client uses this function to write to the Logger. The data to be
+// written is given out to all the mediums registered. The verbosity type parameter
+// indicates to the medium(s) the type of data or message given to it. The medium has
+// modes of verbosity and depending on the verbosity set determines which writes
+// go in to the logger.
+// The logger must be initialized successfully before a write to any registered
+// can be carried out.
+// Type: Method.
+// Args: vData - (R) The data to write to the logger.
+// veType - (R) Verbosity type.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLog::Write( const CMIUtilString & vData, const ELogVerbosity veType )
+{
+ if( !m_bInitialized && !m_bInitializingATM )
+ return MIstatus::success;
+ if( m_bRecursiveDive )
+ return MIstatus::success;
+ if( !m_bEnabled )
+ return MIstatus::success;
+
+ m_bRecursiveDive = true;
+
+ MIuint cnt = 0;
+ MIuint cntErr = 0;
+ {
+ MapMediumToName_t::const_iterator it = m_mapMediumToName.begin();
+ while( it != m_mapMediumToName.end() )
+ {
+ IMedium * pMedium = (*it).first;
+ const CMIUtilString & rNameMedium = (*it).second; MIunused( rNameMedium );
+ if( pMedium->Write( vData, veType ) )
+ cnt++;
+ else
+ cntErr++;
+
+ // Next
+ ++it;
+ }
+ }
+
+ bool bOk = MIstatus::success;
+ const MIuint mediumCnt = m_mapMediumToName.size();
+ if( (cnt == 0) && (mediumCnt > 0) )
+ {
+ SetErrorDescription( MIRSRC( IDS_LOG_MEDIUM_ERR_WRITE_ANY ) );
+ bOk = MIstatus::failure;
+ }
+ if( bOk && (cntErr != 0) )
+ {
+ SetErrorDescription( MIRSRC( IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL ) );
+ bOk = MIstatus::failure;
+ }
+
+ m_bRecursiveDive = false;
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Short cut function call to write only to the Log file.
+// The logger must be initialized successfully before a write to any registered
+// can be carried out.
+// Type: Static.
+// Args: vData - (R) The data to write to the logger.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLog::WriteLog( const CMIUtilString & vData )
+{
+ return CMICmnLog::Instance().Write( vData, CMICmnLog::eLogVerbosity_Log );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve a string detailing the last error.
+// Type: Method.
+// Args: None,
+// Return: CMIUtilString.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnLog::GetErrorDescription( void ) const
+{
+ return m_strMILastErrorDescription;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the internal description of the last error.
+// Type: Method.
+// Args: (R) String containing a description of the last error.
+// Return: None.
+// Throws: None.
+//--
+void CMICmnLog::SetErrorDescription( const CMIUtilString & vrTxt ) const
+{
+ m_strMILastErrorDescription = vrTxt;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Clear the last error.
+// Type: None.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMICmnLog::ClrErrorDescription( void ) const
+{
+ m_strMILastErrorDescription = CMIUtilString( "" );
+}
diff --git a/tools/lldb-mi/MICmnLog.h b/tools/lldb-mi/MICmnLog.h
new file mode 100644
index 000000000000..57288237840d
--- /dev/null
+++ b/tools/lldb-mi/MICmnLog.h
@@ -0,0 +1,143 @@
+//===-- MICmnLog.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLog.h
+//
+// Overview: CMICmnLog interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <map>
+
+// In-house headers:
+#include "MIUtilString.h"
+#include "MICmnBase.h"
+#include "MIUtilSingletonBase.h"
+
+//++ ============================================================================
+// Details: MI common code implementation class. Handle application trace
+// activity logging. Medium objects derived from the Medium abstract
+/// class are registered with this loggor. The function Write is called
+// by a client callee to log information. That information is given to
+// registered relevant mediums. The medium file is registered during
+// *this logs initialization so it will always have a file log for the
+// application.
+// Singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 01/02/2012.
+// Changes: None.
+//--
+class CMICmnLog : public MI::ISingleton< CMICmnLog >
+{
+ friend MI::ISingleton< CMICmnLog >;
+
+// Enumeration:
+public:
+ //++
+ // Description: Data given to the Logger can be of serveral types. The Logger can be
+ // set at levels of verbosity. Can determine how data is sent to one or
+ // mediums.
+ //--
+ enum ELogVerbosity
+ { // Descriptions of what 'may' occur, depends ultimately on the medium itself. See the medium.
+ eLogVerbosity_FnTrace = 0x00000004, // Debug function stack call tracing
+ eLogVerbosity_DbgOp = 0x00000008, // Send a string to the debugguer for display (not implemented)
+ eLogVerbosity_ClientMsg = 0x00000010, // A client using MI can insert messages into the log (not implemented)
+ eLogVerbosity_Log = 0x00000020 // Send to only the Log file.
+ };
+
+// Class:
+public:
+ //++
+ // Description: Register a medium derived from this interface which will be
+ // called writing log trace data i.e. a file or a console.
+ // Medium objects registered are not owned by *this logger.
+ //--
+ class IMedium
+ {
+ public:
+ virtual bool Initialize( void ) = 0;
+ virtual const CMIUtilString & GetName( void ) const = 0;
+ virtual bool Write( const CMIUtilString & vData, const ELogVerbosity veType ) = 0;
+ virtual const CMIUtilString & GetError( void ) const = 0;
+ virtual bool Shutdown( void ) = 0;
+
+ // Not part of the interface, ignore
+ //AD: This virtual destructor seems to hit a bug in the stdlib
+ // where vector delete is incorrectly called. Workaround is
+ // to comment this out while I investigate.
+ /* dtor */ virtual ~IMedium( void ) {}
+ };
+
+// Statics:
+public:
+ static bool WriteLog( const CMIUtilString & vData );
+
+// Methods:
+public:
+ bool RegisterMedium( const IMedium & vrMedium );
+ bool UnregisterMedium( const IMedium & vrMedium );
+ bool Write( const CMIUtilString & vData, const ELogVerbosity veType );
+ bool SetEnabled( const bool vbYes );
+ bool GetEnabled( void ) const;
+
+ // MI common object handling - duplicate of CMICmnBase functions, necessary for LINUX build
+ // Done to stop locking on object construction init circular dependency.
+ const CMIUtilString & GetErrorDescription( void ) const;
+ void SetErrorDescription( const CMIUtilString & vrTxt ) const;
+ void ClrErrorDescription( void ) const;
+
+// Overridden:
+public:
+ // From MI::ISingleton
+ virtual bool Initialize( void );
+ virtual bool Shutdown( void );
+
+// Methods:
+private:
+ /* ctor */ CMICmnLog( void );
+ /* ctor */ CMICmnLog( const CMICmnLog & );
+ void operator=( const CMICmnLog & );
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnLog( void );
+
+// Typedef:
+private:
+ typedef std::map< IMedium *, CMIUtilString > MapMediumToName_t;
+ typedef std::pair< IMedium *, CMIUtilString > MapPairMediumToName_t;
+
+// Methods:
+private:
+ bool HaveMediumAlready( const IMedium & vrMedium ) const;
+ bool UnregisterMediumAll( void );
+
+// Attributes:
+private:
+ bool m_bRecursiveDive; // True = yes recursive, false = no
+ MapMediumToName_t m_mapMediumToName;
+ bool m_bEnabled; // True = Logger enabled for writing to mediums, false = medium not written to
+ bool m_bInitializingATM; // True = Yes in process of initing *this logger, false = not initing
+ //
+ // MI common object handling - duplicate of CMICmnBase functions, necessary for LINUX build
+ bool m_bInitialized; // True = yes successfully initialized, false = no yet or failed
+ mutable CMIUtilString m_strMILastErrorDescription;
+ MIint m_clientUsageRefCnt; // Count of client using *this object so not shutdown() object to early
+};
diff --git a/tools/lldb-mi/MICmnLogMediumFile.cpp b/tools/lldb-mi/MICmnLogMediumFile.cpp
new file mode 100644
index 000000000000..228a9cf4b3be
--- /dev/null
+++ b/tools/lldb-mi/MICmnLogMediumFile.cpp
@@ -0,0 +1,420 @@
+//===-- MICmnLogMediumFile.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLogMediumFile.cpp
+//
+// Overview: CMICmnLogMediumFile implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnLogMediumFile.h"
+#include "MICmnResources.h"
+#if defined( _MSC_VER )
+ #include "MIUtilSystemWindows.h"
+#elif defined( __FreeBSD__ ) || defined( __linux__ )
+ #include "MIUtilSystemLinux.h"
+#elif defined( __APPLE__ )
+ #include "MIUtilSystemOsx.h"
+#endif // defined( _MSC_VER )
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLogMediumFile constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLogMediumFile::CMICmnLogMediumFile( void )
+: m_constThisMediumName( MIRSRC( IDS_MEDIUMFILE_NAME ) )
+, m_constMediumFileName( "lldb-mi-log.txt" )
+, m_fileNamePath( MIRSRC( IDS_MEDIUMFILE_ERR_INVALID_PATH ) )
+, m_eVerbosityType( CMICmnLog::eLogVerbosity_Log )
+, m_strDate( CMIUtilDateTimeStd().GetDate() )
+, m_fileHeaderTxt( MIRSRC( IDS_MEDIUMFILE_ERR_FILE_HEADER ) )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLogMediumFile destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLogMediumFile::~CMICmnLogMediumFile( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the singleton instance of *this class.
+// Type: Static.
+// Args: None.
+// Return: CMICmnLogMediumFile - Reference to *this object.
+// Throws: None.
+//--
+CMICmnLogMediumFile & CMICmnLogMediumFile::Instance( void )
+{
+ static CMICmnLogMediumFile instance;
+
+ return instance;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize setup *this medium ready for use.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLogMediumFile::Initialize( void )
+{
+ m_bInitialized = FileFormFileNamePath();
+
+ return m_bInitialized;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Unbind detach or release resources used by *this medium.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+bool CMICmnLogMediumFile::Shutdown( void )
+{
+ if( m_bInitialized )
+ {
+ m_bInitialized = false;
+ m_file.Close();
+ }
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the name of *this medium.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString - Text data.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnLogMediumFile::GetName( void ) const
+{
+ return m_constThisMediumName;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The callee client calls the write function on the Logger. The data to be
+// written is given out to all the mediums registered. The verbosity type parameter
+// indicates to the medium the type of data or message given to it. The medium has
+// modes of verbosity and depending on the verbosity set determines which data is
+// sent to the medium's output.
+// Type: Method.
+// Args: vData - (R) The data to write to the logger.
+// veType - (R) Verbosity type.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLogMediumFile::Write( const CMIUtilString & vData, const CMICmnLog::ELogVerbosity veType )
+{
+ if( m_bInitialized && m_file.IsOk() )
+ {
+ const bool bDoWrite = (m_eVerbosityType & veType);
+ if( bDoWrite )
+ {
+ bool bNewCreated = false;
+ bool bOk = m_file.CreateWrite( m_fileNamePath, bNewCreated );
+ if( bOk )
+ {
+ if( bNewCreated )
+ bOk = FileWriteHeader();
+ bOk = bOk && FileWriteEnglish( MassagedData( vData, veType ) );
+ }
+ return bOk;
+ }
+ }
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve *this medium's last error condition.
+// Type: Method.
+// Args: None.
+// Return: CString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnLogMediumFile::GetError( void ) const
+{
+ return m_strMILastErrorDescription;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the verbosity mode for this medium.
+// Type: Method.
+// Args: veType - (R) Mask value.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLogMediumFile::SetVerbosity( const MIuint veType )
+{
+ m_eVerbosityType = veType;
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the verbosity mode for this medium.
+// Type: Method.
+// Args: veType - (R) Mask value.
+// Return: CMICmnLog::ELogVerbosity - Mask value.
+// Throws: None.
+//--
+MIuint CMICmnLogMediumFile::GetVerbosity( void ) const
+{
+ return m_eVerbosityType;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Write data to a file English font.
+// Type: Method.
+// Args: vData - (R) The data to write to the logger.
+// Return: None.
+// Throws: None.
+//--
+bool CMICmnLogMediumFile::FileWriteEnglish( const CMIUtilString & vData )
+{
+ return m_file.Write( vData );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine and form the medium file's directory path and name.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLogMediumFile::FileFormFileNamePath( void )
+{
+ ClrErrorDescription();
+
+ m_fileNamePath = MIRSRC( IDS_MEDIUMFILE_ERR_INVALID_PATH );
+
+ CMIUtilString strPathName;
+ if( CMIUtilSystem().GetLogFilesPath( strPathName ) )
+ {
+ const CMIUtilString strPath = CMIUtilFileStd().StripOffFileName( strPathName );
+
+ // ToDo: Review this LINUX log file quick fix so not hidden
+ // AD:
+ // Linux was creating a log file here called '.\log.txt'. The '.' on linux
+ // signifies that this file is 'hidden' and not normally visible. A quick fix
+ // is to remove the path component all together. Linux also normally uses '/'
+ // as directory separators, again leading to the problem of the hidden log.
+#if defined ( _MSC_VER )
+ m_fileNamePath = CMIUtilString::Format( "%s\\%s", strPath.c_str(), m_constMediumFileName.c_str() );
+#else
+ m_fileNamePath = CMIUtilString::Format( "%s", m_constMediumFileName.c_str() );
+#endif // defined ( _MSC_VER )
+
+ return MIstatus::success;
+ }
+
+ SetErrorDescription( MIRSRC( IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS ) );
+
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the medium file's directory path and name.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - File path.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnLogMediumFile::GetFileNamePath( void ) const
+{
+ return m_fileNamePath;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the medium file's name.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - File name.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnLogMediumFile::GetFileName( void ) const
+{
+ return m_constMediumFileName;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Massage the data to behave correct when submitted to file. Insert extra log
+// specific text. The veType is there to allow in the future to parse the log and
+// filter in out specific types of message to make viewing the log more manageable.
+// Type: Method.
+// Args: vData - (R) Raw data.
+// veType - (R) Message type.
+// Return: CMIUtilString - Massaged data.
+// Throws: None.
+//--
+CMIUtilString CMICmnLogMediumFile::MassagedData( const CMIUtilString & vData, const CMICmnLog::ELogVerbosity veType )
+{
+ const CMIUtilString strCr( "\n" );
+ CMIUtilString data;
+ const MIchar verbosityCode( ConvertLogVerbosityTypeToId( veType ) );
+ const CMIUtilString dt( CMIUtilString::Format( "%s %s", m_strDate.c_str(), m_dateTime.GetTime().c_str() ) );
+
+ data = CMIUtilString::Format( "%c,%s,%s", verbosityCode, dt.c_str(), vData.c_str() );
+ data = ConvertCr( data );
+
+ // Look for EOL...
+ const MIint pos = vData.rfind( strCr );
+ if( pos == (MIint) vData.size() )
+ return data;
+
+ // ... did not have an EOL so add one
+ data += GetLineReturn();
+
+ return data;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Convert the Log's verbosity type number into a single char character.
+// Type: Method.
+// Args: veType - (R) Message type.
+// Return: wchar_t - A letter.
+// Throws: None.
+//--
+MIchar CMICmnLogMediumFile::ConvertLogVerbosityTypeToId( const CMICmnLog::ELogVerbosity veType ) const
+{
+ MIchar c = 0;
+ if( veType != 0 )
+ {
+ MIuint cnt = 0;
+ MIuint number( veType );
+ while( 1 != number )
+ {
+ number = number >> 1;
+ ++cnt;
+ }
+ c = 'A' + cnt;
+ }
+ else
+ {
+ c = '*';
+ }
+
+ return c;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve state of whether the file medium is ok.
+// Type: Method.
+// Args: None.
+// Return: True - file ok.
+// False - file has a problem.
+// Throws: None.
+//--
+bool CMICmnLogMediumFile::IsOk( void ) const
+{
+ return m_file.IsOk();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Status on the file log medium existing already.
+// Type: Method.
+// Args: None.
+// Return: True - Exists.
+// False - Not found.
+// Throws: None.
+//--
+bool CMICmnLogMediumFile::IsFileExist( void ) const
+{
+ return m_file.IsFileExist( GetFileNamePath() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Write the header text the logger file.
+// Type: Method.
+// Args: vText - (R) Text.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLogMediumFile::FileWriteHeader( void )
+{
+ return FileWriteEnglish( ConvertCr( m_fileHeaderTxt ) );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Convert any carriage line returns to be compatible with the platform the
+// Log fiel is being written to.
+// Type: Method.
+// Args: vData - (R) Text data.
+// Return: CMIUtilString - Converted string data.
+// Throws: None.
+//--
+CMIUtilString CMICmnLogMediumFile::ConvertCr( const CMIUtilString & vData ) const
+{
+ const CMIUtilString strCr( "\n" );
+ const CMIUtilString & rCrCmpat( GetLineReturn() );
+
+ if( strCr == rCrCmpat )
+ return vData;
+
+ const MIuint nSizeCmpat( rCrCmpat.size() );
+ const MIuint nSize( strCr.size() );
+ CMIUtilString strConv( vData );
+ MIint pos = strConv.find( strCr );
+ while( pos != (MIint) CMIUtilString::npos )
+ {
+ strConv.replace( pos, nSize, rCrCmpat );
+ pos = strConv.find( strCr, pos + nSizeCmpat );
+ }
+
+ return strConv;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the header text that is written to the logger file at the begining.
+// Type: Method.
+// Args: vText - (R) Text.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnLogMediumFile::SetHeaderTxt( const CMIUtilString & vText )
+{
+ m_fileHeaderTxt = vText;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the file current carriage line return characters used.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - Text.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnLogMediumFile::GetLineReturn( void ) const
+{
+ return m_file.GetLineReturn();
+}
diff --git a/tools/lldb-mi/MICmnLogMediumFile.h b/tools/lldb-mi/MICmnLogMediumFile.h
new file mode 100644
index 000000000000..affe24e09e57
--- /dev/null
+++ b/tools/lldb-mi/MICmnLogMediumFile.h
@@ -0,0 +1,96 @@
+//===-- MICmnLogMediumFile.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLogMediumFile.h
+//
+// Overview: CMICmnLogMediumFile interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MIUtilFileStd.h"
+#include "MIUtilString.h"
+#include "MICmnBase.h"
+#include "MICmnLog.h"
+#include "MIUtilDateTimeStd.h"
+
+//++ ============================================================================
+// Details: MI common code implementation class. Logs application fn trace/message/
+// error messages to a file. Used as part of the CMICmnLog Logger
+// system. When instantiated *this object is register with the Logger
+// which the Logger when given data to write to registered medium comes
+// *this medium.
+// Singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 30/01/2014.
+// Changes: None.
+//--
+class CMICmnLogMediumFile
+: public CMICmnBase
+, public CMICmnLog::IMedium
+{
+// Statics:
+public:
+ static CMICmnLogMediumFile & Instance( void );
+
+// Methods:
+public:
+ bool SetHeaderTxt( const CMIUtilString & vText );
+ bool SetVerbosity( const MIuint veType );
+ MIuint GetVerbosity( void ) const;
+ const CMIUtilString & GetFileName( void ) const;
+ const CMIUtilString & GetFileNamePath( void ) const;
+ bool IsOk( void ) const;
+ bool IsFileExist( void ) const;
+ const CMIUtilString & GetLineReturn( void ) const;
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnLogMediumFile( void );
+ // From CMICmnLog::IMedium
+ virtual bool Initialize( void );
+ virtual const CMIUtilString & GetName( void ) const;
+ virtual bool Write( const CMIUtilString & vData, const CMICmnLog::ELogVerbosity veType );
+ virtual const CMIUtilString & GetError( void ) const;
+ virtual bool Shutdown( void );
+
+// Methods:
+private:
+ /* ctor */ CMICmnLogMediumFile( void );
+ /* ctor */ CMICmnLogMediumFile( const CMICmnLogMediumFile & );
+ void operator=( const CMICmnLogMediumFile & );
+
+ bool FileWriteEnglish( const CMIUtilString & vData );
+ bool FileFormFileNamePath( void );
+ CMIUtilString MassagedData( const CMIUtilString & vData, const CMICmnLog::ELogVerbosity veType );
+ bool FileWriteHeader( void );
+ MIchar ConvertLogVerbosityTypeToId( const CMICmnLog::ELogVerbosity veType ) const;
+ CMIUtilString ConvertCr( const CMIUtilString & vData ) const;
+
+// Attributes:
+private:
+ const CMIUtilString m_constThisMediumName;
+ const CMIUtilString m_constMediumFileName;
+ //
+ CMIUtilString m_fileNamePath;
+ MIuint m_eVerbosityType;
+ CMIUtilString m_strDate;
+ CMIUtilString m_fileHeaderTxt;
+ CMIUtilFileStd m_file;
+ CMIUtilDateTimeStd m_dateTime;
+};
diff --git a/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp b/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp
new file mode 100644
index 000000000000..c3826f01ae85
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp
@@ -0,0 +1,161 @@
+//===-- MICmnMIOutOfBandRecord.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIOutOfBandRecord.h
+//
+// Overview: CMICmnMIOutOfBandRecord implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnMIOutOfBandRecord.h"
+#include "MICmnResources.h"
+
+// Instantiations:
+CMICmnMIOutOfBandRecord::MapOutOfBandToOutOfBandText_t ms_MapOutOfBandToOutOfBandText =
+{
+ { CMICmnMIOutOfBandRecord::eOutOfBand_Running, "running" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, "stopped" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, "breakpoint-created" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, "breakpoint-modified" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_Thread, "" }, // "" Meant to be empty
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded, "thread-group-added" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, "thread-group-exited" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved, "thread-group-removed" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, "thread-group-started" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, "thread-created" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, "thread-exited" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, "thread-selected" }
+};
+CMICmnMIOutOfBandRecord::MapOutOfBandToOutOfBandText_t ms_constMapAsyncRecordTextToToken =
+{
+ { CMICmnMIOutOfBandRecord::eOutOfBand_Running, "*" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, "*" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, "=" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, "=" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_Thread, "@" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded, "=" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, "=" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved, "=" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, "=" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, "=" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, "=" },
+ { CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, "=" }
+};
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIOutOfBandRecord constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord( void )
+: m_strAsyncRecord( MIRSRC( IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION ) )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIOutOfBandRecord constructor.
+// Type: Method.
+// Args: veType - (R) A MI Out-of-Bound enumeration.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord( const OutOfBand_e veType )
+: m_eResultAsyncRecordClass( veType )
+, m_strAsyncRecord( MIRSRC( IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION ) )
+{
+ BuildAsyncRecord();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIOutOfBandRecord constructor.
+// Type: Method.
+// Args: veType - (R) A MI Out-of-Bound enumeration.
+// vMIResult - (R) A MI result object.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord( const OutOfBand_e veType, const CMICmnMIValueResult & vValue )
+: m_eResultAsyncRecordClass( veType )
+, m_strAsyncRecord( MIRSRC( IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION ) )
+, m_partResult( vValue )
+{
+ BuildAsyncRecord();
+ Add( m_partResult );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIOutOfBandRecord destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIOutOfBandRecord::~CMICmnMIOutOfBandRecord( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return the MI Out-of-band record as a string. The string is a direct result of
+// work done on *this Out-of-band record so if not enough data is added then it is
+// possible to return a malformed Out-of-band record. If nothing has been set or
+// added to *this MI Out-of-band record object then text "<Invalid>" will be returned.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - MI output text.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnMIOutOfBandRecord::GetString( void ) const
+{
+ return m_strAsyncRecord;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Build the Out-of-band record's mandatory data part. The part up to the first
+// (additional) result i.e. async-record ==> "*" type.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIOutOfBandRecord::BuildAsyncRecord( void )
+{
+ const MIchar * pFormat = "%s%s";
+ const CMIUtilString & rStrAsyncRecord( ms_MapOutOfBandToOutOfBandText[ m_eResultAsyncRecordClass ] );
+ const CMIUtilString & rStrToken( ms_constMapAsyncRecordTextToToken[ m_eResultAsyncRecordClass ] );
+ m_strAsyncRecord = CMIUtilString::Format( pFormat, rStrToken.c_str(), rStrAsyncRecord.c_str() );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add to *this Out-of-band record additional information.
+// Type: Method.
+// Args: vMIValue - (R) A MI value derived object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIOutOfBandRecord::Add( const CMICmnMIValue & vMIValue )
+{
+ m_strAsyncRecord += ",";
+ m_strAsyncRecord += vMIValue.GetString();
+
+ return MIstatus::success;
+}
+
diff --git a/tools/lldb-mi/MICmnMIOutOfBandRecord.h b/tools/lldb-mi/MICmnMIOutOfBandRecord.h
new file mode 100644
index 000000000000..1a8f7a2e2009
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIOutOfBandRecord.h
@@ -0,0 +1,110 @@
+//===-- MICmnMIOutOfBandRecord.h --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIOutOfBandRecord.h
+//
+// Overview: CMICmnMIOutOfBandRecord interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <map>
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MIUtilString.h"
+#include "MICmnMIValueResult.h"
+
+//++ ============================================================================
+// Details: MI common code MI Out-of-band (Async) Record class. A class that encapsulates
+// MI result record data and the forming/format of data added to it.
+// Out-of-band records are used to notify the GDB/MI client of additional
+// changes that have occurred. Those changes can either be a consequence
+// of GDB/MI (e.g., a breakpoint modified) or a result of target activity
+// (e.g., target stopped).
+// The syntax is as follows:
+// "*" type ( "," result )*
+// type ==> running | stopped
+//
+// The Out-of-band record can be retrieve at any time *this object is
+// instantiated so unless work is done on *this Out-of-band record then it is
+// possible to return a malformed Out-of-band record. If nothing has been set
+// or added to *this MI Out-of-band record object then text "<Invalid>" will
+// be returned.
+//
+// More information see:
+// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html//
+// Gotchas: None.
+// Authors: Illya Rudkin 24/02/2014.
+// Changes: None.
+//--
+class CMICmnMIOutOfBandRecord : public CMICmnBase
+{
+// Enumerations:
+public:
+ //++
+ // Details: Enumeration of the type of Out-of-band for *this Out-of-band record
+ //--
+ enum OutOfBand_e
+ {
+ eOutOfBand_Running = 0,
+ eOutOfBand_Stopped,
+ eOutOfBand_BreakPointCreated,
+ eOutOfBand_BreakPointModified,
+ eOutOfBand_Thread,
+ eOutOfBand_ThreadGroupAdded,
+ eOutOfBand_ThreadGroupExited,
+ eOutOfBand_ThreadGroupRemoved,
+ eOutOfBand_ThreadGroupStarted,
+ eOutOfBand_ThreadCreated,
+ eOutOfBand_ThreadExited,
+ eOutOfBand_ThreadSelected,
+ eOutOfBand_count // Always the last one
+ };
+
+// Typedefs:
+public:
+ typedef std::map< OutOfBand_e, CMIUtilString > MapOutOfBandToOutOfBandText_t;
+ typedef std::map< OutOfBand_e, CMIUtilString > MapOutOfBandToToken_t;
+
+// Methods:
+public:
+ /* ctor */ CMICmnMIOutOfBandRecord( void );
+ /* ctor */ CMICmnMIOutOfBandRecord( const OutOfBand_e veType );
+ /* ctor */ CMICmnMIOutOfBandRecord( const OutOfBand_e veType, const CMICmnMIValueResult & vValue );
+ //
+ const CMIUtilString & GetString( void ) const;
+ bool Add( const CMICmnMIValue & vMIValue );
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnMIOutOfBandRecord( void );
+
+// Methods:
+private:
+ bool BuildAsyncRecord( void );
+
+// Attributes:
+private:
+ static MapOutOfBandToOutOfBandText_t ms_constMapOutOfBandToAsyncRecordText;
+ static MapOutOfBandToToken_t ms_constMapOutOfBandTextToToken;
+ //
+ OutOfBand_e m_eResultAsyncRecordClass;
+ CMIUtilString m_strAsyncRecord; // Holds the text version of the result record to date
+ CMICmnMIValueResult m_partResult;
+};
diff --git a/tools/lldb-mi/MICmnMIResultRecord.cpp b/tools/lldb-mi/MICmnMIResultRecord.cpp
new file mode 100644
index 000000000000..195167981d8c
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIResultRecord.cpp
@@ -0,0 +1,142 @@
+//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIResultRecord.h
+//
+// Overview: CMICmnMIResultRecord implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnMIResultRecord.h"
+#include "MICmnResources.h"
+
+// Instantiations:
+CMICmnMIResultRecord::MapResultClassToResultClassText_t ms_MapResultClassToResultClassText =
+{
+ { CMICmnMIResultRecord::eResultClass_Done, "done" },
+ { CMICmnMIResultRecord::eResultClass_Running, "running" },
+ { CMICmnMIResultRecord::eResultClass_Connected, "connected" },
+ { CMICmnMIResultRecord::eResultClass_Error, "error" },
+ { CMICmnMIResultRecord::eResultClass_Exit, "exit" }
+};
+const CMIUtilString CMICmnMIResultRecord::ms_constStrResultRecordHat( "^");
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIResultRecord constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIResultRecord::CMICmnMIResultRecord( void )
+: m_strResultRecord( MIRSRC( IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION ) )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIResultRecord constructor.
+// Type: Method.
+// Args: vrToken - (R) The command's transaction ID or token.
+// veType - (R) A MI result class enumeration.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIResultRecord::CMICmnMIResultRecord( const CMIUtilString & vrToken, const ResultClass_e veType )
+: m_strResultRecordToken( vrToken )
+, m_eResultRecordResultClass( veType )
+, m_strResultRecord( MIRSRC( IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION ) )
+{
+ BuildResultRecord();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIResultRecord constructor.
+// Type: Method.
+// Args: vrToken - (R) The command's transaction ID or token.
+// veType - (R) A MI result class enumeration.
+// vMIResult - (R) A MI result object.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIResultRecord::CMICmnMIResultRecord( const CMIUtilString & vrToken, const ResultClass_e veType, const CMICmnMIValueResult & vValue )
+: m_strResultRecordToken( vrToken )
+, m_eResultRecordResultClass( veType )
+, m_strResultRecord( MIRSRC( IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION ) )
+, m_partResult( vValue )
+{
+ BuildResultRecord();
+ Add( m_partResult );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIResultRecord destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIResultRecord::~CMICmnMIResultRecord( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return the MI result record as a string. The string is a direct result of
+// work done on *this result record so if not enough data is added then it is
+// possible to return a malformed result record. If nothing has been set or
+// added to *this MI result record object then text "<Invalid>" will be returned.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - MI output text.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnMIResultRecord::GetString( void ) const
+{
+ return m_strResultRecord;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Build the result record's mandatory data part. The part up to the first
+// (additional) result i.e. result-record ==> [ token ] "^" result-class.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIResultRecord::BuildResultRecord( void )
+{
+ const MIchar * pFormat = "%s%s%s";
+ const CMIUtilString & rStrResultRecord( ms_MapResultClassToResultClassText[ m_eResultRecordResultClass ] );
+ m_strResultRecord = CMIUtilString::Format( pFormat, m_strResultRecordToken.c_str(), ms_constStrResultRecordHat.c_str(), rStrResultRecord.c_str() );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add to *this result record additional information.
+// Type: Method.
+// Args: vMIValue - (R) A MI value derived object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIResultRecord::Add( const CMICmnMIValue & vMIValue )
+{
+ m_strResultRecord += ",";
+ m_strResultRecord += vMIValue.GetString();
+
+ return MIstatus::success;
+}
diff --git a/tools/lldb-mi/MICmnMIResultRecord.h b/tools/lldb-mi/MICmnMIResultRecord.h
new file mode 100644
index 000000000000..c76587d606c8
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIResultRecord.h
@@ -0,0 +1,106 @@
+//===-- MICmnMIResultRecord.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIResultRecord.h
+//
+// Overview: CMICmnMIResultRecord interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <map>
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MIUtilString.h"
+#include "MICmnMIValueResult.h"
+
+//++ ============================================================================
+// Details: MI common code MI Result Record class. A class that encapsulates
+// MI result record data and the forming/format of data added to it.
+// The syntax is as follows:
+// result-record ==> [ token ] "^" result-class ( "," result )* nl
+// token = any sequence of digits
+// * = 0 to many
+// nl = CR | CR_LF
+// result-class ==> "done" | "running" | "connected" | "error" | "exit"
+// result ==> variable "=" value
+// value ==> const | tuple | list
+// const ==> c-string (7 bit iso c string content) i.e. "all" inc quotes
+// tuple ==> "{}" | "{" result ( "," result )* "}"
+// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]"
+//
+// The result record can be retrieve at any time *this object is
+// instantiated so unless work is done on *this result record then it is
+// possible to return a malformed result record. If nothing has been set
+// or added to *this MI result record object then text "<Invalid>" will
+// be returned.
+// More information see:
+// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html
+// Gotchas: None.
+// Authors: Illya Rudkin 24/02/2014.
+// Changes: None.
+//--
+class CMICmnMIResultRecord : public CMICmnBase
+{
+// Enumerations:
+public:
+ //++
+ // Details: Enumeration of the result class for *this result record
+ //--
+ enum ResultClass_e
+ {
+ eResultClass_Done = 0,
+ eResultClass_Running,
+ eResultClass_Connected,
+ eResultClass_Error,
+ eResultClass_Exit,
+ eResultClass_count // Always the last one
+ };
+
+// Typedefs:
+public:
+ typedef std::map< ResultClass_e, CMIUtilString > MapResultClassToResultClassText_t;
+
+// Methods:
+public:
+ /* ctor */ CMICmnMIResultRecord( void );
+ /* ctor */ CMICmnMIResultRecord( const CMIUtilString & vrToken, const ResultClass_e veType );
+ /* ctor */ CMICmnMIResultRecord( const CMIUtilString & vrToken, const ResultClass_e veType, const CMICmnMIValueResult & vValue );
+ //
+ const CMIUtilString & GetString( void ) const;
+ bool Add( const CMICmnMIValue & vMIValue );
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnMIResultRecord( void );
+
+// Methods:
+private:
+ bool BuildResultRecord( void );
+
+// Attributes:
+private:
+ static const CMIUtilString ms_constStrResultRecordHat;
+ static MapResultClassToResultClassText_t ms_constMapResultClassToResultClassText;
+ //
+ CMIUtilString m_strResultRecordToken;
+ ResultClass_e m_eResultRecordResultClass;
+ CMIUtilString m_strResultRecord; // Holds the text version of the result record to date
+ CMICmnMIValueResult m_partResult;
+};
diff --git a/tools/lldb-mi/MICmnMIValue.cpp b/tools/lldb-mi/MICmnMIValue.cpp
new file mode 100644
index 000000000000..f9fb08bf642d
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIValue.cpp
@@ -0,0 +1,64 @@
+//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIValue.h
+//
+// Overview: CMICmnMIValue implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnMIValue.h"
+#include "MICmnResources.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValue constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValue::CMICmnMIValue( void )
+: m_strValue( MIRSRC( IDS_WORD_INVALIDBRKTS ) )
+, m_bJustConstructed( true )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValue destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValue::~CMICmnMIValue( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return the MI value as a string. The string is a direct result of
+// work done on *this value so if not enough data is added then it is
+// possible to return a malformed value. If nothing has been set or
+// added to *this MI value object then text "<Invalid>" will be returned.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - MI output text.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnMIValue::GetString( void ) const
+{
+ return m_strValue;
+}
+
diff --git a/tools/lldb-mi/MICmnMIValue.h b/tools/lldb-mi/MICmnMIValue.h
new file mode 100644
index 000000000000..4cf03122cc28
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIValue.h
@@ -0,0 +1,64 @@
+//===-- MICmnMIValue.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIValue.h
+//
+// Overview: CMICmnMIValue interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmnBase.h"
+
+//++ ============================================================================
+// Details: MI common code MI Result class. Part of the CMICmnMIValueRecord
+// set of objects.
+// The syntax is as follows:
+// result-record ==> [ token ] "^" result-class ( "," result )* nl
+// token = any sequence of digits
+// * = 0 to many
+// nl = CR | CR_LF
+// result-class ==> "done" | "running" | "connected" | "error" | "exit"
+// result ==> variable "=" value
+// value ==> const | tuple | list
+// const ==> c-string (7 bit iso c string content)
+// tuple ==> "{}" | "{" result ( "," result )* "}"
+// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]"
+// More information see:
+// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html
+// Gotchas: None.
+// Authors: Illya Rudkin 24/02/2014.
+// Changes: None.
+//--
+class CMICmnMIValue : public CMICmnBase
+{
+// Methods:
+public:
+ /* ctor */ CMICmnMIValue( void );
+ //
+ const CMIUtilString & GetString( void ) const;
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnMIValue( void );
+
+// Attributes:
+protected:
+ CMIUtilString m_strValue;
+ bool m_bJustConstructed; // True = *this just constructed with no value, false = *this has had value added to it
+};
diff --git a/tools/lldb-mi/MICmnMIValueConst.cpp b/tools/lldb-mi/MICmnMIValueConst.cpp
new file mode 100644
index 000000000000..afac8df07d78
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIValueConst.cpp
@@ -0,0 +1,98 @@
+//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIValueConst.h
+//
+// Overview: CMICmnMIValueConst implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnMIValueConst.h"
+
+// Instantiations:
+const CMIUtilString CMICmnMIValueConst::ms_constStrDblQuote( "\"" );
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueConst constructor.
+// Type: Method.
+// Args: vString - (R) MI Const c-string value.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueConst::CMICmnMIValueConst( const CMIUtilString & vString )
+: m_strPartConst( vString )
+, m_bNoQuotes( false )
+{
+ BuildConst();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueConst constructor.
+// Type: Method.
+// Args: vString - (R) MI Const c-string value.
+// vbNoQuotes - (R) True = return string not surrounded with quotes, false = use quotes.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueConst::CMICmnMIValueConst( const CMIUtilString & vString, const bool vbNoQuotes )
+: m_strPartConst( vString )
+, m_bNoQuotes( vbNoQuotes )
+{
+ BuildConst();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueConst destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueConst::~CMICmnMIValueConst( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Build the Value Const data.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueConst::BuildConst( void )
+{
+ if( m_strPartConst.length() != 0 )
+ {
+ const CMIUtilString strValue( m_strPartConst.StripCREndOfLine() );
+ if( m_bNoQuotes )
+ {
+ m_strValue = strValue;
+ }
+ else
+ {
+ const MIchar * pFormat = "%s%s%s";
+ m_strValue = CMIUtilString::Format( pFormat, ms_constStrDblQuote.c_str(), strValue.c_str(), ms_constStrDblQuote.c_str() );
+ }
+ }
+ else
+ {
+ const MIchar * pFormat = "%s%s";
+ m_strValue = CMIUtilString::Format( pFormat, ms_constStrDblQuote.c_str(), ms_constStrDblQuote.c_str() );
+ }
+
+ return MIstatus::success;
+} \ No newline at end of file
diff --git a/tools/lldb-mi/MICmnMIValueConst.h b/tools/lldb-mi/MICmnMIValueConst.h
new file mode 100644
index 000000000000..ddb440d7c6ec
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIValueConst.h
@@ -0,0 +1,72 @@
+//===-- MICmnMIValueConst.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIValueConst.h
+//
+// Overview: CMICmnMIValueConst interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmnMIValue.h"
+
+//++ ============================================================================
+// Details: MI common code MI Result class. Part of the CMICmnMIValueConstRecord
+// set of objects.
+// The syntax is as follows:
+// result-record ==> [ token ] "^" result-class ( "," result )* nl
+// token = any sequence of digits
+// * = 0 to many
+// nl = CR | CR_LF
+// result-class ==> "done" | "running" | "connected" | "error" | "exit"
+// result ==> variable "=" value
+// value ==> const | tuple | list
+// const ==> c-string (7 bit iso c string content)
+// tuple ==> "{}" | "{" result ( "," result )* "}"
+// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]"
+// More information see:
+// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html
+//
+// The text formed in *this Result class is stripped of any '\n' characters.
+//
+// Gotchas: None.
+// Authors: Illya Rudkin 24/02/2014.
+// Changes: None.
+//--
+class CMICmnMIValueConst : public CMICmnMIValue
+{
+// Methods:
+public:
+ /* ctor */ CMICmnMIValueConst( const CMIUtilString & vString );
+ /* ctor */ CMICmnMIValueConst( const CMIUtilString & vString, const bool vbNoQuotes );
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnMIValueConst( void );
+
+// Methods:
+private:
+ bool BuildConst( void );
+
+// Attributes:
+private:
+ static const CMIUtilString ms_constStrDblQuote;
+ //
+ CMIUtilString m_strPartConst;
+ bool m_bNoQuotes; // True = return string not surrounded with quotes, false = use quotes
+};
diff --git a/tools/lldb-mi/MICmnMIValueList.cpp b/tools/lldb-mi/MICmnMIValueList.cpp
new file mode 100644
index 000000000000..97a08cd29f09
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIValueList.cpp
@@ -0,0 +1,203 @@
+//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIValueList.h
+//
+// Overview: CMICmnMIValueList implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnMIValueList.h"
+#include "MICmnResources.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueList constructor.
+// Type: Method.
+// Args: vbValueTypeList - (R) True = yes value type list, false = result type list.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueList::CMICmnMIValueList( const bool vbValueTypeList )
+{
+ m_strValue = "[]";
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueList constructor.
+// Construct a results only list.
+// return MIstatus::failure.
+// Type: Method.
+// Args: vResult - (R) MI result object.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueList::CMICmnMIValueList( const CMICmnMIValueResult & vResult )
+{
+ m_strValue = vResult.GetString();
+ BuildList();
+ m_bJustConstructed = false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueList constructor.
+// Construct a value only list.
+// Type: Method.
+// Args: vValue - (R) MI value object.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueList::CMICmnMIValueList( const CMICmnMIValue & vValue )
+{
+ m_strValue = vValue.GetString();
+ BuildList();
+ m_bJustConstructed = false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueList destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueList::~CMICmnMIValueList( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Build the result value's mandatory data part, one tuple
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueList::BuildList( void )
+{
+ const MIchar * pFormat = "[%s]";
+ m_strValue = CMIUtilString::Format( pFormat, m_strValue.c_str() );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add another MI result object to the value list's of list is results.
+// Only result obejcts can be added to a list of result otherwise this function
+// will return MIstatus::failure.
+// Type: Method.
+// Args: vResult - (R) The MI result object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueList::Add( const CMICmnMIValueResult & vResult )
+{
+ return BuildList( vResult );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add another MI value object to the value list's of list is values.
+// Only values objects can be added to a list of values otherwise this function
+// will return MIstatus::failure.
+// Type: Method.
+// Args: vValue - (R) The MI value object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueList::Add( const CMICmnMIValue & vValue )
+{
+ return BuildList( vValue );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add another MI result object to the value list's of list is results.
+// Only result obejcts can be added to a list of result otherwise this function
+// will return MIstatus::failure.
+// Type: Method.
+// Args: vResult - (R) The MI result object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueList::BuildList( const CMICmnMIValueResult & vResult )
+{
+ // Clear out the default "<Invalid>" text
+ if( m_bJustConstructed )
+ {
+ m_bJustConstructed = false;
+ m_strValue = vResult.GetString();
+ return BuildList();
+ }
+
+ const CMIUtilString data( ExtractContentNoBrackets() );
+ const MIchar * pFormat = "[%s,%s]";
+ m_strValue = CMIUtilString::Format( pFormat, data.c_str(), vResult.GetString().c_str() );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add another MI value object to the value list's of list is values.
+// Only values objects can be added to a list of values otherwise this function
+// will return MIstatus::failure.
+// Type: Method.
+// Args: vValue - (R) The MI value object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueList::BuildList( const CMICmnMIValue & vValue )
+{
+ // Clear out the default "<Invalid>" text
+ if( m_bJustConstructed )
+ {
+ m_bJustConstructed = false;
+ m_strValue = vValue.GetString();
+ return BuildList();
+ }
+
+ const MIchar * pFormat = "[%s,%s]";
+ m_strValue = m_strValue.FindAndReplace( "[", "" );
+ m_strValue = m_strValue.FindAndReplace( "]", "" );
+ m_strValue = CMIUtilString::Format( pFormat, m_strValue.c_str(), vValue.GetString().c_str() );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the contents of *this value object but without the outer most
+// brackets.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Data within the object.
+// Throws: None.
+//--
+CMIUtilString CMICmnMIValueList::ExtractContentNoBrackets( void ) const
+{
+ CMIUtilString data( m_strValue );
+
+ if( data[ 0 ] == '[' )
+ {
+ data = data.substr( 1, data.length() - 1 );
+ }
+ if( data[ data.size() - 1 ] == ']' )
+ {
+ data = data.substr( 0, data.length() - 1 );
+ }
+
+ return data;
+}
diff --git a/tools/lldb-mi/MICmnMIValueList.h b/tools/lldb-mi/MICmnMIValueList.h
new file mode 100644
index 000000000000..cd1a98f7705f
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIValueList.h
@@ -0,0 +1,70 @@
+//===-- MICmnMIValueList.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIValueList.h
+//
+// Overview: CMICmnMIValueList interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmnMIValue.h"
+#include "MICmnMIValueResult.h"
+
+//++ ============================================================================
+// Details: MI common code MI Result class. Part of the CMICmnMIValueListRecord
+// set of objects.
+// The syntax is as follows:
+// result-record ==> [ token ] "^" result-class ( "," result )* nl
+// token = any sequence of digits
+// * = 0 to many
+// nl = CR | CR_LF
+// result-class ==> "done" | "running" | "connected" | "error" | "exit"
+// result ==> variable "=" value
+// value ==> const | tuple | list
+// const ==> c-string (7 bit iso c string content)
+// tuple ==> "{}" | "{" result ( "," result )* "}"
+// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]"
+// More information see:
+// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html
+// Gotchas: None.
+// Authors: Illya Rudkin 24/02/2014.
+// Changes: None.
+//--
+class CMICmnMIValueList : public CMICmnMIValue
+{
+// Methods:
+public:
+ /* ctor */ CMICmnMIValueList( const bool vbValueTypeList );
+ /* ctor */ CMICmnMIValueList( const CMICmnMIValueResult & vResult );
+ /* ctor */ CMICmnMIValueList( const CMICmnMIValue & vValue );
+ //
+ bool Add( const CMICmnMIValueResult & vResult );
+ bool Add( const CMICmnMIValue & vValue );
+ CMIUtilString ExtractContentNoBrackets( void ) const;
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnMIValueList( void );
+
+// Methods:
+private:
+ bool BuildList( void );
+ bool BuildList( const CMICmnMIValueResult & vResult );
+ bool BuildList( const CMICmnMIValue & vResult );
+};
diff --git a/tools/lldb-mi/MICmnMIValueResult.cpp b/tools/lldb-mi/MICmnMIValueResult.cpp
new file mode 100644
index 000000000000..e5cc9ce2bb1c
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIValueResult.cpp
@@ -0,0 +1,141 @@
+//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIResult.h
+//
+// Overview: CMICmnMIValueResult implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnMIValueResult.h"
+#include "MICmnResources.h"
+
+// Instantiations:
+const CMIUtilString CMICmnMIValueResult::ms_constStrEqual( "=" );
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueResult constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueResult::CMICmnMIValueResult( void )
+: m_bEmptyConstruction( true )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueResult constructor.
+// Type: Method.
+// Args: vrVariable - (R) MI value's name.
+// vrValue - (R) The MI value.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueResult::CMICmnMIValueResult( const CMIUtilString & vrVariable, const CMICmnMIValue & vrValue )
+: m_strPartVariable( vrVariable )
+, m_partMIValue( vrValue )
+, m_bEmptyConstruction( false )
+, m_bUseSpacing( false )
+{
+ BuildResult();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueResult constructor.
+// Type: Method.
+// Args: vrVariable - (R) MI value's name.
+// vrValue - (R) The MI value.
+// vbUseSpacing - (R) True = put space seperators into the string, false = no spaces used.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueResult::CMICmnMIValueResult( const CMIUtilString & vrVariable, const CMICmnMIValue & vrValue, const bool vbUseSpacing )
+: m_strPartVariable( vrVariable )
+, m_partMIValue( vrValue )
+, m_bEmptyConstruction( false )
+, m_bUseSpacing( vbUseSpacing )
+{
+ BuildResult();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueResult destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueResult::~CMICmnMIValueResult( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Build the MI value result string.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueResult::BuildResult( void )
+{
+ const MIchar * pFormat = m_bUseSpacing ? "%s %s %s" : "%s%s%s";
+ m_strValue = CMIUtilString::Format( pFormat, m_strPartVariable.c_str(), ms_constStrEqual.c_str(), m_partMIValue.GetString().c_str() );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Build the MI value result string.
+// Type: Method.
+// Args: vrVariable - (R) MI value's name.
+// vrValue - (R) The MI value.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueResult::BuildResult( const CMIUtilString & vVariable, const CMICmnMIValue & vValue )
+{
+ const MIchar * pFormat = m_bUseSpacing ? "%s, %s %s %s" : "%s,%s%s%s";
+ m_strValue = CMIUtilString::Format( pFormat, m_strValue.c_str(), vVariable.c_str(), ms_constStrEqual.c_str(), vValue.GetString().c_str() );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Append another MI value object to *this MI value result.
+// Type: Method.
+// Args: vrVariable - (R) MI value's name.
+// vrValue - (R) The MI value.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueResult::Add( const CMIUtilString & vrVariable, const CMICmnMIValue & vrValue )
+{
+ if( !m_bEmptyConstruction )
+ return BuildResult( vrVariable, vrValue );
+ else
+ {
+ m_bEmptyConstruction = false;
+ m_strPartVariable = vrVariable;
+ m_partMIValue = vrValue;
+ return BuildResult();
+ }
+}
+
diff --git a/tools/lldb-mi/MICmnMIValueResult.h b/tools/lldb-mi/MICmnMIValueResult.h
new file mode 100644
index 000000000000..a9a2a930c93e
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIValueResult.h
@@ -0,0 +1,75 @@
+//===-- MICmnMIResult.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIResult.h
+//
+// Overview: CMICmnMIValueResult interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmnMIValue.h"
+
+//++ ============================================================================
+// Details: MI common code MI Result class. Part of the CMICmnMIValueResultRecord
+// set of objects.
+// The syntax is as follows:
+// result-record ==> [ token ] "^" result-class ( "," result )* nl
+// token = any sequence of digits
+// * = 0 to many
+// nl = CR | CR_LF
+// result-class ==> "done" | "running" | "connected" | "error" | "exit"
+// result ==> variable "=" value
+// value ==> const | tuple | list
+// const ==> c-string (7 bit iso c string content)
+// tuple ==> "{}" | "{" result ( "," result )* "}"
+// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]"
+// More information see:
+// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html
+// Gotchas: None.
+// Authors: Illya Rudkin 24/02/2014.
+// Changes: None.
+//--
+class CMICmnMIValueResult : public CMICmnMIValue
+{
+// Methods:
+public:
+ /* ctor */ CMICmnMIValueResult( void );
+ /* ctor */ CMICmnMIValueResult( const CMIUtilString & vVariable, const CMICmnMIValue & vValue );
+ /* ctor */ CMICmnMIValueResult( const CMIUtilString & vVariable, const CMICmnMIValue & vValue, const bool vbUseSpacing );
+ //
+ bool Add( const CMIUtilString & vVariable, const CMICmnMIValue & vValue );
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnMIValueResult( void );
+
+// Methods:
+private:
+ bool BuildResult( void );
+ bool BuildResult( const CMIUtilString & vVariable, const CMICmnMIValue & vValue );
+
+// Attributes:
+private:
+ static const CMIUtilString ms_constStrEqual;
+ //
+ CMIUtilString m_strPartVariable;
+ CMICmnMIValue m_partMIValue;
+ bool m_bEmptyConstruction; // True = *this object used constructor with no parameters, false = constructor with parameters
+ bool m_bUseSpacing; // True = put space seperators into the string, false = no spaces used
+};
diff --git a/tools/lldb-mi/MICmnMIValueTuple.cpp b/tools/lldb-mi/MICmnMIValueTuple.cpp
new file mode 100644
index 000000000000..2f1349e79795
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIValueTuple.cpp
@@ -0,0 +1,227 @@
+//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIValueTuple.h
+//
+// Overview: CMICmnMIValueTuple implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnMIValueTuple.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueTuple constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueTuple::CMICmnMIValueTuple( void )
+: m_bSpaceAfterComma( false )
+{
+ m_strValue = "{}";
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueTuple constructor.
+// Type: Method.
+// Args: vResult - (R) MI result object.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueTuple::CMICmnMIValueTuple( const CMICmnMIValueResult & vResult )
+: m_bSpaceAfterComma( false )
+{
+ m_strValue = vResult.GetString();
+ BuildTuple();
+ m_bJustConstructed = false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueTuple constructor.
+// Type: Method.
+// Args: vResult - (R) MI result object.
+// vbUseSpacing - (R) True = put space seperators into the string, false = no spaces used.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueTuple::CMICmnMIValueTuple( const CMICmnMIValueResult & vResult, const bool vbUseSpacing )
+: m_bSpaceAfterComma( vbUseSpacing )
+{
+ m_strValue = vResult.GetString();
+ BuildTuple();
+ m_bJustConstructed = false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnMIValueTuple destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnMIValueTuple::~CMICmnMIValueTuple( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Build the result value's mandatory data part, one tuple
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueTuple::BuildTuple( void )
+{
+ const MIchar * pFormat = "{%s}";
+ m_strValue = CMIUtilString::Format( pFormat, m_strValue.c_str() );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add another MI result object to the value's list of tuples.
+// Type: Method.
+// Args: vResult - (R) The MI result object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueTuple::BuildTuple( const CMICmnMIValueResult & vResult )
+{
+ // Clear out the default "<Invalid>" text
+ if( m_bJustConstructed )
+ {
+ m_bJustConstructed = false;
+ m_strValue = vResult.GetString();
+ return BuildTuple();
+ }
+
+ if( m_strValue[ 0 ] == '{' )
+ {
+ m_strValue = m_strValue.substr( 1, m_strValue.size() - 1 );
+ }
+ if( m_strValue[ m_strValue.size() - 1 ] == '}' )
+ {
+ m_strValue = m_strValue.substr( 0, m_strValue.size() - 1 );
+ }
+
+ const MIchar * pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}";
+ m_strValue = CMIUtilString::Format( pFormat, m_strValue.c_str(), vResult.GetString().c_str() );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add string value to the value's list of tuples.
+// Type: Method.
+// Args: vValue - (R) The string object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueTuple::BuildTuple( const CMIUtilString & vValue )
+{
+ // Clear out the default "<Invalid>" text
+ if( m_bJustConstructed )
+ {
+ m_bJustConstructed = false;
+ m_strValue = vValue;
+ return BuildTuple();
+ }
+
+ const CMIUtilString data( ExtractContentNoBrackets() );
+ const MIchar * pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}";
+ m_strValue = CMIUtilString::Format( pFormat, data.c_str(), vValue.c_str() );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add another MI value object to the value list's of list is values.
+// Only values objects can be added to a list of values otherwise this function
+// will return MIstatus::failure.
+// Type: Method.
+// Args: vValue - (R) The MI value object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueTuple::Add( const CMICmnMIValueResult & vResult )
+{
+ return BuildTuple( vResult );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add another MI value object to the value list's of list is values.
+// Only values objects can be added to a list of values otherwise this function
+// will return MIstatus::failure.
+// Type: Method.
+// Args: vValue - (R) The MI value object.
+// vbUseSpacing - (R) True = put space seperators into the string, false = no spaces used.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueTuple::Add( const CMICmnMIValueResult & vResult, const bool vbUseSpacing )
+{
+ m_bSpaceAfterComma = vbUseSpacing;
+ return BuildTuple( vResult );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add another MI value object to the value list's of list is values.
+// Only values objects can be added to a list of values otherwise this function
+// will return MIstatus::failure.
+// Type: Method.
+// Args: vValue - (R) The MI value object.
+// vbUseSpacing - (R) True = put space seperators into the string, false = no spaces used.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnMIValueTuple::Add( const CMICmnMIValueConst & vValue, const bool vbUseSpacing )
+{
+ m_bSpaceAfterComma = vbUseSpacing;
+ return BuildTuple( vValue.GetString() );
+}
+
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the contents of *this value object but without the outer most
+// brackets.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Data within the object.
+// Throws: None.
+//--
+CMIUtilString CMICmnMIValueTuple::ExtractContentNoBrackets( void ) const
+{
+ CMIUtilString data( m_strValue );
+
+ if( data[ 0 ] == '{' )
+ {
+ data = data.substr( 1, data.length() - 1 );
+ }
+ if( data[ data.size() - 1 ] == '}' )
+ {
+ data = data.substr( 0, data.length() - 1 );
+ }
+
+ return data;
+}
+
diff --git a/tools/lldb-mi/MICmnMIValueTuple.h b/tools/lldb-mi/MICmnMIValueTuple.h
new file mode 100644
index 000000000000..0399c9d5068f
--- /dev/null
+++ b/tools/lldb-mi/MICmnMIValueTuple.h
@@ -0,0 +1,76 @@
+//===-- MICmnMIValueTuple.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnMIValueTuple.h
+//
+// Overview: CMICmnMIValueTuple interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmnMIValue.h"
+#include "MICmnMIValueResult.h"
+#include "MICmnMIValueConst.h"
+
+//++ ============================================================================
+// Details: MI common code MI Result class. Part of the CMICmnMIValueTupleRecord
+// set of objects.
+// The syntax is as follows:
+// result-record ==> [ token ] "^" result-class ( "," result )* nl
+// token = any sequence of digits
+// * = 0 to many
+// nl = CR | CR_LF
+// result-class ==> "done" | "running" | "connected" | "error" | "exit"
+// result ==> variable "=" value
+// value ==> const | tuple | list
+// const ==> c-string (7 bit iso c string content)
+// tuple ==> "{}" | "{" result ( "," result )* "}"
+// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]"
+// More information see:
+// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html
+// Gotchas: None.
+// Authors: Illya Rudkin 24/02/2014.
+// Changes: None.
+//--
+class CMICmnMIValueTuple : public CMICmnMIValue
+{
+// Methods:
+public:
+ /* ctor */ CMICmnMIValueTuple( void );
+ /* ctor */ CMICmnMIValueTuple( const CMICmnMIValueResult & vResult );
+ /* ctor */ CMICmnMIValueTuple( const CMICmnMIValueResult & vResult, const bool vbUseSpacing );
+ //
+ bool Add( const CMICmnMIValueResult & vResult );
+ bool Add( const CMICmnMIValueResult & vResult, const bool vbUseSpacing );
+ bool Add( const CMICmnMIValueConst & vValue, const bool vbUseSpacing );
+ CMIUtilString ExtractContentNoBrackets( void ) const;
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnMIValueTuple( void );
+
+// Methods:
+private:
+ bool BuildTuple( void );
+ bool BuildTuple( const CMICmnMIValueResult & vResult );
+ bool BuildTuple( const CMIUtilString & vValue );
+
+// Attributes:
+private:
+ bool m_bSpaceAfterComma; // True = put space seperators into the string, false = no spaces used
+};
diff --git a/tools/lldb-mi/MICmnResources.cpp b/tools/lldb-mi/MICmnResources.cpp
new file mode 100644
index 000000000000..08ac2f0edfe0
--- /dev/null
+++ b/tools/lldb-mi/MICmnResources.cpp
@@ -0,0 +1,409 @@
+//===-- MICmnResources.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnResources.cpp
+//
+// Overview: CMICmnResources implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers
+#include "assert.h"
+
+// In-house headers:
+#include "MICmnResources.h"
+
+// Instantiations:
+const CMICmnResources::SRsrcTextData CMICmnResources::ms_pResourceId2TextData[] =
+{
+ { IDS_PROJNAME, "LLDB Machine Interface Driver (MI) All rights reserved" },
+ { IDS_MI_VERSION_DESCRIPTION_DEBUG, "Version: 1.0.0.9 (Debug)" }, // See version history in MIDriverMain.cpp
+ { IDS_MI_VERSION_DESCRIPTION, "Version: 1.0.0.9" },
+ { IDS_MI_APPNAME_SHORT, "MI" },
+ { IDS_MI_APPNAME_LONG, "Machine Interface Driver" },
+ { IDS_MI_APP_FILEPATHNAME, "Application: %s" },
+ { IDS_MI_APP_ARGS, "Command line args: " },
+ { IDE_MI_VERSION_GDB, "Version: GNU gdb (GDB) 7.4 \n(This is a MI stub on top of LLDB and not GDB)\nAll rights reserved.\n" }, // *** Eclipse needs this exactly!!
+ { IDS_UTIL_FILE_ERR_INVALID_PATHNAME, "File Handler. Invalid file name path" },
+ { IDS_UTIL_FILE_ERR_OPENING_FILE, "File Handler. Error %s opening '%s'" },
+ { IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN, "File Handler. Unknown error opening '%s'" },
+ { IDE_UTIL_FILE_ERR_WRITING_FILE, "File Handler. Error %s writing '%s'" },
+ { IDE_UTIL_FILE_ERR_WRITING_NOTOPEN, "File Handler. File '%s' not open for write" },
+ { IDS_RESOURCES_ERR_STRING_NOT_FOUND, "Resources. String (%d) not found in resources" },
+ { IDS_RESOURCES_ERR_STRING_TABLE_INVALID, "Resources. String resource table is not set up" },
+ { IDS_MI_CLIENT_MSG, "Client message: \"%s\"" },
+ { IDS_LOG_MSG_CREATION_DATE, "Creation date %s time %s%s" },
+ { IDS_LOG_MSG_FILE_LOGGER_PATH, "File logger path: %s%s" },
+ { IDS_LOG_MSG_VERSION, "Version: %s%s" },
+ { IDS_LOG_ERR_FILE_LOGGER_DISABLED, "Log. File logger temporarily disabled due to file error '%s'" },
+ { IDS_LOG_MEDIUM_ERR_INIT, "Log. Medium '%s' initialise failed. %s" },
+ { IDS_LOG_MEDIUM_ERR_WRITE_ANY, "Log. Failed to write log data to any medium." },
+ { IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL, "Log. One or mediums failed writing log data." },
+ { IDS_MEDIUMFILE_NAME, "File" },
+ { IDS_MEDIUMFILE_ERR_INVALID_PATH, "<Invalid - not set>" },
+ { IDS_MEDIUMFILE_ERR_FILE_HEADER, "<Invalid - header not set>" },
+ { IDS_MEDIUMFILE_NAME_LOG, "File medium. %s" },
+ { IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS, "File Medium. Failed to retrieve the system/executable path for the Log file" },
+ { IDE_OS_ERR_UNKNOWN, "Unknown OS error" },
+ { IDE_OS_ERR_RETRIEVING, "Unabled to retrieve OS error message" },
+ { IDS_DRIVERMGR_DRIVER_ERR_INIT, "Driver Manager. Driver '%s' (ID:'%s') initialise failed. %s" },
+ { IDE_MEDIUMSTDERR_NAME, "Stderr" },
+ { IDE_MEDIUMSTDOUT_NAME, "Stdout" },
+ { IDE_MI_APP_EXIT_OK, "Program exited OK" },
+ { IDE_MI_APP_EXIT_WITH_PROBLEM, "Program exited with a problem, see '%s' file" },
+ { IDE_MI_APP_EXIT_WITH_PROBLEM_NO_LOG, "Program exited with a problem, the application's log file '%s' was disabled" },
+ { IDE_MI_APP_DESCRIPTION, "Description:\nThe Machine Interface Driver (MI Driver) is a stand alone executable\nthat either be used via a client i.e. Eclipse or directly from the command\nline. It processes MI commands, actions those commands using the internal\ndebugger then forms MI response formatted text which is returned to the\nclient." },
+ { IDE_MI_APP_INFORMATION, "Information:\nCurrent limitations. The MI Driver currently only handles remote target\ndebugging. Local debugging has not been implemented. The MI Driver has\nbeen designed primarily to be used with Eclipse Juno and a custom plugin.\nThe custom plugin is not necessary to operate the MI Driver." },
+ { IDE_MI_APP_ARG_USAGE, "\nMI driver usage:\n\n\tlldb-mi [--longOption] [-s hortOption] [executeable]\n\n[] = optional argument." },
+ { IDE_MI_APP_ARG_HELP, "-h\n--help\n\tPrints out usage information for the MI debugger. Exit the MI\n\tDriver immediately." },
+ { IDE_MI_APP_ARG_VERSION, "--version\n\tPrints out GNU (gdb) version information. Exit the MI Driver\n\timmediately." },
+ { IDE_MI_APP_ARG_VERSION_LONG, "--versionLong\n\tPrints out MI Driver version information. Exit the MI Driver\n\timmediately." },
+ { IDE_MI_APP_ARG_INTERPRETER, "--interpreter\n\tUse the MI Driver for the debugger (MI mode)(Default is the\n\tLLDB driver). Any LLDB command line options are ignored even\n\tif the MI Driver falls through to the LLDB driver. (Depends\n\ton the build configuration see MICmnConfig.h)\n\tNormally specified by the driver client i.e. Eclipse.\n\tCannot specify an executable with this option, use --executable." },
+ { IDE_MI_APP_ARG_EXECUTEABLE, "--executable\n\tUse the MI Driver in MI mode for the debugging the specified\n\texecutable. Any LLDB command line options are ignored even\n\tif the MI Driver falls through to the LLDB driver. (Depends\n\ton the build configuration see MICmnConfig.h)\n\tNormally specified from the command line." },
+ { IDE_MI_APP_ARG_NO_APP_LOG, "--noLog\n\tUse this argument to tell the MI Driver not to update it's log\n\tfile '%s'." },
+ { IDE_MI_APP_ARG_EXAMPLE, "Example MI command:\n\t3-info-gdb-mi-command gdb-set\n\t3^done,command={exists=\"true\"}" },
+ { IDE_MI_APP_ARG_EXECUTABLE, "executable (NOT IMPLEMENTED)\n\tThe file path to the executable i.e. '\"C:\\My Dev\\foo.exe\"'." },
+ { IDS_STDIN_ERR_INVALID_PROMPT, "Stdin. Invalid prompt description '%s'" },
+ { IDS_STDIN_ERR_THREAD_CREATION_FAILED, "Stdin. Thread creation failed '%s'" },
+ { IDS_STDIN_ERR_THREAD_DELETE, "Stdin. Thread failed to delete '%s'" },
+ { IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE, "Stdin. Peeking on stdin stream '%s'" },
+ { IDS_STDIN_INPUT_CTRL_CHARS, "Stdin. Receive characters not handled as a command: " },
+ { IDS_CMD_QUIT_HELP, "MI Driver Command: quit\n\tExit the MI Driver application." },
+ { IDS_THREADMGR_ERR_THREAD_ID_INVALID, "Thread Mgr. Thread ID '%s' is not valid" },
+ { IDS_THREADMGR_ERR_THREAD_FAIL_CREATE, "Thread Mgr: Failed to create thread '%s'" },
+ { IDS_THREADMGR_ERR_THREAD_ID_NOT_FOUND, "Thread Mgr: Thread with ID '%s' not found" },
+ { IDS_THREADMGR_ERR_THREAD_STILL_ALIVE, "Thread Mgr: The thread(s) are still alive at Thread Mgr shutdown: %s" },
+ { IDS_FALLTHRU_DRIVER_CMD_RECEIVED, "Fall Thru Driver. Received command '%s'. Is was %shandled" },
+ { IDS_CMDFACTORY_ERR_INVALID_CMD_NAME, "Command factory. MI command name '%s' is invalid" },
+ { IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN, "Command factory. Command creation function invalid for command '%s'. Does function exist? Pointer assigned to it?" },
+ { IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED, "Command factory. Command '%s' not registered" },
+ { IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED, "Command factory. Command '%s' by that name already registered" },
+ { IDS_CMDMGR_ERR_CMD_FAILED_CREATE, "Command manager. Command creation failed. %s" },
+ { IDS_CMDMGR_ERR_CMD_INVOKER, "Command manager. %s " },
+ { IDS_PROCESS_SIGNAL_RECEIVED, "Process signal. Application received signal '%s' (%d)" },
+ { IDS_MI_INIT_ERR_LOG, "Log. Error occurred during initialisation %s" },
+ { IDS_MI_INIT_ERR_RESOURCES, "Resources. Error occurred during initialisation %s" },
+ { IDS_MI_INIT_ERR_INIT, "Driver. Error occurred during initialisation %s" },
+ { IDS_MI_INIT_ERR_STREAMSTDIN, "Stdin. Error occurred during initialisation %s" },
+ { IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER, "Stdin. The OS specific stdin stream handler has not been specified for this OS" },
+ { IDS_MI_INIT_ERR_OS_STDIN_HANDLER, "Stdin handler. Error occurred during initialisation %s" },
+ { IDS_MI_INIT_ERR_STREAMSTDOUT, "Stdout. Error occurred during initialisation %s" },
+ { IDS_MI_INIT_ERR_STREAMSTDERR, "Stderr. Error occurred during initialisation %s" },
+ { IDS_MI_INIT_ERR_FALLTHRUDRIVER, "Fall Through Driver. Error occurred during initialisation %s" },
+ { IDS_MI_INIT_ERR_THREADMGR, "Thread Mgr. Error occurred during initialisation %s" },
+ { IDS_MI_INIT_ERR_CMDINTERPRETER, "Command interpreter. %s" },
+ { IDS_MI_INIT_ERR_CMDMGR, "Command manager. %s" },
+ { IDS_MI_INIT_ERR_CMDFACTORY, "Command factory. %s" },
+ { IDS_MI_INIT_ERR_CMDINVOKER, "Command invoker. %s" },
+ { IDS_MI_INIT_ERR_CMDMONITOR, "Command monitor. %s" },
+ { IDS_MI_INIT_ERR_LLDBDEBUGGER, "LLDB Debugger. %s" },
+ { IDS_MI_INIT_ERR_DRIVERMGR, "Driver manager. %s" },
+ { IDS_MI_INIT_ERR_DRIVER, "Driver. %s" },
+ { IDS_MI_INIT_ERR_OUTOFBANDHANDLER, "Out-of-band handler. %s " },
+ { IDS_MI_INIT_ERR_DEBUGSESSIONINFO, "LLDB debug session info. %s " },
+ { IDS_MI_INIT_ERR_THREADMANAGER, "Unable to init thread manager." },
+ { IDS_MI_INIT_ERR_CLIENT_USING_DRIVER, "Initialising the client to this driver failed." },
+ { IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION, "Initialising a local debug session failed." },
+ { IDS_CODE_ERR_INVALID_PARAMETER_VALUE, "Code. Invalid parameter passed to function '%s'" },
+ { IDS_CODE_ERR_INVALID_PARAM_NULL_POINTER, "Code. NULL pointer passes as a parameter to function '%s'" },
+ { IDS_CODE_ERR_INVALID_ENUMERATION_VALUE, "Code. Invalid enumeration value encountered in function '%s'" },
+ { IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER, "LLDB Debugger. LLDB Listener is not valid", },
+ { IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER, "LLDB Debugger. LLDB Debugger is not valid", },
+ { IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER, "LLDB Debugger. CMIDriverBase derived driver needs to be set prior to CMICmnLLDBDDebugger initialisation" },
+ { IDS_LLDBDEBUGGER_ERR_STARTLISTENER, "LLDB Debugger. Starting listening events for '%s' failed" },
+ { IDS_LLDBDEBUGGER_ERR_THREADCREATIONFAIL, "LLDB Debugger. Thread creation failed '%s'" },
+ { IDS_LLDBDEBUGGER_ERR_THREAD_DELETE, "LLDB Debugger. Thread failed to delete '%s'" },
+ { IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER, "LLDB Debugger. Invalid SB broadcaster class name '%s' " },
+ { IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME, "LLDB Debugger. Invalid client name '%s' " },
+ { IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERD, "LLDB Debugger. Client name '%s' not registered for listening events" },
+ { IDS_LLDBDEBUGGER_ERR_STOPLISTENER, "LLDB Debugger. Failure occurred stopping event for client '%s' SBBroadcaster '%s'" },
+ { IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME, "LLDB Debugger. Broardcaster's name '%s' is not valid" },
+ { IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT, "LLDB Debugger. Unhandled event '%s'" },
+ { IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT, "LLDB Out-of-band. Handling event for '%s', an event enumeration '%d' not recognised" },
+ { IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID, "LLDB Out-of-band. Invalid '%s' in '%s'" },
+ { IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND, "LLDB Out-of-band. %s. Breakpoint information for breakpoint ID %d not found" },
+ { IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET, "LLDB Out-of-band. %s. Failed to retrieve breakpoint information for for breakpoint ID %d" },
+ { IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET, "LLDB Out-of-band. %s. Failed to set breakpoint information for for breakpoint ID %d" },
+ { IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE, "LLDB Out-of-band. %s. Failed to form the MI Out-of-band response" },
+ { IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET, "LLDB Out-of-band. %s. Failed to retrieve frame information" },
+ { IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE, "LLDB Out-of-band. %s. Event handler tried to set new MI Driver running state and failed. %s" },
+ { IDS_LLDBOUTOFBAND_ERR_BRKPT_CNT_EXCEEDED, "LLDB Out-of-band. '%s'. Number of valid breakpoint exceeded %d. Cannot create new breakpoint with ID %d" },
+ { IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE, "LLDB debug session info. Release some or all of the data shared across command instances failed" },
+ { IDS_DBGSESSION_ERR_SHARED_DATA_ADD, "LLDB debug session info. Failed to add '%s' data to the shared data command container" },
+ { IDS_MI_SHTDWN_ERR_LOG, "Log. Error occurred during shutdown. %s" },
+ { IDS_MI_SHUTDOWN_ERR, "Server shutdown failure. %s" },
+ { IDE_MI_SHTDWN_ERR_RESOURCES, "Resources. Error occurred during shutdown. %s" },
+ { IDE_MI_SHTDWN_ERR_STREAMSTDIN, "Stdin. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, "Stdin handler. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_STREAMSTDOUT, "Stdout. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_STREAMSTDERR, "Stderr. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_THREADMGR, "Thread Mgr. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_CMDINTERPRETER, "Command interpreter. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_CMDMGR, "Command manager. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_CMDFACTORY, "Command factory. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_CMDMONITOR, "Command invoker. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_CMDINVOKER, "Command monitor. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_LLDBDEBUGGER, "LLDB Debugger. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_DRIVERMGR, "Driver manager. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_DRIVER, "Driver. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_OUTOFBANDHANDLER, "Out-of-band handler. Error occurred during shutdown. %s" },
+ { IDS_MI_SHTDWN_ERR_DEBUGSESSIONINFO, "LLDB debug session info. Error occurred during shutdown. %s" },
+ { IDE_MI_SHTDWN_ERR_THREADMANAGER, "Unable to shutdown thread manager" },
+ { IDS_DRIVER_ERR_PARSE_ARGS, "Driver. Driver '%s'. Parse args error '%s'" },
+ { IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN, "Driver. Driver '%s'. Parse args error unknown" },
+ { IDS_DRIVER_ERR_CURRENT_NOT_SET, "Driver. Current working driver has not been set. Call CMIDriverMgr::SetUseThisDriverToDoWork()" },
+ { IDS_DRIVER_ERR_NON_REGISTERED, "Driver. No suitable drivers registered with the CMIDriverMgr to do work" },
+ { IDS_DRIVER_SAY_DRIVER_USING, "Driver. Using driver '%s' internally" },
+ { IDS_DRIVER_ERR_ID_INVALID, "Driver. Driver '%s' invalid ID '%s'" },
+ { IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR, "Driver. Fall through driver '%s' (ID:'%s') error '%s'" },
+ { IDS_DRIVER_CMD_RECEIVED, "Driver. Received command '%s'. It was %shandled%s" },
+ { IDS_DRIVER_CMD_NOT_IN_FACTORY, ". Command '%s' not in Command Factory" },
+ { IDS_DRIVER_ERR_DRIVER_STATE_ERROR, "Driver. Driver running state error. Cannot go to next state from present state as not allowed", },
+ { IDS_DRIVER_WAITING_STDIN_DATA, "Driver. Main thread suspended waiting on Stdin Monitor to resume main thread" },
+ { IDS_DRIVER_ERR_MAINLOOP, "Driver. Error in do main loop. %s" },
+ { IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL, "Driver. --executable argument given. Local debugging is not implemented." },
+ { IDS_DRIVER_ERR_LOCAL_DEBUG_INIT, "Driver. --executable argument given. Initialising local debugging failed." },
+ { IDS_STDOUT_ERR_NOT_ALL_DATA_WRITTEN, "Stdout. Not all data was written to stream. The data '%s'" },
+ { IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN, "Stderr. Not all data was written to stream. The data '%s'" },
+ { IDS_CMD_ARGS_ERR_N_OPTIONS_REQUIRED, "Command Args. Missing options, %d or more required" },
+ { IDS_CMD_ARGS_ERR_OPTION_NOT_FOUND, "Command Args. Option '%s' not found" },
+ { IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY, "Mandatory args not found: %s" },
+ { IDS_CMD_ARGS_ERR_VALIDATION_INVALID, "Invalid args: %s" },
+ { IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID, "Mandatory args not found: %s. Invalid args: %s" },
+ { IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF, "Args missing additional information: %s" },
+ { IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN, "Not all arguments or options were recognised: %s" },
+ { IDS_CMD_ARGS_ERR_PREFIX_MSG, "Command Args. Validation failed. " },
+ { IDS_VARIANT_ERR_USED_BASECLASS, "Variant container: Variant object used the base class. See CMIUtilVariant" },
+ { IDS_VARIANT_ERR_MAP_KEY_INVALID, "Variant container: Invalid ID '%s'" },
+ { IDS_WORD_INVALIDBRKTS, "<Invalid>" },
+ { IDS_WORD_NONE, "None" },
+ { IDS_WORD_NOT, "not" },
+ { IDS_WORD_INVALIDEMPTY, "<empty>" },
+ { IDS_WORD_INVALIDNULLPTR, "<NULL ptr>" },
+ { IDS_WORD_UNKNOWNBRKTS, "<unknown>" },
+ { IDS_WORD_NOT_IMPLEMENTED, "Not implemented" },
+ { IDS_WORD_NOT_IMPLEMENTED_BRKTS, "<not implemented>" },
+ { IDS_WORD_UNKNOWNTYPE_BRKTS, "<unknowntype>" },
+ { IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS, "<error message not implemented>" },
+ { IDS_CMD_ERR_N_OPTIONS_REQUIRED, "Command '%s'. Missing options, %d required" },
+ { IDS_CMD_ERR_OPTION_NOT_FOUND, "Command '%s'. Option '%s' not found" },
+ { IDS_CMD_ERR_ARGS, "Command '%s'. %s" },
+ { IDS_CMD_WRN_ARGS_NOT_HANDLED, "Command '%s'. Warning the following options not handled by the command: %s" },
+ { IDS_CMD_ERR_FNFAILED, "Command '%s'. Fn '%s' failed" },
+ { IDS_CMD_ERR_SHARED_DATA_NOT_FOUND, "Command '%s'. Shared data '%s' not found" },
+ { IDS_CMD_ERR_LLDBPROCESS_DETACH, "Command '%s'. Process detach failed. '%s'" },
+ { IDS_CMD_ERR_SETWKDIR, "Command '%s'. Failed to set working directory '%s'" },
+ { IDS_CMD_ERR_INVALID_TARGET, "Command '%s'. Target binary '%s' is invalid. %s" },
+ { IDS_CMD_ERR_INVALID_TARGET_CURRENT, "Command '%s'. Current SBTarget is invalid" },
+ { IDS_CMD_ERR_INVALID_TARGET_TYPE, "Command '%s'. Target type '%s' is not recognised" },
+ { IDS_CMD_ERR_INVALID_TARGET_PLUGIN, "Command '%s'. Target plugin is invalid. %s" },
+ { IDS_CMD_ERR_CONNECT_TO_TARGET, "Command '%s'. Error connecting to target: '%s'" },
+ { IDS_CMD_ERR_INVALID_TARGETPLUGINCURRENT, "Command '%s'. Current target plugin is invalid" },
+ { IDS_CMD_ERR_NOT_IMPLEMENTED, "Command '%s'. Command not implemented" },
+ { IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED, "Command '%s'. Command not implemented as it has been deprecated" },
+ { IDS_CMD_ERR_CREATE_TARGET, "Command '%s'. Create target failed: %s" },
+ { IDS_CMD_ERR_BRKPT_LOCATION_FORMAT, "Command '%s'. Incorrect format for breakpoint location '%s'" },
+ { IDS_CMD_ERR_BRKPT_INVALID, "Command '%s'. Breakpoint '%s' invalid" },
+ { IDS_CMD_ERR_BRKPT_CNT_EXCEEDED, "Command '%s'. Number of valid breakpoint exceeded %d. Cannot create new breakpoint '%s'" },
+ { IDS_CMD_ERR_SOME_ERROR, "Command '%s'. Error: %s" },
+ { IDS_CMD_ERR_THREAD_INVALID, "Command '%s'. Thread ID invalid" },
+ { IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID, "Command '%s'. Thread frame range invalid" },
+ { IDS_CMD_ERR_FRAME_INVALID, "Command '%s'. Frame ID invalid" },
+ { IDS_CMD_ERR_VARIABLE_DOESNOTEXIST, "Command '%s'. Variable '%s' does not exist" },
+ { IDS_CMD_ERR_VARIABLE_ENUM_INVALID, "Command '%s'. Invalid enumeration for variable '%s' formatted string '%s'" },
+ { IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH, "Command '%s'. Failed to get expression for variable '%s'" },
+ { IDS_CMD_ERR_VARIABLE_CREATION_FAILED, "Failed to create variable object for '%s'" },
+ { IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION, "<Error: Command run but command did not do anything useful. No MI response formed>" },
+ { IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION, "<Error: Command run and event caught, did nothing useful. No MI Out-of-Bound formed>"},
+ { IDS_CMD_ERR_DISASM_ADDR_START_INVALID, "Command '%s'. Invalid start value '%s'" },
+ { IDS_CMD_ERR_DISASM_ADDR_END_INVALID, "Command '%s'. Invalid end value '%s'" },
+ { IDS_CMD_ERR_MEMORY_ALLOC_FAILURE, "Command '%s'. Failed to allocate memory %d bytes" },
+ { IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK, "Command '%s'. LLDB unable to read entire memory block of %u bytes at address 0x%08x" },
+ { IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, "Command '%s'. Unable to read memory block of %u bytes at address 0x%08x: %s " },
+ { IDS_CMD_ERR_INVALID_PROCESS, "Command '%s'. Invalid process during debug session" },
+ { IDS_CMD_ERR_INVALID_FORMAT_TYPE, "Command '%s'. Invalid var format type '%s'" },
+ { IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND, "Command '%s'. Breakpoint information for breakpoint ID %d not found" },
+ { IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, "Command '%s'. Unable to write memory block of %u bytes at address 0x%08x: %s " },
+ { IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK, "Command '%s'. LLDB unable to write entire memory block of %u bytes at address 0x%08x" },
+ { IDS_CMD_ERR_SET_NEW_DRIVER_STATE, "Command '%s'. Command tried to set new MI Driver running state and failed. %s" },
+ { IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND, "The request '%s' was not recogised, not implemented" },
+ { IDS_CMD_ERR_INFO_PRINTFN_FAILED, "The request '%s' failed." },
+ { IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH, "'solib-search-path' requires at least one argument" }
+ };
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnResources constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnResources::CMICmnResources( void )
+: m_nResourceId2TextDataSize( 0 )
+{
+ // Do not use this constructor, use Initialize()
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnResources destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnResources::~CMICmnResources( void )
+{
+ // Do not use this destructor, use Shutdown()
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize the resources and set locality for the server.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnResources::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = ReadResourceStringData();
+
+ return m_bInitialized;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this object.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnResources::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ // Tear down resource explicitly
+ m_mapRscrIdToTextData.clear();
+
+ m_bInitialized = false;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize the resources and set locality for the server.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnResources::ReadResourceStringData( void )
+{
+ m_nResourceId2TextDataSize = sizeof ms_pResourceId2TextData / sizeof ms_pResourceId2TextData[ 0 ];
+ for( MIuint i = 0; i < m_nResourceId2TextDataSize; i++ )
+ {
+ const SRsrcTextData * pRscrData = &ms_pResourceId2TextData[ i ];
+ MapPairRscrIdToTextData_t pr( pRscrData->id, pRscrData->pTextData );
+ m_mapRscrIdToTextData.insert( pr );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the corresponding text assigned to the resource ID.
+// Type: Method.
+// Args: vResourceId - (R) MI resource ID.
+// Return: CMIUtilString - Resource text.
+// Throws: None.
+//--
+CMIUtilString CMICmnResources::GetString( const MIuint vResourceId ) const
+{
+ CMIUtilString str;
+ const bool bFound = GetStringFromResource( vResourceId, str ); MIunused( bFound );
+ assert( bFound );
+
+ return str;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine the MI resource ID existings.
+// Type: Method.
+// Args: vResourceId - (R) MI resource ID.
+// Return: True - Exists.
+// False - Not found.
+// Throws: None.
+//--
+bool CMICmnResources::HasString( const MIuint vResourceId ) const
+{
+ CMIUtilString str;
+ return GetStringFromResource( vResourceId, str );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the resource text data for the given resource ID. If a resourse ID
+// cannot be found and error is given returning the ID of the resource that
+// cannot be located.
+// Type: Method.
+// Args: vResourceId - (R) MI resource ID.
+// vrwResourceString - (W) Text.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnResources::GetStringFromResource( const MIuint vResourceId, CMIUtilString & vrwResourceString ) const
+{
+ MapRscrIdToTextData_t::const_iterator it = m_mapRscrIdToTextData.find( vResourceId );
+ if( it == m_mapRscrIdToTextData.end() )
+ {
+ // Check this is a static variable init that needs this before we are ready
+ if( !m_bInitialized )
+ {
+ (const_cast< CMICmnResources * >( this ))->Initialize();
+ it = m_mapRscrIdToTextData.find( vResourceId );
+ if( it == m_mapRscrIdToTextData.end() )
+ {
+ vrwResourceString = MIRSRC( IDS_RESOURCES_ERR_STRING_TABLE_INVALID );
+ return MIstatus::failure;
+ }
+ }
+
+ if( it == m_mapRscrIdToTextData.end() )
+ {
+ vrwResourceString = CMIUtilString::Format( MIRSRC( IDS_RESOURCES_ERR_STRING_NOT_FOUND ), vResourceId );
+ return MIstatus::failure;
+ }
+ }
+
+ const MIuint nRsrcId( (*it).first ); MIunused( nRsrcId );
+ const MIchar * pRsrcData( (*it).second );
+
+ // Return result
+ vrwResourceString = pRsrcData;
+
+ return MIstatus::success;
+}
+
diff --git a/tools/lldb-mi/MICmnResources.h b/tools/lldb-mi/MICmnResources.h
new file mode 100644
index 000000000000..f836f8d1b8aa
--- /dev/null
+++ b/tools/lldb-mi/MICmnResources.h
@@ -0,0 +1,351 @@
+//===-- MICmnResources.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnResources.h
+//
+// Overview: CMICmnResources interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers
+#include <map>
+
+// In-house headers:
+#include "MIUtilSingletonBase.h"
+#include "MIUtilString.h"
+#include "MICmnBase.h"
+
+//++ ============================================================================
+// Details: MI string test data resource definitions. These IDs match up with
+// actual string data in a map internal to CMICmnResources.
+// *** Be sure to update ms_pResourceId2TextData[] array ****
+enum
+{
+ IDS_PROJNAME = 1,
+ IDS_MI_VERSION_DESCRIPTION_DEBUG ,
+ IDS_MI_VERSION_DESCRIPTION ,
+ IDS_MI_APPNAME_SHORT ,
+ IDS_MI_APPNAME_LONG ,
+ IDS_MI_APP_FILEPATHNAME ,
+ IDS_MI_APP_ARGS ,
+ IDE_MI_VERSION_GDB ,
+
+ IDS_UTIL_FILE_ERR_INVALID_PATHNAME ,
+ IDS_UTIL_FILE_ERR_OPENING_FILE ,
+ IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN ,
+ IDE_UTIL_FILE_ERR_WRITING_FILE ,
+ IDE_UTIL_FILE_ERR_WRITING_NOTOPEN ,
+
+ IDS_RESOURCES_ERR_STRING_NOT_FOUND ,
+ IDS_RESOURCES_ERR_STRING_TABLE_INVALID ,
+
+ IDS_MI_CLIENT_MSG ,
+
+ IDS_LOG_MSG_CREATION_DATE ,
+ IDS_LOG_MSG_FILE_LOGGER_PATH ,
+ IDS_LOG_MSG_VERSION ,
+ IDS_LOG_ERR_FILE_LOGGER_DISABLED ,
+ IDS_LOG_MEDIUM_ERR_INIT ,
+ IDS_LOG_MEDIUM_ERR_WRITE_ANY ,
+ IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL ,
+ IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS,
+
+ IDS_MEDIUMFILE_NAME ,
+ IDS_MEDIUMFILE_ERR_INVALID_PATH ,
+ IDS_MEDIUMFILE_ERR_FILE_HEADER ,
+ IDS_MEDIUMFILE_NAME_LOG ,
+
+ IDE_OS_ERR_UNKNOWN ,
+ IDE_OS_ERR_RETRIEVING ,
+
+ IDS_DRIVERMGR_DRIVER_ERR_INIT ,
+
+ IDE_MEDIUMSTDERR_NAME ,
+ IDE_MEDIUMSTDOUT_NAME ,
+
+ IDE_MI_APP_EXIT_OK ,
+ IDE_MI_APP_EXIT_WITH_PROBLEM ,
+ IDE_MI_APP_EXIT_WITH_PROBLEM_NO_LOG ,
+
+ IDE_MI_APP_DESCRIPTION ,
+ IDE_MI_APP_INFORMATION ,
+ IDE_MI_APP_ARG_USAGE ,
+ IDE_MI_APP_ARG_HELP ,
+ IDE_MI_APP_ARG_VERSION ,
+ IDE_MI_APP_ARG_VERSION_LONG ,
+ IDE_MI_APP_ARG_INTERPRETER ,
+ IDE_MI_APP_ARG_EXECUTEABLE ,
+ IDE_MI_APP_ARG_NO_APP_LOG ,
+ IDE_MI_APP_ARG_EXAMPLE ,
+ IDE_MI_APP_ARG_EXECUTABLE ,
+
+ IDS_STDIN_ERR_INVALID_PROMPT ,
+ IDS_STDIN_ERR_THREAD_CREATION_FAILED ,
+ IDS_STDIN_ERR_THREAD_DELETE ,
+ IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE ,
+ IDS_STDIN_INPUT_CTRL_CHARS ,
+
+ IDS_CMD_QUIT_HELP ,
+
+ IDS_THREADMGR_ERR_THREAD_ID_INVALID ,
+ IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ,
+ IDS_THREADMGR_ERR_THREAD_ID_NOT_FOUND ,
+ IDS_THREADMGR_ERR_THREAD_STILL_ALIVE ,
+
+ IDS_FALLTHRU_DRIVER_CMD_RECEIVED ,
+
+ IDS_CMDFACTORY_ERR_INVALID_CMD_NAME ,
+ IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN ,
+ IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED ,
+ IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED ,
+
+ IDS_CMDMGR_ERR_CMD_FAILED_CREATE ,
+ IDS_CMDMGR_ERR_CMD_INVOKER ,
+
+ IDS_PROCESS_SIGNAL_RECEIVED ,
+
+ IDS_MI_INIT_ERR_LOG ,
+ IDS_MI_INIT_ERR_RESOURCES ,
+ IDS_MI_INIT_ERR_INIT ,
+ IDS_MI_INIT_ERR_STREAMSTDIN ,
+ IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER ,
+ IDS_MI_INIT_ERR_OS_STDIN_HANDLER ,
+ IDS_MI_INIT_ERR_STREAMSTDOUT ,
+ IDS_MI_INIT_ERR_STREAMSTDERR ,
+ IDS_MI_INIT_ERR_FALLTHRUDRIVER ,
+ IDS_MI_INIT_ERR_THREADMGR ,
+ IDS_MI_INIT_ERR_CMDINTERPRETER ,
+ IDS_MI_INIT_ERR_CMDMGR ,
+ IDS_MI_INIT_ERR_CMDFACTORY ,
+ IDS_MI_INIT_ERR_CMDINVOKER ,
+ IDS_MI_INIT_ERR_CMDMONITOR ,
+ IDS_MI_INIT_ERR_LLDBDEBUGGER ,
+ IDS_MI_INIT_ERR_DRIVERMGR ,
+ IDS_MI_INIT_ERR_DRIVER ,
+ IDS_MI_INIT_ERR_OUTOFBANDHANDLER ,
+ IDS_MI_INIT_ERR_DEBUGSESSIONINFO ,
+ IDS_MI_INIT_ERR_THREADMANAGER ,
+ IDS_MI_INIT_ERR_CLIENT_USING_DRIVER ,
+ IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION ,
+
+ IDS_CODE_ERR_INVALID_PARAMETER_VALUE ,
+ IDS_CODE_ERR_INVALID_PARAM_NULL_POINTER ,
+ IDS_CODE_ERR_INVALID_ENUMERATION_VALUE ,
+
+ IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER ,
+ IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER ,
+ IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER ,
+ IDS_LLDBDEBUGGER_ERR_STARTLISTENER ,
+ IDS_LLDBDEBUGGER_ERR_THREADCREATIONFAIL ,
+ IDS_LLDBDEBUGGER_ERR_THREAD_DELETE ,
+ IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER ,
+ IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME ,
+ IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERD ,
+ IDS_LLDBDEBUGGER_ERR_STOPLISTENER ,
+ IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME ,
+ IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT ,
+
+ IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ,
+ IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID ,
+ IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND ,
+ IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET ,
+ IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET ,
+ IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ,
+ IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET ,
+ IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE ,
+ IDS_LLDBOUTOFBAND_ERR_BRKPT_CNT_EXCEEDED,
+
+
+ IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE ,
+ IDS_DBGSESSION_ERR_SHARED_DATA_ADD ,
+
+ IDS_MI_SHTDWN_ERR_LOG ,
+ IDS_MI_SHUTDOWN_ERR ,
+ IDE_MI_SHTDWN_ERR_RESOURCES ,
+ IDE_MI_SHTDWN_ERR_STREAMSTDIN ,
+ IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER ,
+ IDS_MI_SHTDWN_ERR_STREAMSTDOUT ,
+ IDS_MI_SHTDWN_ERR_STREAMSTDERR ,
+ IDS_MI_SHTDWN_ERR_THREADMGR ,
+ IDS_MI_SHTDWN_ERR_CMDINTERPRETER ,
+ IDS_MI_SHTDWN_ERR_CMDMGR ,
+ IDS_MI_SHTDWN_ERR_CMDFACTORY ,
+ IDS_MI_SHTDWN_ERR_CMDINVOKER ,
+ IDS_MI_SHTDWN_ERR_CMDMONITOR ,
+ IDS_MI_SHTDWN_ERR_LLDBDEBUGGER ,
+ IDS_MI_SHTDWN_ERR_DRIVERMGR ,
+ IDS_MI_SHTDWN_ERR_DRIVER ,
+ IDS_MI_SHTDWN_ERR_OUTOFBANDHANDLER ,
+ IDS_MI_SHTDWN_ERR_DEBUGSESSIONINFO ,
+ IDE_MI_SHTDWN_ERR_THREADMANAGER ,
+
+ IDS_DRIVER_ERR_PARSE_ARGS ,
+ IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN ,
+ IDS_DRIVER_ERR_CURRENT_NOT_SET ,
+ IDS_DRIVER_ERR_NON_REGISTERED ,
+ IDS_DRIVER_SAY_DRIVER_USING ,
+ IDS_DRIVER_ERR_ID_INVALID ,
+ IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR ,
+ IDS_DRIVER_CMD_RECEIVED ,
+ IDS_DRIVER_CMD_NOT_IN_FACTORY ,
+ IDS_DRIVER_ERR_DRIVER_STATE_ERROR ,
+ IDS_DRIVER_ERR_MAINLOOP ,
+ IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL ,
+ IDS_DRIVER_ERR_LOCAL_DEBUG_INIT ,
+
+ IDS_DRIVER_WAITING_STDIN_DATA ,
+
+ IDS_STDOUT_ERR_NOT_ALL_DATA_WRITTEN ,
+ IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN ,
+
+ IDS_CMD_ARGS_ERR_N_OPTIONS_REQUIRED ,
+ IDS_CMD_ARGS_ERR_OPTION_NOT_FOUND ,
+ IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY ,
+ IDS_CMD_ARGS_ERR_VALIDATION_INVALID ,
+ IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID ,
+ IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF ,
+ IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN ,
+ IDS_CMD_ARGS_ERR_PREFIX_MSG ,
+
+ IDS_VARIANT_ERR_USED_BASECLASS ,
+ IDS_VARIANT_ERR_MAP_KEY_INVALID,
+
+ IDS_WORD_INVALIDBRKTS ,
+ IDS_WORD_NONE ,
+ IDS_WORD_NOT ,
+ IDS_WORD_INVALIDEMPTY ,
+ IDS_WORD_INVALIDNULLPTR ,
+ IDS_WORD_UNKNOWNBRKTS ,
+ IDS_WORD_NOT_IMPLEMENTED ,
+ IDS_WORD_NOT_IMPLEMENTED_BRKTS ,
+ IDS_WORD_UNKNOWNTYPE_BRKTS ,
+ IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS ,
+
+ IDS_CMD_ERR_N_OPTIONS_REQUIRED ,
+ IDS_CMD_ERR_OPTION_NOT_FOUND ,
+ IDS_CMD_ERR_ARGS ,
+ IDS_CMD_WRN_ARGS_NOT_HANDLED ,
+ IDS_CMD_ERR_FNFAILED ,
+ IDS_CMD_ERR_SHARED_DATA_NOT_FOUND ,
+ IDS_CMD_ERR_LLDBPROCESS_DETACH ,
+ IDS_CMD_ERR_SETWKDIR ,
+ IDS_CMD_ERR_INVALID_TARGET ,
+ IDS_CMD_ERR_INVALID_TARGET_CURRENT ,
+ IDS_CMD_ERR_INVALID_TARGET_TYPE ,
+ IDS_CMD_ERR_INVALID_TARGET_PLUGIN ,
+ IDS_CMD_ERR_CONNECT_TO_TARGET ,
+ IDS_CMD_ERR_INVALID_TARGETPLUGINCURRENT ,
+ IDS_CMD_ERR_NOT_IMPLEMENTED ,
+ IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED ,
+ IDS_CMD_ERR_CREATE_TARGET ,
+ IDS_CMD_ERR_BRKPT_LOCATION_FORMAT ,
+ IDS_CMD_ERR_BRKPT_INVALID ,
+ IDS_CMD_ERR_BRKPT_CNT_EXCEEDED ,
+ IDS_CMD_ERR_SOME_ERROR ,
+ IDS_CMD_ERR_THREAD_INVALID ,
+ IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID ,
+ IDS_CMD_ERR_FRAME_INVALID ,
+ IDS_CMD_ERR_VARIABLE_DOESNOTEXIST ,
+ IDS_CMD_ERR_VARIABLE_ENUM_INVALID ,
+ IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH ,
+ IDS_CMD_ERR_VARIABLE_CREATION_FAILED ,
+ IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION ,
+ IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION ,
+ IDS_CMD_ERR_DISASM_ADDR_START_INVALID ,
+ IDS_CMD_ERR_DISASM_ADDR_END_INVALID ,
+ IDS_CMD_ERR_MEMORY_ALLOC_FAILURE ,
+ IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK ,
+ IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES ,
+ IDS_CMD_ERR_INVALID_PROCESS ,
+ IDS_CMD_ERR_INVALID_FORMAT_TYPE ,
+ IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND ,
+ IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES ,
+ IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK ,
+ IDS_CMD_ERR_SET_NEW_DRIVER_STATE ,
+ IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND ,
+ IDS_CMD_ERR_INFO_PRINTFN_FAILED ,
+ IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH
+};
+
+//++ ============================================================================
+// Details: MI common code implementation class. Handle application resources
+// and locality.
+// Singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 29/01/2014.
+// Changes: None.
+//--
+class CMICmnResources
+: public CMICmnBase
+, public MI::ISingleton< CMICmnResources >
+{
+ friend class MI::ISingleton< CMICmnResources >;
+
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+
+ CMIUtilString GetString( const MIuint vResourceId ) const;
+ bool HasString( const MIuint vResourceId ) const;
+
+// Typedef:
+private:
+ typedef std::map< MIuint, const MIchar * > MapRscrIdToTextData_t;
+ typedef std::pair< MIuint, const MIchar * > MapPairRscrIdToTextData_t;
+
+// Enumerations:
+private:
+ enum Buffer_e
+ {
+ eBufferSize = 2048
+ };
+
+// Structs:
+private:
+ struct SRsrcTextData
+ {
+ MIuint id;
+ const MIchar * pTextData;
+ };
+
+// Methods:
+private:
+ /* ctor */ CMICmnResources( void );
+ /* ctor */ CMICmnResources( const CMICmnResources & );
+ void operator=( const CMICmnResources & );
+
+ bool GetStringFromResource( const MIuint vResourceId, CMIUtilString & vrwResourceString ) const;
+ bool ReadResourceStringData( void );
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnResources( void );
+
+// Attributes:
+private:
+ static const SRsrcTextData ms_pResourceId2TextData[];
+ //
+ MIuint m_nResourceId2TextDataSize;
+ MapRscrIdToTextData_t m_mapRscrIdToTextData;
+};
+
+//++ =========================================================================
+// Details: Macro short cut for retrieving a text data resource
+//--
+#define MIRSRC( x ) CMICmnResources::Instance().GetString( x ).c_str()
diff --git a/tools/lldb-mi/MICmnStreamStderr.cpp b/tools/lldb-mi/MICmnStreamStderr.cpp
new file mode 100644
index 000000000000..1d66110eab07
--- /dev/null
+++ b/tools/lldb-mi/MICmnStreamStderr.cpp
@@ -0,0 +1,257 @@
+//===-- MICmnStreamStderr.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnStreamStderr.cpp
+//
+// Overview: CMICmnStreamStderr implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnStreamStderr.h"
+#include "MICmnLog.h"
+#include "MICmnResources.h"
+#include "MIDriver.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnStreamStderr constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnStreamStderr::CMICmnStreamStderr( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnStreamStderr destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnStreamStderr::~CMICmnStreamStderr( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this stderr stream.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStderr::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+
+#ifdef _MSC_VER
+ // Debugging / I/O issues with client.
+ // This is only required on Windows if you do not use ::flush(stderr). MI uses
+ // ::flush(stderr)
+ // It trys to ensure the process attached to the stderr steam gets ALL the data.
+ //::setbuf( stderr, NULL );
+#endif // _MSC_VER
+
+ m_bInitialized = bOk;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this stderr stream.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStderr::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ ClrErrorDescription();
+
+ m_bInitialized = false;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Write text data to stderr. Prefix the message with "MI:". The text data does
+// not need to include a carrage line return as this is added to the text. The
+// function also then passes the text data into the CMICmnLog logger.
+// Type: Method.
+// Args: vText - (R) Text data.
+// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true)
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStderr::Write( const CMIUtilString & vText, const bool vbSendToLog /* = true */ )
+{
+ if( vText.length() == 0 )
+ return MIstatus::failure;
+
+ const CMIUtilString strPrefixed( CMIUtilString::Format( "%s: %s", CMIDriver::Instance().GetAppNameShort().c_str(), vText.c_str() ) );
+
+ return WritePriv( strPrefixed, vText, vbSendToLog );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Write an LLDB text message to stderr.
+// The text data does not need to include a carrage line return as this is added
+// to the text. The function also then passes the text data into the CMICmnLog
+// logger.
+// Type: Method.
+// Args: vText - (R) Text data.
+// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true)
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStderr::WriteLLDBMsg( const CMIUtilString & vText, const bool vbSendToLog /* = true */ )
+{
+ if( vText.length() == 0 )
+ return MIstatus::failure;
+
+ const CMIUtilString strPrefixed( CMIUtilString::Format( "LLDB: %s", vText.c_str() ) );
+
+ return WritePriv( vText, strPrefixed, vbSendToLog );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Write text data to stderr. The text data does not need to
+// include a carrage line return as this is added to the text. The function also
+// then passes the text data into the CMICmnLog logger.
+// Type: Method.
+// Args: vText - (R) Text data. May be prefixed with MI app's short name.
+// vTxtForLogFile - (R) Text data.
+// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true)
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStderr::WritePriv( const CMIUtilString & vText, const CMIUtilString & vTxtForLogFile, const bool vbSendToLog /* = true */ )
+{
+ if( vText.length() == 0 )
+ return MIstatus::failure;
+
+ bool bOk = MIstatus::success;
+ {
+ // Grab the stderr thread lock while we print
+ CMIUtilThreadLock _lock( m_mutex );
+
+ // Send this text to stderr
+ const MIuint status = ::fputs( vText.c_str(), stderr );
+ if( status == EOF )
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN ), vText.c_str() ) );
+ SetErrorDescription( errMsg );
+ bOk = MIstatus::failure;
+ }
+ else
+ {
+ ::fprintf( stderr, "\n" );
+ ::fflush( stderr );
+ }
+
+ // Send this text to the log
+ if( bOk && vbSendToLog )
+ bOk &= m_pLog->WriteLog( vTxtForLogFile );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Lock the availability of the stream stderr. Other users of *this stream will
+// be stalled until it is available (Unlock()).
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStderr::Lock( void )
+{
+ m_mutex.Lock();
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release a previously locked stderr.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStderr::Unlock( void )
+{
+ m_mutex.Unlock();
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Take MI Driver text message and send to the stderr stream. Also output to the
+// MI Log file.
+// Type: Static method.
+// Args: vrTxt - (R) Text.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnStreamStderr::TextToStderr( const CMIUtilString & vrTxt )
+{
+ const bool bLock = CMICmnStreamStderr::Instance().Lock();
+ const bool bOk = bLock && CMICmnStreamStderr::Instance().Write( vrTxt );
+ bLock && CMICmnStreamStderr::Instance().Unlock();
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Take an LLDB message and send to the stderr stream. The message is not always
+// an error message. The user has typed a command in to the Eclipse console (by-
+// passing Eclipse) and this is the result message from LLDB back to the user.
+// Also output to the MI Log file.
+// Type: Static method.
+// Args: vrTxt - (R) Text.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnStreamStderr::LLDBMsgToConsole( const CMIUtilString & vrTxt )
+{
+ const bool bLock = CMICmnStreamStderr::Instance().Lock();
+ const bool bOk = bLock && CMICmnStreamStderr::Instance().WriteLLDBMsg( vrTxt );
+ bLock && CMICmnStreamStderr::Instance().Unlock();
+
+ return bOk;
+}
+
diff --git a/tools/lldb-mi/MICmnStreamStderr.h b/tools/lldb-mi/MICmnStreamStderr.h
new file mode 100644
index 000000000000..45a1cf3bfc70
--- /dev/null
+++ b/tools/lldb-mi/MICmnStreamStderr.h
@@ -0,0 +1,76 @@
+//===-- MICmnStreamStderr.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnStreamStderr.h
+//
+// Overview: CMICmnStreamStderr interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MIUtilString.h"
+#include "MICmnBase.h"
+#include "MIUtilSingletonBase.h"
+#include "MIUtilThreadBaseStd.h"
+
+//++ ============================================================================
+// Details: MI common code class. The MI driver requires this object.
+// CMICmnStreamStderr sets up and tears downs stderr for the driver.
+//
+// Singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 19/03/2014.
+// Changes: None.
+//--
+class CMICmnStreamStderr
+: public CMICmnBase
+, public MI::ISingleton< CMICmnStreamStderr >
+{
+ friend class MI::ISingleton< CMICmnStreamStderr >;
+
+// Statics:
+public:
+ static bool TextToStderr( const CMIUtilString & vrTxt );
+ static bool LLDBMsgToConsole( const CMIUtilString & vrTxt );
+
+ // Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+ //
+ bool Lock( void );
+ bool Unlock( void );
+ bool Write( const CMIUtilString & vText, const bool vbSendToLog = true );
+ bool WriteLLDBMsg( const CMIUtilString & vText, const bool vbSendToLog = true );
+
+// Methods:
+private:
+ /* ctor */ CMICmnStreamStderr( void );
+ /* ctor */ CMICmnStreamStderr( const CMICmnStreamStderr & );
+ void operator=( const CMICmnStreamStderr & );
+ //
+ bool WritePriv( const CMIUtilString & vText, const CMIUtilString & vTxtForLogFile, const bool vbSendToLog = true );
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnStreamStderr( void );
+
+// Attributes:
+private:
+ CMIUtilThreadMutex m_mutex; // Mutex object for sync during Write()
+};
diff --git a/tools/lldb-mi/MICmnStreamStdin.cpp b/tools/lldb-mi/MICmnStreamStdin.cpp
new file mode 100644
index 000000000000..ccd3544c40f9
--- /dev/null
+++ b/tools/lldb-mi/MICmnStreamStdin.cpp
@@ -0,0 +1,421 @@
+//===-- MIUtilStreamStdin.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilStreamStdin.cpp
+//
+// Overview: CMICmnStreamStdin implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnStreamStdin.h"
+#include "MICmnStreamStdout.h"
+#include "MICmnResources.h"
+#include "MICmnLog.h"
+#include "MICmnThreadMgrStd.h"
+#include "MIUtilSingletonHelper.h"
+#include "MIDriver.h"
+#if defined( _MSC_VER )
+#include "MIUtilSystemWindows.h"
+#include "MICmnStreamStdinWindows.h"
+#else
+#include "MICmnStreamStdinLinux.h"
+#endif // defined( _MSC_VER )
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnStreamStdin constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnStreamStdin::CMICmnStreamStdin( void )
+: m_constStrThisThreadname( "MI stdin thread" )
+, m_pVisitor( nullptr )
+, m_strPromptCurrent( "(gdb)" )
+, m_bKeyCtrlCHit( false )
+, m_bShowPrompt( false )
+, m_bRedrawPrompt( true )
+, m_pStdinReadHandler( nullptr )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnStreamStdin destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnStreamStdin::~CMICmnStreamStdin( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this Stdin stream.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdin::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Note initialisation order is important here as some resources depend on previous
+ MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+ MI::ModuleInit< CMICmnResources > ( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg );
+ MI::ModuleInit< CMICmnThreadMgrStd >( IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg );
+#ifdef _MSC_VER
+ MI::ModuleInit< CMICmnStreamStdinWindows >( IDS_MI_INIT_ERR_OS_STDIN_HANDLER, bOk, errMsg );
+ bOk = bOk && SetOSStdinHandler( CMICmnStreamStdinWindows::Instance() );
+#else
+ MI::ModuleInit< CMICmnStreamStdinLinux >( IDS_MI_INIT_ERR_OS_STDIN_HANDLER, bOk, errMsg );
+ bOk = bOk && SetOSStdinHandler( CMICmnStreamStdinLinux::Instance() );
+#endif // ( _MSC_VER )
+
+ // The OS specific stdin stream handler must be set before *this class initialises
+ if( bOk && m_pStdinReadHandler == nullptr )
+ {
+ CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER ), errMsg.c_str() ) );
+ SetErrorDescription( strInitError );
+ return MIstatus::failure;
+ }
+
+ // Other resources required
+ if( bOk )
+ {
+ m_bKeyCtrlCHit = false; // Reset
+ }
+
+ m_bInitialized = bOk;
+
+ if( !bOk )
+ {
+ CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_STREAMSTDIN ), errMsg.c_str() ) );
+ SetErrorDescription( strInitError );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this Stdin stream.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdin::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = false;
+
+ ClrErrorDescription();
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ m_pVisitor = nullptr;
+ m_bKeyCtrlCHit = false;
+
+ // Note shutdown order is important here
+#ifndef _MSC_VER
+ MI::ModuleShutdown< CMICmnStreamStdinLinux >( IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, bOk, errMsg );
+#else
+ MI::ModuleShutdown< CMICmnStreamStdinWindows >( IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, bOk, errMsg );
+#endif // ( _MSC_VER )
+ MI::ModuleShutdown< CMICmnThreadMgrStd >( IDS_MI_SHTDWN_ERR_THREADMGR, bOk, errMsg );
+ MI::ModuleShutdown< CMICmnResources > ( IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg );
+ MI::ModuleShutdown< CMICmnLog > ( IDS_MI_SHTDWN_ERR_LOG , bOk, errMsg );
+
+ if( !bOk )
+ {
+ SetErrorDescriptionn( MIRSRC( IDE_MI_SHTDWN_ERR_STREAMSTDIN ), errMsg.c_str() );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Validate and set the text that forms the prompt on the command line.
+// Type: Method.
+// Args: vNewPrompt - (R) Text description.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdin::SetPrompt( const CMIUtilString & vNewPrompt )
+{
+ if( vNewPrompt.empty() )
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_STDIN_ERR_INVALID_PROMPT), vNewPrompt.c_str() ) );
+ CMICmnStreamStdout::Instance().Write( msg );
+ return MIstatus::failure;
+ }
+
+ m_strPromptCurrent = vNewPrompt;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the command line prompt text currently being used.
+// Type: Method.
+// Args: None.
+// Return: const CMIUtilString & - Functional failed.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnStreamStdin::GetPrompt( void ) const
+{
+ return m_strPromptCurrent;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Wait on input from stream Stdin. On each line of input received it is
+// validated and providing there are no errors on the stream or the input
+// buffer is not exceeded the data is passed to the visitor.
+// Type: Method.
+// Args: vrVisitor - (W) A client deriver callback.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdin::SetVisitor( IStreamStdin & vrVisitor )
+{
+ m_pVisitor = &vrVisitor;
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set whether to display optional command line prompt. The prompt is output to
+// stdout. Disable it when this may interfere with the client reading stdout as
+// input and it tries to interpret the prompt text to.
+// Type: Method.
+// Args: vbYes - (R) True = Yes prompt is shown/output to the user (stdout), false = no prompt.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+void CMICmnStreamStdin::SetEnablePrompt( const bool vbYes )
+{
+ m_bShowPrompt = vbYes;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get whether to display optional command line prompt. The prompt is output to
+// stdout. Disable it when this may interfere with the client reading stdout as
+// input and it tries to interpret the prompt text to.
+// Type: Method.
+// Args: None.
+// Return: bool - True = Yes prompt is shown/output to the user (stdout), false = no prompt.
+// Throws: None.
+//--
+bool CMICmnStreamStdin::GetEnablePrompt( void ) const
+{
+ return m_bShowPrompt;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine if stdin has any characters present in its buffer.
+// Type: Method.
+// Args: vwbAvail - (W) True = There is chars available, false = nothing there.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdin::InputAvailable( bool & vwbAvail )
+{
+ return m_pStdinReadHandler->InputAvailable( vwbAvail );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The monitoring on new line data calls back to the visitor object registered
+// with *this stdin monitoring. The monitoring to stops when the visitor returns
+// true for bYesExit flag. Errors output to log file.
+// This function runs in the thread "MI stdin monitor".
+// Type: Method.
+// vrwbYesAlive - (W) False = yes exit stdin monitoring, true = continue monitor.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdin::MonitorStdin( bool & vrwbYesAlive )
+{
+ if( m_bShowPrompt )
+ {
+ CMICmnStreamStdout & rStdoutMan = CMICmnStreamStdout::Instance();
+ rStdoutMan.WriteMIResponse( m_strPromptCurrent.c_str() );
+ m_bRedrawPrompt = false;
+ }
+
+ // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+ if( m_bKeyCtrlCHit )
+ {
+ CMIDriver & rMIDriver = CMIDriver::Instance();
+ rMIDriver.SetExitApplicationFlag( false );
+ if( rMIDriver.GetExitApplicationFlag() )
+ {
+ vrwbYesAlive = false;
+ return MIstatus::success;
+ }
+
+ // Reset - the MI Driver received SIGINT during a running debug programm session
+ m_bKeyCtrlCHit = false;
+ }
+
+#if MICONFIG_POLL_FOR_STD_IN
+ bool bAvail = true;
+ // Check if there is stdin available
+ if( InputAvailable( bAvail ) )
+ {
+ // Early exit when there is no input
+ if( !bAvail )
+ return MIstatus::success;
+ }
+ else
+ {
+ vrwbYesAlive = false;
+ CMIDriver::Instance().SetExitApplicationFlag( true );
+ return MIstatus::failure;
+ }
+#endif // MICONFIG_POLL_FOR_STD_IN
+
+ // Read a line from std input
+ CMIUtilString stdinErrMsg;
+ const MIchar * pText = ReadLine( stdinErrMsg );
+
+ // Did something go wrong
+ const bool bHaveError( !stdinErrMsg.empty() );
+ if( (pText == nullptr) || bHaveError )
+ {
+ if( bHaveError )
+ {
+ CMICmnStreamStdout::Instance().Write( stdinErrMsg );
+ }
+ return MIstatus::failure;
+ }
+
+ // We have text so send it off to the visitor
+ bool bOk = MIstatus::success;
+ if( m_pVisitor != nullptr )
+ {
+ bool bYesExit = false;
+ bOk = m_pVisitor->ReadLine( CMIUtilString( pText ), bYesExit );
+ m_bRedrawPrompt = true;
+ vrwbYesAlive = !bYesExit;
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r').
+// Type: Method.
+// Args: vwErrMsg - (W) Empty string ok or error description.
+// Return: MIchar * - text buffer pointer or NULL on failure.
+// Throws: None.
+//--
+const MIchar * CMICmnStreamStdin::ReadLine( CMIUtilString & vwErrMsg )
+{
+ return m_pStdinReadHandler->ReadLine( vwErrMsg );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Inform *this stream that the user hit Control-C key to exit.
+// The function is normally called by the SIGINT signal in sigint_handler() to
+// simulate kill app from the client.
+// This function is called by a Kernel thread.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMICmnStreamStdin::SetCtrlCHit( void )
+{
+ CMIUtilThreadLock lock( m_mutex );
+ m_bKeyCtrlCHit = true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The main worker method for this thread.
+// Type: Overridden.
+// Args: vrbIsAlive = (W) True = *this thread is working, false = thread has exited.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdin::ThreadRun( bool & vrbIsAlive )
+{
+ return MonitorStdin( vrbIsAlive );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Let this thread clean up after itself.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdin::ThreadFinish( void )
+{
+ // Do nothing - override to implement
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve *this thread object's name.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Text.
+// Throws: None.
+//--
+const CMIUtilString & CMICmnStreamStdin::ThreadGetName( void ) const
+{
+ return m_constStrThisThreadname;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Mandatory set the OS specific stream stdin handler. *this class utilises the
+// handler to read data from the stdin stream and put into a queue for the
+// driver to read when able.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdin::SetOSStdinHandler( IOSStdinHandler & vrHandler )
+{
+ m_pStdinReadHandler = &vrHandler;
+
+ return MIstatus::success;
+}
diff --git a/tools/lldb-mi/MICmnStreamStdin.h b/tools/lldb-mi/MICmnStreamStdin.h
new file mode 100644
index 000000000000..edd79f60b8d4
--- /dev/null
+++ b/tools/lldb-mi/MICmnStreamStdin.h
@@ -0,0 +1,125 @@
+//===-- MIUtilStreamStdin.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilStreamStdin.h
+//
+// Overview: CMICmnStreamStdin interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MIUtilString.h"
+#include "MIUtilThreadBaseStd.h"
+#include "MICmnBase.h"
+#include "MIUtilSingletonBase.h"
+
+//++ ============================================================================
+// Details: MI common code class. Used to handle stream data from Stdin.
+// Singleton class using the Visitor pattern. A driver using the interface
+// provide can receive callbacks when a new line of data is received.
+// Each line is determined by a carriage return.
+// A singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 10/02/2014.
+// Changes: Factored out OS specific handling of reading stdin - IOR 16/06/2014.
+//--
+class CMICmnStreamStdin
+: public CMICmnBase
+, public CMIUtilThreadActiveObjBase
+, public MI::ISingleton< CMICmnStreamStdin >
+{
+ // Give singleton access to private constructors
+ friend MI::ISingleton< CMICmnStreamStdin >;
+
+// Class:
+public:
+ //++
+ // Description: Visitor pattern. Driver(s) use this interface to get a callback
+ // on each new line of data received from stdin.
+ //--
+ class IStreamStdin
+ {
+ public:
+ virtual bool ReadLine( const CMIUtilString & vStdInBuffer, bool & vrwbYesExit ) = 0;
+
+ /* dtor */ virtual ~IStreamStdin( void ) {};
+ };
+
+ //++
+ // Description: Specific OS stdin handling implementations are created and used by *this
+ // class. Seperates out functionality and enables handler to be set
+ // dynamically depended on the OS detected.
+ //--
+ class IOSStdinHandler
+ {
+ public:
+ virtual bool InputAvailable( bool & vwbAvail ) = 0;
+ virtual const MIchar * ReadLine( CMIUtilString & vwErrMsg ) = 0;
+
+ /* dtor */ virtual ~IOSStdinHandler( void ) {};
+ };
+
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+ //
+ const CMIUtilString & GetPrompt( void ) const;
+ bool SetPrompt( const CMIUtilString & vNewPrompt );
+ void SetEnablePrompt( const bool vbYes );
+ bool GetEnablePrompt( void ) const;
+ void SetCtrlCHit( void );
+ bool SetVisitor( IStreamStdin & vrVisitor );
+ bool SetOSStdinHandler( IOSStdinHandler & vrHandler );
+
+// Overridden:
+public:
+ // From CMIUtilThreadActiveObjBase
+ virtual const CMIUtilString & ThreadGetName( void ) const;
+
+// Overridden:
+protected:
+ // From CMIUtilThreadActiveObjBase
+ virtual bool ThreadRun( bool & vrIsAlive );
+ virtual bool ThreadFinish( void ); // Let this thread clean up after itself
+
+// Methods:
+private:
+ /* ctor */ CMICmnStreamStdin( void );
+ /* ctor */ CMICmnStreamStdin( const CMICmnStreamStdin & );
+ void operator=( const CMICmnStreamStdin & );
+
+ bool MonitorStdin( bool & vrwbYesExit );
+ const MIchar * ReadLine( CMIUtilString & vwErrMsg );
+ bool InputAvailable( bool & vbAvail ); // Bytes are available on stdin
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnStreamStdin( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_constStrThisThreadname;
+ IStreamStdin * m_pVisitor;
+ CMIUtilString m_strPromptCurrent; // Command line prompt as shown to the user
+ volatile bool m_bKeyCtrlCHit; // True = User hit Ctrl-C, false = has not yet
+ bool m_bShowPrompt; // True = Yes prompt is shown/output to the user (stdout), false = no prompt
+ bool m_bRedrawPrompt; // True = Prompt needs to be redrawn
+ IOSStdinHandler * m_pStdinReadHandler;
+};
+
diff --git a/tools/lldb-mi/MICmnStreamStdinLinux.cpp b/tools/lldb-mi/MICmnStreamStdinLinux.cpp
new file mode 100644
index 000000000000..f73dc32d8258
--- /dev/null
+++ b/tools/lldb-mi/MICmnStreamStdinLinux.cpp
@@ -0,0 +1,212 @@
+//===-- MICmnStreamStdinLinux.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilStreamStdin.cpp
+//
+// Overview: CMICmnStreamStdinLinux implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third Party Headers:
+#if !defined( _MSC_VER )
+#include <sys/select.h>
+#include <termios.h>
+#endif // !defined( _MSC_VER )
+#include <string.h> // For std::strerror()
+
+// In-house headers:
+#include "MICmnStreamStdinLinux.h"
+#include "MICmnLog.h"
+#include "MICmnResources.h"
+#include "MIUtilSingletonHelper.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnStreamStdinLinux constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnStreamStdinLinux::CMICmnStreamStdinLinux( void )
+: m_constBufferSize( 1024 )
+, m_pStdin( nullptr )
+, m_pCmdBuffer( nullptr )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnStreamStdinLinux destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnStreamStdinLinux::~CMICmnStreamStdinLinux( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this Stdin stream.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdinLinux::Initialize( void )
+{
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Note initialisation order is important here as some resources depend on previous
+ MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+ MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg );
+
+ // Other resources required
+ if( bOk )
+ {
+ m_pCmdBuffer = new MIchar[ m_constBufferSize ];
+ m_pStdin = stdin;
+ }
+
+ // Clear error indicators for std input
+ ::clearerr( stdin );
+
+ m_bInitialized = bOk;
+
+ if( !bOk )
+ {
+ CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_OS_STDIN_HANDLER ), errMsg.c_str() ) );
+ SetErrorDescription( strInitError );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this Stdin stream.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdinLinux::Shutdown( void )
+{
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = false;
+
+ ClrErrorDescription();
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Tidy up
+ if( m_pCmdBuffer != nullptr )
+ {
+ delete [] m_pCmdBuffer;
+ m_pCmdBuffer = nullptr;
+ }
+ m_pStdin = nullptr;
+
+ // Note shutdown order is important here
+ MI::ModuleShutdown< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg );
+ MI::ModuleShutdown< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+
+ if( !bOk )
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER ), errMsg.c_str() );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine if stdin has any characters present in its buffer.
+// Type: Method.
+// Args: vwbAvail - (W) True = There is chars available, false = nothing there.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdinLinux::InputAvailable( bool & vwbAvail )
+{
+/* AD: Not used ATM but could come in handy just in case we need to do
+ this, poll for input
+
+ static const int STDIN = 0;
+ static bool bInitialized = false;
+
+ if( !bInitialized )
+ {
+ // Use termios to turn off line buffering
+ ::termios term;
+ ::tcgetattr( STDIN, &term );
+ ::term.c_lflag &= ~ICANON;
+ ::tcsetattr( STDIN, TCSANOW, &term );
+ ::setbuf( stdin, NULL );
+ bInitialized = true;
+ }
+
+ int nBytesWaiting;
+ ::ioctl( STDIN, FIONREAD, &nBytesWaiting );
+ vwbAvail = (nBytesWaiting > 0);
+
+ return MIstatus::success;
+*/
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r').
+// Type: Method.
+// Args: vwErrMsg - (W) Empty string ok or error description.
+// Return: MIchar * - text buffer pointer or NULL on failure.
+// Throws: None.
+//--
+const MIchar * CMICmnStreamStdinLinux::ReadLine( CMIUtilString & vwErrMsg )
+{
+ vwErrMsg.clear();
+
+ // Read user input
+ const MIchar * pText = ::fgets( &m_pCmdBuffer[ 0 ], m_constBufferSize, stdin );
+ if( pText == nullptr )
+ {
+ if( ::ferror( m_pStdin ) != 0 )
+ vwErrMsg = ::strerror( errno );
+ return nullptr;
+ }
+
+ // Strip off new line characters
+ for( MIchar * pI = m_pCmdBuffer; *pI != '\0'; pI++ )
+ {
+ if( (*pI == '\n') || (*pI == '\r') )
+ {
+ *pI = '\0';
+ break;
+ }
+ }
+
+ return pText;
+}
+
diff --git a/tools/lldb-mi/MICmnStreamStdinLinux.h b/tools/lldb-mi/MICmnStreamStdinLinux.h
new file mode 100644
index 000000000000..78d796634b34
--- /dev/null
+++ b/tools/lldb-mi/MICmnStreamStdinLinux.h
@@ -0,0 +1,75 @@
+//===-- MICmnStreamStdinWindows.h --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilStreamStdin.h
+//
+// Overview: CMICmnStreamStdinLinux interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MICmnStreamStdin.h"
+#include "MIUtilSingletonBase.h"
+
+//++ ============================================================================
+// Details: MI common code class. Specific OS stdin handling implementation.
+// CMICmnStreamStdin instance is set with stdin handler before using the
+// the stream. An instance of this class must be set up and ready to give
+// to the CMICmnStreamStdin before it initialises other CMICmnStreamStdin
+// will give an error.
+// Gotchas: None.
+// Authors: Illya Rudkin 16/06/2014.
+// Changes: None.
+//--
+class CMICmnStreamStdinLinux
+: public CMICmnBase
+, public CMICmnStreamStdin::IOSStdinHandler
+, public MI::ISingleton< CMICmnStreamStdinLinux >
+{
+ // Give singleton access to private constructors
+ friend MI::ISingleton< CMICmnStreamStdinLinux >;
+
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+
+// Overridden:
+public:
+ // From CMICmnStreamStdin::IOSpecificReadStreamStdin
+ virtual bool InputAvailable( bool & vwbAvail );
+ virtual const MIchar * ReadLine( CMIUtilString & vwErrMsg );
+
+// Methods:
+private:
+ /* ctor */ CMICmnStreamStdinLinux( void );
+ /* ctor */ CMICmnStreamStdinLinux( const CMICmnStreamStdin & );
+ void operator=( const CMICmnStreamStdin & );
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnStreamStdinLinux( void );
+
+// Attributes:
+private:
+ const MIuint m_constBufferSize;
+ FILE * m_pStdin;
+ MIchar * m_pCmdBuffer;
+};
+
diff --git a/tools/lldb-mi/MICmnStreamStdinWindows.cpp b/tools/lldb-mi/MICmnStreamStdinWindows.cpp
new file mode 100644
index 000000000000..2b24df8d61a6
--- /dev/null
+++ b/tools/lldb-mi/MICmnStreamStdinWindows.cpp
@@ -0,0 +1,279 @@
+//===-- MICmnStreamStdinWindows.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilStreamStdin.cpp
+//
+// Overview: CMICmnStreamStdinWindows implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third Party Headers:
+#if defined( _MSC_VER )
+#include <stdio.h>
+#include <Windows.h>
+#include <io.h>
+#include <conio.h>
+#endif // defined( _MSC_VER )
+#include <string.h>
+
+// In-house headers:
+#include "MICmnStreamStdinWindows.h"
+#include "MICmnLog.h"
+#include "MICmnResources.h"
+#include "MIUtilSystemWindows.h"
+#include "MIUtilSingletonHelper.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnStreamStdinWindows constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnStreamStdinWindows::CMICmnStreamStdinWindows( void )
+: m_constBufferSize( 1024 )
+, m_pStdin( nullptr )
+, m_pCmdBuffer( nullptr )
+, m_pStdinBuffer( nullptr )
+, m_nBytesToBeRead( 0 )
+, m_bRunningInConsoleWin( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnStreamStdinWindows destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnStreamStdinWindows::~CMICmnStreamStdinWindows( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this Stdin stream.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdinWindows::Initialize( void )
+{
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Note initialisation order is important here as some resources depend on previous
+ MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+ MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg );
+
+ // Other resources required
+ if( bOk )
+ {
+ m_pCmdBuffer = new MIchar[ m_constBufferSize ];
+ m_pStdin = stdin;
+
+#if MICONFIG_CREATE_OWN_STDIN_BUFFER
+ // Give stdinput a user defined buffer
+ m_pStdinBuffer = new char[ 1024 ];
+ ::setbuf( stdin, m_pStdinBuffer );
+#endif // MICONFIG_CREATE_OWN_STDIN_BUFFER
+
+ // Clear error indicators for std input
+ ::clearerr( stdin );
+
+#if defined( _MSC_VER )
+ m_bRunningInConsoleWin = ::_isatty( ::fileno( stdin ) );
+#endif // #if defined( _MSC_VER )
+ }
+
+ m_bInitialized = bOk;
+
+ if( !bOk )
+ {
+ CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_OS_STDIN_HANDLER ), errMsg.c_str() ) );
+ SetErrorDescription( strInitError );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this Stdin stream.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdinWindows::Shutdown( void )
+{
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = false;
+
+ ClrErrorDescription();
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Tidy up
+ if( m_pCmdBuffer != nullptr )
+ {
+ delete [] m_pCmdBuffer;
+ m_pCmdBuffer = nullptr;
+ }
+ m_pStdin = nullptr;
+
+#if MICONFIG_CREATE_OWN_STDIN_BUFFER
+ if ( m_pStdinBuffer )
+ delete [] m_pStdinBuffer;
+ m_pStdinBuffer = nullptr;
+#endif // MICONFIG_CREATE_OWN_STDIN_BUFFER
+
+ // Note shutdown order is important here
+ MI::ModuleShutdown< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg );
+ MI::ModuleShutdown< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+
+ if( !bOk )
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER ), errMsg.c_str() );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine if stdin has any characters present in its buffer.
+// Type: Method.
+// Args: vwbAvail - (W) True = There is chars available, false = nothing there.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdinWindows::InputAvailable( bool & vwbAvail )
+{
+ return m_bRunningInConsoleWin ? InputAvailableConsoleWin( vwbAvail ) : InputAvailableApplication( vwbAvail );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine if stdin has any characters present in its buffer. If running in a
+// terminal use _kbhit().
+// Type: Method.
+// Args: vwbAvail - (W) True = There is chars available, false = nothing there.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdinWindows::InputAvailableConsoleWin( bool & vwbAvail )
+{
+#if defined( _MSC_VER )
+ if( m_nBytesToBeRead == 0 )
+ {
+ // Get a windows handle to std input stream
+ HANDLE handle = ::GetStdHandle( STD_INPUT_HANDLE );
+ DWORD nBytesWaiting = ::_kbhit();
+
+ // Save the number of bytes to be read so that we can check if input is available to be read
+ m_nBytesToBeRead = nBytesWaiting;
+
+ // Return state of whether bytes are waiting or not
+ vwbAvail = (nBytesWaiting > 0);
+ }
+#endif // #if defined( _MSC_VER )
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine if stdin has any characters present in its buffer.
+// Type: Method.
+// Args: vwbAvail - (W) True = There is chars available, false = nothing there.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdinWindows::InputAvailableApplication( bool & vwbAvail )
+{
+ #if defined( _MSC_VER )
+ if( m_nBytesToBeRead == 0 )
+ {
+ // Get a windows handle to std input stream
+ HANDLE handle = ::GetStdHandle( STD_INPUT_HANDLE );
+ DWORD nBytesWaiting = 0;
+
+ // Ask how many bytes are available
+ if( ::PeekNamedPipe( handle, nullptr, 0, nullptr, &nBytesWaiting, nullptr ) == FALSE )
+ {
+ // This can occur when the client i.e. Eclipse closes the stdin stream 'cause it deems its work is finished
+ // for that debug session. May be we should be handling SIGKILL somehow?
+ const CMIUtilString osErrMsg( CMIUtilSystemWindows().GetOSLastError().StripCRAll() );
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE ), osErrMsg.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ // Save the number of bytes to be read so that we can check if input is available to be read
+ m_nBytesToBeRead = nBytesWaiting;
+
+ // Return state of whether bytes are waiting or not
+ vwbAvail = (nBytesWaiting > 0);
+ }
+#endif // #if defined( _MSC_VER )
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r').
+// Type: Method.
+// Args: vwErrMsg - (W) Empty string ok or error description.
+// Return: MIchar * - text buffer pointer or NULL on failure.
+// Throws: None.
+//--
+const MIchar * CMICmnStreamStdinWindows::ReadLine( CMIUtilString & vwErrMsg )
+{
+ vwErrMsg.clear();
+
+ // Read user input
+ const MIchar * pText = ::fgets( &m_pCmdBuffer[ 0 ], m_constBufferSize, stdin );
+ if( pText == nullptr )
+ {
+ if( ::ferror( m_pStdin ) != 0 )
+ vwErrMsg = ::strerror( errno );
+ return nullptr;
+ }
+
+ // Subtract the number of bytes read so that we can check if input is available to be read
+ m_nBytesToBeRead = m_nBytesToBeRead - ::strlen( pText );
+
+ // Strip off new line characters
+ for( MIchar * pI = m_pCmdBuffer; *pI != '\0'; pI++ )
+ {
+ if( (*pI == '\n') || (*pI == '\r') )
+ {
+ *pI = '\0';
+ break;
+ }
+ }
+
+ return pText;
+} \ No newline at end of file
diff --git a/tools/lldb-mi/MICmnStreamStdinWindows.h b/tools/lldb-mi/MICmnStreamStdinWindows.h
new file mode 100644
index 000000000000..8feff8babfbf
--- /dev/null
+++ b/tools/lldb-mi/MICmnStreamStdinWindows.h
@@ -0,0 +1,81 @@
+//===-- MICmnStreamStdinWindows.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilStreamStdin.h
+//
+// Overview: CMICmnStreamStdinWindows interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MICmnStreamStdin.h"
+#include "MIUtilSingletonBase.h"
+
+//++ ============================================================================
+// Details: MI common code class. Specific OS stdin handling implementation.
+// CMICmnStreamStdin instance is set with stdin handler before using the
+// the stream. An instance of this class must be set up and ready to give
+// to the CMICmnStreamStdin before it initialises other CMICmnStreamStdin
+// will give an error.
+// Gotchas: None.
+// Authors: Illya Rudkin 16/06/2014.
+// Changes: None.
+//--
+class CMICmnStreamStdinWindows
+: public CMICmnBase
+, public CMICmnStreamStdin::IOSStdinHandler
+, public MI::ISingleton< CMICmnStreamStdinWindows >
+{
+ // Give singleton access to private constructors
+ friend MI::ISingleton< CMICmnStreamStdinWindows >;
+
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+
+// Overridden:
+public:
+ // From CMICmnStreamStdin::IOSpecificReadStreamStdin
+ virtual bool InputAvailable( bool & vwbAvail );
+ virtual const MIchar * ReadLine( CMIUtilString & vwErrMsg );
+
+// Methods:
+private:
+ /* ctor */ CMICmnStreamStdinWindows( void );
+ /* ctor */ CMICmnStreamStdinWindows( const CMICmnStreamStdinWindows & );
+ void operator=( const CMICmnStreamStdinWindows & );
+ //
+ bool InputAvailableConsoleWin( bool & vwbAvail );
+ bool InputAvailableApplication( bool & vwbAvail );
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnStreamStdinWindows( void );
+
+// Attributes:
+private:
+ const MIuint m_constBufferSize;
+ FILE * m_pStdin;
+ MIchar * m_pCmdBuffer;
+ MIchar * m_pStdinBuffer; // Custom buffer to store std input
+ MIuint m_nBytesToBeRead; // Checks that ::fgets() is holding on to data while ::PeekNamedPipe() returns nothing which causes a problem
+ bool m_bRunningInConsoleWin; // True = The application is being run in a Windows command line prompt window, false = by other means
+};
+
diff --git a/tools/lldb-mi/MICmnStreamStdout.cpp b/tools/lldb-mi/MICmnStreamStdout.cpp
new file mode 100644
index 000000000000..0532820eb790
--- /dev/null
+++ b/tools/lldb-mi/MICmnStreamStdout.cpp
@@ -0,0 +1,230 @@
+//===-- MIUtilStreamStdout.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilStreamcStdout.cpp
+//
+// Overview: CMICmnStreamStdout implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnStreamStdout.h"
+#include "MICmnLog.h"
+#include "MICmnResources.h"
+#include "MIDriver.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnStreamStdout constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnStreamStdout::CMICmnStreamStdout( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnStreamStdout destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnStreamStdout::~CMICmnStreamStdout( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this Stdout stream.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdout::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+
+#ifdef _MSC_VER
+ // Debugging / I/O issues with client.
+ // This is only required on Windows if you do not use ::flush(stdout). MI uses
+ // ::flush(stdout)
+ // It trys to ensure the process attached to the stdout steam gets ALL the data.
+ //::setbuf( stdout, NULL );
+#endif // _MSC_VER
+
+ m_bInitialized = bOk;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this Stdout stream.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdout::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ ClrErrorDescription();
+
+ m_bInitialized = false;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Write an MI format type response to stdout. The text data does not need to
+// include a carrage line return as this is added to the text. The function also
+// then passes the text data into the CMICmnLog logger.
+// Type: Method.
+// Args: vText - (R) MI formatted text.
+// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true)
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdout::WriteMIResponse( const CMIUtilString & vText, const bool vbSendToLog /* = true */ )
+{
+ return WritePriv( vText, vText, vbSendToLog );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Write text data to stdout. The text data does not need to
+// include a carrage line return as this is added to the text. The function also
+// then passes the text data into the CMICmnLog logger.
+// Type: Method.
+// Args: vText - (R) Text data.
+// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true)
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdout::Write( const CMIUtilString & vText, const bool vbSendToLog /* = true */ )
+{
+ if( vText.length() == 0 )
+ return MIstatus::failure;
+
+ const CMIUtilString strPrefixed( CMIUtilString::Format( "%s: %s", CMIDriver::Instance().GetAppNameShort().c_str(), vText.c_str() ) );
+
+ return WritePriv( strPrefixed, vText, vbSendToLog );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Write text data to stdout. The text data does not need to
+// include a carrage line return as this is added to the text. The function also
+// then passes the text data into the CMICmnLog logger.
+// Type: Method.
+// Args: vText - (R) Text data prefixed with MI app's short name.
+// vTxtForLogFile - (R) Text data.
+// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true)
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdout::WritePriv( const CMIUtilString & vText, const CMIUtilString & vTxtForLogFile, const bool vbSendToLog /* = true */ )
+{
+ if( vText.length() == 0 )
+ return MIstatus::failure;
+
+ bool bOk = MIstatus::success;
+ {
+ // Grab the stdout thread lock while we print
+ CMIUtilThreadLock _lock( m_mutex );
+
+ // Send this text to stdout
+ const MIuint status = ::fputs( vText.c_str(), stdout );
+ if( status == EOF )
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_STDOUT_ERR_NOT_ALL_DATA_WRITTEN ), vText.c_str() ) );
+ SetErrorDescription( errMsg );
+ bOk = MIstatus::failure;
+ }
+ else
+ {
+ ::fprintf( stdout, "\n" );
+ ::fflush( stdout );
+ }
+
+ // Send this text to the log
+ if( bOk && vbSendToLog )
+ bOk &= m_pLog->WriteLog( vTxtForLogFile );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Lock the availability of the stream stdout. Other users of *this stream will
+// be stalled until it is available (Unlock()).
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdout::Lock( void )
+{
+ m_mutex.Lock();
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release a previously locked stdout.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdout::Unlock( void )
+{
+ m_mutex.Unlock();
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Take a text data and send to the stdout stream. Also output to the MI Log
+// file.
+// Type: Static method.
+// Args: vrTxt - (R) Text.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnStreamStdout::TextToStdout( const CMIUtilString & vrTxt )
+{
+ const bool bLock = CMICmnStreamStdout::Instance().Lock();
+ const bool bOk = bLock && CMICmnStreamStdout::Instance().WriteMIResponse( vrTxt );
+ bLock && CMICmnStreamStdout::Instance().Unlock();
+
+ return bOk;
+}
diff --git a/tools/lldb-mi/MICmnStreamStdout.h b/tools/lldb-mi/MICmnStreamStdout.h
new file mode 100644
index 000000000000..90f50478f06d
--- /dev/null
+++ b/tools/lldb-mi/MICmnStreamStdout.h
@@ -0,0 +1,75 @@
+//===-- MICmnStreamStdout.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnStreamStdout.h
+//
+// Overview: CMICmnStreamStdout interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MIUtilString.h"
+#include "MICmnBase.h"
+#include "MIUtilThreadBaseStd.h"
+#include "MIUtilSingletonBase.h"
+
+//++ ============================================================================
+// Details: MI common code class. The MI driver requires this object.
+// CMICmnStreamStdout sets up and tears downs stdout for the driver.
+//
+// Singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 12/02/2014.
+// Changes: None.
+//--
+class CMICmnStreamStdout
+: public CMICmnBase
+, public MI::ISingleton< CMICmnStreamStdout >
+{
+ friend class MI::ISingleton< CMICmnStreamStdout >;
+
+// Statics:
+public:
+ static bool TextToStdout( const CMIUtilString & vrTxt );
+
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+ //
+ bool Lock( void );
+ bool Unlock( void );
+ bool Write( const CMIUtilString & vText, const bool vbSendToLog = true );
+ bool WriteMIResponse( const CMIUtilString & vText, const bool vbSendToLog = true );
+
+// Methods:
+private:
+ /* ctor */ CMICmnStreamStdout( void );
+ /* ctor */ CMICmnStreamStdout( const CMICmnStreamStdout & );
+ void operator=( const CMICmnStreamStdout & );
+ //
+ bool WritePriv( const CMIUtilString & vText, const CMIUtilString & vTxtForLogFile, const bool vbSendToLog = true );
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnStreamStdout( void );
+
+// Attributes:
+private:
+ CMIUtilThreadMutex m_mutex; // Mutex object for sync during writing to stream
+};
diff --git a/tools/lldb-mi/MICmnThreadMgrStd.cpp b/tools/lldb-mi/MICmnThreadMgrStd.cpp
new file mode 100644
index 000000000000..757012a697e0
--- /dev/null
+++ b/tools/lldb-mi/MICmnThreadMgrStd.cpp
@@ -0,0 +1,167 @@
+//===-- MICmnThreadMgr.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnThreadMgr.cpp
+//
+// Overview: CMICmnThreadMgr implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MICmnThreadMgrStd.h"
+#include "MICmnLog.h"
+#include "MICmnResources.h"
+#include "MIUtilSingletonHelper.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnThreadMgr constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnThreadMgrStd::CMICmnThreadMgrStd( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnThreadMgr destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnThreadMgrStd::~CMICmnThreadMgrStd( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialise resources for *this thread manager.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnThreadMgrStd::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+
+ ClrErrorDescription();
+ CMIUtilString errMsg;
+
+ // Note initialisation order is important here as some resources depend on previous
+ MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+ MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg );
+
+ m_bInitialized = bOk;
+
+ if( !bOk )
+ {
+ CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_THREADMGR ), errMsg.c_str() ) );
+ SetErrorDescription( strInitError );
+ return MIstatus::failure;
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this thread manager.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnThreadMgrStd::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = false;
+
+ ClrErrorDescription();
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Tidy up
+ ThreadAllTerminate();
+
+ // Note shutdown order is important here
+ MI::ModuleShutdown< CMICmnResources >( IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg );
+ MI::ModuleShutdown< CMICmnLog > ( IDS_MI_SHTDWN_ERR_LOG , bOk, errMsg );
+
+ if( !bOk )
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_MI_SHUTDOWN_ERR ), errMsg.c_str() );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Ask the thread manager to kill all threads and wait until they have died
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnThreadMgrStd::ThreadAllTerminate( void )
+{
+ ThreadList_t::const_iterator it = m_threadList.begin();
+ for( ; it != m_threadList.end(); ++it )
+ {
+ // If the thread is still running
+ CMIUtilThreadActiveObjBase * pThread = *it;
+ if( pThread->ThreadIsActive() )
+ {
+ // Ask this thread to kill itself
+ pThread->ThreadKill();
+
+ // Wait for this thread to die
+ pThread->ThreadJoin();
+ }
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add a thread object to *this manager's list of thread objects. The list to
+// used to manage thread objects centrally.
+// Type: Method.
+// Args: vrObj - (R) A thread object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMICmnThreadMgrStd::AddThread( const CMIUtilThreadActiveObjBase & vrObj )
+{
+ m_threadList.push_back( const_cast< CMIUtilThreadActiveObjBase * >( &vrObj ) );
+
+ return MIstatus::success;
+}
diff --git a/tools/lldb-mi/MICmnThreadMgrStd.h b/tools/lldb-mi/MICmnThreadMgrStd.h
new file mode 100644
index 000000000000..f0c157a468af
--- /dev/null
+++ b/tools/lldb-mi/MICmnThreadMgrStd.h
@@ -0,0 +1,134 @@
+//===-- MICmnThreadMgrStd.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnThreadMgrStd.h
+//
+// Overview: CMICmnThreadMgr interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <vector>
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MIUtilThreadBaseStd.h"
+#include "MICmnResources.h"
+#include "MIUtilSingletonBase.h"
+
+//++ ============================================================================
+// Details: MI's worker thread (active thread) manager.
+// The manager creates threads and behalf of clients. Client are
+// responsible for their threads and can delete them when necessary.
+// This manager will stop and delete all threads on *this manager's
+// shutdown.
+// Singleton class.
+// Gotchas: None.
+// Authors: Aidan Dodds 12/03/2014.
+// Changes: None.
+//--
+class CMICmnThreadMgrStd
+: public CMICmnBase
+, public MI::ISingleton< CMICmnThreadMgrStd >
+{
+ friend MI::ISingleton< CMICmnThreadMgrStd >;
+
+// Methods:
+public:
+ bool Initialize( void );
+ bool Shutdown( void );
+ bool ThreadAllTerminate( void ); // Ask all threads to stop (caution)
+ template< typename T > // Ask the thread manager to start and stop threads on our behalf
+ bool ThreadStart( T & vrwObject );
+
+// Typedef:
+private:
+ typedef std::vector< CMIUtilThreadActiveObjBase * > ThreadList_t;
+
+// Methods:
+private:
+ /* ctor */ CMICmnThreadMgrStd( void );
+ /* ctor */ CMICmnThreadMgrStd( const CMICmnThreadMgrStd & );
+ void operator=( const CMICmnThreadMgrStd & );
+ //
+ bool AddThread( const CMIUtilThreadActiveObjBase & vrObj ); // Add a thread for monitoring by the threadmanager
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmnThreadMgrStd( void );
+
+// Attributes:
+private:
+ CMIUtilThreadMutex m_mutex;
+ ThreadList_t m_threadList;
+};
+
+//++ ------------------------------------------------------------------------------------
+// Details: Given a thread object start its (worker) thread to do work. The object is
+// added to the *this manager for housekeeping and deletion of all thread objects.
+// Type: Template method.
+// Args: vrwThreadObj - (RW) A CMIUtilThreadActiveObjBase derived object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+template< typename T >
+bool CMICmnThreadMgrStd::ThreadStart( T & vrwThreadObj )
+{
+ bool bOk = MIstatus::success;
+
+ // Grab a reference to the base object type
+ CMIUtilThreadActiveObjBase & rObj = static_cast< CMIUtilThreadActiveObjBase & >( vrwThreadObj );
+
+ // Add to the thread managers internal database
+ bOk &= AddThread( rObj );
+ if( !bOk )
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ), vrwThreadObj.ThreadGetName().c_str() ) );
+ SetErrorDescription( errMsg );
+ return MIstatus::failure;
+ }
+
+ // Grab a reference on behalf of the caller
+ bOk &= vrwThreadObj.Acquire();
+ if( !bOk )
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ), vrwThreadObj.ThreadGetName().c_str() ) );
+ SetErrorDescription( errMsg );
+ return MIstatus::failure;
+ }
+
+ // Thread is already started
+ // This call must come after the reference count increment
+ if( vrwThreadObj.ThreadIsActive() )
+ {
+ // Early exit on thread already running condition
+ return MIstatus::success;
+ }
+
+ // Start the thread running
+ bOk &= vrwThreadObj.ThreadExecute();
+ if( !bOk )
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ), vrwThreadObj.ThreadGetName().c_str() ) );
+ SetErrorDescription( errMsg );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
diff --git a/tools/lldb-mi/MIDataTypes.h b/tools/lldb-mi/MIDataTypes.h
new file mode 100644
index 000000000000..c7980a8851a3
--- /dev/null
+++ b/tools/lldb-mi/MIDataTypes.h
@@ -0,0 +1,100 @@
+//===-- MIDataTypes.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIDataTypes.h
+//
+// Overview: Common global switches, macros, etc.
+//
+// This file contains common data types required by applications
+// generally. If supported by the compiler, this file should be
+// #include'd as part of the project's PCH (precompiled header).
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+//--------------------------------------------------------------------------------------
+// Windows headers:
+#ifdef _WIN32
+
+// Debugging:
+#ifdef _DEBUG
+#include <crtdbg.h> // C-runtime debugging library (defines _ASSERT).
+#endif // _DEBUG
+
+#endif // _WIN32
+
+//--------------------------------------------------------------------------------------
+// Common definitions:
+
+// Function return status
+namespace MIstatus
+{
+ const bool success = true;
+ const bool failure = false;
+}
+
+// Use to avoid "unused parameter" compiler warnings:
+#define MIunused( x ) (void) x;
+
+#ifdef _WIN32
+#define MI_NO_INITIALIZE_VTABLE __declspec( novtable )
+#define MI_FORCE_INLINE __forceinline
+#else
+#define MI_NO_INITIALIZE_VTABLE
+#define MI_FORCE_INLINE inline
+// __attribute__( ( always_inline ) )
+#endif // _WIN32
+
+// Portability issues
+#ifdef _WIN64
+ typedef unsigned __int64 size_t;
+ typedef unsigned __int64 PointerToInteger_t;
+ typedef __int64 MIint;
+ typedef unsigned __int64 MIuint;
+#else
+ #ifdef _WIN32
+ typedef unsigned int size_t;
+ typedef unsigned int PointerToInteger_t;
+ typedef int MIint;
+ typedef unsigned int MIuint;
+ #else
+// typedef long unsigned int size_t; // size_t already defined
+ typedef unsigned int PointerToInteger_t;
+ typedef int MIint;
+ typedef unsigned int MIuint;
+
+ #define MAX_PATH 4096
+ #endif // _WIN32
+#endif // _WIN64
+
+//--------------------------------------------------------------------------------------
+// Common types:
+
+// Fundamentals:
+typedef float MIflt;
+typedef double MIdbl;
+typedef char MIchar; // Defaults to signed char, i.e. MIschar.
+typedef signed char MIschar; // Range: -128 to 127. More explicit than using MIchar.
+typedef unsigned char MIuchar; // Range: 0 to 255.
+typedef long long MIint64; // 64bit signed integer.
+typedef unsigned long long MIuint64; // 64bit unsigned integer.
+
+//using namespace std; // Better to put this or std:: at translation units scope.
+
+//--------------------------------------------------------------------------------------
+// Common routines:
+
+//--------------------------------------------------------------------------------------
diff --git a/tools/lldb-mi/MIDriver.cpp b/tools/lldb-mi/MIDriver.cpp
new file mode 100644
index 000000000000..759d54a5364d
--- /dev/null
+++ b/tools/lldb-mi/MIDriver.cpp
@@ -0,0 +1,1276 @@
+//===-- MIDriver.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIDriver.cpp
+//
+// Overview: CMIDriver implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers:
+#include <stdarg.h> // va_list, va_start, var_end
+#include <iostream>
+#include <lldb/API/SBError.h>
+
+// In-house headers:
+#include "Driver.h"
+#include "MIDriver.h"
+#include "MICmnResources.h"
+#include "MICmnLog.h"
+#include "MICmdMgr.h"
+#include "MICmnLLDBDebugger.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnThreadMgrStd.h"
+#include "MIUtilDebug.h"
+#include "MIUtilSingletonHelper.h"
+#include "MICmnStreamStdout.h"
+#include "MICmnStreamStderr.h"
+#include "MICmdArgValFile.h"
+#include "MICmdArgValString.h"
+#include "MICmnConfig.h"
+
+// Instantiations:
+#if _DEBUG
+ const CMIUtilString CMIDriver::ms_constMIVersion = MIRSRC( IDS_MI_VERSION_DESCRIPTION_DEBUG );
+#else
+ const CMIUtilString CMIDriver::ms_constMIVersion = MIRSRC( IDS_MI_VERSION_DESCRIPTION ); // Matches version in resources file
+#endif // _DEBUG
+const CMIUtilString CMIDriver::ms_constAppNameShort( MIRSRC( IDS_MI_APPNAME_SHORT ) );
+const CMIUtilString CMIDriver::ms_constAppNameLong( MIRSRC( IDS_MI_APPNAME_LONG ) );
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIDriver constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIDriver::CMIDriver( void )
+: m_bFallThruToOtherDriverEnabled( false )
+, m_bDriverIsExiting( false )
+, m_handleMainThread( 0 )
+, m_rStdin( CMICmnStreamStdin::Instance() )
+, m_rLldbDebugger( CMICmnLLDBDebugger::Instance() )
+, m_rStdOut( CMICmnStreamStdout::Instance() )
+, m_eCurrentDriverState( eDriverState_NotRunning )
+, m_bHaveExecutableFileNamePathOnCmdLine( false )
+, m_bDriverDebuggingArgExecutable( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIDriver destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIDriver::~CMIDriver( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set whether *this driver (the parent) is enabled to pass a command to its
+// fall through (child) driver to interpret the command and do work instead
+// (if *this driver decides it can't hanled the command).
+// Type: Method.
+// Args: vbYes - (R) True = yes fall through, false = do not pass on command.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::SetEnableFallThru( const bool vbYes )
+{
+ m_bFallThruToOtherDriverEnabled = vbYes;
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get whether *this driver (the parent) is enabled to pass a command to its
+// fall through (child) driver to interpret the command and do work instead
+// (if *this driver decides it can't hanled the command).
+// Type: Method.
+// Args: None.
+// Return: bool - True = yes fall through, false = do not pass on command.
+// Throws: None.
+//--
+bool CMIDriver::GetEnableFallThru( void ) const
+{
+ return m_bFallThruToOtherDriverEnabled;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve MI's application name of itself.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetAppNameShort( void ) const
+{
+ return ms_constAppNameShort;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve MI's application name of itself.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetAppNameLong( void ) const
+{
+ return ms_constAppNameLong;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve MI's version description of itself.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetVersionDescription( void ) const
+{
+ return ms_constMIVersion;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize setup *this driver ready for use.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::Initialize( void )
+{
+ m_eCurrentDriverState = eDriverState_Initialising;
+ m_clientUsageRefCnt++;
+
+ ClrErrorDescription();
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Initialize all of the modules we depend on
+ MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+ MI::ModuleInit< CMICmnStreamStdout >( IDS_MI_INIT_ERR_STREAMSTDOUT , bOk, errMsg );
+ MI::ModuleInit< CMICmnStreamStderr >( IDS_MI_INIT_ERR_STREAMSTDERR , bOk, errMsg );
+ MI::ModuleInit< CMICmnResources > ( IDS_MI_INIT_ERR_RESOURCES , bOk, errMsg );
+ MI::ModuleInit< CMICmnThreadMgrStd >( IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg );
+ MI::ModuleInit< CMICmnStreamStdin > ( IDS_MI_INIT_ERR_STREAMSTDIN , bOk, errMsg );
+ MI::ModuleInit< CMICmdMgr > ( IDS_MI_INIT_ERR_CMDMGR , bOk, errMsg );
+ bOk &= m_rLldbDebugger.SetDriver( *this );
+ MI::ModuleInit< CMICmnLLDBDebugger >( IDS_MI_INIT_ERR_LLDBDEBUGGER , bOk, errMsg );
+
+#if MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
+ CMIDriverMgr & rDrvMgr = CMIDriverMgr::Instance();
+ bOk = bOk && rDrvMgr.RegisterDriver( *g_driver, "LLDB driver" ); // Will be pass thru driver
+ if( bOk )
+ {
+ bOk = SetEnableFallThru( false ); // This is intentional at this time - yet to be fully implemented
+ bOk = bOk && SetDriverToFallThruTo( *g_driver );
+ CMIUtilString strOtherDrvErrMsg;
+ if( bOk && GetEnableFallThru() && !g_driver->MISetup( strOtherDrvErrMsg ) )
+ {
+ bOk = false;
+ errMsg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_FALLTHRUDRIVER ), strOtherDrvErrMsg.c_str() );
+ }
+ }
+#endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
+
+ m_bExitApp = false;
+
+ m_bInitialized = bOk;
+
+ if( !bOk )
+ {
+ const CMIUtilString msg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_DRIVER ), errMsg.c_str() );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+
+ m_eCurrentDriverState = eDriverState_RunningNotDebugging;
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Unbind detach or release resources used by *this driver.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ m_eCurrentDriverState = eDriverState_ShuttingDown;
+
+ ClrErrorDescription();
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Shutdown all of the modules we depend on
+ MI::ModuleShutdown< CMICmnLLDBDebugger >( IDS_MI_INIT_ERR_LLDBDEBUGGER , bOk, errMsg );
+ MI::ModuleShutdown< CMICmdMgr > ( IDS_MI_INIT_ERR_CMDMGR , bOk, errMsg );
+ MI::ModuleShutdown< CMICmnStreamStdin > ( IDS_MI_INIT_ERR_STREAMSTDIN , bOk, errMsg );
+ MI::ModuleShutdown< CMICmnThreadMgrStd >( IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg );
+ MI::ModuleShutdown< CMICmnResources > ( IDS_MI_INIT_ERR_RESOURCES , bOk, errMsg );
+ MI::ModuleShutdown< CMICmnStreamStderr >( IDS_MI_INIT_ERR_STREAMSTDERR , bOk, errMsg );
+ MI::ModuleShutdown< CMICmnStreamStdout >( IDS_MI_INIT_ERR_STREAMSTDOUT , bOk, errMsg );
+ MI::ModuleShutdown< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+
+ if( !bOk )
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_MI_SHUTDOWN_ERR ), errMsg.c_str() );
+ }
+
+ m_eCurrentDriverState = eDriverState_NotRunning;
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Work function. Client (the driver's user) is able to append their own message
+// in to the MI's Log trace file.
+// Type: Method.
+// Args: vMessage - (R) Client's text message.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::WriteMessageToLog( const CMIUtilString & vMessage )
+{
+ CMIUtilString msg;
+ msg = CMIUtilString::Format( MIRSRC( IDS_MI_CLIENT_MSG ), vMessage.c_str() );
+ return m_pLog->Write( msg, CMICmnLog::eLogVerbosity_ClientMsg );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDriverMgr calls *this driver initialize setup ready for use.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::DoInitialize( void )
+{
+ return CMIDriver::Instance().Initialize();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDriverMgr calls *this driver to unbind detach or release resources used by
+// *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::DoShutdown( void )
+{
+ return CMIDriver::Instance().Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the name for *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Driver name.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetName( void ) const
+{
+ const CMIUtilString & rName = GetAppNameLong();
+ const CMIUtilString & rVsn = GetVersionDescription();
+ static CMIUtilString strName = CMIUtilString::Format( "%s %s", rName.c_str(), rVsn.c_str() );
+
+ return strName;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve *this driver's last error condition.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString - Text description.
+// Throws: None.
+//--
+CMIUtilString CMIDriver::GetError( void ) const
+{
+ return GetErrorDescription();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Call *this driver to resize the console window.
+// Type: Overridden.
+// Args: vTermWidth - (R) New window column size.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+void CMIDriver::DoResizeWindow( const uint32_t vTermWidth )
+{
+ GetTheDebugger().SetTerminalWidth( vTermWidth );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Call *this driver to return it's debugger.
+// Type: Overridden.
+// Args: None.
+// Return: lldb::SBDebugger & - LLDB debugger object reference.
+// Throws: None.
+//--
+lldb::SBDebugger & CMIDriver::GetTheDebugger( void )
+{
+ return m_rLldbDebugger.GetTheDebugger();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Specify another driver *this driver can call should this driver not be able
+// to handle the client data input. DoFallThruToAnotherDriver() makes the call.
+// Type: Overridden.
+// Args: vrOtherDriver - (R) Reference to another driver object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::SetDriverToFallThruTo( const CMIDriverBase & vrOtherDriver )
+{
+ m_pDriverFallThru = const_cast< CMIDriverBase * >( &vrOtherDriver );
+
+ return m_pDriverFallThru->SetDriverParent( *this );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Proxy function CMIDriverMgr IDriver interface implementation. *this driver's
+// implementation called from here to match the existing function name of the
+// original LLDb driver class (the extra indirection is not necessarily required).
+// Check the arguments that were passed to this program to make sure they are
+// valid and to get their argument values (if any).
+// Type: Overridden.
+// Args: argc - (R) An integer that contains the count of arguments that follow in
+// argv. The argc parameter is always greater than or equal to 1.
+// argv - (R) An array of null-terminated strings representing command-line
+// arguments entered by the user of the program. By convention,
+// argv[0] is the command with which the program is invoked.
+// vpStdOut - (R) Pointer to a standard output stream.
+// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s),
+// version information only.
+// False = Continue to work, start debugger i.e. Command
+// interpreter.
+// Return: lldb::SBError - LLDB current error status.
+// Throws: None.
+//--
+lldb::SBError CMIDriver::DoParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting )
+{
+ return ParseArgs( argc, argv, vpStdOut, vwbExiting );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Check the arguments that were passed to this program to make sure they are
+// valid and to get their argument values (if any). The following are options
+// that are only handled by *this driver:
+// --executable
+// The application's options --interpreter and --executable in code act very similar.
+// The --executable is necessary to differentiate whither the MI Driver is being
+// using by a client i.e. Eclipse or from the command line. Eclipse issues the option
+// --interpreter and also passes additional arguments which can be interpreted as an
+// executable if called from the command line. Using --executable tells the MI
+// Driver is being called the command line and that the executable argument is indeed
+// a specified executable an so actions commands to set up the executable for a
+// debug session. Using --interpreter on the commnd line does not action additional
+// commands to initialise a debug session and so be able to launch the process.
+// Type: Overridden.
+// Args: argc - (R) An integer that contains the count of arguments that follow in
+// argv. The argc parameter is always greater than or equal to 1.
+// argv - (R) An array of null-terminated strings representing command-line
+// arguments entered by the user of the program. By convention,
+// argv[0] is the command with which the program is invoked.
+// vpStdOut - (R) Pointer to a standard output stream.
+// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s),
+// version information only.
+// False = Continue to work, start debugger i.e. Command
+// interpreter.
+// Return: lldb::SBError - LLDB current error status.
+// Throws: None.
+//--
+lldb::SBError CMIDriver::ParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting )
+{
+ lldb::SBError errStatus;
+ const bool bHaveArgs( argc >= 2 );
+
+ // *** Add any args handled here to GetHelpOnCmdLineArgOptions() ***
+
+ // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING
+ // Look for the command line options
+ bool bHaveExecutableFileNamePath = false;
+ bool bHaveExecutableLongOption = false;
+
+ if( bHaveArgs )
+ {
+ // Search right to left to look for the executable
+ for( MIint i = argc - 1; i > 0; i-- )
+ {
+ const CMIUtilString strArg( argv[ i ] );
+ const CMICmdArgValFile argFile;
+ if( argFile.IsFilePath( strArg ) ||
+ CMICmdArgValString( true, false, true ).IsStringArg( strArg ))
+ {
+ bHaveExecutableFileNamePath = true;
+ m_strCmdLineArgExecuteableFileNamePath = argFile.GetFileNamePath( strArg );
+ m_bHaveExecutableFileNamePathOnCmdLine = true;
+ }
+ // This argument is also check for in CMIDriverMgr::ParseArgs()
+ if( 0 == strArg.compare( "--executable" ) ) // Used to specify that there is executable argument also on the command line
+ { // See fn description.
+ bHaveExecutableLongOption = true;
+ }
+ }
+ }
+
+ if( bHaveExecutableFileNamePath && bHaveExecutableLongOption )
+ {
+ // CODETAG_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION
+#if MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION
+ SetDriverDebuggingArgExecutable();
+#else
+ vwbExiting = true;
+ errStatus.SetErrorString( MIRSRC( IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL ) );
+#endif // MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION
+ }
+
+ return errStatus;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: A client can ask if *this driver is GDB/MI compatible.
+// Type: Overridden.
+// Args: None.
+// Return: True - GBD/MI compatible LLDB front end.
+// False - Not GBD/MI compatible LLDB front end.
+// Throws: None.
+//--
+bool CMIDriver::GetDriverIsGDBMICompatibleDriver( void ) const
+{
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Callback function for monitoring stream stdin object. Part of the visitor
+// pattern.
+// This function is called by the CMICmnStreamStdin::CThreadStdin
+// "stdin monitor" thread (ID).
+// Type: Overridden.
+// Args: vStdInBuffer - (R) Copy of the current stdin line data.
+// vrbYesExit - (RW) True = yes exit stdin monitoring, false = continue monitor.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::ReadLine( const CMIUtilString & vStdInBuffer, bool & vrwbYesExit )
+{
+ // For debugging. Update prompt show stdin is working
+ //printf( "%s\n", vStdInBuffer.c_str() );
+ //fflush( stdout );
+
+ // Special case look for the quit command here so stop monitoring stdin stream
+ // So we do not go back to fgetc() and wait and hang thread on exit
+ if( vStdInBuffer == "quit" )
+ vrwbYesExit = true;
+
+ // 1. Put new line in the queue container by stdin monitor thread
+ // 2. Then *this driver calls ReadStdinLineQueue() when ready to read the queue in its
+ // own thread
+ const bool bOk = QueueMICommand( vStdInBuffer );
+
+ // Check to see if the *this driver is shutting down (exit application)
+ if( !vrwbYesExit )
+ vrwbYesExit = m_bDriverIsExiting;
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Start worker threads for the driver.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::StartWorkerThreads( void )
+{
+ bool bOk = MIstatus::success;
+
+ // Grab the thread manager
+ CMICmnThreadMgrStd & rThreadMgr = CMICmnThreadMgrStd::Instance();
+
+ // Start the stdin thread
+ bOk &= m_rStdin.SetVisitor( *this );
+ if( bOk && !rThreadMgr.ThreadStart< CMICmnStreamStdin >( m_rStdin ))
+ {
+ const CMIUtilString errMsg = CMIUtilString::Format( MIRSRC( IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ), CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str() );
+ SetErrorDescriptionn( errMsg );
+ return MIstatus::failure;
+ }
+
+ // Start the event polling thread
+ if( bOk && !rThreadMgr.ThreadStart< CMICmnLLDBDebugger >( m_rLldbDebugger ) )
+ {
+ const CMIUtilString errMsg = CMIUtilString::Format( MIRSRC( IDS_THREADMGR_ERR_THREAD_FAIL_CREATE ), CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str() );
+ SetErrorDescriptionn( errMsg );
+ return MIstatus::failure;
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Stop worker threads for the driver.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::StopWorkerThreads( void )
+{
+ CMICmnThreadMgrStd & rThreadMgr = CMICmnThreadMgrStd::Instance();
+ return rThreadMgr.ThreadAllTerminate();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Call this function puts *this driver to work.
+// This function is used by the application's main thread.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::DoMainLoop( void )
+{
+ if( !InitClientIDEToMIDriver() ) // Init Eclipse IDE
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_MI_INIT_ERR_CLIENT_USING_DRIVER ) );
+ return MIstatus::failure;
+ }
+
+ if( !StartWorkerThreads() )
+ return MIstatus::failure;
+
+ // App is not quitting currently
+ m_bExitApp = false;
+
+ // CODETAG_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION
+#if MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION
+ if( HaveExecutableFileNamePathOnCmdLine() )
+ {
+ if( !LocalDebugSessionStartupInjectCommands() )
+ {
+ SetErrorDescription( MIRSRC( IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION ) );
+ return MIstatus::failure;
+ }
+ }
+#endif // MICONFIG_ENABLE_MI_DRIVER_MI_MODE_CMDLINE_ARG_EXECUTABLE_DEBUG_SESSION
+
+ // While the app is active
+ while( !m_bExitApp )
+ {
+ // Poll stdin queue and dispatch
+ if( !ReadStdinLineQueue() )
+ {
+ // Something went wrong
+ break;
+ }
+ }
+
+ // Signal that the application is shutting down
+ DoAppQuit();
+
+ // Close and wait for the workers to stop
+ StopWorkerThreads();
+
+ // Ensure that a new line is sent as the last act of the dying driver
+ m_rStdOut.WriteMIResponse( "\n", false );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: *this driver sits and waits for input to the stdin line queue shared by *this
+// driver and the stdin monitor thread, it queues, *this reads, interprets and
+// reacts.
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::ReadStdinLineQueue( void )
+{
+ // True when queue contains input
+ bool bHaveInput = false;
+
+ // Stores the current input line
+ CMIUtilString lineText;
+ {
+ // Lock while we access the queue
+ CMIUtilThreadLock lock( m_threadMutex );
+ if( !m_queueStdinLine.empty() )
+ {
+ lineText = m_queueStdinLine.front();
+ m_queueStdinLine.pop();
+ bHaveInput = !lineText.empty();
+ }
+ }
+
+ // Process while we have input
+ if( bHaveInput )
+ {
+ if( lineText == "quit" )
+ {
+ // We want to be exiting when receiving a quit command
+ m_bExitApp = true;
+ return MIstatus::success;
+ }
+
+ // Process the command
+ const bool bOk = InterpretCommand( lineText );
+
+ // Draw prompt if desired
+ if( bOk && m_rStdin.GetEnablePrompt() )
+ m_rStdOut.WriteMIResponse( m_rStdin.GetPrompt() );
+
+ // Input has been processed
+ bHaveInput = false;
+ }
+ else
+ {
+ // Give resources back to the OS
+ const std::chrono::milliseconds time( 1 );
+ std::this_thread::sleep_for( time );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set things in motion, set state etc that brings *this driver (and the
+// application) to a tidy shutdown.
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::DoAppQuit( void )
+{
+ bool bYesQuit = true;
+
+ // Shutdown stuff, ready app for exit
+ {
+ CMIUtilThreadLock lock( m_threadMutex );
+ m_bDriverIsExiting = true;
+ }
+
+ return bYesQuit;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: *this driver passes text commands to a fall through driver is it does not
+// understand them (the LLDB driver).
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: vTextLine - (R) Text data representing a possible command.
+// vwbCmdYesValid - (W) True = Command valid, false = command not handled.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::InterpretCommandFallThruDriver( const CMIUtilString & vTextLine, bool & vwbCmdYesValid )
+{
+ MIunused( vTextLine );
+ MIunused( vwbCmdYesValid );
+
+ // ToDo: Implement when less urgent work to be done or decide remove as not required
+ //bool bOk = MIstatus::success;
+ //bool bCmdNotUnderstood = true;
+ //if( bCmdNotUnderstood && GetEnableFallThru() )
+ //{
+ // CMIUtilString errMsg;
+ // bOk = DoFallThruToAnotherDriver( vStdInBuffer, errMsg );
+ // if( !bOk )
+ // {
+ // errMsg = errMsg.StripCREndOfLine();
+ // errMsg = errMsg.StripCRAll();
+ // const CMIDriverBase * pOtherDriver = GetDriverToFallThruTo();
+ // const MIchar * pName = pOtherDriver->GetDriverName().c_str();
+ // const MIchar * pId = pOtherDriver->GetDriverId().c_str();
+ // const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR ), pName, pId, errMsg.c_str() ) );
+ // m_pLog->WriteMsg( msg );
+ // }
+ //}
+ //
+ //vwbCmdYesValid = bOk;
+ //CMIUtilString strNot;
+ //if( vwbCmdYesValid)
+ // strNot = CMIUtilString::Format( "%s ", MIRSRC( IDS_WORD_NOT ) );
+ //const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_FALLTHRU_DRIVER_CMD_RECEIVED ), vTextLine.c_str(), strNot.c_str() ) );
+ //m_pLog->WriteLog( msg );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the name for *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Driver name.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetDriverName( void ) const
+{
+ return GetName();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the unique ID for *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetDriverId( void ) const
+{
+ return GetId();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: This function allows *this driver to call on another driver to perform work
+// should this driver not be able to handle the client data input.
+// SetDriverToFallThruTo() specifies the fall through to driver.
+// Check the error message if the function returns a failure.
+// Type: Overridden.
+// Args: vCmd - (R) Command instruction to interpret.
+// vwErrMsg - (W) Error description on command failing.
+// Return: MIstatus::success - Command succeeded.
+// MIstatus::failure - Command failed.
+// Throws: None.
+//--
+bool CMIDriver::DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg )
+{
+ bool bOk = MIstatus::success;
+
+ CMIDriverBase * pOtherDriver = GetDriverToFallThruTo();
+ if( pOtherDriver == nullptr )
+ return bOk;
+
+ return pOtherDriver->DoFallThruToAnotherDriver( vCmd, vwErrMsg );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: *this driver provides a file stream to other drivers on which *this driver
+// write's out to and they read as expected input. *this driver is passing
+// through commands to the (child) pass through assigned driver.
+// Type: Overrdidden.
+// Args: None.
+// Return: FILE * - Pointer to stream.
+// Throws: None.
+//--
+FILE * CMIDriver::GetStdin( void ) const
+{
+ // Note this fn is called on CMIDriverMgr register driver so stream has to be
+ // available before *this driver has been initialized! Flaw?
+
+ // This very likely to change later to a stream that the pass thru driver
+ // will read and we write to give it 'input'
+ return stdin;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: *this driver provides a file stream to other pass through assigned drivers
+// so they know what to write to.
+// Type: Overidden.
+// Args: None.
+// Return: FILE * - Pointer to stream.
+// Throws: None.
+//--
+FILE * CMIDriver::GetStdout( void ) const
+{
+ // Note this fn is called on CMIDriverMgr register driver so stream has to be
+ // available before *this driver has been initialized! Flaw?
+
+ // Do not want to pass through driver to write to stdout
+ return NULL;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: *this driver provides a error file stream to other pass through assigned drivers
+// so they know what to write to.
+// Type: Overidden.
+// Args: None.
+// Return: FILE * - Pointer to stream.
+// Throws: None.
+//--
+FILE * CMIDriver::GetStderr( void ) const
+{
+ // Note this fn is called on CMIDriverMgr register driver so stream has to be
+ // available before *this driver has been initialized! Flaw?
+
+ // This very likely to change later to a stream that the pass thru driver
+ // will write to and *this driver reads from to pass on the CMICmnLog object
+ return stderr;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set a unique ID for *this driver. It cannot be empty.
+// Type: Overridden.
+// Args: vId - (R) Text description.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::SetId( const CMIUtilString & vId )
+{
+ if( vId.empty() )
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_DRIVER_ERR_ID_INVALID ), GetName().c_str(), vId.c_str() );
+ return MIstatus::failure;
+ }
+
+ m_strDriverId = vId;
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the unique ID for *this driver.
+// Type: Overridden.
+// Args: None.
+// Return: CMIUtilString & - Text description.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetId( void ) const
+{
+ return m_strDriverId;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Inject a command into the command processing system to be interpreted as a
+// command read from stdin. The text representing the command is also written
+// out to stdout as the command did not come from via stdin.
+// Type: Method.
+// Args: vMICmd - (R) Text data representing a possible command.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::InjectMICommand( const CMIUtilString & vMICmd )
+{
+ const bool bOk = m_rStdOut.WriteMIResponse( vMICmd );
+
+ return bOk && QueueMICommand( vMICmd );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add a new command candidate to the command queue to be processed by the
+// command system.
+// Type: Method.
+// Args: vMICmd - (R) Text data representing a possible command.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::QueueMICommand( const CMIUtilString & vMICmd )
+{
+ CMIUtilThreadLock lock( m_threadMutex );
+ m_queueStdinLine.push( vMICmd );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Interpret the text data and match against current commands to see if there
+// is a match. If a match then the command is issued and actioned on. The
+// text data if not understood by *this driver is past on to the Fall Thru
+// driver.
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: vTextLine - (R) Text data representing a possible command.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::InterpretCommand( const CMIUtilString & vTextLine )
+{
+ bool bCmdYesValid = false;
+ bool bOk = InterpretCommandThisDriver( vTextLine, bCmdYesValid );
+ if( bOk && !bCmdYesValid )
+ bOk = InterpretCommandFallThruDriver( vTextLine, bCmdYesValid );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Interpret the text data and match against current commands to see if there
+// is a match. If a match then the command is issued and actioned on. If a
+// command cannot be found to match then vwbCmdYesValid is set to false and
+// nothing else is done here.
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: vTextLine - (R) Text data representing a possible command.
+// vwbCmdYesValid - (W) True = Command invalid, false = command acted on.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::InterpretCommandThisDriver( const CMIUtilString & vTextLine, bool & vwbCmdYesValid )
+{
+ vwbCmdYesValid = false;
+
+ bool bCmdNotInCmdFactor = false;
+ SMICmdData cmdData;
+ CMICmdMgr & rCmdMgr = CMICmdMgr::Instance();
+ if( !rCmdMgr.CmdInterpret( vTextLine, vwbCmdYesValid, bCmdNotInCmdFactor, cmdData ) )
+ return MIstatus::failure;
+
+ if( vwbCmdYesValid )
+ {
+ // For debugging only
+ //m_pLog->WriteLog( cmdData.strMiCmdAll.c_str() );
+
+ return ExecuteCommand( cmdData );
+ }
+
+ // Check for escape character, may be cursor control characters
+ // This code is not necessary for application operation, just want to keep tabs on what
+ // is been given to the driver to try and intepret.
+ if( vTextLine.at( 0 ) == 27 )
+ {
+ CMIUtilString logInput( MIRSRC( IDS_STDIN_INPUT_CTRL_CHARS ) );
+ for( MIuint i = 0; i < vTextLine.length(); i++ )
+ {
+ logInput += CMIUtilString::Format( "%d ", vTextLine.at( i ) );
+ }
+ m_pLog->WriteLog( logInput );
+ return MIstatus::success;
+ }
+
+ // Write to the Log that a 'command' was not valid.
+ // Report back to the MI client via MI result record.
+ CMIUtilString strNotInCmdFactory;
+ if( bCmdNotInCmdFactor )
+ strNotInCmdFactory = CMIUtilString::Format( MIRSRC( IDS_DRIVER_CMD_NOT_IN_FACTORY ), cmdData.strMiCmd.c_str() );
+ const CMIUtilString strNot( CMIUtilString::Format( "%s ", MIRSRC( IDS_WORD_NOT ) ) );
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_CMD_RECEIVED ), vTextLine.c_str(), strNot.c_str(), strNotInCmdFactory.c_str() ) );
+ const CMICmnMIValueConst vconst = CMICmnMIValueConst( msg );
+ const CMICmnMIValueResult valueResult( "msg", vconst );
+ const CMICmnMIResultRecord miResultRecord( cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, valueResult );
+ m_rStdOut.WriteMIResponse( miResultRecord.GetString() );
+
+ // Proceed to wait for or execute next command
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Having previously had the potential command validated and found valid now
+// get the command executed.
+// This function is used by the application's main thread.
+// Type: Method.
+// Args: vCmdData - (RW) Command meta data.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriver::ExecuteCommand( const SMICmdData & vCmdData )
+{
+ CMICmdMgr & rCmdMgr = CMICmdMgr::Instance();
+ return rCmdMgr.CmdExecute( vCmdData );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the MI Driver's exit application flag. The application checks this flag
+// after every stdin line is read so the exit may not be instantaneous.
+// If vbForceExit is false the MI Driver queries its state and determines if is
+// should exit or continue operating depending on that running state.
+// This is related to the running state of the MI driver.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMIDriver::SetExitApplicationFlag( const bool vbForceExit )
+{
+ if( vbForceExit )
+ {
+ CMIUtilThreadLock lock( m_threadMutex );
+ m_bExitApp = true;
+ return;
+ }
+
+ // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+ // Did we receive a SIGINT from the client during a running debug program, if
+ // so then SIGINT is not to be taken as meaning kill the MI driver application
+ // but halt the inferior program being debugged instead
+ if( m_eCurrentDriverState == eDriverState_RunningDebugging )
+ {
+ InjectMICommand( "-exec-interrupt" );
+ return;
+ }
+
+ m_bExitApp = true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the MI Driver's exit exit application flag.
+// This is related to the running state of the MI driver.
+// Type: Method.
+// Args: None.
+// Return: bool - True = MI Driver is shutting down, false = MI driver is running.
+// Throws: None.
+//--
+bool CMIDriver::GetExitApplicationFlag( void ) const
+{
+ return m_bExitApp;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the current running state of the MI Driver.
+// Type: Method.
+// Args: None.
+// Return: DriverState_e - The current running state of the application.
+// Throws: None.
+//--
+CMIDriver::DriverState_e CMIDriver::GetCurrentDriverState( void ) const
+{
+ return m_eCurrentDriverState;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the current running state of the MI Driver to running and currently not in
+// a debug session.
+// Type: Method.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Return: DriverState_e - The current running state of the application.
+// Throws: None.
+//--
+bool CMIDriver::SetDriverStateRunningNotDebugging( void )
+{
+ // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+
+ if( m_eCurrentDriverState == eDriverState_RunningNotDebugging )
+ return MIstatus::success;
+
+ // Driver cannot be in the following states to set eDriverState_RunningNotDebugging
+ switch( m_eCurrentDriverState )
+ {
+ case eDriverState_NotRunning:
+ case eDriverState_Initialising:
+ case eDriverState_ShuttingDown:
+ {
+ SetErrorDescription( MIRSRC( IDS_DRIVER_ERR_DRIVER_STATE_ERROR ) );
+ return MIstatus::failure;
+ }
+ case eDriverState_RunningDebugging:
+ case eDriverState_RunningNotDebugging:
+ break;
+ case eDriverState_count:
+ default:
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CODE_ERR_INVALID_ENUMERATION_VALUE ), "SetDriverStateRunningNotDebugging()" ) );
+ return MIstatus::failure;
+ }
+
+ // Driver must be in this state to set eDriverState_RunningNotDebugging
+ if( m_eCurrentDriverState != eDriverState_RunningDebugging )
+ {
+ SetErrorDescription( MIRSRC( IDS_DRIVER_ERR_DRIVER_STATE_ERROR ) );
+ return MIstatus::failure;
+ }
+
+ m_eCurrentDriverState = eDriverState_RunningNotDebugging;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the current running state of the MI Driver to running and currently not in
+// a debug session. The driver's state must in the state running and in a
+// debug session to set this new state.
+// Type: Method.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Return: DriverState_e - The current running state of the application.
+// Throws: None.
+//--
+bool CMIDriver::SetDriverStateRunningDebugging( void )
+{
+ // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+
+ if( m_eCurrentDriverState == eDriverState_RunningDebugging )
+ return MIstatus::success;
+
+ // Driver cannot be in the following states to set eDriverState_RunningDebugging
+ switch( m_eCurrentDriverState )
+ {
+ case eDriverState_NotRunning:
+ case eDriverState_Initialising:
+ case eDriverState_ShuttingDown:
+ {
+ SetErrorDescription( MIRSRC( IDS_DRIVER_ERR_DRIVER_STATE_ERROR ) );
+ return MIstatus::failure;
+ }
+ case eDriverState_RunningDebugging:
+ case eDriverState_RunningNotDebugging:
+ break;
+ case eDriverState_count:
+ default:
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CODE_ERR_INVALID_ENUMERATION_VALUE ), "SetDriverStateRunningDebugging()" ) );
+ return MIstatus::failure;
+ }
+
+ // Driver must be in this state to set eDriverState_RunningDebugging
+ if( m_eCurrentDriverState != eDriverState_RunningNotDebugging )
+ {
+ SetErrorDescription( MIRSRC( IDS_DRIVER_ERR_DRIVER_STATE_ERROR ) );
+ return MIstatus::failure;
+ }
+
+ m_eCurrentDriverState = eDriverState_RunningDebugging;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Prepare the client IDE so it will start working/communicating with *this MI
+// driver.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMIDriver::InitClientIDEToMIDriver( void ) const
+{
+ // Put other IDE init functions here
+ return InitClientIDEEclipse();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The IDE Eclipse when debugging locally expects "(gdb)\n" character
+// sequence otherwise it refuses to communicate and times out. This should be
+// sent to Eclipse before anything else.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMIDriver::InitClientIDEEclipse( void ) const
+{
+ std::cout << "(gdb)" << std::endl;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Ask *this driver whether it found an executable in the MI Driver's list of
+// arguments which to open and debug. If so instigate commands to set up a debug
+// session for that executable.
+// Type: Method.
+// Args: None.
+// Return: bool - True = True = Yes executable given as one of the parameters to the MI
+// Driver.
+// False = not found.
+// Throws: None.
+//--
+bool CMIDriver::HaveExecutableFileNamePathOnCmdLine( void ) const
+{
+ return m_bHaveExecutableFileNamePathOnCmdLine;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve from *this driver executable file name path to start a debug session
+// with (if present see HaveExecutableFileNamePathOnCmdLine()).
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - Executeable file name path or empty string.
+// Throws: None.
+//--
+const CMIUtilString & CMIDriver::GetExecutableFileNamePathOnCmdLine( void ) const
+{
+ return m_strCmdLineArgExecuteableFileNamePath;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Execute commands (by injecting them into the stdin line queue container) and
+// other code to set up the MI Driver such that is can take the executable
+// argument passed on the command and create a debug session for it.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMIDriver::LocalDebugSessionStartupInjectCommands( void )
+{
+ const CMIUtilString strCmd( CMIUtilString::Format( "-file-exec-and-symbols %s", m_strCmdLineArgExecuteableFileNamePath.c_str() ) );
+
+ return InjectMICommand( strCmd );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the MI Driver into "its debugging an executable passed as an argument"
+// mode as against running via a client like Eclipse.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMIDriver::SetDriverDebuggingArgExecutable( void )
+{
+ m_bDriverDebuggingArgExecutable = true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the MI Driver state indicating if it is operating in "its debugging
+// an executable passed as an argument" mode as against running via a client
+// like Eclipse.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+bool CMIDriver::IsDriverDebuggingArgExecutable( void ) const
+{
+ return m_bDriverDebuggingArgExecutable;
+}
+
diff --git a/tools/lldb-mi/MIDriver.h b/tools/lldb-mi/MIDriver.h
new file mode 100644
index 000000000000..c565e825096e
--- /dev/null
+++ b/tools/lldb-mi/MIDriver.h
@@ -0,0 +1,182 @@
+//===-- MIDriver.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIDriver.h
+//
+// Overview: CMIDriver interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers
+#include <queue>
+
+// In-house headers:
+#include "MICmnConfig.h"
+#include "MICmnBase.h"
+#include "MIDriverBase.h"
+#include "MIDriverMgr.h"
+#include "MICmnStreamStdin.h"
+#include "MICmdData.h"
+#include "MIUtilSingletonBase.h"
+
+// Declarations:
+class CMICmnLLDBDebugger;
+class CMICmnStreamStdout;
+
+//++ ============================================================================
+// Details: MI driver implementation class. A singleton class derived from
+// LLDB SBBroadcaster class. Register the instance of *this class with
+// the CMIDriverMgr. The CMIDriverMgr sets the driver(s) of to start
+// work depending on the one selected to work. A driver can if not able
+// to handle an instruction or 'command' can pass that command onto
+// another driver object registered with the Driver Manager.
+// Gotchas: None.
+// Authors: Illya Rudkin 29/01/2014.
+// Changes: None.
+//--
+class CMIDriver
+: public CMICmnBase
+, public CMIDriverMgr::IDriver
+, public CMIDriverBase
+, public CMICmnStreamStdin::IStreamStdin
+, public MI::ISingleton< CMIDriver >
+{
+ friend class MI::ISingleton< CMIDriver >;
+
+// Enumerations:
+public:
+ //++ ----------------------------------------------------------------------
+ // Details: The MI Driver has a running state which is used to help determin
+ // which specific action(s) it should take or not allow.
+ // The driver when operational and not shutting down alternates
+ // between eDriverState_RunningNotDebugging and
+ // eDriverState_RunningDebugging. eDriverState_RunningNotDebugging
+ // is normally set when a breakpoint is hit or halted.
+ // eDriverState_RunningDebugging is normally set when "exec-continue"
+ // or "exec-run" is issued.
+ //--
+ enum DriverState_e
+ {
+ eDriverState_NotRunning = 0, // The MI Driver is not operating
+ eDriverState_Initialising, // The MI Driver is setting itself up
+ eDriverState_RunningNotDebugging, // The MI Driver is operational acting on any MI commands sent to it
+ eDriverState_RunningDebugging, // The MI Driver is currently overseeing an inferior program that is running
+ eDriverState_ShuttingDown, // The MI Driver is tearing down resources and about exit
+ eDriverState_count // Always last
+ };
+
+// Methods:
+public:
+ // MI system
+ bool Initialize( void );
+ bool Shutdown( void );
+
+ // MI state
+ bool GetExitApplicationFlag( void ) const;
+ DriverState_e GetCurrentDriverState( void ) const;
+ bool SetDriverStateRunningNotDebugging( void );
+ bool SetDriverStateRunningDebugging( void );
+ void SetDriverDebuggingArgExecutable( void );
+ bool IsDriverDebuggingArgExecutable( void ) const;
+
+ // MI information about itself
+ const CMIUtilString & GetAppNameShort( void ) const;
+ const CMIUtilString & GetAppNameLong( void ) const;
+ const CMIUtilString & GetVersionDescription( void ) const;
+
+ // MI do work
+ bool WriteMessageToLog( const CMIUtilString & vMessage );
+ bool SetEnableFallThru( const bool vbYes );
+ bool GetEnableFallThru( void ) const;
+ bool InjectMICommand( const CMIUtilString & vMICmd );
+ bool HaveExecutableFileNamePathOnCmdLine( void ) const;
+ const CMIUtilString & GetExecutableFileNamePathOnCmdLine( void ) const;
+
+// Overridden:
+public:
+ // From CMIDriverMgr::IDriver
+ virtual bool DoInitialize( void );
+ virtual bool DoShutdown( void );
+ virtual bool DoMainLoop( void );
+ virtual void DoResizeWindow( const uint32_t vWindowSizeWsCol );
+ virtual lldb::SBError DoParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting );
+ virtual CMIUtilString GetError( void ) const;
+ virtual const CMIUtilString & GetName( void ) const;
+ virtual lldb::SBDebugger & GetTheDebugger( void );
+ virtual bool GetDriverIsGDBMICompatibleDriver( void ) const;
+ virtual bool SetId( const CMIUtilString & vId );
+ virtual const CMIUtilString & GetId( void ) const;
+ // From CMIDriverBase
+ virtual void SetExitApplicationFlag( const bool vbForceExit );
+ virtual bool DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg );
+ virtual bool SetDriverToFallThruTo( const CMIDriverBase & vrOtherDriver );
+ virtual FILE * GetStdin( void ) const;
+ virtual FILE * GetStdout( void ) const;
+ virtual FILE * GetStderr( void ) const;
+ virtual const CMIUtilString & GetDriverName( void ) const;
+ virtual const CMIUtilString & GetDriverId( void ) const;
+ // From CMICmnStreamStdin
+ virtual bool ReadLine( const CMIUtilString & vStdInBuffer, bool & vrbYesExit );
+
+// Typedefs:
+private:
+ typedef std::queue< CMIUtilString > QueueStdinLine_t;
+
+// Methods:
+private:
+ /* ctor */ CMIDriver( void );
+ /* ctor */ CMIDriver( const CMIDriver & );
+ void operator=( const CMIDriver & );
+
+ lldb::SBError ParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting );
+ bool ReadStdinLineQueue( void );
+ bool DoAppQuit( void );
+ bool InterpretCommand( const CMIUtilString & vTextLine );
+ bool InterpretCommandThisDriver( const CMIUtilString & vTextLine, bool & vwbCmdYesValid );
+ bool InterpretCommandFallThruDriver( const CMIUtilString & vTextLine, bool & vwbCmdYesValid );
+ bool ExecuteCommand( const SMICmdData & vCmdData );
+ bool StartWorkerThreads( void );
+ bool StopWorkerThreads( void );
+ bool InitClientIDEToMIDriver( void ) const;
+ bool InitClientIDEEclipse( void ) const;
+ bool QueueMICommand( const CMIUtilString & vMICmd );
+ bool LocalDebugSessionStartupInjectCommands( void );
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMIDriver( void );
+
+// Attributes:
+private:
+ static const CMIUtilString ms_constAppNameShort;
+ static const CMIUtilString ms_constAppNameLong;
+ static const CMIUtilString ms_constMIVersion;
+ //
+ bool m_bFallThruToOtherDriverEnabled; // True = yes fall through, false = do not pass on command
+ CMIUtilThreadMutex m_threadMutex;
+ QueueStdinLine_t m_queueStdinLine; // Producer = stdin monitor, consumer = *this driver
+ bool m_bDriverIsExiting; // True = yes, driver told to quit, false = continue working
+ void * m_handleMainThread; // *this driver is run by the main thread
+ CMICmnStreamStdin & m_rStdin;
+ CMICmnLLDBDebugger & m_rLldbDebugger;
+ CMICmnStreamStdout & m_rStdOut;
+ DriverState_e m_eCurrentDriverState;
+ bool m_bHaveExecutableFileNamePathOnCmdLine; // True = Yes executable given as one of the parameters to the MI Driver, false = not found
+ CMIUtilString m_strCmdLineArgExecuteableFileNamePath;
+ bool m_bDriverDebuggingArgExecutable; // True = The MI Driver (MI mode) is debugging executable passed as argument, false = running via a client i.e Eclipse
+};
diff --git a/tools/lldb-mi/MIDriverBase.cpp b/tools/lldb-mi/MIDriverBase.cpp
new file mode 100644
index 000000000000..353f5c32a164
--- /dev/null
+++ b/tools/lldb-mi/MIDriverBase.cpp
@@ -0,0 +1,195 @@
+//===-- MIDriverBase.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIDriverBase.cpp
+//
+// Overview: CMIDriverBase implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers:
+#include <lldb/API/SBEvent.h>
+#include <lldb/API/SBBroadcaster.h>
+
+// In-house headers:
+#include "MIDriverBase.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIDriverBase constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIDriverBase::CMIDriverBase( void )
+: m_pDriverFallThru( nullptr )
+, m_pDriverParent( nullptr )
+, m_bExitApp( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIDriverBase destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIDriverBase::~CMIDriverBase( void )
+{
+ m_pDriverFallThru = NULL;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: This function allows *this driver to call on another driver to perform work
+// should this driver not be able to handle the client data input.
+// Type: Overrideable.
+// Check the error message if the function returns a failure.
+// Type: Overridden.
+// Args: vCmd - (R) Command instruction to interpret.
+// vwErrMsg - (W) Error description on command failing.
+// Return: MIstatus::success - Command succeeded.
+// MIstatus::failure - Command failed.
+// Throws: None.
+//--
+bool CMIDriverBase::DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg )
+{
+ // Do nothing - override and implement. Use m_pDriverFallThru.
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: This function allows *this driver to call on another driver to perform work
+// should this driver not be able to handle the client data input.
+// Type: Overrideable.
+// Args: vrOtherDriver - (R) Reference to another driver object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverBase::SetDriverToFallThruTo( const CMIDriverBase & vrOtherDriver )
+{
+ MIunused( vrOtherDriver );
+
+ // Do nothing - override and implement. Set m_pDriverFallThru.
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: This function allows *this driver to call functionality on the parent driver
+// ask for information for example.
+// Type: Overrideable.
+// Args: vrOtherDriver - (R) Reference to another driver object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverBase::SetDriverParent( const CMIDriverBase & vrOtherDriver )
+{
+ MIunused( vrOtherDriver );
+
+ // Do nothing - override and implement. Set m_pDriverParent.
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the parent driver to *this driver if one assigned. If assigned *this
+// is the pass through driver that the parent driver passes work to.
+// Type: Method.
+// Args: None.
+// Return: CMIDriverBase * - Pointer to a driver object.
+// - NULL = there is not parent to *this driver.
+// Throws: None.
+//--
+CMIDriverBase * CMIDriverBase::GetDriversParent( void ) const
+{
+ return m_pDriverParent;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the pointer to the other fall through driver *this driver is using
+// (or not using).
+// Type: Method.
+// Args: None.
+// Return: CMIDriverBase * - Pointer to other driver.
+// - NULL if no driver set.
+// Throws: None.
+//--
+CMIDriverBase * CMIDriverBase::GetDriverToFallThruTo( void ) const
+{
+ return m_pDriverFallThru;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: *this driver provides a file stream to other drivers on which *this driver
+// write's out to and they read as expected input. *this driver is passing
+// through commands to the (child) pass through assigned driver.
+// Type: Overrideable.
+// Args: None.
+// Return: FILE * - Pointer to stream.
+// Throws: None.
+//--
+FILE * CMIDriverBase::GetStdin( void ) const
+{
+ // Do nothing - override and implement
+ return nullptr;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: *this driver provides a file stream to other pass through assigned drivers
+// so they know what to write to.
+// Type: Overrideable.
+// Args: None.
+// Return: FILE * - Pointer to stream.
+// Throws: None.
+//--
+FILE * CMIDriverBase::GetStdout( void ) const
+{
+ // Do nothing - override and implement
+ return nullptr;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: *this driver provides a error file stream to other pass through assigned drivers
+// so they know what to write to.
+// Type: Overrideable.
+// Args: None.
+// Return: FILE * - Pointer to stream.
+// Throws: None.
+//--
+FILE * CMIDriverBase::GetStderr( void ) const
+{
+ // Do nothing - override and implement
+ return nullptr;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the MI Driver's exit application flag. The application checks this flag
+// after every stdin line is read so the exit may not be instantious.
+// If vbForceExit is false the MI Driver queries its state and determines if is
+// should exit or continue operating depending on that running state.
+// Type: Overrideable.
+// Args: vbForceExit - (R) True = Do not query, set state to exit, false = query if can/should exit right now.
+// Return: None.
+// Throws: None.
+//--
+void CMIDriverBase::SetExitApplicationFlag( const bool vbForceExit )
+{
+ MIunused( vbForceExit );
+
+ // Do nothing - override and implement
+} \ No newline at end of file
diff --git a/tools/lldb-mi/MIDriverBase.h b/tools/lldb-mi/MIDriverBase.h
new file mode 100644
index 000000000000..ed6b930cfd83
--- /dev/null
+++ b/tools/lldb-mi/MIDriverBase.h
@@ -0,0 +1,78 @@
+//===-- MIDriverBase.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIDriverBase.h
+//
+// Overview: CMIDriverBase interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <lldb/API/SBDebugger.h>
+#include <lldb/API/SBBroadcaster.h>
+
+// In-house headers:
+#include "MIUtilString.h"
+
+// Declarations:
+namespace lldb { class SBBroadcaster; }
+
+//++ ============================================================================
+// Details: MI driver base implementation class. This class has been created so
+// not have to edit the lldb::SBBroadcaster class code. Functionality
+// and attributes need to be common to the LLDB Driver class and the
+// MI Driver class (derived from lldb::SBBroadcaster) so they can call
+// upon each other for functionality fall through and allow the
+// CDriverMgr to manage either (any) driver to be operated on.
+// Each driver instance (the CMIDriver, LLDB::Driver) has its own
+// LLDB::SBDebugger object.
+// Gotchas: None.
+// Authors: Illya Rudkin 30/01/2014.
+// Changes: None.
+//--
+class CMIDriverBase
+{
+// Methods:
+public:
+ /* ctor */ CMIDriverBase( void );
+
+ CMIDriverBase * GetDriverToFallThruTo( void ) const;
+ CMIDriverBase * GetDriversParent( void ) const;
+
+// Overrideable:
+public:
+ /* dtor */ virtual ~CMIDriverBase( void );
+
+ virtual bool DoFallThruToAnotherDriver( const CMIUtilString & vCmd, CMIUtilString & vwErrMsg );
+ virtual bool SetDriverToFallThruTo( const CMIDriverBase & vrOtherDriver );
+ virtual bool SetDriverParent( const CMIDriverBase & vrOtherDriver );
+ virtual const CMIUtilString & GetDriverName( void ) const = 0;
+ virtual const CMIUtilString & GetDriverId( void ) const = 0;
+ virtual void SetExitApplicationFlag( const bool vbForceExit );
+
+ // MI provide information for the pass through (child) assigned driver
+ virtual FILE * GetStdin( void ) const;
+ virtual FILE * GetStdout( void ) const;
+ virtual FILE * GetStderr( void ) const;
+
+// Attributes:
+protected:
+ CMIDriverBase * m_pDriverFallThru; // Child driver to use should *this driver not be able to handle client input
+ CMIDriverBase * m_pDriverParent; // The parent driver who passes work to *this driver to do work
+ CMIUtilString m_strDriverId;
+ bool m_bExitApp; // True = Yes, exit application, false = continue execution
+};
diff --git a/tools/lldb-mi/MIDriverMain.cpp b/tools/lldb-mi/MIDriverMain.cpp
new file mode 100644
index 000000000000..a72e4ab20f3d
--- /dev/null
+++ b/tools/lldb-mi/MIDriverMain.cpp
@@ -0,0 +1,393 @@
+//===-- MIDriverMain.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIDriverMain.cpp
+//
+// Overview: Defines the entry point for the console application.
+// The MI application (project name MI) runs in two modes:
+// An LLDB native driver mode where it acts no different from the LLDB driver.
+// The other mode is the MI when it finds on the command line
+// the --interpreter option. Command line argument --help on its own will give
+// help for the LLDB driver. If entered with --interpreter then MI help will
+// provided.
+// To implement new MI commands derive a new command class from the command base
+// class. To enable the new command for interpretation add the new command class
+// to the command factory. The files of relevance are:
+// MICmdCommands.cpp
+// MICmdBase.h / .cpp
+// MICmdCmd.h / .cpp
+// Versions: 1.0.0.1 First version from scratch 28/1/2014 to 28/3/2014. MI not complete.
+// 1.0.0.2 First deliverable to client 7/3/2014. MI not complete.
+// 1.0.0.3 Code refactor tidy. Release to community for evaluation 17/5/2014. MI not complete.
+// 1.0.0.4 Post release to the community for evaluation 17/5/2014. MI not complete.
+// 1.0.0.5 Second deliverable to client 16/6/2014.
+// 1.0.0.6 Post release of second deliverable to client 16/6/2014.
+// Released to the community 24/6/2014.
+// 1.0.0.7 Post release to the community.
+// Delivered to client 30/6/2014.
+// 1.0.0.8 Delivered to client 29/7/2014.
+// 1.0.0.9 Post release to client 29/7/2014.
+// See MIreadme.txt for list of MI commands implemented.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadme.txt.
+//
+// Copyright: None.
+//--
+
+#if defined( _MSC_VER )
+ #define _INC_SIGNAL // Stop window's signal.h being included - CODETAG_IOR_SIGNALS
+#endif // _MSC_VER
+
+// Third party headers:
+#include <stdio.h>
+#include <lldb/API/SBHostOS.h>
+
+// In house headers:
+#include "MICmnConfig.h"
+#include "Platform.h" // Define signals - CODETAG_IOR_SIGNALS
+#include "Driver.h"
+#include "MIDriverMgr.h"
+#include "MIDriver.h"
+#include "MICmnResources.h"
+#include "MICmnStreamStdin.h"
+#include "MIUtilDebug.h"
+#include "MICmnLog.h"
+
+#if MICONFIG_COMPILE_MIDRIVER_VERSION
+
+#if defined( _MSC_VER )
+#pragma warning( once : 4530 ) // Warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
+#endif // _MSC_VER
+
+// ToDo: Reevaluate if this function needs to be implemented like the UNIX equivalent
+// CODETAG_IOR_SIGNALS
+//++ ------------------------------------------------------------------------------------
+// Details: The SIGWINCH signal is sent to a process when its controlling terminal
+// changes its size (a window change).
+// Type: Function.
+// Args: vSigno - (R) Signal number.
+// Return: None.
+// Throws: None.
+//--
+void sigwinch_handler( int vSigno )
+{
+ MIunused( vSigno );
+
+ struct winsize window_size;
+ if( ::isatty( STDIN_FILENO ) && ::ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) == 0 )
+ {
+ CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance();
+ if( window_size.ws_col > 0 )
+ {
+ rDriverMgr.DriverResizeWindow( (uint32_t) window_size.ws_col );
+ }
+ }
+
+ CMICmnLog::Instance().WriteLog( CMIUtilString::Format( MIRSRC( IDS_PROCESS_SIGNAL_RECEIVED ), "SIGWINCH", vSigno ) );
+}
+
+// CODETAG_IOR_SIGNALS
+//++ ------------------------------------------------------------------------------------
+// Details: The SIGINT signal is sent to a process by its controlling terminal when a
+// user wishes to interrupt the process. This is typically initiated by pressing
+// Control-C, but on some systems, the "delete" character or "break" key can be
+// used.
+// Be aware this function may be called on another thread besides the main thread.
+// Type: Function.
+// Args: vSigno - (R) Signal number.
+// Return: None.
+// Throws: None.
+//--
+void sigint_handler( int vSigno )
+{
+ static bool g_interrupt_sent = false;
+ CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance();
+ lldb::SBDebugger * pDebugger = rDriverMgr.DriverGetTheDebugger();
+ if( pDebugger != nullptr )
+ {
+ if( !g_interrupt_sent )
+ {
+ g_interrupt_sent = true;
+ pDebugger->DispatchInputInterrupt();
+ g_interrupt_sent = false;
+ }
+ }
+
+ CMICmnLog::Instance().WriteLog( CMIUtilString::Format( MIRSRC( IDS_PROCESS_SIGNAL_RECEIVED ), "SIGINT", vSigno ) );
+
+ // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+ // Signal MI to shutdown or halt a running debug session
+ CMICmnStreamStdin::Instance().SetCtrlCHit();
+}
+
+// ToDo: Reevaluate if this function needs to be implemented like the UNIX equivalent
+// CODETAG_IOR_SIGNALS
+//++ ------------------------------------------------------------------------------------
+// Details: The SIGTSTP signal is sent to a process by its controlling terminal to
+// request it to stop temporarily. It is commonly initiated by the user pressing
+// Control-Z. Unlike SIGSTOP, the process can register a signal handler for or
+// ignore the signal.
+// *** The function does not behave ATM like the UNIX equivalent ***
+// Type: Function.
+// Args: vSigno - (R) Signal number.
+// Return: None.
+// Throws: None.
+//--
+void sigtstp_handler( int vSigno )
+{
+ CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance();
+ lldb::SBDebugger * pDebugger = rDriverMgr.DriverGetTheDebugger();
+ if( pDebugger != nullptr )
+ {
+ pDebugger->SaveInputTerminalState();
+ }
+
+ CMICmnLog::Instance().WriteLog( CMIUtilString::Format( MIRSRC( IDS_PROCESS_SIGNAL_RECEIVED ), "SIGTSTP", vSigno ) );
+
+ // Signal MI to shutdown
+ CMICmnStreamStdin::Instance().SetCtrlCHit();
+}
+
+// ToDo: Reevaluate if this function needs to be implemented like the UNIX equivalent
+// CODETAG_IOR_SIGNALS
+//++ ------------------------------------------------------------------------------------
+// Details: The SIGCONT signal instructs the operating system to continue (restart) a
+// process previously paused by the SIGSTOP or SIGTSTP signal. One important use
+// of this signal is in job control in the UNIX shell.
+// *** The function does not behave ATM like the UNIX equivalent ***
+// Type: Function.
+// Args: vSigno - (R) Signal number.
+// Return: None.
+// Throws: None.
+//--
+void sigcont_handler( int vSigno )
+{
+ CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance();
+ lldb::SBDebugger * pDebugger = rDriverMgr.DriverGetTheDebugger();
+ if( pDebugger != nullptr )
+ {
+ pDebugger->RestoreInputTerminalState();
+ }
+
+ CMICmnLog::Instance().WriteLog( CMIUtilString::Format( MIRSRC( IDS_PROCESS_SIGNAL_RECEIVED ), "SIGCONT", vSigno ) );
+
+ // Signal MI to shutdown
+ CMICmnStreamStdin::Instance().SetCtrlCHit();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Init the MI driver system. Initialize the whole driver system which includes
+// both the original LLDB driver and the MI driver.
+// Type: Function.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool DriverSystemInit( void )
+{
+ bool bOk = MIstatus::success;
+
+#if MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
+ Driver * pDriver = Driver::CreateSelf();
+ if( pDriver == nullptr )
+ return MIstatus::failure;
+#endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
+
+ CMIDriver & rMIDriver = CMIDriver::Instance();
+ CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance();
+ bOk = rDriverMgr.Initialize();
+
+ // Register MIDriver first as it needs to initialize and be ready
+ // for the Driver to get information from MIDriver when it initializes
+ // (LLDB Driver is registered with the Driver Manager in MI's Initialize())
+ bOk = bOk && rDriverMgr.RegisterDriver( rMIDriver, "MIDriver" ); // Will be main driver
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Shutdown the debugger system. Release / terminate resources external to
+// specifically the MI driver.
+// Type: Function.
+// Args: vbAppExitOk - (R) True = No problems, false = App exiting with problems (investigate!).
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool DriverSystemShutdown( const bool vbAppExitOk )
+{
+ bool bOk = MIstatus::success;
+
+ // *** Order is important here ***
+ CMIDriverMgr::Instance().Shutdown();
+
+#if MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
+ delete g_driver;
+ g_driver = nullptr;
+#endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
+
+ return bOk;
+}
+
+#else
+void
+sigwinch_handler (int signo)
+{
+ struct winsize window_size;
+ if (isatty (STDIN_FILENO)
+ && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
+ {
+ if ((window_size.ws_col > 0) && g_driver != NULL)
+ {
+ g_driver->ResizeWindow (window_size.ws_col);
+ }
+ }
+}
+
+void
+sigint_handler (int signo)
+{
+ static bool g_interrupt_sent = false;
+ if (g_driver)
+ {
+ if (!g_interrupt_sent)
+ {
+ g_interrupt_sent = true;
+ g_driver->GetDebugger().DispatchInputInterrupt();
+ g_interrupt_sent = false;
+ return;
+ }
+ }
+
+ exit (signo);
+}
+
+void
+sigtstp_handler (int signo)
+{
+ g_driver->GetDebugger().SaveInputTerminalState();
+ signal (signo, SIG_DFL);
+ kill (getpid(), signo);
+ signal (signo, sigtstp_handler);
+}
+
+void
+sigcont_handler (int signo)
+{
+ g_driver->GetDebugger().RestoreInputTerminalState();
+ signal (signo, SIG_DFL);
+ kill (getpid(), signo);
+ signal (signo, sigcont_handler);
+}
+#endif // #if MICONFIG_COMPILE_MIDRIVER_VERSION
+
+//++ ------------------------------------------------------------------------------------
+// Details: MI's application start point of execution. The applicaton runs in two modes.
+// An LLDB native driver mode where it acts no different from the LLDB driver.
+// The other mode is the MI when it finds on the command line
+// the --interpreter option. Command line argument --help on its own will give
+// help for the LLDB driver. If entered with --interpreter then application
+// help will provided.
+// Type: Method.
+// Args: argc - (R) An integer that contains the count of arguments that follow in
+// argv. The argc parameter is always greater than or equal to 1.
+// argv - (R) An array of null-terminated strings representing command-line
+// arguments entered by the user of the program. By convention,
+// argv[0] is the command with which the program is invoked.
+// Return: int - 0 = Normal exit, program success.
+// >0 = Program success with status i.e. Control-C signal status
+// <0 = Program failed.
+// -1 = Program failed reason not specified here, see MI log file.
+// -1000 = Program failed did not initailize successfully.
+// Throws: None.
+//--
+#if MICONFIG_COMPILE_MIDRIVER_VERSION
+int main( int argc, char const *argv[] )
+{
+#if MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG
+#ifdef _WIN32
+ CMIUtilDebug::ShowDlgWaitForDbgAttach();
+#else
+ CMIUtilDebug::WaitForDbgAttachInfinteLoop();
+#endif // _WIN32
+#endif // MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG
+
+ // *** Order is important here ***
+ bool bOk = DriverSystemInit();
+ if( !bOk )
+ {
+ DriverSystemShutdown( bOk );
+ return -1000;
+ }
+
+ // CODETAG_IOR_SIGNALS
+ signal( SIGPIPE, SIG_IGN );
+ signal( SIGWINCH, sigwinch_handler );
+ signal( SIGINT, sigint_handler );
+ signal( SIGTSTP, sigtstp_handler );
+ signal( SIGCONT, sigcont_handler );
+
+ bool bExiting = false;
+ CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance();
+ bOk = bOk && rDriverMgr.ParseArgs( argc, argv, bExiting );
+ if( bOk && !bExiting )
+ bOk = rDriverMgr.DriverParseArgs( argc, argv, stdout, bExiting );
+ if( bOk && !bExiting )
+ bOk = rDriverMgr.DriverMainLoop();
+
+ // Logger and other resources shutdown now
+ DriverSystemShutdown( bOk );
+
+ const int appResult = bOk ? 0 : -1;
+
+ return appResult;
+}
+#else // Operate the lldb Driver only version of the code
+int main(int argc, char const *argv[], char *envp[])
+{
+ MIunused( envp );
+ using namespace lldb;
+ SBDebugger::Initialize();
+
+ SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
+
+ signal (SIGPIPE, SIG_IGN);
+ signal (SIGWINCH, sigwinch_handler);
+ signal (SIGINT, sigint_handler);
+ signal (SIGTSTP, sigtstp_handler);
+ signal (SIGCONT, sigcont_handler);
+
+ // Create a scope for driver so that the driver object will destroy itself
+ // before SBDebugger::Terminate() is called.
+ {
+ Driver driver;
+
+ bool exiting = false;
+ SBError error (driver.ParseArgs (argc, argv, stdout, exiting));
+ if (error.Fail())
+ {
+ const char *error_cstr = error.GetCString ();
+ if (error_cstr)
+ ::fprintf (stderr, "error: %s\n", error_cstr);
+ }
+ else if (!exiting)
+ {
+ driver.MainLoop();
+ }
+ }
+
+ SBDebugger::Terminate();
+ return 0;
+}
+#endif // MICONFIG_COMPILE_MIDRIVER_VERSION
+
diff --git a/tools/lldb-mi/MIDriverMgr.cpp b/tools/lldb-mi/MIDriverMgr.cpp
new file mode 100644
index 000000000000..b5cb7d4b5151
--- /dev/null
+++ b/tools/lldb-mi/MIDriverMgr.cpp
@@ -0,0 +1,762 @@
+//===-- MIDriverMgr.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIDriverMgr.cpp
+//
+// Overview: CMIDriverMgr implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third Party Headers:
+#include <lldb/API/SBError.h>
+
+// In-house headers:
+#include "MIDriverMgr.h"
+#include "MICmnResources.h"
+#include "MICmnLog.h"
+#include "MICmnLogMediumFile.h"
+#include "MIDriver.h"
+#include "MIUtilTermios.h"
+#include "MICmnStreamStdout.h"
+#include "MIUtilSingletonHelper.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIDriverMgr constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIDriverMgr::CMIDriverMgr( void )
+: m_pDriverCurrent( nullptr )
+, m_bInMi2Mode( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIDriverMgr destructor.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIDriverMgr::~CMIDriverMgr( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize *this manager.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ ClrErrorDescription();
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Note initialisation order is important here as some resources depend on previous
+ MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg );
+ MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg );
+
+ if( bOk )
+ {
+ MIUtilTermios::StdinTermiosSet();
+ }
+
+ m_bInitialized = bOk;
+
+ if( !bOk )
+ {
+ CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_DRIVERMGR ), errMsg.c_str() ) );
+ SetErrorDescription( strInitError );
+ return MIstatus::failure;
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Unbind detach or release resources used by this server in general common
+// functionality shared between versions of any server interfaces implemented.
+// Type: Method.
+// Args: vbAppExitOk - (R) True = No problems, false = App exiting with problems (investigate!).
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::Shutdown( void )
+{
+ // Do not want a ref counter because this function needs to be called how ever this
+ // application stops running
+ //if( --m_clientUsageRefCnt > 0 )
+ // return MIstatus::success;
+
+ bool vbAppExitOk = true;
+
+ ClrErrorDescription();
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ if( vbAppExitOk )
+ {
+ // The MI Driver's log updating may have been switched off switch back on to say all is ok.
+ CMICmnLog::Instance().SetEnabled( true );
+#if _DEBUG
+ CMICmnStreamStdout::Instance().Write( MIRSRC( IDE_MI_APP_EXIT_OK ) ); // Both stdout and Log
+#else
+ CMICmnLog::WriteLog( MIRSRC( IDE_MI_APP_EXIT_OK ) ); // Just to the Log
+#endif // _DEBUG
+ }
+ else
+ {
+ CMICmnLog & rAppLog = CMICmnLog::Instance();
+ if( rAppLog.GetEnabled() )
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDE_MI_APP_EXIT_WITH_PROBLEM ), CMICmnLogMediumFile::Instance().GetFileName().c_str() ) );
+ CMICmnStreamStdout::Instance().Write( msg );
+ }
+ else
+ {
+ // The MI Driver's log updating may have been switched off switch back on to say there has been problem.
+ rAppLog.SetEnabled( true );
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDE_MI_APP_EXIT_WITH_PROBLEM_NO_LOG ), CMICmnLogMediumFile::Instance().GetFileName().c_str() ) );
+ CMICmnStreamStdout::Instance().Write( msg );
+ }
+ }
+
+ m_bInitialized = false;
+
+ bool bOk = MIstatus::success;
+ CMIUtilString errMsg;
+
+ // Tidy up
+ UnregisterDriverAll();
+ MIUtilTermios::StdinTermiosReset();
+
+ // Note shutdown order is important here
+ MI::ModuleShutdown< CMICmnResources >( IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg );
+ MI::ModuleShutdown< CMICmnLog > ( IDS_MI_SHTDWN_ERR_LOG , bOk, errMsg );
+
+ if( !bOk )
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_MI_SHTDWN_ERR_DRIVERMGR ), errMsg.c_str() );
+ }
+
+ return bOk;
+}
+//++ ------------------------------------------------------------------------------------
+// Details: Unregister all the Driver registered with *this manager. The manager also
+// deletes
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::UnregisterDriverAll( void )
+{
+ MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
+ while( it != m_mapDriverIdToDriver.end() )
+ {
+ IDriver * pDriver = (*it).second;
+ pDriver->DoShutdown();
+
+ // Next
+ ++it;
+ }
+
+ m_mapDriverIdToDriver.clear();
+ m_pDriverCurrent = NULL;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Register a driver with *this Driver Manager. Call SetUseThisDriverToDoWork()
+// inform the manager which driver is the one to the work. The manager calls
+// the driver's init function which must be successful in order to complete the
+// registration.
+// Type: Method.
+// Args: vrDriver - (R) The driver to register.
+// vrDriverID - (R) The driver's ID to lookup by.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::RegisterDriver( const IDriver & vrDriver, const CMIUtilString & vrDriverID )
+{
+ if( HaveDriverAlready( vrDriver ) )
+ return MIstatus::success;
+
+ IDriver * pDriver = const_cast< IDriver * >( &vrDriver );
+ if( !pDriver->SetId( vrDriverID ) )
+ return MIstatus::failure;
+ if( !pDriver->DoInitialize() )
+ {
+ SetErrorDescriptionn( MIRSRC( IDS_DRIVERMGR_DRIVER_ERR_INIT ), pDriver->GetName().c_str(), vrDriverID.c_str(), pDriver->GetError().c_str() );
+ return MIstatus::failure;
+ }
+
+ MapPairDriverIdToDriver_t pr( vrDriverID, pDriver );
+ m_mapDriverIdToDriver.insert( pr );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Query the Driver Manager to see if *this manager has the driver already
+// registered.
+// Type: Method.
+// Args: vrDriver - (R) The driver to query.
+// Return: True - registered.
+// False - not registered.
+// Throws: None.
+//--
+bool CMIDriverMgr::HaveDriverAlready( const IDriver & vrDriver ) const
+{
+ MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
+ while( it != m_mapDriverIdToDriver.end() )
+ {
+ const IDriver * pDrvr = (*it).second;
+ if( pDrvr == &vrDriver )
+ return true;
+
+ // Next
+ ++it;
+ }
+
+ return false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Unregister a driver from the Driver Manager. Call the SetUseThisDriverToDoWork()
+// function to define another driver to do work if the one being unregistered did
+// the work previously.
+// Type: Method.
+// Args: vrDriver - (R) The driver to unregister.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::UnregisterDriver( const IDriver & vrDriver )
+{
+ const IDriver * pDrvr = nullptr;
+ MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
+ while( it != m_mapDriverIdToDriver.end() )
+ {
+ pDrvr = (*it).second;
+ if( pDrvr == &vrDriver )
+ break;
+
+ // Next
+ ++it;
+ }
+ m_mapDriverIdToDriver.erase( it );
+
+ if( m_pDriverCurrent == pDrvr )
+ m_pDriverCurrent = nullptr;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Specify the driver to do work. The Driver Manager drives this driver. Any
+// previous driver doing work is not called anymore (so be sure the previous
+// driver is in a tidy state before stopping it working).
+// Type: Method.
+// Args: vrADriver - (R) A lldb::SBBroadcaster/IDriver derived object.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::SetUseThisDriverToDoWork( const IDriver & vrADriver )
+{
+ m_pDriverCurrent = const_cast< IDriver * >( &vrADriver );
+
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_SAY_DRIVER_USING ), m_pDriverCurrent->GetName().c_str() ) );
+ m_pLog->Write( msg, CMICmnLog::eLogVerbosity_Log );
+
+ m_bInMi2Mode = m_pDriverCurrent->GetDriverIsGDBMICompatibleDriver();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Ask *this manager which driver is currently doing the work.
+// Type: Method.
+// Args: None.
+// Return: IDriver * - Pointer to a driver, NULL if there is no current working driver.
+// Throws: None.
+//--
+CMIDriverMgr::IDriver * CMIDriverMgr::GetUseThisDriverToDoWork( void ) const
+{
+ return m_pDriverCurrent;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Call this function puts *this driver to work.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::DriverMainLoop( void )
+{
+ if( m_pDriverCurrent != nullptr )
+ {
+ if( !m_pDriverCurrent->DoMainLoop() )
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_MAINLOOP ), m_pDriverCurrent->GetError().c_str() ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ return MIstatus::failure;
+ }
+ }
+ else
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Call *this driver to resize the console window.
+// Type: Method.
+// Args: vWindowSizeWsCol - (R) New window column size.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+void CMIDriverMgr::DriverResizeWindow( const uint32_t vWindowSizeWsCol )
+{
+ if( m_pDriverCurrent != nullptr )
+ return m_pDriverCurrent->DoResizeWindow( vWindowSizeWsCol );
+ else
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ }
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Get the current driver to validate executable command line arguments.
+// Type: Method.
+// Args: argc - (R) An integer that contains the count of arguments that follow in
+// argv. The argc parameter is always greater than or equal to 1.
+// argv - (R) An array of null-terminated strings representing command-line
+// arguments entered by the user of the program. By convention,
+// argv[0] is the command with which the program is invoked.
+// vpStdOut - (R) Point to a standard output stream.
+// vwbExiting - (W) True = *this want to exit, false = continue to work.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIDriverMgr::DriverParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting )
+{
+ if( m_pDriverCurrent == nullptr )
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ return MIstatus::failure;
+ }
+
+ const lldb::SBError error( m_pDriverCurrent->DoParseArgs( argc, argv, vpStdOut, vwbExiting ) );
+ bool bOk = !error.Fail();
+ if( !bOk )
+ {
+ CMIUtilString errMsg;
+ const MIchar * pErrorCstr = error.GetCString();
+ if( pErrorCstr != nullptr )
+ errMsg = CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_PARSE_ARGS ), m_pDriverCurrent->GetName().c_str(), pErrorCstr );
+ else
+ errMsg = CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN ), m_pDriverCurrent->GetName().c_str() );
+
+ bOk = CMICmnStreamStdout::Instance().Write( errMsg, true );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the current driver's last error condition.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Text description.
+// Throws: None.
+//--
+CMIUtilString CMIDriverMgr::DriverGetError( void ) const
+{
+ if( m_pDriverCurrent != nullptr )
+ return m_pDriverCurrent->GetError();
+ else
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ }
+
+ return CMIUtilString();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the current driver's name.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Driver name.
+// Empty string = no current working driver specified.
+// Throws: None.
+//--
+CMIUtilString CMIDriverMgr::DriverGetName( void ) const
+{
+ if( m_pDriverCurrent != nullptr )
+ return m_pDriverCurrent->GetName();
+ else
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ }
+
+ return CMIUtilString();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the current driver's debugger object.
+// Type: Method.
+// Args: None.
+// Return: lldb::SBDebugger * - Ptr to driver's debugger object.
+// - NULL = no current working driver specified.
+// Throws: None.
+//--
+lldb::SBDebugger * CMIDriverMgr::DriverGetTheDebugger( void )
+{
+ lldb::SBDebugger * pDebugger = nullptr;
+ if( m_pDriverCurrent != nullptr )
+ pDebugger = &m_pDriverCurrent->GetTheDebugger();
+ else
+ {
+ const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_CURRENT_NOT_SET ) ) );
+ CMICmnStreamStdout::Instance().Write( errMsg, true );
+ }
+
+ return pDebugger;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Check the arguments given on the command line. The main purpose of this
+// function is to check for the presence of the --interpreter option. Having
+// this option present tells *this manager to set the CMIDriver to do work. If
+// not use the LLDB driver. The following are options that are only handled by
+// the CMIDriverMgr are:
+// --help or -h
+// --interpreter
+// --version
+// --versionLong
+// --noLog
+// --executable
+// The above arguments are not handled by any driver object except for --executable.
+// The options --interpreter and --executable in code act very similar. The
+// --executable is necessary to differentiate whither the MI Driver is being using
+// by a client i.e. Eclipse or from the command line. Eclipse issues the option
+// --interpreter and also passes additional arguments which can be interpreted as an
+// executable if called from the command line. Using --executable tells the MI
+// Driver is being called the command line and that the executable argument is indeed
+// a specified executable an so actions commands to set up the executable for a
+// debug session. Using --interpreter on the commnd line does not action additional
+// commands to initialise a debug session and so be able to launch the process.
+// Type: Method.
+// Args: argc - (R) An integer that contains the count of arguments that follow in
+// argv. The argc parameter is always greater than or equal to 1.
+// argv - (R) An array of null-terminated strings representing command-line
+// arguments entered by the user of the program. By convention,
+// argv[0] is the command with which the program is invoked.
+// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s),
+// version information only.
+// False = Continue to work, start debugger i.e. Command
+// interpreter.
+// Return: lldb::SBError - LLDB current error status.
+// Throws: None.
+//--
+bool CMIDriverMgr::ParseArgs( const int argc, const char * argv[], bool & vwbExiting )
+{
+ bool bOk = MIstatus::success;
+
+ vwbExiting = false;
+
+ // Print MI application path to the Log file
+ const CMIUtilString appPath( CMIUtilString::Format( MIRSRC( IDS_MI_APP_FILEPATHNAME ), argv[ 0 ] ) );
+ bOk = m_pLog->Write( appPath, CMICmnLog::eLogVerbosity_Log );
+
+ // Print application arguments to the Log file
+ const bool bHaveArgs( argc >= 2 );
+ CMIUtilString strArgs( MIRSRC( IDS_MI_APP_ARGS ) );
+ if( !bHaveArgs )
+ {
+ strArgs += MIRSRC( IDS_WORD_NONE );
+ bOk = bOk && m_pLog->Write( strArgs, CMICmnLog::eLogVerbosity_Log );
+ }
+ else
+ {
+ for( MIint i = 1; i < argc; i++ )
+ {
+ strArgs += CMIUtilString::Format( "%d:'%s' ", i, argv[ i ] );
+ }
+ bOk = bOk && m_pLog->Write( strArgs, CMICmnLog::eLogVerbosity_Log );
+ }
+
+ // Look for the command line options
+ bool bHaveArgInterpret = false;
+ bool bHaveArgVersion = false;
+ bool bHaveArgVersionLong = false;
+ bool bHaveArgNoLog = false;
+ bool bHaveArgHelp = false;
+
+ // Hardcode the use of the MI driver
+#if MICONFIG_DEFAULT_TO_MI_DRIVER
+ bHaveArgInterpret = true;
+#endif // MICONFIG_DEFAULT_TO_MI_DRIVER
+
+ if( bHaveArgs )
+ {
+ // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING
+ for( MIint i = 1; i < argc; i++ )
+ {
+ // *** Add args to help in GetHelpOnCmdLineArgOptions() ***
+ const CMIUtilString strArg( argv[ i ] );
+
+ // Argument "--executable" is also check for in CMIDriver::ParseArgs()
+ if( (0 == strArg.compare( "--interpreter" )) || // Given by the client such as Eclipse
+ (0 == strArg.compare( "--executable" )) ) // Used to specify that there is executable argument also on the command line
+ { // See fn description.
+ bHaveArgInterpret = true;
+ }
+ if( 0 == strArg.compare( "--version" ) )
+ {
+ bHaveArgVersion = true;
+ }
+ if( 0 == strArg.compare( "--versionLong" ) )
+ {
+ bHaveArgVersionLong = true;
+ }
+ if( 0 == strArg.compare( "--noLog" ) )
+ {
+ bHaveArgNoLog = true;
+ }
+ if( (0 == strArg.compare( "--help" )) || (0 == strArg.compare( "-h" )) )
+ {
+ bHaveArgHelp = true;
+ }
+ }
+ }
+
+ if( bHaveArgNoLog )
+ {
+ CMICmnLog::Instance().SetEnabled( false );
+ }
+
+ // Todo: Remove this output when MI is finished. It is temporary to persuade Ecllipse plugin to work.
+ // Eclipse reads this literally and will not work unless it gets this exact version text.
+ // Handle --version option (ignore the --interpreter option if present)
+ if( bHaveArgVersion )
+ {
+ vwbExiting = true;
+ bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse( MIRSRC( IDE_MI_VERSION_GDB ) );
+ return bOk;
+ }
+
+ // Todo: Make this the --version when the the above --version version is removed
+ // Handle --versionlong option (ignore the --interpreter option if present)
+ if( bHaveArgVersionLong )
+ {
+ vwbExiting = true;
+ bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse( GetAppVersion() );
+ return bOk;
+ }
+
+ // Both '--help' and '--intepreter' means give help for MI only. Without
+ // '--interpreter' help the LLDB driver is working and so help is for that.
+ if( bHaveArgHelp && bHaveArgInterpret )
+ {
+ vwbExiting = true;
+ bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse( GetHelpOnCmdLineArgOptions() );
+ return bOk;
+ }
+
+ // This makes the assumption that there is at least one MI compatible
+ // driver registered and one LLDB driver registerd and the CMIDriver
+ // is the first one found.
+ // ToDo: Implement a better solution that handle any order, any number
+ // of drivers. Or this 'feature' may be removed if deemed not required.
+ IDriver * pLldbDriver = GetFirstNonMIDriver();
+ IDriver * pMi2Driver = GetFirstMIDriver();
+ if( bHaveArgInterpret && (pMi2Driver != nullptr) )
+ bOk = bOk && SetUseThisDriverToDoWork( *pMi2Driver );
+ else if( pLldbDriver != nullptr )
+ bOk = bOk && SetUseThisDriverToDoWork( *pLldbDriver );
+ else
+ {
+ if( bOk )
+ {
+ vwbExiting = true;
+ const CMIUtilString msg( MIRSRC( IDS_DRIVER_ERR_NON_REGISTERED ) );
+ bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse( msg );
+ }
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return formatted application version and name information.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Text data.
+// Throws: None.
+//--
+CMIUtilString CMIDriverMgr::GetAppVersion( void ) const
+{
+ const CMIUtilString strProj( MIRSRC( IDS_PROJNAME ) );
+ const CMIUtilString strVsn( CMIDriver::Instance().GetVersionDescription() );
+ const CMIUtilString strGdb( MIRSRC( IDE_MI_VERSION_GDB ) );
+ const CMIUtilString strVrsnInfo( CMIUtilString::Format( "%s\n%s\n%s", strProj.c_str(), strVsn.c_str(), strGdb.c_str() ) );
+
+ return strVrsnInfo;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return formatted help information on all the MI command line options.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Text data.
+// Throws: None.
+//--
+CMIUtilString CMIDriverMgr::GetHelpOnCmdLineArgOptions( void ) const
+{
+ const CMIUtilString pHelp[] =
+ {
+ MIRSRC( IDE_MI_APP_DESCRIPTION ),
+ MIRSRC( IDE_MI_APP_INFORMATION ),
+ MIRSRC( IDE_MI_APP_ARG_USAGE ),
+ MIRSRC( IDE_MI_APP_ARG_HELP ),
+ MIRSRC( IDE_MI_APP_ARG_VERSION ),
+ MIRSRC( IDE_MI_APP_ARG_VERSION_LONG ),
+ MIRSRC( IDE_MI_APP_ARG_INTERPRETER ),
+ MIRSRC( IDE_MI_APP_ARG_EXECUTEABLE ),
+ CMIUtilString::Format( MIRSRC( IDE_MI_APP_ARG_NO_APP_LOG ), CMICmnLogMediumFile::Instance().GetFileName().c_str() ),
+ MIRSRC( IDE_MI_APP_ARG_EXECUTABLE ),
+ MIRSRC( IDS_CMD_QUIT_HELP ),
+ MIRSRC( IDE_MI_APP_ARG_EXAMPLE )
+ };
+ const MIuint nHelpItems = sizeof pHelp / sizeof pHelp[ 0 ];
+ CMIUtilString strHelp;
+ for( MIuint i = 0; i < nHelpItems; i++ )
+ {
+ strHelp += pHelp[ i ];
+ strHelp += "\n\n";
+ }
+
+ return strHelp;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Search the registered drivers and return the first driver which says it is
+// GDB/MI compatible i.e. the CMIDriver class.
+// Type: Method.
+// Args: None.
+// Return: IDriver * - Ptr to driver, NULL = no driver found.
+// Throws: None.
+//--
+CMIDriverMgr::IDriver * CMIDriverMgr::GetFirstMIDriver( void ) const
+{
+ IDriver * pDriver = nullptr;
+ MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
+ while( it != m_mapDriverIdToDriver.end() )
+ {
+ const CMIUtilString & rDrvId = (*it).first; MIunused( rDrvId );
+ IDriver * pDvr = (*it).second;
+ if( pDvr->GetDriverIsGDBMICompatibleDriver() )
+ {
+ pDriver = pDvr;
+ break;
+ }
+
+ // Next
+ ++it;
+ }
+
+ return pDriver;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Search the registered drivers and return the first driver which says it is
+// not GDB/MI compatible i.e. the LLDB Driver class.
+// Type: Method.
+// Args: None.
+// Return: IDriver * - Ptr to driver, NULL = no driver found.
+// Throws: None.
+//--
+CMIDriverMgr::IDriver * CMIDriverMgr::GetFirstNonMIDriver( void ) const
+{
+ IDriver * pDriver = nullptr;
+ MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
+ while( it != m_mapDriverIdToDriver.end() )
+ {
+ const CMIUtilString & rDrvId = (*it).first; MIunused( rDrvId );
+ IDriver * pDvr = (*it).second;
+ if( !pDvr->GetDriverIsGDBMICompatibleDriver() )
+ {
+ pDriver = pDvr;
+ break;
+ }
+
+ // Next
+ ++it;
+ }
+
+ return pDriver;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Search the registered drivers and return driver with the specified ID.
+// Type: Method.
+// Args: vrDriverId - (R) ID of a driver.
+// Return: IDriver * - Ptr to driver, NULL = no driver found.
+// Throws: None.
+//--
+CMIDriverMgr::IDriver * CMIDriverMgr::GetDriver( const CMIUtilString & vrDriverId ) const
+{
+ MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.find( vrDriverId );
+ if( it == m_mapDriverIdToDriver.end() )
+ return nullptr;
+
+ IDriver * pDriver = (*it).second;
+
+ return pDriver;
+}
+
diff --git a/tools/lldb-mi/MIDriverMgr.h b/tools/lldb-mi/MIDriverMgr.h
new file mode 100644
index 000000000000..438d184895b1
--- /dev/null
+++ b/tools/lldb-mi/MIDriverMgr.h
@@ -0,0 +1,138 @@
+//===-- MIDriverMgr.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIDriverMgr.h
+//
+// Overview: CMIImplCmn interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadme.txt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <map>
+#include <lldb/API/SBDebugger.h>
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MIUtilString.h"
+#include "MICmnLog.h"
+#include "MIUtilSingletonBase.h"
+
+//++ ============================================================================
+// Details: MI Driver Manager. Register lldb::SBBroadcaster derived Driver type
+// objects with *this manager. The manager does not own driver objects
+// registered with it and so will not delete when this manager is
+// shutdown. The Driver flagged as "use this one" will be set as current
+// driver and will be the one that is used. Other drivers are not
+// operated. A Driver can call another Driver should it not handle a
+// command.
+// It also initializes other resources as part it's setup such as the
+// Logger and Resources objects (explicit indicate *this object requires
+// those objects (modules/components) to support it's own functionality).
+// The Driver manager is the first object instantiated as part of the
+// MI code base. It is also the first thing to interpret the command
+// line arguments passed to the executeable. Bases on options it
+// understands the manage will set up the appropriate driver or give
+// help information. Other options are passed on to the driver chosen
+// to do work.
+// Each driver instance (the CMIDriver, LLDB::Driver) has its own
+// LLDB::SBDebugger.
+// Singleton class.
+// Gotchas: None.
+// Authors: Illya Rudkin 28/02/2014.
+// Changes: None.
+//--
+class CMIDriverMgr
+: public CMICmnBase
+, public MI::ISingleton< CMIDriverMgr >
+{
+ friend MI::ISingleton< CMIDriverMgr >;
+
+// Class:
+public:
+ //++
+ // Description: Driver deriver objects need this interface to work with
+ // *this manager.
+ //--
+ class IDriver
+ {
+ public:
+ virtual bool DoInitialize( void ) = 0;
+ virtual bool DoShutdown( void ) = 0;
+ virtual bool DoMainLoop( void ) = 0;
+ virtual void DoResizeWindow( const uint32_t vWindowSizeWsCol ) = 0;
+ virtual lldb::SBError DoParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting ) = 0;
+ virtual CMIUtilString GetError( void ) const = 0;
+ virtual const CMIUtilString & GetName( void ) const = 0;
+ virtual lldb::SBDebugger & GetTheDebugger( void ) = 0;
+ virtual bool GetDriverIsGDBMICompatibleDriver( void ) const = 0;
+ virtual bool SetId( const CMIUtilString & vId ) = 0;
+ virtual const CMIUtilString & GetId( void ) const = 0;
+
+ // Not part of the interface, ignore
+ /* dtor */ virtual ~IDriver( void ) {}
+ };
+
+// Methods:
+public:
+ // MI system
+ bool Initialize( void );
+ bool Shutdown( void );
+ //
+ CMIUtilString GetAppVersion( void ) const;
+ bool RegisterDriver( const IDriver & vrADriver, const CMIUtilString & vrDriverID );
+ bool UnregisterDriver( const IDriver & vrADriver );
+ bool SetUseThisDriverToDoWork( const IDriver & vrADriver ); // Specify working main driver
+ IDriver * GetUseThisDriverToDoWork( void ) const;
+ bool ParseArgs( const int argc, const char * argv[], bool & vwbExiting );
+ IDriver * GetDriver( const CMIUtilString & vrDriverId ) const;
+ //
+ // MI Proxy fn to current specified working driver
+ bool DriverMainLoop( void );
+ void DriverResizeWindow( const uint32_t vWindowSizeWsCol );
+ bool DriverParseArgs( const int argc, const char * argv[], FILE * vpStdOut, bool & vwbExiting );
+ CMIUtilString DriverGetError( void ) const;
+ CMIUtilString DriverGetName( void ) const;
+ lldb::SBDebugger * DriverGetTheDebugger( void );
+
+// Typedef:
+private:
+ typedef std::map< CMIUtilString, IDriver * > MapDriverIdToDriver_t;
+ typedef std::pair< CMIUtilString, IDriver * > MapPairDriverIdToDriver_t;
+
+// Methods:
+private:
+ /* ctor */ CMIDriverMgr( void );
+ /* ctor */ CMIDriverMgr( const CMIDriverMgr & );
+ void operator=( const CMIDriverMgr & );
+ //
+ bool HaveDriverAlready( const IDriver & vrMedium ) const;
+ bool UnregisterDriverAll( void );
+ IDriver * GetFirstMIDriver( void ) const;
+ IDriver * GetFirstNonMIDriver( void ) const;
+ CMIUtilString GetHelpOnCmdLineArgOptions( void ) const;
+
+// Overridden:
+private:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMIDriverMgr( void );
+
+// Attributes:
+private:
+ MapDriverIdToDriver_t m_mapDriverIdToDriver;
+ IDriver * m_pDriverCurrent; // This driver is used by this manager to do work. It is the main driver.
+ bool m_bInMi2Mode; // True = --interpreter entered on the cmd line, false = operate LLDB driver (non GDB)
+};
diff --git a/tools/lldb-mi/MIReadMe.txt b/tools/lldb-mi/MIReadMe.txt
new file mode 100644
index 000000000000..fbd3b2d364f6
--- /dev/null
+++ b/tools/lldb-mi/MIReadMe.txt
@@ -0,0 +1,261 @@
+========================================================================
+ The MI Driver - LLDB Machine Interface V2 (MI) Project Overview
+ 24/07/2014
+========================================================================
+
+The MI Driver is a stand alone executable that either be used via a
+client i.e. Eclipse or directly from the command line.
+
+All the files in this directory are required to build the MI executable.
+The executable is intended to compile and work on the following platforms:
+
+ Windows (Vista or newer) (Compiler: Visual C++ 12)
+ LINUX (Compiler: gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1)
+ OSX (Not tested)
+
+THe MI Driver has two modes of operation; LLDB and MI. The MI Driver (CMIDriver)
+which operates the MI mode is a driver in its own right to work alongside
+the LLDB driver (driver .h/.cpp). Only one is operatational at a time depending
+on the options entered on the command line. The MI Driver reads MI inputs and
+outputs MI responses to be interpreted by a client i.e. Eclipse.
+Should the MI Driver not understand an instruction it could be passed to the
+LLDB driver for interpretation (MI Driver build configuration dependant). Should
+the LLDB driver mode be chosen then it the MI Driver will behave as the normal
+LLDB driver.
+
+For help information on using the MI driver type at the command line:
+
+ lldb-mi --interpreter --help
+
+A blog about the MI Driver is available on CodePlay's website
+http://www.codeplay.com/portal/.
+
+The MI Driver produces a MILog.txt file which records the actions of the MI
+Driver when in the MI mode only.
+
+Note any command or text sent to the MI Driver in MI mode that is not a command
+registered in the MI Driver's Command Factory will be rejected given an error.
+
+The MILogfile.txt keeps a history of the MI Driver's activity for one session
+only. It is used to aid the debugging of the MI Driver in MI mode only. As well
+as recorded commands that are recognised by the MI Driver it also gives warnings
+about command's which do not support certain argument or options.
+
+All the files prefix with MI are specifically for the MI driver code only.
+Non prefixed code is the original LLDB driver which has been left untouched
+as much as possible. This allows the LLDB driver code to develop
+independently and make future integration more straight forward.
+
+File MIDriverMain.cpp contains the executables main() function and some
+common global functions common to the two drivers.
+
+=========================================================================
+Current limitations:
+1. Commands implemented likely not to have all their arguments supported
+2. The MI Driver has only been tested with Eclipse Juno with an in-house
+ plugin
+3. Local target has been implemented but not tested
+4. The MI Driver has been designed primarily to work in a 'remote-target'
+ mode only. The MI Driver does not currently except arguments beyond
+ those described above.
+5. The MI Driver does not accept as arguments an executable to create a
+ target instance.
+6. Not all MI commands have been implemented. See section MI Driver
+ commands for those that have been fully or partially implemented (not
+ indicated - see command class).
+7. Not necessarily a limitation but the MI Driver is used with Codeplay's
+ own Eclipse plugin (not supplied) which has allowed more control over
+ the interaction with the MI Driver between Eclipse.
+
+=========================================================================
+Versions:
+1.0.0.1 First version from scratch 28/1/2014 to 28/3/2014.
+ MI working alpha. MI framework not complete.
+1.0.0.2 First deliverable to client 7/3/2014.
+ MI working beta. MI framework not complete.
+1.0.0.3 Code refactor tidy. Release to community for evaluation
+ 7/5/2014.
+ MI working beta - code refactored and tidied. MI framework
+ complete. Just missing commands (which may still require
+ changes).
+1.0.0.4 Post release to community for evaluation 7/5/2014.
+ 1. MI command token now optional
+ 2. MI command token is now fixed length
+ 3. New commands added see section "MI commands implemented are:"
+ 4. Able to debug a local target as well as remote target
+ 5. MI Driver now sends to the client "(gdb)" + '\n' on
+ initialising
+ 6. Improve coverage of parsing and fix command argument parsing
+ 7. Fix bug with stdin thinking there was no input when there was which
+ caused communication between the client and the MI Driver to halt
+ due to internal buffering, we now keep track of it ourself.
+ 8. Code comment fixes and additions. Code style fixes.
+ 9. MI Driver now on receiving Ctrl-C (SIGINT) when the client pauses
+ an inferior program does not quit but continues operating.
+ 10.Fix commands "var-update", "var-evaluate-expression" to which did
+ not send back information to correctly update arrays and structures.
+ 11.Commands "Not implemented" are now not registered to the command
+ factory except for GDB command "thread". Commands not registered
+ with the command factory produce MI error message "...not in
+ Command Factory". (Removed from command section in this readme.txt)
+1.0.0.5 Second deliverable to client 16/6/2014.
+1.0.0.6 Post release of second deliverable to client 16/6/2014.
+ Released to the community 24/6/2014.
+ 1. The MI Driver has a new option --noLog. If present the MI Driver
+ does not output progress or status messages to it's log file.
+ 2. Moved OS specific handling of the stdin stream to their own class
+ implementations so any changes to one handler will not affect
+ another OS's handler.
+ 3. The session data/information map for sharing data between commands
+ now uses a variant object which enables objects of different types
+ to be stored instead of previously just text information.
+ 4. Debug session var object create, update and retrieve efficiency
+ improved by using a map type container.
+ 5. Re-enable the MI Driver's command line option --interpreter (see
+ --help). Up until now it was implementented but not enforced, it
+ was always the MI Driver interpreter.
+ 6. Re-enable the compilation of the original LLDB driver code into
+ the MI Driver's code. See MICmnConfig.h for build configuration.
+1.0.0.7 Post release to community. Delivered to client 30/6/2014.
+ 1. Fix MI Driver's output of "(gdb)" appearing when running in LLDB
+ mode (no --interpreter argument)'
+ 2. Fix command "interpret-exec" to allow commands to be entered
+ directly in the IDE console.
+1.0.0.8 Post release to client. Delivered to client 29/07/2014
+ 1. Fix command "break-insert" argument -f not accepting file paths
+ as a string. Looked like the MI Driver was not accepting LINUX
+ style file paths in the Windows version and vice versa.
+ 2. Fix command "stack-list-arguments" handling only the current
+ stack frame. Eclipse now shows variables for all frames.
+ 3. Fix and improve MI response for sending back information on
+ stack local variables, stack arguments and stack frame selection.
+ 4. Fix recursive crash when asking to gather information on link
+ lists.
+ 5. Fix MI Driver's Log date and time field.
+ 6. Fix MI response return from event 'StopReason' and 'Breakpoint-
+ hit'.
+ 7. Fix command "environment-cd" to handle paths with spaces in the
+ path.
+ 8. Fix not displaying backtrace (stack) variable information when
+ choosing frames other than the current frame.
+ 9. Fix command "data-evaluate-expression" to be able to handle
+ valid SBValue objects but have no value object name. Fix same
+ command to handle expressions surround by string format inserted
+ quotes.
+ 10.Fix command "break-insert" to handle file location that is
+ surrounded by quotes.
+ 11.For commands "var-create" and "data-evaluate-expression" improve
+ variable type handling for quoted expressions.
+ 12.Implement command "inferior-tty-set". It just responds with
+ "^Done".
+ 13.Improve the MI Driver's help description.
+ 14.Fix file name paths that contained '.', '-' and '_' in the path
+ as being treated as invalid.
+ 15.Fix trying to interpret escapse character text as an errorous
+ command.
+1.0.0.9 Post release to client.
+
+=========================================================================
+MI Driver Commands
+MI commands below are written to work for Eclipse Juno 7.4. If may be
+one are more commands required by other IDEs are missing or do not
+support all arguments or options. Additionally some commands may handle
+additional arguments or options not documented here
+https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Data-Manipulation.html#GDB_002fMI-Data-Manipulation.
+The implemented commands are:
+CMICmdCmdBreakAfter
+CMICmdCmdBreakCondition
+CMICmdCmdBreakDelete
+CMICmdCmdBreakDisable
+CMICmdCmdBreakEnable
+CMICmdCmdBreakInsert
+CMICmdCmdDataEvaluateExpression
+CMICmdCmdDataDisassemble
+CMICmdCmdDataListRegisterChanged
+CMICmdCmdDataListRegisterNames
+CMICmdCmdDataListRegisterValues
+CMICmdCmdDataReadMemory
+CMICmdCmdDataReadMemoryBytes
+CMICmdCmdDataWriteMemory
+CMICmdCmdEnablePrettyPrinting
+CMICmdCmdEnvironmentCd
+CMICmdCmdExecContinue
+CMICmdCmdExecFinish
+CMICmdCmdExecInterrupt
+CMICmdCmdExecNext
+CMICmdCmdExecNextInstruction
+CMICmdCmdExecRun
+CMICmdCmdExecStep
+CMICmdCmdExecStepInstruction
+CMICmdCmdFileExecAndSymbols
+CMICmdCmdGdbExit
+CMICmdCmdGdbInfo
+CMICmdCmdGdbSet
+CMICmdCmdGdbSet - solib-search-path option
+CMICmdCmdInferiorTtySet (not functionally implemented)
+CMICmdCmdInterpreterExec
+CMICmdCmdListThreadGroups
+CMICmdCmdSource
+CMICmdCmdStackInfoDepth
+CMICmdCmdStackListArguments
+CMICmdCmdStackListFrames
+CMICmdCmdStackListLocals
+CMICmdCmdSupportInfoMiCmdQuery
+CMICmdCmdSupportListFeatures
+CMICmdCmdTargetSelect
+CMICmdCmdThread
+CMICmdCmdThreadInfo
+CMICmdCmdTraceStatus (not functionally implemented)
+CMICmdCmdVarAssign
+CMICmdCmdVarCreate
+CMICmdCmdVarDelete
+CMICmdCmdVarEvaluateExpression
+CMICmdCmdVarInfoPathExpression
+CMICmdCmdVarListChildren
+CMICmdCmdVarSetFormat
+CMICmdCmdVarShowAttributes
+CMICmdCmdVarUpdate
+
+=========================================================================
+The MI Driver build configuration:
+MICmnConfig.h defines various preprocessor build options i.e. enable
+LLDB driver fall through (Driver.h/.cpp) should MI Driver not recognise a
+command (option not fully implemented - may be removed in the future).
+
+=========================================================================
+Code standard, documentation and code style scope:
+The coding style and coding documentation scope covers all MI prefixed
+files and where MI code is implemented in the LLDB driver files. Should
+you wish to make improvements or fixes to the MI code (which is encouraged)
+please DO comment your code in the style already applied. The same applies
+to the coding style. Class names should also follow this lead and ideally
+should be one class per file (.h/.cpp). Class interface files (.h) should
+not contain any implementation code unless there is a performance issue or
+templated functions. You get the idea, look around the existing code and
+follow by example :)
+
+Where code comment or documentation is wrong or can be improved to help
+others then it is strongly encouraged you DO improve the documentation.
+
+=========================================================================
+MI Driver license:
+The MI Driver code is under the University of Illinois Open Source License
+agreement. Submitted by Codeplay Ltd UK.
+
+Source code found at: llvm/tools/lldb/tools/lldb-mi.
+
+=========================================================================
+The MI Driver uses the following libraries:
+Standard Template library
+ Thread
+ Containers
+ String
+ File
+ Time
+LLDB public API
+OS specific
+ OS error reporting windows
+ OS error handling OSX (not implemented)
+ OS error handling LINUX (not implemented)
+
+
diff --git a/tools/lldb-mi/MIUtilDateTimeStd.cpp b/tools/lldb-mi/MIUtilDateTimeStd.cpp
new file mode 100644
index 000000000000..9938deb131cc
--- /dev/null
+++ b/tools/lldb-mi/MIUtilDateTimeStd.cpp
@@ -0,0 +1,84 @@
+//===-- MIUtilDateTimeStd.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilDateTimeStd.cpp
+//
+// Overview: CMIUtilDateTimeStd implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MIUtilDateTimeStd.h"
+#include "MICmnResources.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilDateTimeStd constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilDateTimeStd::CMIUtilDateTimeStd( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilDateTimeStd destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilDateTimeStd::~CMIUtilDateTimeStd( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve system local current date. Format is MM/DD/YYYY.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Text description.
+// Throws: None.
+//--
+CMIUtilString CMIUtilDateTimeStd::GetDate( void )
+{
+ CMIUtilString strDate( MIRSRC( IDS_WORD_INVALIDBRKTS ) );
+
+ std::time( &m_rawTime );
+ const std::tm * pTi = std::localtime( &m_rawTime );
+ if( std::strftime( &m_pScratch[ 0 ], sizeof( m_pScratch ), "%d/%m/%y", pTi ) > 0 )
+ strDate = m_pScratch;
+
+ return strDate;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve system local current time. Format is HH:MM:SS 24 hour clock.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Text description.
+// Throws: None.
+//--
+CMIUtilString CMIUtilDateTimeStd::GetTime( void )
+{
+ std::time( &m_rawTime );
+ const std::tm * pTi = std::localtime( &m_rawTime );
+ const CMIUtilString seconds( CMIUtilString::Format( "%d", pTi->tm_sec ) );
+ const CMIUtilString zero( (seconds.length() == 1) ? "0" : "" );
+ const CMIUtilString strTime( CMIUtilString::Format( "%d:%d:%s%s", pTi->tm_hour, pTi->tm_min, zero.c_str(), seconds.c_str() ) );
+
+ return strTime;
+}
+
diff --git a/tools/lldb-mi/MIUtilDateTimeStd.h b/tools/lldb-mi/MIUtilDateTimeStd.h
new file mode 100644
index 000000000000..da857d6358ee
--- /dev/null
+++ b/tools/lldb-mi/MIUtilDateTimeStd.h
@@ -0,0 +1,55 @@
+//===-- MIUtilDateTimeStd.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilDateTimeStd.h
+//
+// Overview: CMIUtilDateTimeStd interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers
+#include <ctime>
+
+// In-house headers:
+#include "MIUtilString.h"
+
+//++ ============================================================================
+// Details: MI common code utility class. Used to retrieve system local date
+// time.
+// Gotchas: None.
+// Authors: Illya Rudkin 16/07/2014.
+// Changes: None.
+//--
+class CMIUtilDateTimeStd
+{
+// Methods:
+public:
+ /* ctor */ CMIUtilDateTimeStd( void );
+
+ CMIUtilString GetDate( void );
+ CMIUtilString GetTime( void );
+
+// Overrideable:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMIUtilDateTimeStd( void );
+
+// Attributes:
+private:
+ std::time_t m_rawTime;
+ MIchar m_pScratch[ 16 ];
+};
diff --git a/tools/lldb-mi/MIUtilDebug.cpp b/tools/lldb-mi/MIUtilDebug.cpp
new file mode 100644
index 000000000000..754920880ec4
--- /dev/null
+++ b/tools/lldb-mi/MIUtilDebug.cpp
@@ -0,0 +1,128 @@
+//===-- MIUtilDebug.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilDebug.h
+//
+// Overview: Terminal setting termios functions.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers:
+#ifdef _WIN32
+#include <Windows.h>
+#endif
+
+// In-house headers:
+#include "MIUtilDebug.h"
+#include "MIDriver.h"
+#include "MICmnLog.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilDebug constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilDebug::CMIUtilDebug( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilDebug destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilDebug::~CMIUtilDebug( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Show a dialog to the process/application halts. It gives the opportunity to
+// attach a debugger.
+// Type: Static method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMIUtilDebug::ShowDlgWaitForDbgAttach( void )
+{
+ const CMIUtilString strCaption( CMIDriver::Instance().GetAppNameShort() );
+#ifdef _WIN32
+ ::MessageBoxA( NULL, "Attach your debugger now", strCaption.c_str(), MB_OK );
+#else
+ // ToDo: Implement other platform version of an Ok to continue dialog box
+#endif // _WIN32
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Temporarily stall the process/application to give the programmer the
+// opportunity to attach a debugger. How to use: Put a break in the programmer
+// where you want to visit, run the application then attach your debugger to the
+// application. Hit the debugger's pause button and the debugger should should
+// show this loop. Change the i variable value to break out of the loop and
+// visit your break point.
+// Type: Static method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMIUtilDebug::WaitForDbgAttachInfinteLoop( void )
+{
+ MIuint i = 0;
+ while( i == 0 )
+ {
+ const std::chrono::milliseconds time( 100 );
+ std::this_thread::sleep_for( time );
+ }
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+// Instantiations:
+CMICmnLog & CMIUtilDebugFnTrace::ms_rLog = CMICmnLog::Instance();
+MIuint CMIUtilDebugFnTrace::ms_fnDepthCnt = 0;
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilDebugFnTrace constructor.
+// Type: Method.
+// Args: vFnName - (R) The text to insert into the log.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilDebugFnTrace::CMIUtilDebugFnTrace( const CMIUtilString & vFnName )
+: m_strFnName( vFnName )
+{
+ const CMIUtilString txt( CMIUtilString::Format( "%d>%s", ++ms_fnDepthCnt, m_strFnName.c_str() ) );
+ ms_rLog.Write( txt, CMICmnLog::eLogVerbosity_FnTrace );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilDebugFnTrace destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilDebugFnTrace::~CMIUtilDebugFnTrace( void )
+{
+ const CMIUtilString txt( CMIUtilString::Format( "%d<%s", ms_fnDepthCnt--, m_strFnName.c_str() ) );
+ ms_rLog.Write( txt, CMICmnLog::eLogVerbosity_FnTrace );
+}
+
diff --git a/tools/lldb-mi/MIUtilDebug.h b/tools/lldb-mi/MIUtilDebug.h
new file mode 100644
index 000000000000..b163b05f5de5
--- /dev/null
+++ b/tools/lldb-mi/MIUtilDebug.h
@@ -0,0 +1,96 @@
+//===-- MIUtilDebug.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilDebug.h
+//
+// Overview: CMIUtilDebug interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+#define MI_USE_DEBUG_TRACE_FN // Undefine to compile out fn trace code
+
+// In-house headers:
+#include "MIUtilString.h"
+
+// Declarations:
+class CMICmnLog;
+
+//++ ============================================================================
+// Details: MI debugging aid utility class.
+// Gotchas: None.
+// Authors:
+// Changes: None.
+//--
+class CMIUtilDebug
+{
+// Statics:
+public:
+ static void ShowDlgWaitForDbgAttach( void );
+ static void WaitForDbgAttachInfinteLoop( void );
+
+// Methods:
+public:
+ /* ctor */ CMIUtilDebug( void );
+
+// Overrideable:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMIUtilDebug( void );
+};
+
+//++ ============================================================================
+// Details: MI debug utility class. Used to indicate the current function
+// depth in the call stack. It uses the CMIlCmnLog logger to output
+// the current fn trace information.
+// Use macro MI_TRACEFN( "Some fn name" ) and implement the scope of
+// the functions you wish to build up a trace off.
+// Use preprocessor definition MI_USE_DEBUG_TRACE_FN to turn off or on
+// tracing code.
+// Gotchas: None.
+// Authors: Illya Rudkin 07/03/2014.
+// Changes: None.
+//--
+class CMIUtilDebugFnTrace
+{
+// Methods:
+public:
+ /* ctor */ CMIUtilDebugFnTrace( const CMIUtilString & vFnName );
+
+// Overrideable:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMIUtilDebugFnTrace( void );
+
+// Attributes:
+private:
+ const CMIUtilString m_strFnName;
+
+ static CMICmnLog & ms_rLog;
+ static MIuint ms_fnDepthCnt; // Increment count as fn depth increases, decrement count as fn stack pops off
+};
+
+//++ ============================================================================
+// Details: Take the given text and send it to the server's Logger to output to the
+// trace file.
+// Type: Compile preprocess.
+// Args: x - (R) Message (may be seen by user).
+//--
+#ifdef MI_USE_DEBUG_TRACE_FN
+#define MI_TRACEFN( x ) CMIUtilDebugFnTrace __MITrace( x )
+#else
+#define MI_TRACEFN( x )
+#endif // MI_USE_DEBUG_TRACE_FN
diff --git a/tools/lldb-mi/MIUtilFileStd.cpp b/tools/lldb-mi/MIUtilFileStd.cpp
new file mode 100644
index 000000000000..853fd7455680
--- /dev/null
+++ b/tools/lldb-mi/MIUtilFileStd.cpp
@@ -0,0 +1,290 @@
+//===-- MIUtilFileStd.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilFileStd.cpp
+//
+// Overview: CMIUtilFileStd implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers
+#include <stdio.h>
+#include <assert.h>
+#include <string.h> // For strerror()
+#include <cerrno>
+
+// In-house headers:
+#include "MIUtilFileStd.h"
+#include "MICmnResources.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilFileStd constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilFileStd::CMIUtilFileStd( void )
+: m_fileNamePath( CMIUtilString() )
+, m_pFileHandle( nullptr )
+#if defined( _MSC_VER )
+, m_constCharNewLine( "\r\n" )
+#else
+, m_constCharNewLine( "\n" )
+#endif // #if defined( _MSC_VER )
+, m_bFileError( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilFileStd destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilFileStd::~CMIUtilFileStd( void )
+{
+ Close();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Open file for writing. On the first call to this function after *this object
+// is created the file is either created or replace, from then on open only opens
+// an existing file.
+// Type: Method.
+// Args: vFileNamePath - (R) File name path.
+// vwrbNewCreated - (W) True - file recreated, false - file appended too.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilFileStd::CreateWrite( const CMIUtilString & vFileNamePath, bool & vwrbNewCreated )
+{
+ // Reset
+ m_bFileError = false;
+ vwrbNewCreated = false;
+
+ if( vFileNamePath.empty() )
+ {
+ m_bFileError = true;
+ SetErrorDescription( MIRSRC( IDS_UTIL_FILE_ERR_INVALID_PATHNAME ) );
+ return MIstatus::failure;
+ }
+
+ // File is already open so exit
+ if( m_pFileHandle != nullptr )
+ return MIstatus::success;
+
+#if !defined( _MSC_VER )
+ // Open with 'write' and 'binary' mode
+ m_pFileHandle = ::fopen( vFileNamePath.c_str(), "wb" );
+#else
+ // Open a file with exclusive write and shared read permissions
+ m_pFileHandle = ::_fsopen( vFileNamePath.c_str(), "wb", _SH_DENYWR );
+#endif // !defined( _MSC_VER )
+
+ if( m_pFileHandle == nullptr )
+ {
+ m_bFileError = true;
+ SetErrorDescriptionn( MIRSRC( IDS_UTIL_FILE_ERR_OPENING_FILE ), strerror( errno ), vFileNamePath.c_str() );
+ return MIstatus::failure;
+ }
+
+ vwrbNewCreated = true;
+ m_fileNamePath = vFileNamePath;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Write data to existing opened file.
+// Type: Method.
+// Args: vData - (R) Text data.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilFileStd::Write( const CMIUtilString & vData )
+{
+ if( vData.size() == 0 )
+ return MIstatus::success;
+
+ if( m_bFileError )
+ return MIstatus::failure;
+
+ if( m_pFileHandle == nullptr )
+ {
+ m_bFileError = true;
+ SetErrorDescriptionn( MIRSRC( IDE_UTIL_FILE_ERR_WRITING_NOTOPEN ), m_fileNamePath.c_str() );
+ return MIstatus::failure;
+ }
+
+ // Get the string size
+ MIuint size = vData.size();
+ if( ::fwrite( vData.c_str(), 1, size, m_pFileHandle ) == size )
+ {
+ // Flush the data to the file
+ ::fflush( m_pFileHandle );
+ return MIstatus::success;
+ }
+
+ // Not all of the data has been transferred
+ m_bFileError = true;
+ SetErrorDescriptionn( MIRSRC( IDE_UTIL_FILE_ERR_WRITING_FILE ), m_fileNamePath.c_str() );
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Write data to existing opened file.
+// Type: Method.
+// Args: vData - (R) Text data.
+// vCharCnt - (R) Text data length.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilFileStd::Write( const MIchar * vpData, const MIuint vCharCnt )
+{
+ if( vCharCnt == 0 )
+ return MIstatus::success;
+
+ if( m_bFileError )
+ return MIstatus::failure;
+
+ if( m_pFileHandle == nullptr )
+ {
+ m_bFileError = true;
+ SetErrorDescriptionn( MIRSRC( IDE_UTIL_FILE_ERR_WRITING_NOTOPEN ), m_fileNamePath.c_str() );
+ return MIstatus::failure;
+ }
+
+ if( ::fwrite( vpData, 1, vCharCnt, m_pFileHandle ) == vCharCnt )
+ {
+ // Flush the data to the file
+ ::fflush( m_pFileHandle );
+ return MIstatus::success;
+ }
+
+ // Not all of the data has been transferred
+ m_bFileError = true;
+ SetErrorDescriptionn( MIRSRC( IDE_UTIL_FILE_ERR_WRITING_FILE ), m_fileNamePath.c_str() );
+ return MIstatus::failure;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Close existing opened file. Note Close() must must an open!
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMIUtilFileStd::Close( void )
+{
+ if( m_pFileHandle == nullptr )
+ return;
+
+ ::fclose( m_pFileHandle );
+ m_pFileHandle = nullptr;
+ //m_bFileError = false; Do not reset as want to remain until next attempt at open or create
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve state of whether the file is ok.
+// Type: Method.
+// Args: None.
+// Return: True - file ok.
+// False - file has a problem.
+// Throws: None.
+//--
+bool CMIUtilFileStd::IsOk( void ) const
+{
+ return !m_bFileError;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Status on a file existing already.
+// Type: Method.
+// Args: vFileNamePath.
+// Return: True - Exists.
+// False - Not found.
+// Throws: None.
+//--
+bool CMIUtilFileStd::IsFileExist( const CMIUtilString & vFileNamePath ) const
+{
+ if( vFileNamePath.empty() )
+ return false;
+
+ FILE * pTmp = nullptr;
+ pTmp = ::fopen( vFileNamePath.c_str(), "wb" );
+ if( pTmp != nullptr )
+ {
+ ::fclose( pTmp );
+ return true;
+ }
+
+ return false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the file current carriage line return characters used.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString & - Text.
+// Throws: None.
+//--
+const CMIUtilString & CMIUtilFileStd::GetLineReturn( void ) const
+{
+ return m_constCharNewLine;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Given a file name directory path, strip off the filename and return the path.
+// It look for either backslash or forward slash.
+// Type: Method.
+// Args: vDirectoryPath - (R) Text directory path.
+// Return: CMIUtilString - Directory path.
+// Throws: None.
+//--
+CMIUtilString CMIUtilFileStd::StripOffFileName( const CMIUtilString & vDirectoryPath ) const
+{
+ const MIint nPos = vDirectoryPath.rfind( '\\' );
+ MIint nPos2 = vDirectoryPath.rfind( '/' );
+ if( (nPos == (MIint) std::string::npos) && (nPos2 == (MIint) std::string::npos) )
+ return vDirectoryPath;
+
+ if( nPos > nPos2 )
+ nPos2 = nPos;
+
+ const CMIUtilString strPath( vDirectoryPath.substr( 0, nPos2 ).c_str() );
+ return strPath;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Return either backslash or forward slash appropriate to the OS this applilcation
+// is running on.
+// Type: Static method.
+// Args: None.
+// Return: MIchar - '/' or '\' character.
+// Throws: None.
+//--
+MIchar CMIUtilFileStd::GetSlash( void )
+{
+#if !defined( _MSC_VER )
+ return '/';
+#else
+ return '\\';
+#endif // !defined( _MSC_VER )
+}
diff --git a/tools/lldb-mi/MIUtilFileStd.h b/tools/lldb-mi/MIUtilFileStd.h
new file mode 100644
index 000000000000..b6655b2ecfe9
--- /dev/null
+++ b/tools/lldb-mi/MIUtilFileStd.h
@@ -0,0 +1,65 @@
+//===-- MIUtilFileStd.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilFileStd.h
+//
+// Overview: CMIUtilFileStd interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MIUtilString.h"
+#include "MICmnBase.h"
+
+//++ ============================================================================
+// Details: MI common code utility class. File handling.
+// Gotchas: None.
+// Authors: Aidan Dodds 10/03/2014.
+// Changes: None.
+//--
+class CMIUtilFileStd : public CMICmnBase
+{
+// Static:
+public:
+ static MIchar GetSlash( void );
+
+// Methods:
+public:
+ /* ctor */ CMIUtilFileStd( void );
+ //
+ bool CreateWrite( const CMIUtilString & vFileNamePath, bool & vwrbNewCreated );
+ bool Write( const CMIUtilString & vData );
+ bool Write( const MIchar * vpData, const MIuint vCharCnt );
+ void Close( void );
+ bool IsOk( void ) const;
+ bool IsFileExist( const CMIUtilString & vFileNamePath ) const;
+ const CMIUtilString & GetLineReturn( void ) const;
+ CMIUtilString StripOffFileName( const CMIUtilString & vDirectoryPath ) const;
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMIUtilFileStd( void );
+
+// Attributes:
+private:
+ CMIUtilString m_fileNamePath;
+ FILE * m_pFileHandle;
+ CMIUtilString m_constCharNewLine;
+ bool m_bFileError; // True = have a file error ATM, false = all ok
+};
+
diff --git a/tools/lldb-mi/MIUtilMapIdToVariant.cpp b/tools/lldb-mi/MIUtilMapIdToVariant.cpp
new file mode 100644
index 000000000000..485ae2c0f0d2
--- /dev/null
+++ b/tools/lldb-mi/MIUtilMapIdToVariant.cpp
@@ -0,0 +1,124 @@
+//===-- MIUtilMapIdToVariant.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilMapIdToVariant.cpp
+//
+// Overview: CMIUtilMapIdToVariant implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MIUtilMapIdToVariant.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilMapIdToVariant constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilMapIdToVariant::CMIUtilMapIdToVariant( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilMapIdToVariant destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilMapIdToVariant::~CMIUtilMapIdToVariant( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Remove at the data from *this container.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMIUtilMapIdToVariant::Clear( void )
+{
+ m_mapKeyToVariantValue.clear();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Check an ID is present already in *this container.
+// Type: Method.
+// Args: vId - (R) Unique ID i.e. GUID.
+// Return: True - registered.
+// False - not found.
+// Throws: None.
+//--
+bool CMIUtilMapIdToVariant::HaveAlready( const CMIUtilString & vId ) const
+{
+ const MapKeyToVariantValue_t::const_iterator it = m_mapKeyToVariantValue.find( vId );
+ if( it != m_mapKeyToVariantValue.end() )
+ return true;
+
+ return false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine if *this container is currently holding any data.
+// Type: Method.
+// Args: None.
+// Return: bool - True - Yes empty, false - one or more data object present.
+// Throws: None.
+//--
+bool CMIUtilMapIdToVariant::IsEmpty( void ) const
+{
+ return m_mapKeyToVariantValue.empty();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Check the ID is valid to be registered.
+// Type: Method.
+// Args: vId - (R) Unique ID i.e. GUID.
+// Return: True - valid.
+// False - not valid.
+// Throws: None.
+//--
+bool CMIUtilMapIdToVariant::IsValid( const CMIUtilString & vId ) const
+{
+ bool bValid = true;
+
+ if( vId.empty() )
+ bValid = false;
+
+ return bValid;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Remove from *this contain a data object specified by ID. The data object
+// when removed also calls its destructor should it have one.
+// Type: Method.
+// Args: vId - (R) Unique ID i.e. GUID.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilMapIdToVariant::Remove( const CMIUtilString & vId )
+{
+ const MapKeyToVariantValue_t::const_iterator it = m_mapKeyToVariantValue.find( vId );
+ if( it != m_mapKeyToVariantValue.end() )
+ {
+ m_mapKeyToVariantValue.erase( it );
+ }
+
+ return MIstatus::success;
+}
diff --git a/tools/lldb-mi/MIUtilMapIdToVariant.h b/tools/lldb-mi/MIUtilMapIdToVariant.h
new file mode 100644
index 000000000000..9570bfa0306f
--- /dev/null
+++ b/tools/lldb-mi/MIUtilMapIdToVariant.h
@@ -0,0 +1,148 @@
+//===-- MIUtilMapIdToVariant.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilMapIdToVariant.h
+//
+// Overview: CMIUtilMapIdToVariant interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <map>
+
+// In-house headers:
+#include "MICmnBase.h"
+#include "MICmnResources.h"
+#include "MIUtilString.h"
+#include "MIUtilVariant.h"
+
+//++ ============================================================================
+// Details: MI common code utility class. Map type container that hold general
+// object types (by being wrappin an variant wrapper)
+// objects by ID.
+// Gotchas: None.
+// Authors: Illya Rudkin 19/06/2014.
+// Changes: None.
+//--
+class CMIUtilMapIdToVariant : public CMICmnBase
+{
+// Methods:
+public:
+ /* ctor */ CMIUtilMapIdToVariant( void );
+
+ template< typename T >
+ bool Add( const CMIUtilString & vId, const T & vData );
+ void Clear( void );
+ template< typename T >
+ bool Get( const CMIUtilString & vId, T & vrwData, bool & vrwbFound ) const;
+ bool HaveAlready( const CMIUtilString & vId ) const;
+ bool IsEmpty( void ) const;
+ bool Remove( const CMIUtilString & vId );
+
+// Overridden:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMIUtilMapIdToVariant( void );
+
+// Typdefs:
+private:
+ typedef std::map< CMIUtilString, CMIUtilVariant > MapKeyToVariantValue_t;
+ typedef std::pair< CMIUtilString, CMIUtilVariant > MapPairKeyToVariantValue_t;
+
+// Methods:
+private:
+ bool IsValid( const CMIUtilString & vId ) const;
+
+// Attributes:
+ MapKeyToVariantValue_t m_mapKeyToVariantValue;
+};
+
+//++ ------------------------------------------------------------------------------------
+// Details: Add to *this container a data object of general type identified by an ID.
+// If the data with that ID already exists in the container it is replace with
+// the new data specified.
+// Type: Method.
+// Args: T - The data object's variable type.
+// vId - (R) Unique ID i.e. GUID.
+// vData - (R) The general data object to be stored of some type.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+template< typename T >
+bool CMIUtilMapIdToVariant::Add( const CMIUtilString & vId, const T & vData )
+{
+ if( !IsValid( vId ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_VARIANT_ERR_MAP_KEY_INVALID ), vId.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ const bool bOk = HaveAlready( vId ) ? Remove( vId ) : MIstatus::success;
+ if( bOk )
+ {
+ CMIUtilVariant data;
+ data.Set< T >( vData );
+ MapPairKeyToVariantValue_t pr( vId, data );
+ m_mapKeyToVariantValue.insert( pr );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve a data object from *this container identified by the specified ID.
+// Type: Method.
+// Args: T - The data object's variable type.
+// vId - (R) Unique ID i.e. GUID.
+// vrwData - (W) Copy of the data object held.
+// vrwbFound - (W) True = data found, false = data not found.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+template< typename T >
+bool CMIUtilMapIdToVariant::Get( const CMIUtilString & vId, T & vrwData, bool & vrwbFound ) const
+{
+ vrwbFound = false;
+
+ if( !IsValid( vId ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_VARIANT_ERR_MAP_KEY_INVALID ), vId.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ const MapKeyToVariantValue_t::const_iterator it = m_mapKeyToVariantValue.find( vId );
+ if( it != m_mapKeyToVariantValue.end() )
+ {
+ const CMIUtilVariant & rData = (*it).second;
+ const T * pDataObj = rData.Get< T >();
+ if( pDataObj != nullptr )
+ {
+ vrwbFound = true;
+ vrwData = *pDataObj;
+ return MIstatus::success;
+ }
+ else
+ {
+ SetErrorDescription( MIRSRC( IDS_VARIANT_ERR_USED_BASECLASS ) );
+ return MIstatus::failure;
+ }
+ }
+
+ return MIstatus::success;
+}
diff --git a/tools/lldb-mi/MIUtilSingletonBase.h b/tools/lldb-mi/MIUtilSingletonBase.h
new file mode 100644
index 000000000000..23e971014882
--- /dev/null
+++ b/tools/lldb-mi/MIUtilSingletonBase.h
@@ -0,0 +1,71 @@
+//===-- MIUtilSingletonBase.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilSingletonBase.h
+//
+// Overview: MI::ISingleton interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+namespace MI
+{
+
+// MI::ISingleton base class usage:
+//
+// class CMIDerivedClass
+// : public MI::ISingleton< CMIDerivedClass >
+// {
+// friend MI::ISingleton< CMIDerivedClass >;
+//
+// // Overridden:
+// public:
+// // From MI::ISingleton
+// virtual bool Initialize( void );
+// virtual bool Shutdown( void );
+// };
+
+//++ ============================================================================
+// Details: Base class for the singleton pattern.
+// Gotchas: Derived class must specify MI::ISingleton<> as a friend class.
+// Authors: Aidan Dodds 17/03/2014.
+// Changes: None.
+//--
+template< typename T >
+class ISingleton
+{
+// Statics:
+public:
+ // Return an instance of the derived class
+ static T & Instance( void )
+ {
+ // This will fail if the derived class has not
+ // declared itself to be a friend of MI::ISingleton
+ static T instance;
+
+ return instance;
+ }
+
+// Overrideable:
+public:
+ virtual bool Initialize( void ) = 0;
+ virtual bool Shutdown( void ) = 0;
+ //
+ /* dtor */ virtual ~ISingleton( void ) { };
+};
+
+} // namespace MI
+
diff --git a/tools/lldb-mi/MIUtilSingletonHelper.h b/tools/lldb-mi/MIUtilSingletonHelper.h
new file mode 100644
index 000000000000..ad36366830b7
--- /dev/null
+++ b/tools/lldb-mi/MIUtilSingletonHelper.h
@@ -0,0 +1,95 @@
+//===-- MIUtilSingletonHelper.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilSingletonHelper.h
+//
+// Overview: Contains template functions to aid the initialisation and
+// shutdown of MI modules. MI modules (or components) can
+// use other MI modules to help them achieve their one task
+// (Modules only do one task).
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+namespace MI
+{
+
+// In house headers:
+#include "MIUtilString.h"
+#include "MICmnResources.h"
+
+//++ ============================================================================
+// Details: Short cut helper function to simplify repeated initialisation of
+// MI components (singletons) required by a client module.
+// Type: Template method.
+// Args: vErrorResrcId - (R) The string resource ID error message identifier to place in errMsg.
+// vwrbOk - (RW) On input True = Try to initalise MI driver module.
+// On output True = MI driver module initialise successfully.
+// vwrErrMsg - (W) MI driver module initialise error description on failure.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Authors: Aidan Dodds 17/03/2014.
+// Changes: None.
+//--
+template< typename T >
+bool ModuleInit( const MIint vErrorResrcId, bool & vwrbOk, CMIUtilString & vwrErrMsg )
+{
+ if( vwrbOk && !T::Instance().Initialize() )
+ {
+ vwrbOk = MIstatus::failure;
+ vwrErrMsg = CMIUtilString::Format( MIRSRC( vErrorResrcId ), T::Instance().GetErrorDescription().c_str() );
+ }
+
+ return vwrbOk;
+}
+
+//++ ============================================================================
+// Details: Short cut helper function to simplify repeated shutodown of
+// MI components (singletons) required by a client module.
+// Type: Template method.
+// Args: vErrorResrcId - (R) The string resource ID error message identifier
+// to place in errMsg.
+// vwrbOk - (W) If not already false make false on module
+// shutdown failure.
+// vwrErrMsg - (RW) Append to existing error description string MI
+// driver module initialise error description on
+// failure.
+// Return: True - Module shutdown succeeded.
+// False - Module shutdown failed.
+// Authors: Aidan Dodds 17/03/2014.
+// Changes: None.
+//--
+template< typename T >
+bool ModuleShutdown( const MIint vErrorResrcId, bool & vwrbOk, CMIUtilString & vwrErrMsg )
+{
+ bool bOk = MIstatus::success;
+
+ if( !T::Instance().Shutdown() )
+ {
+ const bool bMoreThanOneError( !vwrErrMsg.empty() );
+ bOk = MIstatus::failure;
+ if( bMoreThanOneError )
+ vwrErrMsg += ", ";
+ vwrErrMsg += CMIUtilString::Format( MIRSRC( vErrorResrcId ), T::Instance().GetErrorDescription().c_str() );
+ }
+
+ vwrbOk = bOk ? vwrbOk : MIstatus::failure;
+
+ return bOk;
+}
+
+} // namespace MI
+
diff --git a/tools/lldb-mi/MIUtilString.cpp b/tools/lldb-mi/MIUtilString.cpp
new file mode 100644
index 000000000000..11c246290cab
--- /dev/null
+++ b/tools/lldb-mi/MIUtilString.cpp
@@ -0,0 +1,680 @@
+//===-- MIUtilString.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilString.h
+//
+// Overview: CMIUtilString implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers
+#include <memory> // std::unique_ptr
+#include <stdarg.h> // va_list, va_start, var_end
+#include <sstream> // std::stringstream
+#include <string.h> // for strcpy
+#include <limits.h> // for ULONG_MAX
+
+// In-house headers:
+#include "MIUtilString.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilString constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilString::CMIUtilString( void )
+: std::string()
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilString constructor.
+// Type: Method.
+// Args: vpData - Pointer to UTF8 text data.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilString::CMIUtilString( const MIchar * vpData )
+: std::string( vpData )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilString constructor.
+// Type: Method.
+// Args: vpData - Pointer to UTF8 text data.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilString::CMIUtilString( const MIchar * const * vpData )
+: std::string( (const char *) vpData )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilString assigment operator.
+// Type: Method.
+// Args: vpRhs - Pointer to UTF8 text data.
+// Return: CMIUtilString & - *this string.
+// Throws: None.
+//--
+CMIUtilString & CMIUtilString::operator= ( const MIchar * vpRhs )
+{
+ if( *this == vpRhs )
+ return *this;
+
+ if( vpRhs != nullptr )
+ {
+ assign( vpRhs );
+ }
+
+ return *this;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilString assigment operator.
+// Type: Method.
+// Args: vrRhs - The other string to copy from.
+// Return: CMIUtilString & - *this string.
+// Throws: None.
+//--
+CMIUtilString & CMIUtilString::operator= ( const std::string & vrRhs )
+{
+ if( *this == vrRhs )
+ return *this;
+
+ assign( vrRhs );
+
+ return *this;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilString destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilString::~CMIUtilString( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Perform a snprintf format style on a string data. A new string object is
+// created and returned.
+// Type: Static method.
+// Args: vrFormat - (R) Format string data instruction.
+// vArgs - (R) Var list args of any type.
+// Return: CMIUtilString - Number of splits found in the string data.
+// Throws: None.
+//--
+CMIUtilString CMIUtilString::FormatPriv( const CMIUtilString & vrFormat, va_list vArgs )
+{
+ CMIUtilString strResult;
+ MIint nFinal = 0;
+ MIint n = vrFormat.size();
+
+ // IOR: mysterious crash in this function on some windows builds not able to duplicate
+ // but found article which may be related. Crash occurs in vsnprintf() or va_copy()
+ // Duplicate vArgs va_list argument pointer to ensure that it can be safely used in
+ // a new frame
+ // http://julipedia.meroh.net/2011/09/using-vacopy-to-safely-pass-ap.html
+ va_list argsDup;
+ va_copy( argsDup, vArgs );
+
+ // Create a copy va_list to reset when we spin
+ va_list argsCpy;
+ va_copy( argsCpy, argsDup );
+
+ if( n == 0 )
+ return strResult;
+
+ n = n << 4; // Reserve 16 times as much the length of the vrFormat
+
+ std::unique_ptr< char[] > pFormatted;
+ while( 1 )
+ {
+ pFormatted.reset( new char[ n + 1 ] ); // +1 for safety margin
+ ::strncpy( &pFormatted[ 0 ], vrFormat.c_str(), n );
+
+ // We need to restore the variable argument list pointer to the start again
+ // before running vsnprintf() more then once
+ va_copy( argsDup, argsCpy );
+
+ nFinal = ::vsnprintf( &pFormatted[ 0 ], n, vrFormat.c_str(), argsDup );
+ if( (nFinal < 0) || (nFinal >= n) )
+ n += abs( nFinal - n + 1 );
+ else
+ break;
+ }
+
+ va_end( argsCpy );
+ va_end( argsDup );
+
+ strResult = pFormatted.get();
+
+ return strResult;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Perform a snprintf format style on a string data. A new string object is
+// created and returned.
+// Type: Static method.
+// Args: vrFormat - (R) Format string data instruction.
+// ... - (R) Var list args of any type.
+// Return: CMIUtilString - Number of splits found in the string data.
+// Throws: None.
+//--
+CMIUtilString CMIUtilString::Format( const CMIUtilString & vrFormating, ... )
+{
+ va_list args;
+ va_start( args, vrFormating );
+ CMIUtilString strResult = CMIUtilString::FormatPriv( vrFormating, args );
+ va_end( args );
+
+ return strResult;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Perform a snprintf format style on a string data. A new string object is
+// created and returned.
+// Type: Static method.
+// Args: vrFormat - (R) Format string data instruction.
+// vArgs - (R) Var list args of any type.
+// Return: CMIUtilString - Number of splits found in the string data.
+// Throws: None.
+//--
+CMIUtilString CMIUtilString::FormatValist( const CMIUtilString & vrFormating, va_list vArgs )
+{
+ return CMIUtilString::FormatPriv( vrFormating, vArgs );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Splits string into array of strings using delimiter. If multiple delimiter
+// are found in sequence then they are not added to the list of splits.
+// Type: Method.
+// Args: vData - (R) String data to be split up.
+// vDelimiter - (R) Delimiter char or text.
+// vwVecSplits - (W) Container of splits found in string data.
+// Return: MIuint - Number of splits found in the string data.
+// Throws: None.
+//--
+MIuint CMIUtilString::Split( const CMIUtilString & vDelimiter, VecString_t & vwVecSplits ) const
+{
+ vwVecSplits.clear();
+
+ if( this->empty() || vDelimiter.empty() )
+ return 0;
+
+ MIint nPos = find( vDelimiter );
+ if( nPos == (MIint) std::string::npos )
+ {
+ vwVecSplits.push_back( *this );
+ return 1;
+ }
+ const MIint strLen( length() );
+ if( nPos == strLen )
+ {
+ vwVecSplits.push_back( *this );
+ return 1;
+ }
+
+ MIuint nAdd1( 1 );
+ if( (nPos > 0) && (substr( 0, nPos ) != vDelimiter) )
+ {
+ nPos = 0;
+ nAdd1 = 0;
+ }
+ MIint nPos2 = find( vDelimiter, nPos + 1 );
+ while( nPos2 != (MIint) std::string::npos )
+ {
+ const MIuint len( nPos2 - nPos - nAdd1 );
+ const std::string strSection( substr( nPos + nAdd1, len ) );
+ if( strSection != vDelimiter )
+ vwVecSplits.push_back( strSection.c_str() );
+ nPos += len + 1;
+ nPos2 = find( vDelimiter, nPos + 1 );
+ nAdd1 = 0;
+ }
+ const std::string strSection( substr( nPos, strLen - nPos ) );
+ if( (strSection.length() != 0) && (strSection != vDelimiter) )
+ vwVecSplits.push_back( strSection.c_str() );
+
+ return vwVecSplits.size();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Splits string into array of strings using delimiter. However the string is
+// also considered for text surrounded by quotes. Text with quotes including the
+// delimiter is treated as a whole. If multiple delimiter are found in sequence
+// then they are not added to the list of splits. Quotes that are embedded in the
+// the string as string formatted quotes are ignored (proceeded by a '\\') i.e.
+// "\"MI GDB local C++.cpp\":88".
+// Type: Method.
+// Args: vData - (R) String data to be split up.
+// vDelimiter - (R) Delimiter char or text.
+// vwVecSplits - (W) Container of splits found in string data.
+// Return: MIuint - Number of splits found in the string data.
+// Throws: None.
+//--
+MIuint CMIUtilString::SplitConsiderQuotes( const CMIUtilString & vDelimiter, VecString_t & vwVecSplits ) const
+{
+ vwVecSplits.clear();
+
+ if( this->empty() || vDelimiter.empty() )
+ return 0;
+
+ MIint nPos = find( vDelimiter );
+ if( nPos == (MIint) std::string::npos )
+ {
+ vwVecSplits.push_back( *this );
+ return 1;
+ }
+ const MIint strLen( length() );
+ if( nPos == strLen )
+ {
+ vwVecSplits.push_back( *this );
+ return 1;
+ }
+
+ // Look for more quotes
+ bool bHaveQuotes = false;
+ const MIchar cBckSlash = '\\';
+ const MIchar cQuote = '"';
+ MIint nPosQ = find( cQuote );
+ MIint nPosQ2 = (MIint) std::string::npos;
+ if( nPosQ != (MIint) std::string::npos )
+ {
+ nPosQ2 = nPosQ + 1;
+ while( nPosQ2 < strLen )
+ {
+ nPosQ2 = find( cQuote, nPosQ2 );
+ if( (nPosQ2 == (MIint) std::string::npos) || (at( nPosQ2 - 1 ) != cBckSlash) )
+ break;
+ nPosQ2++;
+ }
+ bHaveQuotes = (nPosQ2 != (MIint) std::string::npos);
+ }
+
+ MIuint nAdd1( 1 );
+ if( (nPos > 0) && (substr( 0, nPos ) != vDelimiter) )
+ {
+ nPos = 0;
+ nAdd1 = 0;
+ }
+ MIint nPos2 = find( vDelimiter, nPos + 1 );
+ while( nPos2 != (MIint) std::string::npos )
+ {
+ if( !bHaveQuotes || (bHaveQuotes && ((nPos2 > nPosQ2) || (nPos2 < nPosQ))) )
+ {
+ // Extract text or quoted text
+ const MIuint len( nPos2 - nPos - nAdd1 );
+ const std::string strSection( substr( nPos + nAdd1, len ) );
+ if( strSection != vDelimiter )
+ vwVecSplits.push_back( strSection.c_str() );
+ nPos += len + 1;
+ nPos2 = find( vDelimiter, nPos + 1 );
+ nAdd1 = 0;
+
+ if( bHaveQuotes && (nPos2 > nPosQ2) )
+ {
+ // Reset, look for more quotes
+ bHaveQuotes = false;
+ nPosQ = find( cQuote, nPos );
+ nPosQ2 = (MIint) std::string::npos;
+ if( nPosQ != (MIint) std::string::npos )
+ {
+ nPosQ2 = find( cQuote, nPosQ + 1 );
+ bHaveQuotes = (nPosQ2 != (MIint) std::string::npos);
+ }
+ }
+ }
+ else
+ {
+ // Skip passed text in quotes
+ nPos2 = find( vDelimiter, nPosQ2 + 1 );
+ }
+ }
+ const std::string strSection( substr( nPos, strLen - nPos ) );
+ if( (strSection.length() != 0) && (strSection != vDelimiter) )
+ vwVecSplits.push_back( strSection.c_str() );
+
+ return vwVecSplits.size();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Remove '\n' from the end of string if found. It does not alter
+// *this string.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - New version of the string.
+// Throws: None.
+//--
+CMIUtilString CMIUtilString::StripCREndOfLine( void ) const
+{
+ const MIint nPos = rfind( '\n' );
+ if( nPos == (MIint) std::string::npos )
+ return *this;
+
+ const CMIUtilString strNew( substr( 0, nPos ).c_str() );
+
+ return strNew;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Remove all '\n' from the string and replace with a space. It does not alter
+// *this string.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - New version of the string.
+// Throws: None.
+//--
+CMIUtilString CMIUtilString::StripCRAll( void ) const
+{
+ return FindAndReplace( "\n", " " );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Find and replace all matches of a sub string with another string. It does not
+// alter *this string.
+// Type: Method.
+// Args: vFind - (R) The string to look for.
+// vReplaceWith - (R) The string to replace the vFind match.
+// Return: CMIUtilString - New version of the string.
+// Throws: None.
+//--
+CMIUtilString CMIUtilString::FindAndReplace( const CMIUtilString & vFind, const CMIUtilString & vReplaceWith ) const
+{
+ if( vFind.empty() || this->empty() )
+ return *this;
+
+ MIint nPos = find( vFind );
+ if( nPos == (MIint) std::string::npos )
+ return *this;
+
+ CMIUtilString strNew( *this );
+ while( nPos != (MIint) std::string::npos )
+ {
+ strNew.replace( nPos, vFind.length(), vReplaceWith );
+ nPos += vReplaceWith.length();
+ nPos = strNew.find( vFind, nPos );
+ }
+
+ return strNew;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Check if *this string is a decimal number.
+// Type: Method.
+// Args: None.
+// Return: bool - True = yes number, false not a number.
+// Throws: None.
+//--
+bool CMIUtilString::IsNumber( void ) const
+{
+ if( empty() )
+ return false;
+
+ if( (at( 0 ) == '-') && (length() == 1) )
+ return false;
+
+ const MIint nPos = find_first_not_of( "-.0123456789" );
+ if( nPos != (MIint) std::string::npos )
+ return false;
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Extract the number from the string. The number can be either a hexadecimal or
+// natural number. It cannot contain other non-numeric characters.
+// Type: Method.
+// Args: vwrNumber - (W) Number exracted from the string.
+// Return: bool - True = yes number, false not a number.
+// Throws: None.
+//--
+bool CMIUtilString::ExtractNumber( MIint64 & vwrNumber ) const
+{
+ vwrNumber = 0;
+
+ if( !IsNumber() )
+ {
+ if( ExtractNumberFromHexadecimal( vwrNumber ) )
+ return true;
+
+ return false;
+ }
+
+ std::stringstream ss( const_cast< CMIUtilString & >( *this ) );
+ ss >> vwrNumber;
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Extract the number from the hexadecimal string..
+// Type: Method.
+// Args: vwrNumber - (W) Number exracted from the string.
+// Return: bool - True = yes number, false not a number.
+// Throws: None.
+//--
+bool CMIUtilString::ExtractNumberFromHexadecimal( MIint64 & vwrNumber ) const
+{
+ vwrNumber = 0;
+
+ const MIint nPos = find_first_not_of( "x01234567890ABCDEFabcedf" );
+ if( nPos != (MIint) std::string::npos )
+ return false;
+
+ const MIint64 nNum = ::strtoul( this->c_str(), nullptr, 16 );
+ if( nNum != ULONG_MAX )
+ {
+ vwrNumber = nNum;
+ return true;
+ }
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine if the text is all valid alpha numeric characters. Letters can be
+// either upper or lower case.
+// Type: Static method.
+// Args: vrText - (R) The text data to examine.
+// Return: bool - True = yes all alpha, false = one or more chars is non alpha.
+// Throws: None.
+//--
+bool CMIUtilString::IsAllValidAlphaAndNumeric( const MIchar & vrText )
+{
+ const MIuint len = ::strlen( &vrText );
+ if( len == 0 )
+ return false;
+
+ MIchar * pPtr = const_cast< MIchar * >( &vrText );
+ for( MIuint i = 0; i < len; i++, pPtr++ )
+ {
+ const MIchar c = *pPtr;
+ if( ::isalnum( (int) c ) == 0 )
+ return false;
+ }
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Check if two strings share equal contents.
+// Type: Method.
+// Args: vrLhs - (R) String A.
+// vrRhs - (R) String B.
+// Return: bool - True = yes equal, false - different.
+// Throws: None.
+//--
+bool CMIUtilString::Compare( const CMIUtilString & vrLhs, const CMIUtilString & vrRhs )
+{
+ // Check the sizes match
+ if( vrLhs.size() != vrRhs.size() )
+ return false;
+
+ return (::strncmp( vrLhs.c_str(), vrRhs.c_str(), vrLhs.size() ) == 0);
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Remove from either end of *this string the following: " \t\n\v\f\r".
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Trimmed string.
+// Throws: None.
+//--
+CMIUtilString CMIUtilString::Trim( void ) const
+{
+ CMIUtilString strNew( *this );
+ const MIchar * pWhiteSpace = " \t\n\v\f\r";
+ const MIint nPos = find_last_not_of( pWhiteSpace );
+ if( nPos != (MIint) std::string::npos )
+ {
+ strNew = substr( 0, nPos + 1 ).c_str();
+ }
+ const MIint nPos2 = strNew.find_first_not_of( pWhiteSpace );
+ if( nPos2 != (MIint) std::string::npos )
+ {
+ strNew = strNew.substr( nPos2 ).c_str();
+ }
+
+ return strNew;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Remove from either end of *this string the specified character.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Trimmed string.
+// Throws: None.
+//--
+CMIUtilString CMIUtilString::Trim( const MIchar vChar ) const
+{
+ CMIUtilString strNew( *this );
+ const MIint nLen = strNew.length();
+ if( nLen > 1 )
+ {
+ if( (strNew[ 0 ] == vChar) && (strNew[ nLen - 1 ] == vChar) )
+ strNew = strNew.substr( 1, nLen - 2 ).c_str();
+ }
+
+ return strNew;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Do a printf equivalent for printing a number in binary i.e. "b%llB".
+// Type: Static method.
+// Args: vnDecimal - (R) The number to represent in binary.
+// Return: CMIUtilString - Binary number in text.
+// Throws: None.
+//--
+CMIUtilString CMIUtilString::FormatBinary( const MIuint64 vnDecimal )
+{
+ CMIUtilString strBinaryNumber;
+
+ const MIuint nConstBits = 64;
+ MIuint nRem[ nConstBits + 1 ];
+ MIint i = 0;
+ MIuint nLen = 0;
+ MIuint64 nNum = vnDecimal;
+ while( (nNum > 0) && (nLen < nConstBits) )
+ {
+ nRem[ i++ ] = nNum % 2;
+ nNum = nNum >> 1;
+ nLen++;
+ }
+ MIchar pN[ nConstBits + 1 ];
+ MIuint j = 0;
+ for( i = nLen; i > 0; --i, j++ )
+ {
+ pN[ j ] = '0' + nRem[ i - 1 ];
+ }
+ pN[ j ] = 0; // String NUL termination
+
+ strBinaryNumber = CMIUtilString::Format( "0b%s", &pN[ 0 ] );
+
+ return strBinaryNumber;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Remove from a string doubled up characters so only one set left. Characters
+// are only removed if the previous character is already a same character.
+// Type: Method.
+// Args: vChar - (R) The character to search for and remove adjacent duplicates.
+// Return: CMIUtilString - New version of the string.
+// Throws: None.
+//--
+CMIUtilString CMIUtilString::RemoveRepeatedCharacters( const MIchar vChar )
+{
+ return RemoveRepeatedCharacters( 0, vChar );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Recursively remove from a string doubled up characters so only one set left.
+// Characters are only removed if the previous character is already a same
+// character.
+// Type: Method.
+// Args: vChar - (R) The character to search for and remove adjacent duplicates.
+// vnPos - (R) Character position in the string.
+// Return: CMIUtilString - New version of the string.
+// Throws: None.
+//--
+CMIUtilString CMIUtilString::RemoveRepeatedCharacters( const MIint vnPos, const MIchar vChar )
+{
+ const MIchar cQuote = '"';
+
+ // Look for first quote of two
+ MIint nPos = find( cQuote, vnPos );
+ if( nPos == (MIint) std::string::npos )
+ return *this;
+
+ const MIint nPosNext = nPos + 1;
+ if( nPosNext > (MIint) length() )
+ return *this;
+
+ if( at( nPosNext ) == cQuote )
+ {
+ *this = substr( 0, nPos ) + substr( nPosNext, length() );
+ RemoveRepeatedCharacters( nPosNext, vChar );
+ }
+
+ return *this;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Is the text in *this string surrounded by quotes.
+// Type: Method.
+// Args: None.
+// Return: bool - True = Yes string is quoted, false = no quoted.
+// Throws: None.
+//--
+bool CMIUtilString::IsQuoted( void ) const
+{
+ const MIchar cQuote = '"';
+
+ if( at( 0 ) != cQuote )
+ return false;
+
+ const MIint nLen = length();
+ if( (nLen > 0) && (at( nLen - 1 ) != cQuote) )
+ return false;
+
+ return true;
+}
+ \ No newline at end of file
diff --git a/tools/lldb-mi/MIUtilString.h b/tools/lldb-mi/MIUtilString.h
new file mode 100644
index 000000000000..30b027a9d314
--- /dev/null
+++ b/tools/lldb-mi/MIUtilString.h
@@ -0,0 +1,85 @@
+//===-- MIUtilString.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilString.h
+//
+// Overview: CMIUtilString interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#include <string>
+#include <vector>
+
+// In-house headers:
+#include "MIDataTypes.h"
+
+//++ ============================================================================
+// Details: MI common code utility class. Used to help handle text.
+// Derived from std::string
+// Gotchas: None.
+// Authors: Illya Rudkin 02/02/2014.
+// Changes: None.
+//--
+class CMIUtilString : public std::string
+{
+// Typdefs:
+public:
+ typedef std::vector< CMIUtilString > VecString_t;
+
+// Static method:
+public:
+ static CMIUtilString Format( const CMIUtilString & vrFormating, ... );
+ static CMIUtilString FormatBinary( const MIuint64 vnDecimal );
+ static CMIUtilString FormatValist( const CMIUtilString & vrFormating, va_list vArgs );
+ static bool IsAllValidAlphaAndNumeric( const MIchar & vrText );
+ static bool Compare( const CMIUtilString & vrLhs, const CMIUtilString & vrRhs );
+
+// Methods:
+public:
+ /* ctor */ CMIUtilString( void );
+ /* ctor */ CMIUtilString( const MIchar * vpData );
+ /* ctor */ CMIUtilString( const MIchar * const * vpData );
+ //
+ bool ExtractNumber( MIint64 & vwrNumber ) const;
+ CMIUtilString FindAndReplace( const CMIUtilString & vFind, const CMIUtilString & vReplaceWith ) const;
+ bool IsNumber( void ) const;
+ bool IsQuoted( void ) const;
+ CMIUtilString RemoveRepeatedCharacters( const MIchar vChar );
+ MIuint Split( const CMIUtilString & vDelimiter, VecString_t & vwVecSplits ) const;
+ MIuint SplitConsiderQuotes( const CMIUtilString & vDelimiter, VecString_t & vwVecSplits ) const;
+ CMIUtilString StripCREndOfLine( void ) const;
+ CMIUtilString StripCRAll( void ) const;
+ CMIUtilString Trim( void ) const;
+ CMIUtilString Trim( const MIchar vChar ) const;
+ //
+ CMIUtilString & operator= ( const MIchar * vpRhs );
+ CMIUtilString & operator= ( const std::string & vrRhs );
+
+// Overrideable:
+public:
+ /* dtor */ virtual ~CMIUtilString( void );
+
+// Static method:
+private:
+ static CMIUtilString FormatPriv( const CMIUtilString & vrFormat, va_list vArgs );
+
+// Methods:
+private:
+ bool ExtractNumberFromHexadecimal( MIint64 & vwrNumber ) const;
+ CMIUtilString RemoveRepeatedCharacters( const MIint vnPos, const MIchar vChar );
+};
diff --git a/tools/lldb-mi/MIUtilSystemLinux.cpp b/tools/lldb-mi/MIUtilSystemLinux.cpp
new file mode 100644
index 000000000000..b1755a32a67e
--- /dev/null
+++ b/tools/lldb-mi/MIUtilSystemLinux.cpp
@@ -0,0 +1,119 @@
+//===-- MIUtilSystemLinux.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilSystemLinux.cpp
+//
+// Overview: CMIUtilSystemLinux implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#if defined( __FreeBSD__ ) || defined( __linux__ )
+
+// In-house headers:
+#include "MIUtilSystemLinux.h"
+#include "MICmnResources.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilSystemLinux constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilSystemLinux::CMIUtilSystemLinux( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilSystemLinux destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilSystemLinux::~CMIUtilSystemLinux( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the OS system error message for the given system error code.
+// Type: Method.
+// Args: vError - (R) OS error code value.
+// vrwErrorMsg - (W) The error message.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilSystemLinux::GetOSErrorMsg( const MIint vError, CMIUtilString & vrwErrorMsg ) const
+{
+ // Reset
+ vrwErrorMsg.clear();
+
+ bool bOk = MIstatus::failure;
+
+ // ToDo: Implement LINUX version
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve if possible the OS last error description.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Error description.
+// Throws: None.
+//--
+CMIUtilString CMIUtilSystemLinux::GetOSLastError( void ) const
+{
+ CMIUtilString errorMsg( "Error fn not implemented " );
+
+ // ToDo: Implement LINUX version
+
+ return errorMsg;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieves the fully qualified path for the this application. If the function
+// fails the string is filled with the error message.
+// Type: Method.
+// Args: vrwFileNamePath - (W) The excutable's name and path or last error description.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilSystemLinux::GetExecutablesPath( CMIUtilString & vrwFileNamePath ) const
+{
+ vrwFileNamePath = CMIUtilString( "." );
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieves the fully qualified path for the Log file for this application.
+// If the function fails the string is filled with the error message.
+// Append a dummy file name on the end of the path. This will be stripped off
+// later and the real log file name replaces it.
+// Type: Method.
+// Args: vrwFileNamePath - (W) The Log file's name and path or last error description.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilSystemLinux::GetLogFilesPath( CMIUtilString & vrwFileNamePath ) const
+{
+ vrwFileNamePath = CMIUtilString( "." );
+ return MIstatus::success;
+}
+
+#endif // #if defined( __linux__ )
diff --git a/tools/lldb-mi/MIUtilSystemLinux.h b/tools/lldb-mi/MIUtilSystemLinux.h
new file mode 100644
index 000000000000..1fd2c525992a
--- /dev/null
+++ b/tools/lldb-mi/MIUtilSystemLinux.h
@@ -0,0 +1,57 @@
+//===-- CMIUtilSystemLinux.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: CMIUtilSystemLinux.h
+//
+// Overview: CMIUtilSystemLinux interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+#if defined( __FreeBSD__ ) || defined( __linux__ )
+
+// In-house headers:
+#include "MIUtilString.h"
+
+//++ ============================================================================
+// Details: MI common code utility class. Used to set or retrieve information
+// about the current system or user.
+// *** If you change, remove or add functionality it must be replicated
+// *** for the all platforms supported; Windows, OSX, LINUX
+// Gotchas: None.
+// Authors: Illya Rudkin 29/01/2014.
+// Changes: None.
+//--
+class CMIUtilSystemLinux
+{
+// Methods:
+public:
+ /* ctor */ CMIUtilSystemLinux( void );
+
+ bool GetOSErrorMsg( const MIint vError, CMIUtilString & vrwErrorMsg ) const;
+ CMIUtilString GetOSLastError( void ) const;
+ bool GetExecutablesPath( CMIUtilString & vrwFileNamePath ) const;
+ bool GetLogFilesPath( CMIUtilString & vrwFileNamePath ) const;
+
+// Overrideable:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMIUtilSystemLinux( void );
+};
+
+typedef CMIUtilSystemLinux CMIUtilSystem;
+
+#endif // #if defined( __linux__ )
diff --git a/tools/lldb-mi/MIUtilSystemOsx.cpp b/tools/lldb-mi/MIUtilSystemOsx.cpp
new file mode 100644
index 000000000000..e291304789d5
--- /dev/null
+++ b/tools/lldb-mi/MIUtilSystemOsx.cpp
@@ -0,0 +1,125 @@
+//===-- MIUtilSystemOsx.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilSystemOsx.cpp
+//
+// Overview: CMIUtilSystemOsx implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#if defined( __APPLE__ )
+
+// In-house headers:
+#include "MIUtilSystemOsx.h"
+#include "MICmnResources.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilSystemOsx constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilSystemOsx::CMIUtilSystemOsx( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilSystemOsx destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilSystemOsx::~CMIUtilSystemOsx( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the OS system error message for the given system error code.
+// Type: Method.
+// Args: vError - (R) OS error code value.
+// vrwErrorMsg - (W) The error message.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilSystemOsx::GetOSErrorMsg( const MIint vError, CMIUtilString & vrwErrorMsg ) const
+{
+ // Reset
+ vrwErrorMsg.clear();
+
+ bool bOk = MIstatus::failure;
+
+ // ToDo: Implement LINUX version
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve if possible the OS last error description.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Error description.
+// Throws: None.
+//--
+CMIUtilString CMIUtilSystemOsx::GetOSLastError( void ) const
+{
+ CMIUtilString errorMsg( "Error fn not implemented" );
+
+ // ToDo: Implement LINUX version
+
+ return errorMsg;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieves the fully qualified path for the this application. If the function
+// fails the string is filled with the error message.
+// Type: Method.
+// Args: vrwFileNamePath - (W) The excutable's name and path or last error description.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilSystemOsx::GetExecutablesPath( CMIUtilString & vrwFileNamePath ) const
+{
+ bool bOk = MIstatus::failure;
+
+ // ToDo: Implement OSX version
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieves the fully qualified path for the Log file for this application.
+// If the function fails the string is filled with the error message.
+// Append a dummy file name on the end of the path. This will be stripped off
+// later and the real log file name replaces it.
+// Type: Method.
+// Args: vrwFileNamePath - (W) The Log file's name and path or last error description.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilSystemOsx::GetLogFilesPath( CMIUtilString & vrwFileNamePath ) const
+{
+ bool bOk = MIstatus::failure;
+
+ // ToDo: Implement OSX version
+
+ return bOk;
+}
+
+#endif // #if defined( __APPLE__ )
diff --git a/tools/lldb-mi/MIUtilSystemOsx.h b/tools/lldb-mi/MIUtilSystemOsx.h
new file mode 100644
index 000000000000..d0825c6e3441
--- /dev/null
+++ b/tools/lldb-mi/MIUtilSystemOsx.h
@@ -0,0 +1,57 @@
+//===-- MICmnConfig.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: CMIUtilSystemOsx.h
+//
+// Overview: CMIUtilSystemOsx interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+#if defined( __APPLE__ )
+
+// In-house headers:
+#include "MIUtilString.h"
+
+//++ ============================================================================
+// Details: MI common code utility class. Used to set or retrieve information
+// about the current system or user.
+// *** If you change, remove or add functionality it must be replicated
+// *** for the all platforms supported; Windows, OSX, LINUX
+// Gotchas: None.
+// Authors: Illya Rudkin 29/01/2014.
+// Changes: None.
+//--
+class CMIUtilSystemOsx
+{
+// Methods:
+public:
+ /* ctor */ CMIUtilSystemOsx( void );
+
+ bool GetOSErrorMsg( const MIint vError, CMIUtilString & vrwErrorMsg ) const;
+ CMIUtilString GetOSLastError( void ) const;
+ bool GetExecutablesPath( CMIUtilString & vrwFileNamePath ) const;
+ bool GetLogFilesPath( CMIUtilString & vrwFileNamePath ) const;
+
+// Overrideable:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMIUtilSystemOsx( void );
+};
+
+typedef CMIUtilSystemOsx CMIUtilSystem;
+
+#endif // #if defined( __APPLE__ )
diff --git a/tools/lldb-mi/MIUtilSystemWindows.cpp b/tools/lldb-mi/MIUtilSystemWindows.cpp
new file mode 100644
index 000000000000..5873aad0ec62
--- /dev/null
+++ b/tools/lldb-mi/MIUtilSystemWindows.cpp
@@ -0,0 +1,151 @@
+//===-- MIUtilSystemWindows.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilSystemWindows.cpp
+//
+// Overview: CMIUtilSystemWindows implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#if defined( _MSC_VER )
+
+// Third party headers
+#include <memory> // std::unique_ptr
+#include <Windows.h>
+#include <WinBase.h> // ::FormatMessage()
+
+// In-house headers:
+#include "MIUtilSystemWindows.h"
+#include "MICmnResources.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilSystemWindows constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilSystemWindows::CMIUtilSystemWindows( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilSystemWindows destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilSystemWindows::~CMIUtilSystemWindows( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the OS system error message for the given system error code.
+// Type: Method.
+// Args: vError - (R) OS error code value.
+// vrwErrorMsg - (W) The error message.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilSystemWindows::GetOSErrorMsg( const MIint vError, CMIUtilString & vrwErrorMsg ) const
+{
+ // Reset
+ vrwErrorMsg.clear();
+
+ const MIuint nBufLen = 1024;
+ std::unique_ptr< char[] > pBuffer;
+ pBuffer.reset( new char[ nBufLen ] );
+
+ // CMIUtilString Format is not used as cannot replicate the behavior of ::FormatMessage which
+ // can take into account locality while retrieving the error message from the system.
+ const int nLength = ::FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, (DWORD) vError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
+ reinterpret_cast< LPTSTR >( &pBuffer[ 0 ] ),
+ nBufLen, nullptr );
+ bool bOk = MIstatus::success;
+ if( nLength != 0 )
+ vrwErrorMsg = &pBuffer[ 0 ];
+ else
+ bOk = MIstatus::failure;
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve if possible the OS last error description.
+// Type: Method.
+// Args: None.
+// Return: CMIUtilString - Error description.
+// Throws: None.
+//--
+CMIUtilString CMIUtilSystemWindows::GetOSLastError( void ) const
+{
+ CMIUtilString errorMsg;
+ const DWORD dwLastError = ::GetLastError();
+ if( dwLastError != 0 )
+ {
+ if( !GetOSErrorMsg( dwLastError, errorMsg ) )
+ errorMsg = MIRSRC( IDE_OS_ERR_RETRIEVING );
+ }
+ else
+ errorMsg = MIRSRC( IDE_OS_ERR_UNKNOWN );
+
+ return errorMsg;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieves the fully qualified path for the this application. If the function
+// fails the string is filled with the error message.
+// Type: Method.
+// Args: vrwFileNamePath - (W) The excutable's name and path or last error description.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilSystemWindows::GetExecutablesPath( CMIUtilString & vrwFileNamePath ) const
+{
+ bool bOk = MIstatus::success;
+ HMODULE hModule = ::GetModuleHandle( nullptr );
+ char pPath[ MAX_PATH ];
+ const DWORD nLen = ::GetModuleFileName( hModule, &pPath[ 0 ], MAX_PATH );
+ const CMIUtilString strLastErr( GetOSLastError() );
+ if( (nLen != 0) && (strLastErr == "Unknown OS error") )
+ vrwFileNamePath = &pPath[ 0 ];
+ else
+ {
+ bOk = MIstatus::failure;
+ vrwFileNamePath = strLastErr;
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieves the fully qualified path for the Log file for this application.
+// If the function fails the string is filled with the error message.
+// Type: Method.
+// Args: vrwFileNamePath - (W) The Log file's name and path or last error description.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilSystemWindows::GetLogFilesPath( CMIUtilString & vrwFileNamePath ) const
+{
+ return GetExecutablesPath( vrwFileNamePath );
+}
+
+#endif // #if defined( _MSC_VER )
diff --git a/tools/lldb-mi/MIUtilSystemWindows.h b/tools/lldb-mi/MIUtilSystemWindows.h
new file mode 100644
index 000000000000..c0d8b543a2f0
--- /dev/null
+++ b/tools/lldb-mi/MIUtilSystemWindows.h
@@ -0,0 +1,56 @@
+//===-- MIUtilSystemWindows.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilSystemWindows.h
+//
+// Overview: CMIUtilSystemWindows interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+#pragma once
+
+#if defined( _MSC_VER )
+
+// In-house headers:
+#include "MIUtilString.h"
+
+//++ ============================================================================
+// Details: MI common code utility class. Used to set or retrieve information
+// about the current system or user.
+// *** If you change, remove or add functionality it must be replicated
+// *** for the all platforms supported; Windows, OSX, LINUX
+// Gotchas: None.
+// Authors: Illya Rudkin 29/01/2014.
+// Changes: None.
+//--
+class CMIUtilSystemWindows
+{
+// Methods:
+public:
+ /* ctor */ CMIUtilSystemWindows( void );
+
+ bool GetOSErrorMsg( const MIint vError, CMIUtilString & vrwErrorMsg ) const;
+ CMIUtilString GetOSLastError( void ) const;
+ bool GetExecutablesPath( CMIUtilString & vrwFileNamePath ) const;
+ bool GetLogFilesPath( CMIUtilString & vrwFileNamePath ) const;
+
+// Overrideable:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMIUtilSystemWindows( void );
+};
+
+typedef CMIUtilSystemWindows CMIUtilSystem;
+
+#endif // #if defined( _MSC_VER )
diff --git a/tools/lldb-mi/MIUtilTermios.cpp b/tools/lldb-mi/MIUtilTermios.cpp
new file mode 100644
index 000000000000..f026436e3fa3
--- /dev/null
+++ b/tools/lldb-mi/MIUtilTermios.cpp
@@ -0,0 +1,69 @@
+//===-- MIUtilTermios.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilTermios.cpp
+//
+// Overview: Terminal setting termios functions.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers:
+#include <stdlib.h>
+
+// In-house headers:
+#include "MIUtilTermios.h"
+#include "Platform.h"
+
+namespace MIUtilTermios
+{
+// Instantiations:
+static bool g_bOldStdinTermiosIsValid = false; // True = yes valid, false = no valid
+static struct termios g_sOldStdinTermios;
+
+//++ ------------------------------------------------------------------------------------
+// Details: Reset the terminal settings. This function is added as an ::atexit handler
+// to make sure we clean up. See StdinTerminosSet().
+// Type: Global function.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void StdinTermiosReset( void )
+{
+ if( g_bOldStdinTermiosIsValid )
+ {
+ g_bOldStdinTermiosIsValid = false;
+ ::tcsetattr( STDIN_FILENO, TCSANOW, &g_sOldStdinTermios );
+ }
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set the terminal settings function. StdinTermiosReset() is called when to
+// reset to this to before and application exit.
+// Type: Global function.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void StdinTermiosSet( void )
+{
+ if( ::tcgetattr( STDIN_FILENO, &g_sOldStdinTermios ) == 0 )
+ {
+ g_bOldStdinTermiosIsValid = true;
+ ::atexit( StdinTermiosReset );
+ }
+}
+
+} // namespace MIUtilTermios
diff --git a/tools/lldb-mi/MIUtilTermios.h b/tools/lldb-mi/MIUtilTermios.h
new file mode 100644
index 000000000000..b38f367b68ea
--- /dev/null
+++ b/tools/lldb-mi/MIUtilTermios.h
@@ -0,0 +1,30 @@
+//===-- MIUtilTermios.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilTermios.h
+//
+// Overview: Terminal setting termios functions.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+namespace MIUtilTermios
+{
+
+extern void StdinTermiosReset( void );
+extern void StdinTermiosSet( void );
+
+} // MIUtilTermios
diff --git a/tools/lldb-mi/MIUtilThreadBaseStd.cpp b/tools/lldb-mi/MIUtilThreadBaseStd.cpp
new file mode 100644
index 000000000000..38f3eb4fae3b
--- /dev/null
+++ b/tools/lldb-mi/MIUtilThreadBaseStd.cpp
@@ -0,0 +1,339 @@
+//===-- MIUtilThreadBaseStd.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilThreadBaseStd.cpp
+//
+// Overview: CMIUtilThread implementation.
+// CMIUtilThreadActiveObjBase implementation.
+// CMIUtilThreadMutex implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third Party Headers:
+#include <assert.h>
+
+// In-house headers:
+#include "MIUtilThreadBaseStd.h"
+#include "MICmnThreadMgrStd.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: Constructor.
+// Type: None.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilThreadActiveObjBase::CMIUtilThreadActiveObjBase( void )
+: m_references( 0 )
+, m_bHasBeenKilled( false )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Destructor.
+// Type: None.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase( void )
+{
+ // Make sure our thread is not alive before we die
+ m_thread.Join();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Check if an object is already running.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilThreadActiveObjBase::ThreadIsActive( void )
+{
+ // Create a new thread to occupy this threads Run() function
+ return m_thread.IsActive();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set up *this thread.
+// Type: Mrthod.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilThreadActiveObjBase::ThreadExecute( void )
+{
+ // Create a new thread to occupy this threads Run() function
+ return m_thread.Start( ThreadEntry, this );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Aquire a reference to CMIUtilThreadActiveObjBase.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilThreadActiveObjBase::Acquire( void )
+{
+ // Access to this function is serial
+ CMIUtilThreadLock serial( m_mutex );
+
+ // >0 == *this thread is alive
+ m_references++;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release a reference to CMIUtilThreadActiveObjBase.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilThreadActiveObjBase::Release( void )
+{
+ // Access to this function is serial
+ CMIUtilThreadLock serial( m_mutex );
+
+ // 0 == kill off *this thread
+ m_references--;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Force this thread to stop, regardless of references
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilThreadActiveObjBase::ThreadKill( void )
+{
+ // Access to this function is serial
+ CMIUtilThreadLock serial( m_mutex );
+
+ // Set this thread to killed status
+ m_bHasBeenKilled = true;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Proxy to thread join.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilThreadActiveObjBase::ThreadJoin( void )
+{
+ return m_thread.Join();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: This function is the entry point of this object thread.
+// It is a trampoline to an instances operation manager.
+// Type: Static method.
+// Args: vpThisClass - (R) From the system (our CMIUtilThreadActiveObjBase from the ctor).
+// Return: MIuint - 0 = success.
+// Throws: None.
+//--
+MIuint CMIUtilThreadActiveObjBase::ThreadEntry( void * vpThisClass )
+{
+ // The argument is a pointer to a CMIUtilThreadActiveObjBase class
+ // as passed from the initialize function, so we can safely cast it.
+ assert( vpThisClass != nullptr );
+ CMIUtilThreadActiveObjBase * pActive = reinterpret_cast< CMIUtilThreadActiveObjBase * >( vpThisClass );
+
+ // Start the management routine of this object
+ pActive->ThreadManage();
+
+ // Thread death
+ return 0;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: This function forms a small management routine, to handle the thread's running.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMIUtilThreadActiveObjBase::ThreadManage( void )
+{
+ bool bAlive = true;
+
+ // Infinite loop
+ while( bAlive )
+ {
+ // Scope the lock while we access m_isDying
+ {
+ // Lock down access to the interface
+ CMIUtilThreadLock serial( m_mutex );
+
+ // Quit the run loop if we are dying
+ if( m_references == 0 )
+ break;
+ }
+ // Execute the run routine
+ if( !ThreadRun( bAlive ) )
+ // Thread's run function failed (MIstatus::failure)
+ break;
+
+ // We will die if we have been signaled to die
+ bAlive &= !m_bHasBeenKilled;
+ }
+
+ // Execute the finish routine just before we die
+ // to give the object a chance to clean up
+ ThreadFinish();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//
+CMIUtilThread::CMIUtilThread( void )
+: m_pThread( nullptr )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilThread destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilThread::~CMIUtilThread( void )
+{
+ Join();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Wait for thread to stop.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilThread::Join( void )
+{
+ if( m_pThread != nullptr )
+ {
+ // Wait for this thread to die
+ m_pThread->join();
+
+ // Scope the thread lock while we modify the pointer
+ {
+ CMIUtilThreadLock _lock( m_mutex );
+ delete m_pThread;
+ m_pThread = nullptr;
+ }
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Is the thread doing work.
+// Type: Method.
+// Args: None.
+// Return: bool - True = Yes active, false = not active.
+// Throws: None.
+//--
+bool CMIUtilThread::IsActive( void )
+{
+ // Lock while we access the thread pointer
+ CMIUtilThreadLock _lock( m_mutex );
+ if( m_pThread == nullptr )
+ return false;
+ else
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Set up *this thread.
+// Type: Method.
+// Args: vpFn (R) - Function pointer to thread's main function.
+// vpArg (R) - Pointer arguments to pass to the thread.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool CMIUtilThread::Start( FnThreadProc vpFn, void * vpArg )
+{
+ // Create the std thread, which starts immediately
+ m_pThread = new std::thread( vpFn, vpArg );
+
+ // We expect to always be able to create one
+ assert( m_pThread != nullptr );
+
+ return MIstatus::success;
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: Take resource.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMIUtilThreadMutex::Lock( void )
+{
+ m_mutex.lock();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resource.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMIUtilThreadMutex::Unlock( void )
+{
+ m_mutex.unlock();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Take resource if available. Immediately return in either case.
+// Type: Method.
+// Args: None.
+// Return: True - mutex has been locked.
+// False - mutex could not be locked.
+// Throws: None.
+//--
+bool CMIUtilThreadMutex::TryLock( void )
+{
+ return m_mutex.try_lock();
+}
+
diff --git a/tools/lldb-mi/MIUtilThreadBaseStd.h b/tools/lldb-mi/MIUtilThreadBaseStd.h
new file mode 100644
index 000000000000..277e14c0fc88
--- /dev/null
+++ b/tools/lldb-mi/MIUtilThreadBaseStd.h
@@ -0,0 +1,170 @@
+//===-- MIUtilThreadBaseStd.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilThreadBaseStd.h
+//
+// Overview: CMIUtilThread interface.
+// CMIUtilThreadActiveObjBase interface.
+// CMIUtilThreadMutex interface.
+// CMIUtilThreadLock interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// Third party headers:
+#ifdef _MSC_VER
+#include <eh.h>
+#endif // _MSC_VER
+#include <thread>
+#include <mutex>
+
+// In-house headers:
+#include "MIDataTypes.h"
+#include "MIUtilString.h"
+
+//++ ============================================================================
+// Details: MI common code utility class. Handle thread mutual exclusion.
+// Embed Mutexes in your Active Object and then use them through Locks.
+// Gotchas: None.
+// Authors: Aidan Dodds 10/03/2014.
+// Changes: None.
+//--
+class CMIUtilThreadMutex
+{
+ // Methods:
+public:
+ /* ctor */ CMIUtilThreadMutex( void ) { };
+ //
+ void Lock( void ); // Wait until mutex can be obtained
+ void Unlock( void ); // Release the mutex
+ bool TryLock( void ); // Gain the lock if available
+
+// Overrideable:
+public:
+ // From CMICmnBase
+ /* dtor */ virtual ~CMIUtilThreadMutex( void ) { };
+
+// Attributes:
+private:
+ std::recursive_mutex m_mutex;
+};
+
+//++ ============================================================================
+// Details: MI common code utility class. Thread object.
+// Gotchas: None.
+// Authors: Aidan Dodds 10/03/2014.
+// Changes: None.
+//--
+class CMIUtilThread
+{
+// Typedef:
+public:
+ typedef MIuint (* FnThreadProc) (void * vpThisClass);
+
+// Methods:
+public:
+ /* ctor */ CMIUtilThread( void );
+ //
+ bool Start( FnThreadProc vpFn, void * vpArg ); // Start execution of this thread
+ bool Join( void ); // Wait for this thread to stop
+ bool IsActive( void ); // Returns true if this thread is running
+
+// Overrideable:
+public:
+ /* dtor */ virtual ~CMIUtilThread( void );
+
+// Methods:
+private:
+ CMIUtilThreadMutex m_mutex;
+ std::thread * m_pThread;
+};
+
+//++ ============================================================================
+// Details: MI common code utility class. Base class for a worker thread active
+// object. Runs an 'captive thread'.
+// Gotchas: None.
+// Authors: Aidan Dodds 10/03/2014..
+// Changes: None.
+//--
+class CMIUtilThreadActiveObjBase
+{
+// Methods:
+public:
+ /* ctor */ CMIUtilThreadActiveObjBase( void );
+ //
+ bool Acquire( void ); // Obtain a reference to this object
+ bool Release( void ); // Release a reference to this object
+ bool ThreadIsActive( void ); // Return true if this object is running
+ bool ThreadJoin( void ); // Wait for this thread to stop running
+ bool ThreadKill( void ); // Force this thread to stop, regardless of references
+ bool ThreadExecute( void ); // Start this objects execution in another thread
+ void ThreadManage( void );
+
+// Overrideable:
+public:
+ /* dtor */ virtual ~CMIUtilThreadActiveObjBase( void );
+ //
+ // Each thread object must supple a unique name that can be used to locate it
+ virtual const CMIUtilString & ThreadGetName( void ) const = 0;
+
+// Statics:
+protected:
+ static MIuint ThreadEntry( void * vpThisClass ); // Thread entry point
+
+// Overrideable:
+protected:
+ virtual bool ThreadRun( bool &vrIsAlive ) = 0; // Call the main worker method
+ virtual bool ThreadFinish( void ) = 0; // Finish of what you were doing
+
+// Attributes:
+protected:
+ volatile MIuint m_references; // Stores the current lifetime state of this thread, 0 = running, > 0 = shutting down
+ volatile bool m_bHasBeenKilled; // Set to true when this thread has been killed
+ CMIUtilThread m_thread; // The execution thread
+ CMIUtilThreadMutex m_mutex; // This mutex allows us to safely communicate with this thread object across the interface from multiple threads
+};
+
+//++ ============================================================================
+// Details: MI common code utility class. Handle thread resource locking.
+// Put Locks inside all the methods of your Active Object that access
+// data shared with the captive thread.
+// Gotchas: None.
+// Authors: Aidan Dodds 10/03/2014.
+// Changes: None.
+//--
+class CMIUtilThreadLock
+{
+// Methods:
+public:
+ /* ctor */
+ CMIUtilThreadLock( CMIUtilThreadMutex & vMutex )
+ : m_rMutex( vMutex )
+ {
+ m_rMutex.Lock();
+ }
+
+// Overrideable:
+public:
+ /* dtor */
+ virtual ~CMIUtilThreadLock( void )
+ {
+ m_rMutex.Unlock();
+ }
+
+// Attributes:
+private:
+ CMIUtilThreadMutex & m_rMutex;
+};
diff --git a/tools/lldb-mi/MIUtilVariant.cpp b/tools/lldb-mi/MIUtilVariant.cpp
new file mode 100644
index 000000000000..1c9ea1c9697f
--- /dev/null
+++ b/tools/lldb-mi/MIUtilVariant.cpp
@@ -0,0 +1,392 @@
+//===-- MIUtilVariant.cpp----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilVariant.cpp
+//
+// Overview: CMIUtilVariant implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Gotchas: See CMIUtilVariant class description.
+//
+// Copyright: None.
+//--
+
+// In-house headers:
+#include "MIUtilVariant.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObjectBase constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant::CDataObjectBase::CDataObjectBase( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObjectBase copy constructor.
+// Type: Method.
+// Args: vrOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant::CDataObjectBase::CDataObjectBase( const CDataObjectBase & vrOther )
+{
+ MIunused( vrOther );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObjectBase copy constructor.
+// Type: Method.
+// Args: vrOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant::CDataObjectBase::CDataObjectBase( CDataObjectBase & vrOther )
+{
+ MIunused( vrOther );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObjectBase move constructor.
+// Type: Method.
+// Args: vrwOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant::CDataObjectBase::CDataObjectBase( CDataObjectBase && vrwOther )
+{
+ MIunused( vrwOther );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObjectBase destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant::CDataObjectBase::~CDataObjectBase( void )
+{
+ Destroy();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObjectBase copy assignment.
+// Type: Method.
+// Args: vrOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant::CDataObjectBase & CMIUtilVariant::CDataObjectBase::operator= ( const CDataObjectBase & vrOther )
+{
+ Copy( vrOther );
+ return *this;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObjectBase move assignment.
+// Type: Method.
+// Args: vrwOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant::CDataObjectBase & CMIUtilVariant::CDataObjectBase::operator= ( CDataObjectBase && vrwOther )
+{
+ Copy( vrwOther );
+ vrwOther.Destroy();
+ return *this;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Create a new copy of *this class.
+// Type: Overrideable.
+// Args: None.
+// Return: CDataObjectBase * - Pointer to a new object.
+// Throws: None.
+//--
+CMIUtilVariant::CDataObjectBase * CMIUtilVariant::CDataObjectBase::CreateCopyOfSelf( void )
+{
+ // Override to implement copying of variant's data object
+ return new CDataObjectBase();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine if *this object is a derived from CDataObjectBase.
+// Type: Overrideable.
+// Args: None.
+// Return: bool - True = *this is derived from CDataObjectBase, false = *this is instance of the this base class.
+// Throws: None.
+//--
+bool CMIUtilVariant::CDataObjectBase::GetIsDerivedClass( void ) const
+{
+ // Override to in the derived class and return true
+ return false;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Perform a bitwise copy of *this object.
+// Type: Overrideable.
+// Args: vrOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+void CMIUtilVariant::CDataObjectBase::Copy( const CDataObjectBase & vrOther )
+{
+ // Override to implement
+ MIunused( vrOther );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release any resources used by *this object.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMIUtilVariant::CDataObjectBase::Destroy( void )
+{
+ // Do nothing - override to implement
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObject copy constructor.
+// Type: Method.
+// Args: T - The object's type.
+// vrOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+template< typename T >
+CMIUtilVariant::CDataObject< T >::CDataObject( const CDataObject & vrOther )
+{
+ if( this == &vrOther )
+ return;
+ Copy( vrOther );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObject copy constructor.
+// Type: Method.
+// Args: T - The object's type.
+// vrOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+template< typename T >
+CMIUtilVariant::CDataObject< T >::CDataObject( CDataObject & vrOther )
+{
+ if( this == &vrOther )
+ return;
+ Copy( vrOther );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObject move constructor.
+// Type: Method.
+// Args: T - The object's type.
+// vrwOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+template< typename T >
+CMIUtilVariant::CDataObject< T >::CDataObject( CDataObject && vrwOther )
+{
+ if( this == &vrwOther )
+ return;
+ Copy( vrwOther );
+ vrwOther.Destroy();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObject copy assignment.
+// Type: Method.
+// Args: T - The object's type.
+// vrOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+template< typename T >
+CMIUtilVariant::CDataObject< T > & CMIUtilVariant::CDataObject< T >::operator= ( const CDataObject & vrOther )
+{
+ if( this == &vrOther )
+ return *this;
+ Copy( vrOther );
+ return *this;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObject move assignment.
+// Type: Method.
+// Args: T - The object's type.
+// vrwOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+template< typename T >
+CMIUtilVariant::CDataObject< T > & CMIUtilVariant::CDataObject< T >::operator= ( CDataObject && vrwOther )
+{
+ if( this == &vrwOther )
+ return *this;
+ Copy( vrwOther );
+ vrwOther.Destroy();
+ return *this;
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilVariant constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant::CMIUtilVariant( void )
+: m_pDataObject( nullptr )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilVariant copy constructor.
+// Type: Method.
+// Args: vrOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant::CMIUtilVariant( const CMIUtilVariant & vrOther )
+: m_pDataObject( nullptr )
+{
+ if( this == &vrOther )
+ return;
+
+ Copy( vrOther );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilVariant copy constructor.
+// Type: Method.
+// Args: vrOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant::CMIUtilVariant( CMIUtilVariant & vrOther )
+: m_pDataObject( nullptr )
+{
+ if( this == &vrOther )
+ return;
+
+ Copy( vrOther );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilVariant move constructor.
+// Type: Method.
+// Args: vrwOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant::CMIUtilVariant( CMIUtilVariant && vrwOther )
+: m_pDataObject( nullptr )
+{
+ if( this == &vrwOther )
+ return;
+
+ Copy( vrwOther );
+ vrwOther.Destroy();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilVariant destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant::~CMIUtilVariant( void )
+{
+ Destroy();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilVariant copy assignment.
+// Type: Method.
+// Args: vrOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant & CMIUtilVariant::operator= ( const CMIUtilVariant & vrOther )
+{
+ if( this == &vrOther )
+ return *this;
+
+ Copy( vrOther );
+ return *this;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilVariant move assignment.
+// Type: Method.
+// Args: vrwOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilVariant & CMIUtilVariant::operator= ( CMIUtilVariant && vrwOther )
+{
+ if( this == &vrwOther )
+ return *this;
+
+ Copy( vrwOther );
+ vrwOther.Destroy();
+ return *this;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release the resources used by *this object.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+void CMIUtilVariant::Destroy( void )
+{
+ if( m_pDataObject != nullptr )
+ delete m_pDataObject;
+ m_pDataObject = nullptr;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Bitwise copy another data object to *this variant object.
+// Type: Method.
+// Args: vrOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+void CMIUtilVariant::Copy( const CMIUtilVariant & vrOther )
+{
+ Destroy();
+
+ if( vrOther.m_pDataObject != nullptr )
+ {
+ m_pDataObject = vrOther.m_pDataObject->CreateCopyOfSelf();
+ }
+}
+
diff --git a/tools/lldb-mi/MIUtilVariant.h b/tools/lldb-mi/MIUtilVariant.h
new file mode 100644
index 000000000000..3cb59796e5c0
--- /dev/null
+++ b/tools/lldb-mi/MIUtilVariant.h
@@ -0,0 +1,288 @@
+//===-- MIUtilVariant.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MIUtilVariant.h
+//
+// Overview: CMIUtilVariant interface.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Gotchas: See CMIUtilVariant class description.
+//
+// Copyright: None.
+//--
+
+#pragma once
+
+// In-house headers:
+#include "MIDataTypes.h"
+
+//++ ============================================================================
+// Details: MI common code utility class. The class implements behaviour of a
+// variant object which holds any data object of type T. A copy of the
+// data object specified is made and stored in *this wrapper. When the
+// *this object is destroyed the data object hold within calls its
+// destructor should it have one.
+// Gotchas: None.
+// Authors: Illya Rudkin 18/06/2014.
+// Changes: None.
+//--
+class CMIUtilVariant
+{
+// Methods:
+public:
+ /* ctor */ CMIUtilVariant( void );
+ /* ctor */ CMIUtilVariant( const CMIUtilVariant & vrOther );
+ /* ctor */ CMIUtilVariant( CMIUtilVariant & vrOther );
+ /* ctor */ CMIUtilVariant( CMIUtilVariant && vrwOther );
+ /* dtor */ ~CMIUtilVariant( void );
+
+ template< typename T >
+ void Set( const T & vArg );
+ template< typename T >
+ T * Get( void ) const;
+
+ CMIUtilVariant & operator= ( const CMIUtilVariant & vrOther );
+ CMIUtilVariant & operator= ( CMIUtilVariant && vrwOther );
+
+// Classes:
+private:
+ //++ ----------------------------------------------------------------------
+ // Details: Base class wrapper to hold the variant's data object when
+ // assigned to it by the Set() function. Do not use the CDataObjectBase
+ // to create objects, use only CDataObjectBase derived objects,
+ // see CDataObject() class.
+ //--
+ class CDataObjectBase
+ {
+ // Methods:
+ public:
+ /* ctor */ CDataObjectBase( void );
+ /* ctor */ CDataObjectBase( const CDataObjectBase & vrOther );
+ /* ctor */ CDataObjectBase( CDataObjectBase & vrOther );
+ /* ctor */ CDataObjectBase( CDataObjectBase && vrwOther );
+ //
+ CDataObjectBase & operator= ( const CDataObjectBase & vrOther ) ;
+ CDataObjectBase & operator= ( CDataObjectBase && vrwOther ) ;
+
+ // Overrideable:
+ public:
+ virtual ~CDataObjectBase( void );
+ virtual CDataObjectBase * CreateCopyOfSelf( void );
+ virtual bool GetIsDerivedClass( void ) const;
+
+ // Overrideable:
+ protected:
+ virtual void Copy( const CDataObjectBase & vrOther );
+ virtual void Destroy( void );
+ };
+
+ //++ ----------------------------------------------------------------------
+ // Details: Derived from CDataObjectBase, this class is the wrapper for the
+ // data object as it has an aggregate of type T which is a copy
+ // of the data object assigned to the variant object.
+ //--
+ template< typename T >
+ class CDataObject : public CDataObjectBase
+ {
+ // Methods:
+ public:
+ /* ctor */ CDataObject( void );
+ /* ctor */ CDataObject( const T & vArg );
+ /* ctor */ CDataObject( const CDataObject & vrOther );
+ /* ctor */ CDataObject( CDataObject & vrOther );
+ /* ctor */ CDataObject( CDataObject && vrwOther );
+ //
+ CDataObject & operator= ( const CDataObject & vrOther );
+ CDataObject & operator= ( CDataObject && vrwOther );
+ //
+ T & GetDataObject( void );
+
+ // Overridden:
+ public:
+ // From CDataObjectBase
+ virtual ~CDataObject( void );
+ virtual CDataObjectBase * CreateCopyOfSelf( void );
+ virtual bool GetIsDerivedClass( void ) const;
+
+ // Overridden:
+ private:
+ // From CDataObjectBase
+ virtual void Copy( const CDataObject & vrOther );
+ virtual void Destroy( void );
+
+ // Attributes:
+ private:
+ T m_dataObj;
+ };
+
+// Methods
+private:
+ void Destroy( void );
+ void Copy( const CMIUtilVariant & vrOther );
+
+// Attributes:
+private:
+ CDataObjectBase * m_pDataObject;
+};
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObject constructor.
+// Type: Method.
+// Args: T - The object's type.
+// Return: None.
+// Throws: None.
+//--
+template< typename T >
+CMIUtilVariant::CDataObject< T >::CDataObject( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObject constructor.
+// Type: Method.
+// Args: T - The object's type.
+// vArg - (R) The data object to be stored in the variant object.
+// Return: None.
+// Throws: None.
+//--
+template< typename T >
+CMIUtilVariant::CDataObject< T >::CDataObject( const T & vArg )
+{
+ m_dataObj = vArg;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CDataObject destructor.
+// Type: Overridden.
+// Args: T - The object's type.
+// Return: None.
+// Throws: None.
+//--
+template< typename T >
+CMIUtilVariant::CDataObject< T >::~CDataObject( void )
+{
+ Destroy();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the data object hold by *this object wrapper.
+// Type: Method.
+// Args: T - The object's type.
+// Return: T & - Reference to the data object.
+// Throws: None.
+//--
+template< typename T >
+T & CMIUtilVariant::CDataObject< T >::GetDataObject( void )
+{
+ return m_dataObj;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Create a new copy of *this class.
+// Type: Overridden.
+// Args: T - The object's type.
+// Return: CDataObjectBase * - Pointer to a new object.
+// Throws: None.
+//--
+template< typename T >
+CMIUtilVariant::CDataObjectBase * CMIUtilVariant::CDataObject< T >::CreateCopyOfSelf( void )
+{
+ CDataObject * pCopy = new CDataObject< T >( m_dataObj );
+
+ return pCopy;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Determine if *this object is a derived from CDataObjectBase.
+// Type: Overridden.
+// Args: T - The object's type.
+// Return: bool - True = *this is derived from CDataObjectBase
+// - False = *this is an instance of the base class.
+// Throws: None.
+//--
+template< typename T >
+bool CMIUtilVariant::CDataObject< T >::GetIsDerivedClass( void ) const
+{
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Perform a bitwise copy of *this object.
+// Type: Overridden.
+// Args: T - The object's type.
+// vrOther - (R) The other object.
+// Return: None.
+// Throws: None.
+//--
+template< typename T >
+void CMIUtilVariant::CDataObject< T >::Copy( const CDataObject & vrOther )
+{
+ CDataObjectBase::Copy( vrOther );
+ m_dataObj = vrOther.m_dataObj;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release any resources used by *this object.
+// Type: Overridden.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+template< typename T >
+void CMIUtilVariant::CDataObject< T >::Destroy( void )
+{
+ CDataObjectBase::Destroy();
+}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: Assign to the variant an object of a specified type.
+// Type: Template method.
+// Args: T - The object's type.
+// vArg - (R) The object to store.
+// Return: None.
+// Throws: None.
+//--
+template< typename T >
+void CMIUtilVariant::Set( const T & vArg )
+{
+ m_pDataObject = new CDataObject< T >( vArg );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the data object from *this variant.
+// Type: Template method.
+// Args: T - The object's type.
+// Return: T * - Pointer the data object, NULL = data object not assigned to *this variant.
+// Throws: None.
+//--
+template< typename T >
+T * CMIUtilVariant::Get( void ) const
+{
+ if( (m_pDataObject != nullptr) && m_pDataObject->GetIsDerivedClass() )
+ {
+ CDataObject< T > * pDataObj = static_cast< CDataObject< T > * >( m_pDataObject );
+ return &pDataObj->GetDataObject();
+ }
+
+ // Do not use a CDataObjectBase object, use only CDataObjectBase derived objects
+ return nullptr;
+}
+
diff --git a/tools/lldb-mi/Platform.cpp b/tools/lldb-mi/Platform.cpp
new file mode 100644
index 000000000000..c0208b3518c0
--- /dev/null
+++ b/tools/lldb-mi/Platform.cpp
@@ -0,0 +1,109 @@
+//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// this file is only relevant for Visual C++
+#if defined( _MSC_VER )
+
+#include <process.h>
+#include <assert.h>
+
+#include "Platform.h"
+
+// the control handler or SIGINT handler
+static sighandler_t _ctrlHandler = NULL;
+
+// the default console control handler
+BOOL
+WINAPI CtrlHandler (DWORD ctrlType)
+{
+ if ( _ctrlHandler != NULL )
+ {
+ _ctrlHandler( 0 );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int
+ioctl (int d, int request, ...)
+{
+ switch ( request )
+ {
+ // request the console windows size
+ case ( TIOCGWINSZ ):
+ {
+ va_list vl;
+ va_start(vl,request);
+ // locate the window size structure on stack
+ winsize *ws = va_arg(vl, winsize*);
+ // get screen buffer information
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ if ( GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &info ) == TRUE )
+ // fill in the columns
+ ws->ws_col = info.dwMaximumWindowSize.X;
+ va_end(vl);
+ return 0;
+ }
+ break;
+ default:
+ assert( !"Not implemented!" );
+ }
+ return -1;
+}
+
+int
+kill (pid_t pid, int sig)
+{
+ // is the app trying to kill itself
+ if ( pid == getpid( ) )
+ exit( sig );
+ //
+ assert( !"Not implemented!" );
+ return -1;
+}
+
+int
+tcsetattr (int fd, int optional_actions, const struct termios *termios_p)
+{
+ assert( !"Not implemented!" );
+ return -1;
+}
+
+int
+tcgetattr (int fildes, struct termios *termios_p)
+{
+// assert( !"Not implemented!" );
+ // error return value (0=success)
+ return -1;
+}
+
+sighandler_t
+signal (int sig, sighandler_t sigFunc)
+{
+ switch ( sig )
+ {
+ case ( SIGINT ):
+ {
+ _ctrlHandler = sigFunc;
+ SetConsoleCtrlHandler( CtrlHandler, TRUE );
+ }
+ break;
+ case ( SIGPIPE ):
+ case ( SIGWINCH ):
+ case ( SIGTSTP ):
+ case ( SIGCONT ):
+ // ignore these for now
+ break;
+ default:
+ assert( !"Not implemented!" );
+ }
+ return 0;
+}
+
+#endif
diff --git a/tools/lldb-mi/Platform.h b/tools/lldb-mi/Platform.h
new file mode 100644
index 000000000000..443eedcef1ee
--- /dev/null
+++ b/tools/lldb-mi/Platform.h
@@ -0,0 +1,109 @@
+//===-- Platform.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#pragma once
+
+#if defined( _MSC_VER )
+
+ // this will stop signal.h being included
+ #define _INC_SIGNAL
+
+ #include <io.h>
+ #include <eh.h>
+ #include <inttypes.h>
+ #include <lldb/Host/windows/Windows.h>
+ #include <lldb/Host/HostGetOpt.h>
+
+ // This is not used by MI
+ struct timeval
+ {
+ long tv_sec;
+ long tv_usec;
+ };
+
+ struct winsize
+ {
+ long ws_col;
+ };
+
+ typedef unsigned char cc_t;
+ typedef unsigned int speed_t;
+ typedef unsigned int tcflag_t;
+
+ // fcntl.h // This is not used by MI
+ #define O_NOCTTY 0400
+
+ // ioctls.h
+ #define TIOCGWINSZ 0x5413
+
+ // tcsetattr arguments
+ #define TCSANOW 0
+
+ #define NCCS 32
+ struct termios
+ {
+ tcflag_t c_iflag; // input mode flags
+ tcflag_t c_oflag; // output mode flags
+ tcflag_t c_cflag; // control mode flags
+ tcflag_t c_lflag; // local mode flags
+ cc_t c_line; // line discipline
+ cc_t c_cc[NCCS]; // control characters
+ speed_t c_ispeed; // input speed
+ speed_t c_ospeed; // output speed
+ };
+
+ typedef long pid_t;
+
+ #define STDIN_FILENO 0
+ #define PATH_MAX MAX_PATH
+ #define snprintf _snprintf
+
+ extern int ioctl( int d, int request, ... );
+ extern int kill ( pid_t pid, int sig );
+ extern int tcsetattr( int fd, int optional_actions, const struct termios *termios_p );
+ extern int tcgetattr( int fildes, struct termios *termios_p );
+
+ // signal handler function pointer type
+ typedef void (*sighandler_t)(int);
+
+ // CODETAG_IOR_SIGNALS
+ // signal.h
+ #define SIGINT 2 // Terminal interrupt signal
+ #define SIGQUIT 3 // Terminal quit signal
+ #define SIGKILL 9 // Kill (cannot be caught or ignored)
+ #define SIGPIPE 13 // Write on a pipe with no one to read it
+ #define SIGCONT 18 // Continue executing, if stopped.
+ #define SIGTSTP 20 // Terminal stop signal
+ #define SIGSTOP 23 // Stop executing (cannot be caught or ignored)
+ #define SIGWINCH 28 // (== SIGVTALRM)
+ #define SIG_DFL ( (sighandler_t) -1 ) // Default handler
+ #define SIG_IGN ( (sighandler_t) -2 ) // Ignored
+
+ extern sighandler_t signal( int sig, sighandler_t );
+
+#else
+
+ #include <inttypes.h>
+
+ #include <getopt.h>
+ #include <libgen.h>
+ #include <sys/ioctl.h>
+ #include <termios.h>
+ #include <unistd.h>
+
+ #include <histedit.h>
+ #include <pthread.h>
+ #include <sys/time.h>
+
+ #if defined(__FreeBSD__)
+ #include <readline/readline.h>
+ #else
+ #include <editline/readline.h>
+ #endif
+
+#endif
diff --git a/tools/lldb-platform/lldb-platform.cpp b/tools/lldb-platform/lldb-platform.cpp
index e18ebabc784d..0ab292aa4afb 100644
--- a/tools/lldb-platform/lldb-platform.cpp
+++ b/tools/lldb-platform/lldb-platform.cpp
@@ -11,7 +11,9 @@
// C Includes
#include <errno.h>
-#include "lldb/Host/HostGetOpt.h"
+#if defined(__APPLE__)
+#include <netinet/in.h>
+#endif
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
@@ -27,6 +29,7 @@
#include "lldb/Core/ConnectionMachPort.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Host/HostGetOpt.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -286,7 +289,7 @@ main (int argc, char *argv[])
bool done = false;
while (!interrupt && !done)
{
- if (!gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done))
+ if (gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done) != GDBRemoteCommunication::PacketResult::Success)
break;
}