forked from qt-creator/qt-creator
Debugger: Split long cdbextension commands
Fixes: QTCREATORBUG-22922 Change-Id: I5def321f0f97717728bc5cdcd5309b458a8ecfa1 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -191,6 +191,12 @@ static inline bool isOption(const std::string &opt)
|
|||||||
return opt.size() == 2 && opt.at(0) == '-' && opt != "--";
|
return opt.size() == 2 && opt.at(0) == '-' && opt != "--";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CommandToken
|
||||||
|
{
|
||||||
|
int majorPart = 0;
|
||||||
|
int minorPart = 0;
|
||||||
|
};
|
||||||
|
|
||||||
// Helper for commandTokens() below:
|
// Helper for commandTokens() below:
|
||||||
// Simple splitting of command lines allowing for '"'-quoted tokens
|
// Simple splitting of command lines allowing for '"'-quoted tokens
|
||||||
// 'typecast local.i "class QString *"' -> ('typecast','local.i','class QString *')
|
// '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
|
// Split & Parse the arguments of a command and extract the
|
||||||
// optional first integer token argument ('command -t <number> remaining arguments')
|
// optional first integer token argument ('command -t <number> remaining arguments')
|
||||||
// Each command takes the 'token' argument and includes it in its output
|
// 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>
|
template<class StringContainer>
|
||||||
static inline StringContainer commandTokens(PCSTR args, int *token = 0)
|
static inline StringContainer commandTokens(PCSTR args, int *token = 0)
|
||||||
{
|
{
|
||||||
typedef typename StringContainer::iterator ContainerIterator;
|
static std::map<int, std::string> s_commandBuffer;
|
||||||
|
|
||||||
if (token)
|
if (token)
|
||||||
*token = -1; // Handled as 'display' in engine, so that user can type commands
|
*token = -1; // Handled as 'display' in engine, so that user can type commands
|
||||||
|
|
||||||
StringContainer tokens;
|
StringContainer tokens;
|
||||||
splitCommand(args, std::back_inserter(tokens));
|
CommandToken commandToken = extractToken(args, &args);
|
||||||
// Check for token
|
if (commandToken.majorPart != 0) {
|
||||||
ContainerIterator it = tokens.begin();
|
s_commandBuffer[commandToken.majorPart].append(args);
|
||||||
if (it != tokens.end() && *it == "-t" && ++it != tokens.end()) {
|
if (commandToken.minorPart == 0) {
|
||||||
|
DebugPrint() << commandToken.majorPart << ':' << s_commandBuffer[commandToken.majorPart];
|
||||||
|
splitCommand(s_commandBuffer[commandToken.majorPart].data(), std::back_inserter(tokens));
|
||||||
if (token)
|
if (token)
|
||||||
std::istringstream(*it) >> *token;
|
*token = commandToken.majorPart;
|
||||||
tokens.erase(tokens.begin(), ++it);
|
} else if (token) {
|
||||||
|
*token = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
splitCommand(args, std::back_inserter(tokens));
|
||||||
}
|
}
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
@@ -283,6 +328,8 @@ extern "C" HRESULT CALLBACK pid(CIDebugClient *client, PCSTR args)
|
|||||||
|
|
||||||
int token;
|
int token;
|
||||||
commandTokens<StringList>(args, &token);
|
commandTokens<StringList>(args, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
dprintf("Qt Creator CDB extension version 4.3 %d bit.\n",
|
dprintf("Qt Creator CDB extension version 4.3 %d bit.\n",
|
||||||
sizeof(void *) * 8);
|
sizeof(void *) * 8);
|
||||||
if (const ULONG pid = currentProcessId(client))
|
if (const ULONG pid = currentProcessId(client))
|
||||||
@@ -304,6 +351,9 @@ extern "C" HRESULT CALLBACK expandlocals(CIDebugClient *client, PCSTR args)
|
|||||||
|
|
||||||
int token;
|
int token;
|
||||||
StringList tokens = commandTokens<StringList>(args, &token);
|
StringList tokens = commandTokens<StringList>(args, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
StringVector inames;
|
StringVector inames;
|
||||||
bool runComplexDumpers = false;
|
bool runComplexDumpers = false;
|
||||||
do {
|
do {
|
||||||
@@ -423,10 +473,12 @@ static std::string commandLocals(ExtensionCommandContext &commandExtCtx,PCSTR ar
|
|||||||
typedef InameExpressionMap::value_type InameExpressionMapEntry;
|
typedef InameExpressionMap::value_type InameExpressionMapEntry;
|
||||||
|
|
||||||
// Parse the command
|
// Parse the command
|
||||||
|
StringList tokens = commandTokens<StringList>(args, token);
|
||||||
|
if (token == 0) // partial arguments
|
||||||
|
return {};
|
||||||
ExtensionContext &extCtx = ExtensionContext::instance();
|
ExtensionContext &extCtx = ExtensionContext::instance();
|
||||||
DumpCommandParameters parameters;
|
DumpCommandParameters parameters;
|
||||||
std::string iname;
|
std::string iname;
|
||||||
StringList tokens = commandTokens<StringList>(args, token);
|
|
||||||
StringVector expandedInames;
|
StringVector expandedInames;
|
||||||
StringVector uninitializedInames;
|
StringVector uninitializedInames;
|
||||||
InameExpressionMap watcherInameExpressionMap;
|
InameExpressionMap watcherInameExpressionMap;
|
||||||
@@ -577,8 +629,11 @@ extern "C" HRESULT CALLBACK script(CIDebugClient *client, PCSTR argsIn)
|
|||||||
ExtensionCommandContext exc(client);
|
ExtensionCommandContext exc(client);
|
||||||
int token;
|
int token;
|
||||||
#ifdef WITH_PYTHON
|
#ifdef WITH_PYTHON
|
||||||
|
const StringList args = commandTokens<StringList>(argsIn, &token);
|
||||||
|
if (token == 0) // partial arguments
|
||||||
|
return {};
|
||||||
std::stringstream command;
|
std::stringstream command;
|
||||||
for (std::string arg : commandTokens<StringList>(argsIn, &token))
|
for (std::string arg : args)
|
||||||
command << arg << ' ';
|
command << arg << ' ';
|
||||||
|
|
||||||
PyObject *ptype = NULL;
|
PyObject *ptype = NULL;
|
||||||
@@ -594,6 +649,8 @@ extern "C" HRESULT CALLBACK script(CIDebugClient *client, PCSTR argsIn)
|
|||||||
PyErr_Restore(ptype, pvalue, ptraceback);
|
PyErr_Restore(ptype, pvalue, ptraceback);
|
||||||
#else
|
#else
|
||||||
commandTokens<StringList>(argsIn, &token);
|
commandTokens<StringList>(argsIn, &token);
|
||||||
|
if (token == 0) // partial arguments
|
||||||
|
return {};
|
||||||
ExtensionContext::instance().report('N', token, 0, "script",
|
ExtensionContext::instance().report('N', token, 0, "script",
|
||||||
"Python is not supported in this CDB extension.\n"
|
"Python is not supported in this CDB extension.\n"
|
||||||
"You need to define PYTHON_INSTALL_DIR in your creator build environment "
|
"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;
|
std::string errorMessage;
|
||||||
int token;
|
int token;
|
||||||
const std::string output = commandLocals(exc, args, &token, &errorMessage);
|
const std::string output = commandLocals(exc, args, &token, &errorMessage);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
SymbolGroupValue::verbose = 0;
|
SymbolGroupValue::verbose = 0;
|
||||||
if (output.empty())
|
if (output.empty())
|
||||||
ExtensionContext::instance().report('N', token, 0, "locals", errorMessage.c_str());
|
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
|
// Parse the command
|
||||||
DumpCommandParameters parameters;
|
DumpCommandParameters parameters;
|
||||||
StringList tokens = commandTokens<StringList>(args, token);
|
StringList tokens = commandTokens<StringList>(args, token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return {};
|
||||||
|
|
||||||
// Parse away options
|
// Parse away options
|
||||||
for (bool optionLeft = true; optionLeft && !tokens.empty(); ) {
|
for (bool optionLeft = true; optionLeft && !tokens.empty(); ) {
|
||||||
switch (parameters.parseOption(&tokens)) {
|
switch (parameters.parseOption(&tokens)) {
|
||||||
@@ -662,6 +724,9 @@ extern "C" HRESULT CALLBACK watches(CIDebugClient *client, PCSTR args)
|
|||||||
std::string errorMessage = "e";
|
std::string errorMessage = "e";
|
||||||
int token = 0;
|
int token = 0;
|
||||||
const std::string output = commmandWatches(exc, args, &token, &errorMessage);
|
const std::string output = commmandWatches(exc, args, &token, &errorMessage);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
SymbolGroupValue::verbose = 0;
|
SymbolGroupValue::verbose = 0;
|
||||||
if (output.empty())
|
if (output.empty())
|
||||||
ExtensionContext::instance().report('N', token, 0, "locals", errorMessage.c_str());
|
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
|
// Parse the command
|
||||||
StringList tokens = commandTokens<StringList>(args, token);
|
StringList tokens = commandTokens<StringList>(args, token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return {};
|
||||||
|
|
||||||
// Frame and iname
|
// Frame and iname
|
||||||
unsigned frame;
|
unsigned frame;
|
||||||
if (tokens.empty() || integerFromString(tokens.front(), &frame)) {
|
if (tokens.empty() || integerFromString(tokens.front(), &frame)) {
|
||||||
@@ -714,6 +782,9 @@ extern "C" HRESULT CALLBACK dumplocal(CIDebugClient *client, PCSTR argsIn)
|
|||||||
std::string errorMessage;
|
std::string errorMessage;
|
||||||
int token = 0;
|
int token = 0;
|
||||||
const std::string value = dumplocalHelper(exc,argsIn, &token, &errorMessage);
|
const std::string value = dumplocalHelper(exc,argsIn, &token, &errorMessage);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
if (value.empty())
|
if (value.empty())
|
||||||
ExtensionContext::instance().report('N', token, 0, "dumplocal", errorMessage.c_str());
|
ExtensionContext::instance().report('N', token, 0, "dumplocal", errorMessage.c_str());
|
||||||
else
|
else
|
||||||
@@ -733,6 +804,9 @@ extern "C" HRESULT CALLBACK typecast(CIDebugClient *client, PCSTR args)
|
|||||||
|
|
||||||
int token;
|
int token;
|
||||||
const StringVector tokens = commandTokens<StringVector>(args, &token);
|
const StringVector tokens = commandTokens<StringVector>(args, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
std::string iname;
|
std::string iname;
|
||||||
std::string desiredType;
|
std::string desiredType;
|
||||||
if (tokens.size() == 3u && integerFromString(tokens.front(), &frame)) {
|
if (tokens.size() == 3u && integerFromString(tokens.front(), &frame)) {
|
||||||
@@ -761,6 +835,9 @@ extern "C" HRESULT CALLBACK addsymbol(CIDebugClient *client, PCSTR args)
|
|||||||
|
|
||||||
int token;
|
int token;
|
||||||
const StringVector tokens = commandTokens<StringVector>(args, &token);
|
const StringVector tokens = commandTokens<StringVector>(args, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string iname;
|
std::string iname;
|
||||||
if (tokens.size() >= 2u && integerFromString(tokens.front(), &frame)) {
|
if (tokens.size() >= 2u && integerFromString(tokens.front(), &frame)) {
|
||||||
@@ -790,6 +867,9 @@ extern "C" HRESULT CALLBACK addwatch(CIDebugClient *client, PCSTR argsIn)
|
|||||||
bool success = false;
|
bool success = false;
|
||||||
do {
|
do {
|
||||||
StringList tokens = commandTokens<StringList>(argsIn, &token);
|
StringList tokens = commandTokens<StringList>(argsIn, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
if (tokens.size() != 2) {
|
if (tokens.size() != 2) {
|
||||||
errorMessage = singleLineUsage(commandDescriptions[CmdAddWatch]);
|
errorMessage = singleLineUsage(commandDescriptions[CmdAddWatch]);
|
||||||
break;
|
break;
|
||||||
@@ -824,6 +904,9 @@ extern "C" HRESULT CALLBACK assign(CIDebugClient *client, PCSTR argsIn)
|
|||||||
int token = 0;
|
int token = 0;
|
||||||
do {
|
do {
|
||||||
StringList tokens = commandTokens<StringList>(argsIn, &token);
|
StringList tokens = commandTokens<StringList>(argsIn, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
if (tokens.empty()) {
|
if (tokens.empty()) {
|
||||||
errorMessage = singleLineUsage(commandDescriptions[CmdAssign]);
|
errorMessage = singleLineUsage(commandDescriptions[CmdAssign]);
|
||||||
break;
|
break;
|
||||||
@@ -883,6 +966,8 @@ extern "C" HRESULT CALLBACK threads(CIDebugClient *client, PCSTR argsIn)
|
|||||||
|
|
||||||
int token;
|
int token;
|
||||||
commandTokens<StringList>(argsIn, &token);
|
commandTokens<StringList>(argsIn, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
const std::string gdbmi = gdbmiThreadList(exc.systemObjects(),
|
const std::string gdbmi = gdbmiThreadList(exc.systemObjects(),
|
||||||
exc.symbols(),
|
exc.symbols(),
|
||||||
@@ -906,6 +991,9 @@ extern "C" HRESULT CALLBACK registers(CIDebugClient *Client, PCSTR argsIn)
|
|||||||
|
|
||||||
int token;
|
int token;
|
||||||
const StringList tokens = commandTokens<StringList>(argsIn, &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 bool humanReadable = !tokens.empty() && tokens.front() == "-h";
|
||||||
const std::string regs = gdbmiRegisters(exc.registers(), exc.control(), humanReadable, IncludePseudoRegisters, &errorMessage);
|
const std::string regs = gdbmiRegisters(exc.registers(), exc.control(), humanReadable, IncludePseudoRegisters, &errorMessage);
|
||||||
if (regs.empty())
|
if (regs.empty())
|
||||||
@@ -925,6 +1013,9 @@ extern "C" HRESULT CALLBACK modules(CIDebugClient *Client, PCSTR argsIn)
|
|||||||
|
|
||||||
int token;
|
int token;
|
||||||
const StringList tokens = commandTokens<StringList>(argsIn, &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 bool humanReadable = !tokens.empty() && tokens.front() == "-h";
|
||||||
const std::string modules = gdbmiModules(exc.symbols(), humanReadable, &errorMessage);
|
const std::string modules = gdbmiModules(exc.symbols(), humanReadable, &errorMessage);
|
||||||
if (modules.empty())
|
if (modules.empty())
|
||||||
@@ -949,6 +1040,9 @@ extern "C" HRESULT CALLBACK setparameter(CIDebugClient *, PCSTR args)
|
|||||||
{
|
{
|
||||||
int token;
|
int token;
|
||||||
StringVector tokens = commandTokens<StringVector>(args, &token);
|
StringVector tokens = commandTokens<StringVector>(args, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
const size_t count = tokens.size();
|
const size_t count = tokens.size();
|
||||||
size_t success = 0;
|
size_t success = 0;
|
||||||
for (size_t i = 0; i < count; ++i) {
|
for (size_t i = 0; i < count; ++i) {
|
||||||
@@ -1014,6 +1108,9 @@ extern "C" HRESULT CALLBACK memory(CIDebugClient *Client, PCSTR argsIn)
|
|||||||
ULONG length = 0;
|
ULONG length = 0;
|
||||||
|
|
||||||
const StringVector tokens = commandTokens<StringVector>(argsIn, &token);
|
const StringVector tokens = commandTokens<StringVector>(argsIn, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
if (tokens.size() == 2
|
if (tokens.size() == 2
|
||||||
&& integerFromString(tokens.front(), &address)
|
&& integerFromString(tokens.front(), &address)
|
||||||
&& integerFromString(tokens.at(1), &length)) {
|
&& integerFromString(tokens.at(1), &length)) {
|
||||||
@@ -1041,6 +1138,9 @@ extern "C" HRESULT CALLBACK expression(CIDebugClient *Client, PCSTR argsIn)
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
const StringVector tokens = commandTokens<StringVector>(argsIn, &token);
|
const StringVector tokens = commandTokens<StringVector>(argsIn, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
if (tokens.size() != 1) {
|
if (tokens.size() != 1) {
|
||||||
|
|
||||||
errorMessage = singleLineUsage(commandDescriptions[CmdExpression]);
|
errorMessage = singleLineUsage(commandDescriptions[CmdExpression]);
|
||||||
@@ -1070,6 +1170,9 @@ extern "C" HRESULT CALLBACK stack(CIDebugClient *Client, PCSTR argsIn)
|
|||||||
unsigned maxFrames = ExtensionContext::instance().parameters().maxStackDepth;
|
unsigned maxFrames = ExtensionContext::instance().parameters().maxStackDepth;
|
||||||
|
|
||||||
StringList tokens = commandTokens<StringList>(argsIn, &token);
|
StringList tokens = commandTokens<StringList>(argsIn, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
if (!tokens.empty() && tokens.front() == "-h") {
|
if (!tokens.empty() && tokens.front() == "-h") {
|
||||||
humanReadable = true;
|
humanReadable = true;
|
||||||
tokens.pop_front();
|
tokens.pop_front();
|
||||||
@@ -1106,6 +1209,9 @@ extern "C" HRESULT CALLBACK qmlstack(CIDebugClient *client, PCSTR argsIn)
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
StringList tokens = commandTokens<StringList>(argsIn, &token);
|
StringList tokens = commandTokens<StringList>(argsIn, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
if (!tokens.empty() && tokens.front() == "-h") {
|
if (!tokens.empty() && tokens.front() == "-h") {
|
||||||
humanReadable = true;
|
humanReadable = true;
|
||||||
tokens.pop_front();
|
tokens.pop_front();
|
||||||
@@ -1170,6 +1276,9 @@ extern "C" HRESULT CALLBACK widgetat(CIDebugClient *client, PCSTR argsIn)
|
|||||||
int y = -1;
|
int y = -1;
|
||||||
|
|
||||||
const StringVector tokens = commandTokens<StringVector>(argsIn, &token);
|
const StringVector tokens = commandTokens<StringVector>(argsIn, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
if (tokens.size() != 2) {
|
if (tokens.size() != 2) {
|
||||||
errorMessage = singleLineUsage(commandDescriptions[CmdWidgetAt]);
|
errorMessage = singleLineUsage(commandDescriptions[CmdWidgetAt]);
|
||||||
break;
|
break;
|
||||||
@@ -1197,6 +1306,9 @@ extern "C" HRESULT CALLBACK breakpoints(CIDebugClient *client, PCSTR argsIn)
|
|||||||
bool humanReadable = false;
|
bool humanReadable = false;
|
||||||
unsigned verbose = 0;
|
unsigned verbose = 0;
|
||||||
StringList tokens = commandTokens<StringList>(argsIn, &token);
|
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) == '-') {
|
while (!tokens.empty() && tokens.front().size() == 2 && tokens.front().at(0) == '-') {
|
||||||
switch (tokens.front().at(1)) {
|
switch (tokens.front().at(1)) {
|
||||||
case 'h':
|
case 'h':
|
||||||
@@ -1226,6 +1338,9 @@ extern "C" HRESULT CALLBACK test(CIDebugClient *client, PCSTR argsIn)
|
|||||||
Mode mode = Invalid;
|
Mode mode = Invalid;
|
||||||
int token = 0;
|
int token = 0;
|
||||||
StringList tokens = commandTokens<StringList>(argsIn, &token);
|
StringList tokens = commandTokens<StringList>(argsIn, &token);
|
||||||
|
if (token == 0) // partial message
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
// Parse away options
|
// Parse away options
|
||||||
while (!tokens.empty() && tokens.front().size() == 2 && tokens.front().at(0) == '-') {
|
while (!tokens.empty() && tokens.front().size() == 2 && tokens.front().at(0) == '-') {
|
||||||
const char option = tokens.front().at(1);
|
const char option = tokens.front().at(1);
|
||||||
|
@@ -959,6 +959,13 @@ void CdbEngine::executeDebuggerCommand(const QString &command)
|
|||||||
// Post command to the cdb process
|
// Post command to the cdb process
|
||||||
void CdbEngine::runCommand(const DebuggerCommand &dbgCmd)
|
void CdbEngine::runCommand(const DebuggerCommand &dbgCmd)
|
||||||
{
|
{
|
||||||
|
constexpr int maxCommandLength = 4096;
|
||||||
|
constexpr int maxTokenLength = 4 /*" -t "*/
|
||||||
|
+ 5 /* 99999 tokens should be enough for a single qc run time*/
|
||||||
|
+ 1 /* token part splitter '.' */
|
||||||
|
+ 3 /* 1000 parts should also be more than enough */
|
||||||
|
+ 1 /* final space */;
|
||||||
|
|
||||||
QString cmd = dbgCmd.function + dbgCmd.argsToString();
|
QString cmd = dbgCmd.function + dbgCmd.argsToString();
|
||||||
if (!m_accessible) {
|
if (!m_accessible) {
|
||||||
doInterruptInferior([this, dbgCmd](){
|
doInterruptInferior([this, dbgCmd](){
|
||||||
@@ -970,11 +977,26 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dbgCmd.flags == ScriptCommand) {
|
||||||
|
// repack script command into an extension command
|
||||||
|
DebuggerCommand newCmd("script", ExtensionCommand, dbgCmd.callback);
|
||||||
|
if (!dbgCmd.args.isNull())
|
||||||
|
newCmd.args = QString{dbgCmd.function + '(' + dbgCmd.argsToPython() + ')'};
|
||||||
|
else
|
||||||
|
newCmd.args = dbgCmd.function;
|
||||||
|
runCommand(newCmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QString fullCmd;
|
QString fullCmd;
|
||||||
if (dbgCmd.flags == NoFlags) {
|
if (dbgCmd.flags == NoFlags) {
|
||||||
fullCmd = cmd;
|
fullCmd = cmd + '\n';
|
||||||
|
if (fullCmd.length() > maxCommandLength) {
|
||||||
|
showMessage("Command is longer than 4096 characters execution will likely fail.",
|
||||||
|
LogWarning);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const int token = m_nextCommandToken++;
|
const int token = ++m_nextCommandToken;
|
||||||
StringInputStream str(fullCmd);
|
StringInputStream str(fullCmd);
|
||||||
if (dbgCmd.flags == BuiltinCommand) {
|
if (dbgCmd.flags == BuiltinCommand) {
|
||||||
// Post a built-in-command producing free-format output with a callback.
|
// Post a built-in-command producing free-format output with a callback.
|
||||||
@@ -982,23 +1004,35 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd)
|
|||||||
// printing a specially formatted token to be identifiable in the output.
|
// printing a specially formatted token to be identifiable in the output.
|
||||||
str << ".echo \"" << m_tokenPrefix << token << "<\"\n"
|
str << ".echo \"" << m_tokenPrefix << token << "<\"\n"
|
||||||
<< cmd << "\n"
|
<< cmd << "\n"
|
||||||
<< ".echo \"" << m_tokenPrefix << token << ">\"";
|
<< ".echo \"" << m_tokenPrefix << token << ">\"" << '\n';
|
||||||
|
if (fullCmd.length() > maxCommandLength) {
|
||||||
|
showMessage("Command is longer than 4096 characters execution will likely fail.",
|
||||||
|
LogWarning);
|
||||||
|
}
|
||||||
} else if (dbgCmd.flags == ExtensionCommand) {
|
} else if (dbgCmd.flags == ExtensionCommand) {
|
||||||
|
|
||||||
// Post an extension command producing one-line output with a callback,
|
// Post an extension command producing one-line output with a callback,
|
||||||
// pass along token for identification in hash.
|
// pass along token for identification in hash.
|
||||||
str << m_extensionCommandPrefix << dbgCmd.function << "%1%2";
|
const QString prefix = m_extensionCommandPrefix + dbgCmd.function;
|
||||||
if (dbgCmd.args.isString())
|
QList<QStringRef> splittedArguments;
|
||||||
str << ' ' << dbgCmd.argsToString();
|
if (dbgCmd.args.isString()) {
|
||||||
cmd = fullCmd.arg("", "");
|
const QString &arguments = dbgCmd.argsToString();
|
||||||
fullCmd = fullCmd.arg(" -t ").arg(token);
|
cmd = prefix + arguments;
|
||||||
} else if (dbgCmd.flags == ScriptCommand) {
|
int argumentSplitPos = 0;
|
||||||
// Add extension prefix and quotes the script command
|
QList<QStringRef> splittedArguments;
|
||||||
// pass along token for identification in hash.
|
int maxArgumentSize = maxCommandLength - prefix.length() - maxTokenLength;
|
||||||
str << m_extensionCommandPrefix + "script %1%2 " << dbgCmd.function;
|
while (argumentSplitPos < arguments.size()) {
|
||||||
if (!dbgCmd.args.isNull())
|
splittedArguments << arguments.midRef(argumentSplitPos, maxArgumentSize);
|
||||||
str << '(' << dbgCmd.argsToPython() << ')';
|
argumentSplitPos += splittedArguments.last().length();
|
||||||
cmd = fullCmd.arg("", "");
|
}
|
||||||
fullCmd = fullCmd.arg(" -t ").arg(token);
|
QTC_CHECK(argumentSplitPos == arguments.size());
|
||||||
|
int tokenPart = splittedArguments.size();
|
||||||
|
for (const QStringRef part : qAsConst(splittedArguments))
|
||||||
|
str << prefix << " -t " << token << '.' << --tokenPart << ' ' << part << '\n';
|
||||||
|
} else {
|
||||||
|
cmd = prefix;
|
||||||
|
str << prefix << " -t " << token << '.' << 0 << '\n';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_commandForToken.insert(token, dbgCmd);
|
m_commandForToken.insert(token, dbgCmd);
|
||||||
}
|
}
|
||||||
@@ -1011,7 +1045,7 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd)
|
|||||||
qDebug("CdbEngine::postCommand: resulting command '%s'\n", qPrintable(fullCmd));
|
qDebug("CdbEngine::postCommand: resulting command '%s'\n", qPrintable(fullCmd));
|
||||||
}
|
}
|
||||||
showMessage(cmd, LogInput);
|
showMessage(cmd, LogInput);
|
||||||
m_process.write(fullCmd.toLocal8Bit() + '\n');
|
m_process.write(fullCmd.toLocal8Bit());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbEngine::activateFrame(int index)
|
void CdbEngine::activateFrame(int index)
|
||||||
|
@@ -42,6 +42,7 @@ public:
|
|||||||
StringInputStream &operator<<(char a) { m_target.append(a); return *this; }
|
StringInputStream &operator<<(char a) { m_target.append(a); return *this; }
|
||||||
StringInputStream &operator<<(const char *a) { m_target.append(QString::fromUtf8(a)); return *this; }
|
StringInputStream &operator<<(const char *a) { m_target.append(QString::fromUtf8(a)); return *this; }
|
||||||
StringInputStream &operator<<(const QString &a) { m_target.append(a); return *this; }
|
StringInputStream &operator<<(const QString &a) { m_target.append(a); return *this; }
|
||||||
|
StringInputStream &operator<<(const QStringRef &a) { m_target.append(a); return *this; }
|
||||||
|
|
||||||
StringInputStream &operator<<(int i) { appendInt(i); return *this; }
|
StringInputStream &operator<<(int i) { appendInt(i); return *this; }
|
||||||
StringInputStream &operator<<(unsigned i) { appendInt(i); return *this; }
|
StringInputStream &operator<<(unsigned i) { appendInt(i); return *this; }
|
||||||
|
Reference in New Issue
Block a user