aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp')
-rw-r--r--src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp132
1 files changed, 122 insertions, 10 deletions
diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp
index 77e537c275..f60ad90cc9 100644
--- a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp
+++ b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp
@@ -191,6 +191,12 @@ static inline bool isOption(const std::string &opt)
return opt.size() == 2 && opt.at(0) == '-' && opt != "--";
}
+struct CommandToken
+{
+ int majorPart = 0;
+ int minorPart = 0;
+};
+
// Helper for commandTokens() below:
// Simple splitting of command lines allowing for '"'-quoted tokens
// 'typecast local.i "class QString *"' -> ('typecast','local.i','class QString *')
@@ -251,6 +257,38 @@ static inline void splitCommand(PCSTR args, Inserter it)
}
}
+// check whether arguments start with a "-t 23.1" or "-t 3" token identifier
+CommandToken extractToken(PCSTR args, PCSTR *afterToken)
+{
+ CommandToken token;
+ while (*args == ' ') // skip whitespace
+ ++args;
+ if (*args != '-')
+ return {};
+ if (*(++args) != 't')
+ return {};
+ ++args;
+ while (*args == ' ') // skip whitespace
+ ++args;
+ PSTR end = nullptr;
+ token.majorPart = strtol(args, &end, 10);
+ if (args >= end)
+ return {};
+ args = end;
+ if (*args == '.') {
+ ++args;
+ end = nullptr;
+ token.minorPart = strtol(args, &end, 10);
+ if (args >= end)
+ return {};
+ args = end;
+ }
+ while (*args == ' ') // skip whitespace
+ ++args;
+ *afterToken = args;
+ return token;
+}
+
// Split & Parse the arguments of a command and extract the
// optional first integer token argument ('command -t <number> remaining arguments')
// Each command takes the 'token' argument and includes it in its output
@@ -259,18 +297,25 @@ static inline void splitCommand(PCSTR args, Inserter it)
template<class StringContainer>
static inline StringContainer commandTokens(PCSTR args, int *token = 0)
{
- typedef typename StringContainer::iterator ContainerIterator;
+ static std::map<int, std::string> s_commandBuffer;
if (token)
*token = -1; // Handled as 'display' in engine, so that user can type commands
+
StringContainer tokens;
- splitCommand(args, std::back_inserter(tokens));
- // Check for token
- ContainerIterator it = tokens.begin();
- if (it != tokens.end() && *it == "-t" && ++it != tokens.end()) {
- if (token)
- std::istringstream(*it) >> *token;
- tokens.erase(tokens.begin(), ++it);
+ CommandToken commandToken = extractToken(args, &args);
+ if (commandToken.majorPart != 0) {
+ s_commandBuffer[commandToken.majorPart].append(args);
+ if (commandToken.minorPart == 0) {
+ DebugPrint() << commandToken.majorPart << ':' << s_commandBuffer[commandToken.majorPart];
+ splitCommand(s_commandBuffer[commandToken.majorPart].data(), std::back_inserter(tokens));
+ if (token)
+ *token = commandToken.majorPart;
+ } else if (token) {
+ *token = 0;
+ }
+ } else {
+ splitCommand(args, std::back_inserter(tokens));
}
return tokens;
}
@@ -283,6 +328,8 @@ extern "C" HRESULT CALLBACK pid(CIDebugClient *client, PCSTR args)
int token;
commandTokens<StringList>(args, &token);
+ if (token == 0) // partial message
+ return S_OK;
dprintf("Qt Creator CDB extension version 4.3 %d bit.\n",
sizeof(void *) * 8);
if (const ULONG pid = currentProcessId(client))
@@ -304,6 +351,9 @@ extern "C" HRESULT CALLBACK expandlocals(CIDebugClient *client, PCSTR args)
int token;
StringList tokens = commandTokens<StringList>(args, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
StringVector inames;
bool runComplexDumpers = false;
do {
@@ -423,10 +473,12 @@ static std::string commandLocals(ExtensionCommandContext &commandExtCtx,PCSTR ar
typedef InameExpressionMap::value_type InameExpressionMapEntry;
// Parse the command
+ StringList tokens = commandTokens<StringList>(args, token);
+ if (token == 0) // partial arguments
+ return {};
ExtensionContext &extCtx = ExtensionContext::instance();
DumpCommandParameters parameters;
std::string iname;
- StringList tokens = commandTokens<StringList>(args, token);
StringVector expandedInames;
StringVector uninitializedInames;
InameExpressionMap watcherInameExpressionMap;
@@ -577,8 +629,11 @@ extern "C" HRESULT CALLBACK script(CIDebugClient *client, PCSTR argsIn)
ExtensionCommandContext exc(client);
int token;
#ifdef WITH_PYTHON
+ const StringList args = commandTokens<StringList>(argsIn, &token);
+ if (token == 0) // partial arguments
+ return {};
std::stringstream command;
- for (std::string arg : commandTokens<StringList>(argsIn, &token))
+ for (std::string arg : args)
command << arg << ' ';
PyObject *ptype = NULL;
@@ -594,6 +649,8 @@ extern "C" HRESULT CALLBACK script(CIDebugClient *client, PCSTR argsIn)
PyErr_Restore(ptype, pvalue, ptraceback);
#else
commandTokens<StringList>(argsIn, &token);
+ if (token == 0) // partial arguments
+ return {};
ExtensionContext::instance().report('N', token, 0, "script",
"Python is not supported in this CDB extension.\n"
"You need to define PYTHON_INSTALL_DIR in your creator build environment "
@@ -608,6 +665,8 @@ extern "C" HRESULT CALLBACK locals(CIDebugClient *client, PCSTR args)
std::string errorMessage;
int token;
const std::string output = commandLocals(exc, args, &token, &errorMessage);
+ if (token == 0) // partial message
+ return S_OK;
SymbolGroupValue::verbose = 0;
if (output.empty())
ExtensionContext::instance().report('N', token, 0, "locals", errorMessage.c_str());
@@ -625,6 +684,9 @@ static std::string commmandWatches(ExtensionCommandContext &exc, PCSTR args, int
// Parse the command
DumpCommandParameters parameters;
StringList tokens = commandTokens<StringList>(args, token);
+ if (token == 0) // partial message
+ return {};
+
// Parse away options
for (bool optionLeft = true; optionLeft && !tokens.empty(); ) {
switch (parameters.parseOption(&tokens)) {
@@ -662,6 +724,9 @@ extern "C" HRESULT CALLBACK watches(CIDebugClient *client, PCSTR args)
std::string errorMessage = "e";
int token = 0;
const std::string output = commmandWatches(exc, args, &token, &errorMessage);
+ if (token == 0) // partial message
+ return S_OK;
+
SymbolGroupValue::verbose = 0;
if (output.empty())
ExtensionContext::instance().report('N', token, 0, "locals", errorMessage.c_str());
@@ -677,6 +742,9 @@ static std::string dumplocalHelper(ExtensionCommandContext &exc,PCSTR args, int
{
// Parse the command
StringList tokens = commandTokens<StringList>(args, token);
+ if (token == 0) // partial message
+ return {};
+
// Frame and iname
unsigned frame;
if (tokens.empty() || integerFromString(tokens.front(), &frame)) {
@@ -714,6 +782,9 @@ extern "C" HRESULT CALLBACK dumplocal(CIDebugClient *client, PCSTR argsIn)
std::string errorMessage;
int token = 0;
const std::string value = dumplocalHelper(exc,argsIn, &token, &errorMessage);
+ if (token == 0) // partial message
+ return S_OK;
+
if (value.empty())
ExtensionContext::instance().report('N', token, 0, "dumplocal", errorMessage.c_str());
else
@@ -733,6 +804,9 @@ extern "C" HRESULT CALLBACK typecast(CIDebugClient *client, PCSTR args)
int token;
const StringVector tokens = commandTokens<StringVector>(args, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
std::string iname;
std::string desiredType;
if (tokens.size() == 3u && integerFromString(tokens.front(), &frame)) {
@@ -761,6 +835,9 @@ extern "C" HRESULT CALLBACK addsymbol(CIDebugClient *client, PCSTR args)
int token;
const StringVector tokens = commandTokens<StringVector>(args, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
std::string name;
std::string iname;
if (tokens.size() >= 2u && integerFromString(tokens.front(), &frame)) {
@@ -790,6 +867,9 @@ extern "C" HRESULT CALLBACK addwatch(CIDebugClient *client, PCSTR argsIn)
bool success = false;
do {
StringList tokens = commandTokens<StringList>(argsIn, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
if (tokens.size() != 2) {
errorMessage = singleLineUsage(commandDescriptions[CmdAddWatch]);
break;
@@ -903,6 +983,8 @@ extern "C" HRESULT CALLBACK threads(CIDebugClient *client, PCSTR argsIn)
int token;
commandTokens<StringList>(argsIn, &token);
+ if (token == 0) // partial message
+ return S_OK;
const std::string gdbmi = gdbmiThreadList(exc.systemObjects(),
exc.symbols(),
@@ -926,6 +1008,9 @@ extern "C" HRESULT CALLBACK registers(CIDebugClient *Client, PCSTR argsIn)
int token;
const StringList tokens = commandTokens<StringList>(argsIn, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
const bool humanReadable = !tokens.empty() && tokens.front() == "-h";
const std::string regs = gdbmiRegisters(exc.registers(), exc.control(), humanReadable, IncludePseudoRegisters, &errorMessage);
if (regs.empty())
@@ -945,6 +1030,9 @@ extern "C" HRESULT CALLBACK modules(CIDebugClient *Client, PCSTR argsIn)
int token;
const StringList tokens = commandTokens<StringList>(argsIn, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
const bool humanReadable = !tokens.empty() && tokens.front() == "-h";
const std::string modules = gdbmiModules(exc.symbols(), humanReadable, &errorMessage);
if (modules.empty())
@@ -969,6 +1057,9 @@ extern "C" HRESULT CALLBACK setparameter(CIDebugClient *, PCSTR args)
{
int token;
StringVector tokens = commandTokens<StringVector>(args, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
const size_t count = tokens.size();
size_t success = 0;
for (size_t i = 0; i < count; ++i) {
@@ -1034,6 +1125,9 @@ extern "C" HRESULT CALLBACK memory(CIDebugClient *Client, PCSTR argsIn)
ULONG length = 0;
const StringVector tokens = commandTokens<StringVector>(argsIn, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
if (tokens.size() == 2
&& integerFromString(tokens.front(), &address)
&& integerFromString(tokens.at(1), &length)) {
@@ -1061,6 +1155,9 @@ extern "C" HRESULT CALLBACK expression(CIDebugClient *Client, PCSTR argsIn)
do {
const StringVector tokens = commandTokens<StringVector>(argsIn, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
if (tokens.size() != 1) {
errorMessage = singleLineUsage(commandDescriptions[CmdExpression]);
@@ -1090,6 +1187,9 @@ extern "C" HRESULT CALLBACK stack(CIDebugClient *Client, PCSTR argsIn)
unsigned maxFrames = ExtensionContext::instance().parameters().maxStackDepth;
StringList tokens = commandTokens<StringList>(argsIn, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
if (!tokens.empty() && tokens.front() == "-h") {
humanReadable = true;
tokens.pop_front();
@@ -1126,6 +1226,9 @@ extern "C" HRESULT CALLBACK qmlstack(CIDebugClient *client, PCSTR argsIn)
do {
StringList tokens = commandTokens<StringList>(argsIn, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
if (!tokens.empty() && tokens.front() == "-h") {
humanReadable = true;
tokens.pop_front();
@@ -1190,6 +1293,9 @@ extern "C" HRESULT CALLBACK widgetat(CIDebugClient *client, PCSTR argsIn)
int y = -1;
const StringVector tokens = commandTokens<StringVector>(argsIn, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
if (tokens.size() != 2) {
errorMessage = singleLineUsage(commandDescriptions[CmdWidgetAt]);
break;
@@ -1217,6 +1323,9 @@ extern "C" HRESULT CALLBACK breakpoints(CIDebugClient *client, PCSTR argsIn)
bool humanReadable = false;
unsigned verbose = 0;
StringList tokens = commandTokens<StringList>(argsIn, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
while (!tokens.empty() && tokens.front().size() == 2 && tokens.front().at(0) == '-') {
switch (tokens.front().at(1)) {
case 'h':
@@ -1246,6 +1355,9 @@ extern "C" HRESULT CALLBACK test(CIDebugClient *client, PCSTR argsIn)
Mode mode = Invalid;
int token = 0;
StringList tokens = commandTokens<StringList>(argsIn, &token);
+ if (token == 0) // partial message
+ return S_OK;
+
// Parse away options
while (!tokens.empty() && tokens.front().size() == 2 && tokens.front().at(0) == '-') {
const char option = tokens.front().at(1);