You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1423 lines
37 KiB
1423 lines
37 KiB
/*
|
|
* Copyright Johannes Sixt, Keith Isdale
|
|
* This file is licensed under the GNU General Public License Version 2.
|
|
* See the file COPYING in the toplevel directory of the source directory.
|
|
*/
|
|
|
|
#include "xsldbgdriver.h"
|
|
#include "exprwnd.h"
|
|
#include <tqstringlist.h>
|
|
#include <tdelocale.h> /* i18n */
|
|
#include <ctype.h>
|
|
#include <stdlib.h> /* strtol, atoi */
|
|
#include <string.h> /* strcpy */
|
|
#include <tdemessagebox.h>
|
|
|
|
#include "assert.h"
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
#include "mydebug.h"
|
|
|
|
|
|
static ExprValue *parseVar(const char *&s);
|
|
static bool parseName(const char *&s, TQString & name,
|
|
VarTree::NameKind & kind);
|
|
static bool parseValue(const char *&s, ExprValue * variable);
|
|
static bool isErrorExpr(const char *output);
|
|
|
|
#define TERM_IO_ALLOWED 1
|
|
|
|
// TODO: make this cmd info stuff non-static to allow multiple
|
|
// simultaneous gdbs to run!
|
|
|
|
struct XsldbgCmdInfo {
|
|
DbgCommand cmd;
|
|
const char *fmt; /* format string */
|
|
enum Args {
|
|
argNone, argString, argNum,
|
|
argStringNum, argNumString,
|
|
argString2, argNum2
|
|
} argsNeeded;
|
|
};
|
|
|
|
/*
|
|
* The following array of commands must be sorted by the DC* values,
|
|
* because they are used as indices.
|
|
*/
|
|
static XsldbgCmdInfo cmds[] = {
|
|
{DCinitialize, "init\n", XsldbgCmdInfo::argNone},
|
|
{DCtty, "tty %s\n", XsldbgCmdInfo::argString},
|
|
{DCexecutable, "source %s\n", XsldbgCmdInfo::argString}, /* force a restart */
|
|
{DCtargetremote, "print 'target remote %s'\n", XsldbgCmdInfo::argString},
|
|
{DCcorefile, "data %s\n", XsldbgCmdInfo::argString}, /* force a restart */
|
|
{DCattach, "print 'attach %s'\n", XsldbgCmdInfo::argString},
|
|
{DCinfolinemain, "print 'info main line'\n", XsldbgCmdInfo::argNone},
|
|
{DCinfolocals, "locals -f\n", XsldbgCmdInfo::argNone},
|
|
{DCinforegisters, "print 'info reg'\n", XsldbgCmdInfo::argNone},
|
|
{DCexamine, "print 'x %s %s'\n", XsldbgCmdInfo::argString2},
|
|
{DCinfoline, "print 'templates %s:%d'\n", XsldbgCmdInfo::argStringNum},
|
|
{DCdisassemble, "print 'disassemble %s %s'\n", XsldbgCmdInfo::argString2},
|
|
{DCsetargs, "data %s\n", XsldbgCmdInfo::argString},
|
|
{DCsetenv, "addparam %s %s\n", XsldbgCmdInfo::argString2},
|
|
{DCunsetenv, "unset env %s\n", XsldbgCmdInfo::argString},
|
|
{DCsetoption, "setoption %s %d\n", XsldbgCmdInfo::argStringNum},
|
|
{DCcd, "chdir %s\n", XsldbgCmdInfo::argString},
|
|
{DCbt, "where\n", XsldbgCmdInfo::argNone},
|
|
{DCrun, "run\nsource\n", XsldbgCmdInfo::argNone}, /* Ensure that at the start
|
|
of executing XSLT we show the XSLT file */
|
|
{DCcont, "continue\n", XsldbgCmdInfo::argNone},
|
|
{DCstep, "step\n", XsldbgCmdInfo::argNone},
|
|
{DCstepi, "step\n", XsldbgCmdInfo::argNone},
|
|
{DCnext, "next\n", XsldbgCmdInfo::argNone},
|
|
{DCnexti, "next\n", XsldbgCmdInfo::argNone},
|
|
{DCfinish, "stepup\n", XsldbgCmdInfo::argNone},
|
|
{DCuntil, "continue %s:%d\n", XsldbgCmdInfo::argStringNum},
|
|
{DCkill, "quit\n", XsldbgCmdInfo::argNone},
|
|
{DCbreaktext, "break %s\n", XsldbgCmdInfo::argString},
|
|
{DCbreakline, "break -l %s %d\n", XsldbgCmdInfo::argStringNum},
|
|
{DCtbreakline, "break -l %s %d\n", XsldbgCmdInfo::argStringNum },
|
|
{DCbreakaddr, "print `break *%s`\n", XsldbgCmdInfo::argString },
|
|
{DCtbreakaddr, "print `tbreak *%s`\n", XsldbgCmdInfo::argString },
|
|
{DCwatchpoint, "print 'watch %s'\n", XsldbgCmdInfo::argString},
|
|
{DCdelete, "delete %d\n", XsldbgCmdInfo::argNum},
|
|
{DCenable, "enable %d\n", XsldbgCmdInfo::argNum},
|
|
{DCdisable, "disable %d\n", XsldbgCmdInfo::argNum},
|
|
{DCprint, "print %s\n", XsldbgCmdInfo::argString},
|
|
{DCprintDeref, "print 'print (*%s)'\n", XsldbgCmdInfo::argString},
|
|
{DCprintStruct, "print 'print %s'\n", XsldbgCmdInfo::argString},
|
|
{DCprintTQStringStruct, "print 'print %s'\n", XsldbgCmdInfo::argString},
|
|
{DCframe, "frame %d\n", XsldbgCmdInfo::argNum},
|
|
{DCfindType, "print 'whatis %s'\n", XsldbgCmdInfo::argString},
|
|
{DCinfosharedlib, "stylesheets\n", XsldbgCmdInfo::argNone},
|
|
{DCthread, "print 'thread %d'\n", XsldbgCmdInfo::argNum},
|
|
{DCinfothreads, "print 'info threads'\n", XsldbgCmdInfo::argNone},
|
|
{DCinfobreak, "show\n", XsldbgCmdInfo::argNone},
|
|
{DCcondition, "print 'condition %d %s'\n", XsldbgCmdInfo::argNumString},
|
|
{DCsetpc, "print 'set variable $pc=%s'\n", XsldbgCmdInfo::argString},
|
|
{DCignore, "print 'ignore %d %d'\n", XsldbgCmdInfo::argNum2},
|
|
{DCprintWChar, "print 'ignore %s'\n", XsldbgCmdInfo::argString},
|
|
{DCsetvariable, "set %s %s\n", XsldbgCmdInfo::argString2},
|
|
};
|
|
|
|
#define NUM_CMDS (int(sizeof(cmds)/sizeof(cmds[0])))
|
|
#define MAX_FMTLEN 200
|
|
|
|
XsldbgDriver::XsldbgDriver():
|
|
DebuggerDriver()
|
|
{
|
|
m_promptRE.setPattern("\\(xsldbg\\) .*> ");
|
|
m_promptMinLen = 11;
|
|
m_promptLastChar = ' ';
|
|
|
|
m_markerRE.setPattern("^Breakpoint for file ");
|
|
m_haveDataFile = FALSE;
|
|
|
|
#ifndef NDEBUG
|
|
// check command info array
|
|
const char *perc;
|
|
|
|
for (int i = 0; i < NUM_CMDS; i++) {
|
|
// must be indexable by DbgCommand values, i.e. sorted by DbgCommand values
|
|
assert(i == cmds[i].cmd);
|
|
// a format string must be associated
|
|
assert(cmds[i].fmt != 0);
|
|
assert(strlen(cmds[i].fmt) <= MAX_FMTLEN);
|
|
// format string must match arg specification
|
|
switch (cmds[i].argsNeeded) {
|
|
case XsldbgCmdInfo::argNone:
|
|
assert(strchr(cmds[i].fmt, '%') == 0);
|
|
break;
|
|
case XsldbgCmdInfo::argString:
|
|
perc = strchr(cmds[i].fmt, '%');
|
|
assert(perc != 0 && perc[1] == 's');
|
|
assert(strchr(perc + 2, '%') == 0);
|
|
break;
|
|
case XsldbgCmdInfo::argNum:
|
|
perc = strchr(cmds[i].fmt, '%');
|
|
assert(perc != 0 && perc[1] == 'd');
|
|
assert(strchr(perc + 2, '%') == 0);
|
|
break;
|
|
case XsldbgCmdInfo::argStringNum:
|
|
perc = strchr(cmds[i].fmt, '%');
|
|
assert(perc != 0 && perc[1] == 's');
|
|
perc = strchr(perc + 2, '%');
|
|
assert(perc != 0 && perc[1] == 'd');
|
|
assert(strchr(perc + 2, '%') == 0);
|
|
break;
|
|
case XsldbgCmdInfo::argNumString:
|
|
perc = strchr(cmds[i].fmt, '%');
|
|
assert(perc != 0 && perc[1] == 'd');
|
|
perc = strchr(perc + 2, '%');
|
|
assert(perc != 0 && perc[1] == 's');
|
|
assert(strchr(perc + 2, '%') == 0);
|
|
break;
|
|
case XsldbgCmdInfo::argString2:
|
|
perc = strchr(cmds[i].fmt, '%');
|
|
assert(perc != 0 && perc[1] == 's');
|
|
perc = strchr(perc + 2, '%');
|
|
assert(perc != 0 && perc[1] == 's');
|
|
assert(strchr(perc + 2, '%') == 0);
|
|
break;
|
|
case XsldbgCmdInfo::argNum2:
|
|
perc = strchr(cmds[i].fmt, '%');
|
|
assert(perc != 0 && perc[1] == 'd');
|
|
perc = strchr(perc + 2, '%');
|
|
assert(perc != 0 && perc[1] == 'd');
|
|
assert(strchr(perc + 2, '%') == 0);
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
XsldbgDriver::~XsldbgDriver()
|
|
{
|
|
}
|
|
|
|
|
|
TQString
|
|
XsldbgDriver::driverName() const
|
|
{
|
|
return "XSLDBG";
|
|
}
|
|
|
|
TQString
|
|
XsldbgDriver::defaultXsldbg()
|
|
{
|
|
return "xsldbg --lang en --shell --gdb";
|
|
}
|
|
|
|
TQString
|
|
XsldbgDriver::defaultInvocation() const
|
|
{
|
|
return defaultXsldbg();
|
|
}
|
|
|
|
TQStringList XsldbgDriver::boolOptionList() const
|
|
{
|
|
TQStringList allOptions;
|
|
allOptions.append("verbose");
|
|
allOptions.append("repeat");
|
|
allOptions.append("debug");
|
|
allOptions.append("novalid");
|
|
allOptions.append("noout");
|
|
allOptions.append("html");
|
|
allOptions.append("docbook");
|
|
allOptions.append("nonet");
|
|
allOptions.append("catalogs");
|
|
allOptions.append("xinclude");
|
|
allOptions.append("profile");
|
|
return allOptions;
|
|
}
|
|
|
|
|
|
void
|
|
XsldbgDriver::slotReceiveOutput(TDEProcess * process, char *buffer,
|
|
int buflen)
|
|
{
|
|
//TRACE(buffer);
|
|
if (m_state != DSidle) {
|
|
// TRACE(buffer);
|
|
DebuggerDriver::slotReceiveOutput(process, buffer, buflen);
|
|
} else {
|
|
if (strncmp(buffer, "quit", 4) == 0) {
|
|
TRACE("Ignoring text when xsldbg is quiting");
|
|
} else {
|
|
TRACE
|
|
("Stray output received by XsldbgDriver::slotReceiveOutput");
|
|
TRACE(buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool
|
|
XsldbgDriver::startup(TQString cmdStr)
|
|
{
|
|
if (!DebuggerDriver::startup(cmdStr))
|
|
return false;
|
|
|
|
static const char xsldbgInitialize[] = "pwd\nsetoption gdb 2\n"; /* don't need to do anything else */
|
|
|
|
executeCmdString(DCinitialize, xsldbgInitialize, false);
|
|
|
|
return true;
|
|
}
|
|
|
|
void
|
|
XsldbgDriver::commandFinished(CmdQueueItem * cmd)
|
|
{
|
|
|
|
TRACE(__PRETTY_FUNCTION__);
|
|
// command string must be committed
|
|
if (!cmd->m_committed) {
|
|
// not commited!
|
|
TRACE("calling " +
|
|
(__PRETTY_FUNCTION__ +
|
|
(" with uncommited command:\n\t" + cmd->m_cmdString)));
|
|
return;
|
|
}
|
|
|
|
/* ok, the command is ready */
|
|
emit commandReceived(cmd, m_output);
|
|
|
|
switch (cmd->m_cmd) {
|
|
case DCbt:
|
|
case DCinfolocals:
|
|
case DCrun:
|
|
case DCcont:
|
|
case DCstep:
|
|
case DCnext:
|
|
case DCfinish:{
|
|
if (!::isErrorExpr(m_output))
|
|
parseMarker();
|
|
else{
|
|
// This only shows an error for DCinfolocals
|
|
// need to update KDebugger::handleRunCommand ?
|
|
KMessageBox::sorry(0L, m_output);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DCinfolinemain:
|
|
if (!m_xslFile.isEmpty())
|
|
emit activateFileLine(m_xslFile, 0, DbgAddr());
|
|
break;
|
|
|
|
default:;
|
|
}
|
|
}
|
|
|
|
void
|
|
XsldbgDriver::parseMarker()
|
|
{
|
|
|
|
// TRACE("parseMarker : xsldbg");
|
|
// TRACE(m_output);
|
|
int len = 0, markerStart = -1;
|
|
char *p = m_output;
|
|
|
|
while (markerStart == -1) {
|
|
if ((p == 0) || (*p == '\0')) {
|
|
m_output[0] = '\0';
|
|
return;
|
|
}
|
|
//TRACE(TQString("parseMarker is looking at :") + p);
|
|
markerStart = m_markerRE.search(p, 0);
|
|
if (markerStart == -1) {
|
|
// try to marker on next line !
|
|
p = strchr(p, '\n');
|
|
if ((p != 0) && (*p != '\0'))
|
|
p++;
|
|
}
|
|
else {
|
|
len = m_markerRE.matchedLength();
|
|
}
|
|
}
|
|
|
|
|
|
// extract the marker
|
|
char *startMarker = p + markerStart + len;
|
|
|
|
//TRACE(TQString("found marker:") + startMarker);
|
|
char *endMarker = strchr(startMarker, '\n');
|
|
|
|
if (endMarker == 0)
|
|
return;
|
|
|
|
*endMarker = '\0';
|
|
|
|
// extract filename and line number
|
|
static TQRegExp MarkerRE(" at line [0-9]+");
|
|
|
|
int lineNoStart = MarkerRE.search(startMarker, 0);
|
|
|
|
if (lineNoStart >= 0) {
|
|
int lineNo = atoi(startMarker + lineNoStart + 8);
|
|
|
|
DbgAddr address;
|
|
|
|
// now show the window
|
|
startMarker[lineNoStart-1] = '\0'; /* split off file name */
|
|
TRACE("Got file and line number");
|
|
startMarker++;
|
|
TRACE(TQString(startMarker) + ": " + TQString::number(lineNo));
|
|
emit activateFileLine(startMarker, lineNo - 1, address);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Escapes characters that might lead to problems when they appear on gdb's
|
|
* command line.
|
|
*/
|
|
static void
|
|
normalizeStringArg(TQString & arg)
|
|
{
|
|
/*
|
|
* Remove trailing backslashes. This approach is a little simplistic,
|
|
* but we know that there is at the moment no case where a trailing
|
|
* backslash would make sense.
|
|
*/
|
|
while (!arg.isEmpty() && arg[arg.length() - 1] == '\\') {
|
|
arg = arg.left(arg.length() - 1);
|
|
}
|
|
}
|
|
|
|
|
|
TQString
|
|
XsldbgDriver::makeCmdString(DbgCommand cmd, TQString strArg)
|
|
{
|
|
assert(cmd >= 0 && cmd < NUM_CMDS);
|
|
assert(cmds[cmd].argsNeeded == XsldbgCmdInfo::argString);
|
|
|
|
normalizeStringArg(strArg);
|
|
|
|
if (cmd == DCcd) {
|
|
// need the working directory when parsing the output
|
|
m_programWD = strArg;
|
|
} else if (cmd == DCexecutable) {
|
|
// want to display the XSL file
|
|
m_xslFile = strArg;
|
|
}
|
|
|
|
TQString cmdString;
|
|
cmdString.sprintf(cmds[cmd].fmt, strArg.latin1());
|
|
return cmdString;
|
|
}
|
|
|
|
TQString
|
|
XsldbgDriver::makeCmdString(DbgCommand cmd, int intArg)
|
|
{
|
|
assert(cmd >= 0 && cmd < NUM_CMDS);
|
|
assert(cmds[cmd].argsNeeded == XsldbgCmdInfo::argNum);
|
|
|
|
TQString cmdString;
|
|
cmdString.sprintf(cmds[cmd].fmt, intArg);
|
|
return cmdString;
|
|
}
|
|
|
|
TQString
|
|
XsldbgDriver::makeCmdString(DbgCommand cmd, TQString strArg, int intArg)
|
|
{
|
|
assert(cmd >= 0 && cmd < NUM_CMDS);
|
|
assert(cmds[cmd].argsNeeded == XsldbgCmdInfo::argStringNum ||
|
|
cmds[cmd].argsNeeded == XsldbgCmdInfo::argNumString ||
|
|
cmd == DCexamine || cmd == DCtty);
|
|
|
|
normalizeStringArg(strArg);
|
|
|
|
TQString cmdString;
|
|
|
|
if (cmd == DCtty) {
|
|
/*
|
|
* intArg specifies which channels should be redirected to
|
|
* /dev/null. It is a value or'ed together from RDNstdin,
|
|
* RDNstdout, RDNstderr.
|
|
*/
|
|
static const char *const runRedir[8] = {
|
|
"",
|
|
" </dev/null",
|
|
" >/dev/null",
|
|
" </dev/null >/dev/null",
|
|
" 2>/dev/null",
|
|
" </dev/null 2>/dev/null",
|
|
" >/dev/null 2>&1",
|
|
" </dev/null >/dev/null 2>&1"
|
|
};
|
|
|
|
if (strArg.isEmpty())
|
|
intArg = 7; /* failsafe if no tty */
|
|
m_redirect = runRedir[intArg & 7];
|
|
|
|
return makeCmdString(DCtty, strArg); /* note: no problem if strArg empty */
|
|
}
|
|
|
|
if (cmd == DCexamine) {
|
|
// make a format specifier from the intArg
|
|
static const char size[16] = {
|
|
'\0', 'b', 'h', 'w', 'g'
|
|
};
|
|
static const char format[16] = {
|
|
'\0', 'x', 'd', 'u', 'o', 't',
|
|
'a', 'c', 'f', 's', 'i'
|
|
};
|
|
|
|
assert(MDTsizemask == 0xf); /* lowest 4 bits */
|
|
assert(MDTformatmask == 0xf0); /* next 4 bits */
|
|
int count = 16; /* number of entities to print */
|
|
char sizeSpec = size[intArg & MDTsizemask];
|
|
char formatSpec = format[(intArg & MDTformatmask) >> 4];
|
|
|
|
assert(sizeSpec != '\0');
|
|
assert(formatSpec != '\0');
|
|
// adjust count such that 16 lines are printed
|
|
switch (intArg & MDTformatmask) {
|
|
case MDTstring:
|
|
case MDTinsn:
|
|
break; /* no modification needed */
|
|
default:
|
|
// all cases drop through:
|
|
switch (intArg & MDTsizemask) {
|
|
case MDTbyte:
|
|
case MDThalfword:
|
|
count *= 2;
|
|
case MDTword:
|
|
count *= 2;
|
|
case MDTgiantword:
|
|
count *= 2;
|
|
}
|
|
break;
|
|
}
|
|
TQString spec;
|
|
|
|
spec.sprintf("/%d%c%c", count, sizeSpec, formatSpec);
|
|
|
|
return makeCmdString(DCexamine, spec, strArg);
|
|
}
|
|
|
|
if (cmds[cmd].argsNeeded == XsldbgCmdInfo::argStringNum) {
|
|
// line numbers are zero-based
|
|
if (cmd == DCuntil || cmd == DCbreakline ||
|
|
cmd == DCtbreakline || cmd == DCinfoline) {
|
|
intArg++;
|
|
}
|
|
if (cmd == DCinfoline) {
|
|
// must split off file name part
|
|
int slash = strArg.findRev('/');
|
|
|
|
if (slash >= 0)
|
|
strArg = strArg.right(strArg.length() - slash - 1);
|
|
}
|
|
cmdString.sprintf(cmds[cmd].fmt, strArg.latin1(), intArg);
|
|
} else {
|
|
cmdString.sprintf(cmds[cmd].fmt, intArg, strArg.latin1());
|
|
}
|
|
return cmdString;
|
|
}
|
|
|
|
TQString
|
|
XsldbgDriver::makeCmdString(DbgCommand cmd, TQString strArg1,
|
|
TQString strArg2)
|
|
{
|
|
assert(cmd >= 0 && cmd < NUM_CMDS);
|
|
assert(cmds[cmd].argsNeeded == XsldbgCmdInfo::argString2);
|
|
|
|
normalizeStringArg(strArg1);
|
|
normalizeStringArg(strArg2);
|
|
|
|
TQString cmdString;
|
|
cmdString.sprintf(cmds[cmd].fmt, strArg1.latin1(), strArg2.latin1());
|
|
return cmdString;
|
|
}
|
|
|
|
TQString
|
|
XsldbgDriver::makeCmdString(DbgCommand cmd, int intArg1, int intArg2)
|
|
{
|
|
assert(cmd >= 0 && cmd < NUM_CMDS);
|
|
assert(cmds[cmd].argsNeeded == XsldbgCmdInfo::argNum2);
|
|
|
|
TQString cmdString;
|
|
cmdString.sprintf(cmds[cmd].fmt, intArg1, intArg2);
|
|
return cmdString;
|
|
}
|
|
|
|
CmdQueueItem *
|
|
XsldbgDriver::executeCmd(DbgCommand cmd, bool clearLow)
|
|
{
|
|
assert(cmd >= 0 && cmd < NUM_CMDS);
|
|
assert(cmds[cmd].argsNeeded == XsldbgCmdInfo::argNone);
|
|
|
|
if (cmd == DCrun) {
|
|
m_haveCoreFile = false;
|
|
}
|
|
|
|
return executeCmdString(cmd, cmds[cmd].fmt, clearLow);
|
|
}
|
|
|
|
CmdQueueItem *
|
|
XsldbgDriver::executeCmd(DbgCommand cmd, TQString strArg, bool clearLow)
|
|
{
|
|
return executeCmdString(cmd, makeCmdString(cmd, strArg), clearLow);
|
|
}
|
|
|
|
CmdQueueItem *
|
|
XsldbgDriver::executeCmd(DbgCommand cmd, int intArg, bool clearLow)
|
|
{
|
|
|
|
return executeCmdString(cmd, makeCmdString(cmd, intArg), clearLow);
|
|
}
|
|
|
|
CmdQueueItem *
|
|
XsldbgDriver::executeCmd(DbgCommand cmd, TQString strArg, int intArg,
|
|
bool clearLow)
|
|
{
|
|
return executeCmdString(cmd, makeCmdString(cmd, strArg, intArg),
|
|
clearLow);
|
|
}
|
|
|
|
CmdQueueItem *
|
|
XsldbgDriver::executeCmd(DbgCommand cmd, TQString strArg1, TQString strArg2,
|
|
bool clearLow)
|
|
{
|
|
return executeCmdString(cmd, makeCmdString(cmd, strArg1, strArg2),
|
|
clearLow);
|
|
}
|
|
|
|
CmdQueueItem *
|
|
XsldbgDriver::executeCmd(DbgCommand cmd, int intArg1, int intArg2,
|
|
bool clearLow)
|
|
{
|
|
return executeCmdString(cmd, makeCmdString(cmd, intArg1, intArg2),
|
|
clearLow);
|
|
}
|
|
|
|
CmdQueueItem *
|
|
XsldbgDriver::queueCmd(DbgCommand cmd, QueueMode mode)
|
|
{
|
|
return queueCmdString(cmd, cmds[cmd].fmt, mode);
|
|
}
|
|
|
|
CmdQueueItem *
|
|
XsldbgDriver::queueCmd(DbgCommand cmd, TQString strArg, QueueMode mode)
|
|
{
|
|
return queueCmdString(cmd, makeCmdString(cmd, strArg), mode);
|
|
}
|
|
|
|
CmdQueueItem *
|
|
XsldbgDriver::queueCmd(DbgCommand cmd, int intArg, QueueMode mode)
|
|
{
|
|
return queueCmdString(cmd, makeCmdString(cmd, intArg), mode);
|
|
}
|
|
|
|
CmdQueueItem *
|
|
XsldbgDriver::queueCmd(DbgCommand cmd, TQString strArg, int intArg,
|
|
QueueMode mode)
|
|
{
|
|
return queueCmdString(cmd, makeCmdString(cmd, strArg, intArg), mode);
|
|
}
|
|
|
|
CmdQueueItem *
|
|
XsldbgDriver::queueCmd(DbgCommand cmd, TQString strArg1, TQString strArg2,
|
|
QueueMode mode)
|
|
{
|
|
return queueCmdString(cmd, makeCmdString(cmd, strArg1, strArg2), mode);
|
|
}
|
|
|
|
void
|
|
XsldbgDriver::terminate()
|
|
{
|
|
tqDebug("XsldbgDriver::Terminate");
|
|
flushCommands();
|
|
executeCmdString(DCinitialize, "quit\n", true);
|
|
kill(SIGTERM);
|
|
m_state = DSidle;
|
|
}
|
|
|
|
void
|
|
XsldbgDriver::detachAndTerminate()
|
|
{
|
|
tqDebug("XsldbgDriver::detachAndTerminate");
|
|
flushCommands();
|
|
executeCmdString(DCinitialize, "quit\n", true);
|
|
kill(SIGINT);
|
|
}
|
|
|
|
void
|
|
XsldbgDriver::interruptInferior()
|
|
{
|
|
// remove accidentally queued commands
|
|
tqDebug("interruptInferior");
|
|
flushHiPriQueue();
|
|
kill(SIGINT);
|
|
}
|
|
|
|
static bool
|
|
isErrorExpr(const char *output)
|
|
{
|
|
int wordIndex;
|
|
bool result = false;
|
|
#define ERROR_WORD_COUNT 6
|
|
static const char *errorWords[ERROR_WORD_COUNT] = {
|
|
"Error:",
|
|
"error:", // libxslt error
|
|
"Unknown command",
|
|
"Warning:",
|
|
"warning:", // libxslt warning
|
|
"Information:" // xsldbg information
|
|
};
|
|
static int errorWordLength[ERROR_WORD_COUNT] = {
|
|
6, /* Error */
|
|
6, /* rror */
|
|
15, /* Unknown command*/
|
|
8, /* Warning */
|
|
8, /* warning */
|
|
12 /* Information */
|
|
};
|
|
|
|
for (wordIndex = 0; wordIndex < ERROR_WORD_COUNT; wordIndex++){
|
|
// ignore any warnings relating to local variables not being available
|
|
if (strncmp(output,
|
|
errorWords[wordIndex],
|
|
errorWordLength[wordIndex]) == 0 &&
|
|
(wordIndex == 0 && strstr(output, "try stepping past the xsl:param") == 0) ) {
|
|
result = true;
|
|
TRACE(TQString("Error/Warning/Information from xsldbg ") + output);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the output is an error message. If wantErrorValue is
|
|
* true, a new ExprValue object is created and filled with the error message.
|
|
*/
|
|
static bool
|
|
parseErrorMessage(const char *output,
|
|
ExprValue * &variable, bool wantErrorValue)
|
|
{
|
|
if (isErrorExpr(output)) {
|
|
if (wantErrorValue) {
|
|
// put the error message as value in the variable
|
|
variable = new ExprValue(TQString(), VarTree::NKplain);
|
|
const char *endMsg = strchr(output, '\n');
|
|
|
|
if (endMsg == 0)
|
|
endMsg = output + strlen(output);
|
|
variable->m_value = TQString::fromLatin1(output, endMsg - output);
|
|
} else {
|
|
variable = 0;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void
|
|
XsldbgDriver::setPrintTQStringDataCmd(const char* /*cmd*/)
|
|
{
|
|
}
|
|
|
|
ExprValue *
|
|
XsldbgDriver::parseTQCharArray(const char */*output*/, bool /*wantErrorValue*/,
|
|
bool /*qt3like*/)
|
|
{
|
|
ExprValue *variable = 0;
|
|
|
|
TRACE("XsldbgDriver::parseTQCharArray not implmented");
|
|
return variable;
|
|
}
|
|
|
|
static ExprValue *
|
|
parseVar(const char *&s)
|
|
{
|
|
const char *p = s;
|
|
bool foundLocalVar = false;
|
|
ExprValue *variable = 0L;
|
|
TQString name;
|
|
|
|
VarTree::NameKind kind;
|
|
|
|
TRACE(__PRETTY_FUNCTION__);
|
|
TRACE(p);
|
|
|
|
if (parseErrorMessage(p, variable, false) == true) {
|
|
TRACE("Found error message");
|
|
return variable;
|
|
}
|
|
|
|
if (strncmp(p, " Local", 6) == 0) {
|
|
foundLocalVar = true;
|
|
/* skip " Local" */
|
|
p = p + 6;
|
|
TRACE("Found local variable");
|
|
} else if (strncmp(p, " Global", 7) == 0) {
|
|
/* skip " Global" */
|
|
p = p + 7;
|
|
TRACE("Found global variable");
|
|
} else if (strncmp(p, "= ", 2) == 0) {
|
|
/* we're processing the result of a "print command" */
|
|
/* find next line */
|
|
const char *nextLine = strchr(p, '\n');
|
|
|
|
TRACE("Found print expr");
|
|
if (nextLine) {
|
|
p = p + 2; /* skip the "= " */
|
|
name = TQString::fromLatin1(p, nextLine - p);
|
|
kind = VarTree::NKplain;
|
|
p = nextLine + 1;
|
|
variable = new ExprValue(name, kind);
|
|
variable->m_varKind = VarTree::VKsimple;
|
|
parseValue(p, variable);
|
|
return variable;
|
|
}
|
|
} else
|
|
return variable; /* don't know what to do this this data abort!! */
|
|
|
|
// skip whitespace
|
|
while (isspace(*p))
|
|
p++;
|
|
|
|
if (*p != '='){
|
|
// No value provided just a name
|
|
TRACE(TQString("Parse var: name") + p);
|
|
if (!parseName(p, name, kind)) {
|
|
return 0;
|
|
}
|
|
variable = new ExprValue(name, kind);
|
|
if (variable != 0L) {
|
|
variable->m_varKind = VarTree::VKsimple;
|
|
}
|
|
}else{
|
|
p++;
|
|
// skip whitespace
|
|
while (isspace(*p))
|
|
p++;
|
|
TRACE(TQString("Parse var: name") + p);
|
|
if (!parseName(p, name, kind)) {
|
|
return 0;
|
|
}
|
|
variable = new ExprValue(name, kind);
|
|
if (variable != 0L) {
|
|
variable->m_varKind = VarTree::VKsimple;
|
|
}
|
|
if (*p == '\n')
|
|
p++;
|
|
if (!parseValue(p, variable)) {
|
|
delete variable;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (*p == '\n')
|
|
p++;
|
|
|
|
s = p;
|
|
return variable;
|
|
}
|
|
|
|
|
|
inline void
|
|
skipName(const char *&p)
|
|
{
|
|
// allow : (for enumeration values) and $ and . (for _vtbl.)
|
|
while (isalnum(*p) || *p == '_' || *p == ':' || *p == '$' || *p == '.')
|
|
p++;
|
|
}
|
|
|
|
static bool
|
|
parseName(const char *&s, TQString & name, VarTree::NameKind & kind)
|
|
{
|
|
/* tqDebug(__PRETTY_FUNCTION__); */
|
|
kind = VarTree::NKplain;
|
|
|
|
const char *p = s;
|
|
int len = 0;
|
|
|
|
// examples of names:
|
|
// help_cmd
|
|
|
|
while ((*p != '\n') && (*p != '\0')) {
|
|
len++;
|
|
p++;
|
|
}
|
|
|
|
|
|
name = TQString::fromLatin1(s, len);
|
|
/* XSL variables will have a $ prefix to be evaluated
|
|
* properly */
|
|
//TRACE(TQString("parseName got name" ) + name);
|
|
|
|
// return the new position
|
|
s = p;
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
parseValue(const char *&s, ExprValue * variable)
|
|
{
|
|
const char *start = s, *end = s;
|
|
ExprValue * childValue;
|
|
#define VALUE_END_MARKER_INDEX 0
|
|
|
|
/* This mark the end of a value */
|
|
static const char *marker[] = {
|
|
"\032\032", /* value end marker*/
|
|
"(xsldbg) ",
|
|
"Breakpoint at", /* stepped to next location */
|
|
"Breakpoint in", /* reached a set breakpoint */
|
|
"Reached ", /* reached template */
|
|
"Error:",
|
|
"Warning:",
|
|
"Information:",
|
|
"runtime error",
|
|
"xmlXPathEval:",
|
|
0
|
|
};
|
|
static char valueBuffer[2048];
|
|
int markerIndex = 0, foundEnd = 0;
|
|
size_t copySize;
|
|
|
|
if (variable == 0L)
|
|
return false; /* should never happen but .. */
|
|
|
|
while (start && (*start != '\0')) {
|
|
/* look for the next marker */
|
|
for (markerIndex = 0; marker[markerIndex] != 0; markerIndex++) {
|
|
foundEnd =
|
|
strncmp(start, marker[markerIndex],
|
|
strlen(marker[markerIndex])) == 0;
|
|
if (foundEnd)
|
|
break;
|
|
}
|
|
|
|
if (foundEnd)
|
|
break;
|
|
|
|
|
|
end = strchr(start, '\n');
|
|
if (end)
|
|
copySize = end - start;
|
|
else
|
|
copySize = strlen(start);
|
|
if (copySize >= sizeof(valueBuffer))
|
|
copySize = sizeof(valueBuffer)-1;
|
|
|
|
strncpy(valueBuffer, start, copySize);
|
|
valueBuffer[copySize] = '\0';
|
|
TRACE("Got value :");
|
|
TRACE(valueBuffer);
|
|
if ((variable->m_varKind == VarTree::VKsimple)) {
|
|
if (!variable->m_value.isEmpty()){
|
|
variable->m_varKind = VarTree::VKarray;
|
|
childValue = new ExprValue(variable->m_value, VarTree::NKplain);
|
|
variable->appendChild(childValue);
|
|
childValue = new ExprValue(valueBuffer, VarTree::NKplain);
|
|
variable->appendChild(childValue);
|
|
variable->m_value = "";
|
|
}else{
|
|
variable->m_value = valueBuffer;
|
|
}
|
|
}else{
|
|
childValue = new ExprValue(valueBuffer, VarTree::NKplain);
|
|
variable->appendChild(childValue);
|
|
}
|
|
|
|
if (*end =='\n'){
|
|
start = end + 1;
|
|
}else{
|
|
start = end + 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (foundEnd == 0)
|
|
TRACE(TQString("Unable to find end on value near :") + start);
|
|
|
|
// If we've got something otherthan a end of value marker then
|
|
// advance to the end of this buffer
|
|
if (markerIndex != VALUE_END_MARKER_INDEX){
|
|
while (start && *start != '\0')
|
|
start++;
|
|
}else{
|
|
start = start + strlen(marker[0]);
|
|
}
|
|
|
|
s = start;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Parses a stack frame.
|
|
*/
|
|
static void
|
|
parseFrameInfo(const char *&s, TQString & func,
|
|
TQString & file, int &lineNo, DbgAddr & /*address*/)
|
|
{
|
|
const char *p = s, *endPos = s + strlen(s);
|
|
TQString lineNoString;
|
|
|
|
TRACE("parseFrameInfo");
|
|
|
|
lineNo = -1;
|
|
|
|
/* skip 'template :\" */
|
|
p = p + 11;
|
|
// TRACE(p);
|
|
func = "";
|
|
while ((*p != '\"') && (*p != '\0')) {
|
|
func.append(*p);
|
|
p++;
|
|
}
|
|
while ((*p != '\0') && *p != '"')
|
|
p++;
|
|
if (*p != '\0')
|
|
p++;
|
|
ASSERT(p <= endPos);
|
|
if (p >= endPos) {
|
|
/* panic */
|
|
return;
|
|
}
|
|
|
|
/* skip mode :".*" */
|
|
while ((*p != '\0') && *p != '"')
|
|
p++;
|
|
if (*p != '\0')
|
|
p++;
|
|
while ((*p != '\0') && *p != '"')
|
|
p++;
|
|
|
|
/* skip '" in file ' */
|
|
p = p + 10;
|
|
if(*p == '"')
|
|
p++;
|
|
// TRACE(p);
|
|
file = "";
|
|
while (!isspace(*p) && (*p != '\"') && (*p != '\0')) {
|
|
file.append(*p);
|
|
p++;
|
|
}
|
|
if(*p == '"')
|
|
p++;
|
|
ASSERT(p <= endPos);
|
|
if (p >= endPos) {
|
|
/* panic */
|
|
return;
|
|
}
|
|
|
|
// TRACE(p);
|
|
/* skip ' : line '" */
|
|
p = p + 9;
|
|
// TRACE(p);
|
|
ASSERT(p <= endPos);
|
|
if (p >= endPos) {
|
|
/* panic */
|
|
return;
|
|
}
|
|
// TRACE(p);
|
|
if (isdigit(*p)) {
|
|
/* KDbg uses an offset of +1 for its line numbers */
|
|
lineNo = atoi(p) - 1;
|
|
lineNoString = TQString::number(lineNo);
|
|
}
|
|
/* convert func into format needed */
|
|
func.append(" at ");
|
|
func.append(file);
|
|
func.append(':');
|
|
func.append(lineNoString);
|
|
|
|
/*advance to next line */
|
|
p = strchr(p, '\n');
|
|
if (p)
|
|
p++;
|
|
s = p;
|
|
|
|
}
|
|
|
|
#undef ISSPACE
|
|
|
|
/**
|
|
* Parses a stack frame including its frame number
|
|
*/
|
|
static bool
|
|
parseFrame(const char *&s, int &frameNo, TQString & func,
|
|
TQString & file, int &lineNo, DbgAddr & address)
|
|
{
|
|
|
|
// TRACE("XsldbgDriver ::parseFrame");
|
|
/* skip leading 'where' or 'frame <frame_no>' */
|
|
if ((strncmp(s, "where", 5) == 0) || (strncmp(s, "frame", 5) == 0)) {
|
|
s = strchr(s, '\n');
|
|
if ((*s != '\0') && (*s != '#'))
|
|
s++;
|
|
}
|
|
// TRACE(s);
|
|
|
|
// Example:
|
|
//#1 template :"/" in file /home/keith/anon_CVS/xsldbg/docs/en/xsldoc.xsl : line 21
|
|
// must start with a hash mark followed by number
|
|
if (s[0] != '#' || !isdigit(s[1]))
|
|
return false;
|
|
|
|
//TRACE("XsldbgDriver ::parseFrame got #");
|
|
s++; /* skip the hash mark */
|
|
// frame number
|
|
frameNo = atoi(s);
|
|
while (isdigit(*s))
|
|
s++;
|
|
|
|
//TRACE(TQString("Got frame ").append(TQString::number(frameNo)));
|
|
// space
|
|
while (isspace(*s))
|
|
s++;
|
|
parseFrameInfo(s, func, file, lineNo, address);
|
|
// TRACE("Will next look at ");
|
|
// TRACE(s);
|
|
return true;
|
|
}
|
|
|
|
void
|
|
XsldbgDriver::parseBackTrace(const char *output,
|
|
std::list < StackFrame > &stack)
|
|
{
|
|
TQString func, file;
|
|
int lineNo, frameNo;
|
|
DbgAddr address;
|
|
|
|
while (::parseFrame(output, frameNo, func, file, lineNo, address)) {
|
|
stack.push_back(StackFrame());
|
|
StackFrame* frm = &stack.back();
|
|
|
|
frm->frameNo = frameNo;
|
|
frm->fileName = file;
|
|
frm->lineNo = lineNo;
|
|
frm->address = address;
|
|
frm->var = new ExprValue(func, VarTree::NKplain);
|
|
}
|
|
}
|
|
|
|
bool
|
|
XsldbgDriver::parseFrameChange(const char *output, int &frameNo,
|
|
TQString & file, int &lineNo,
|
|
DbgAddr & address)
|
|
{
|
|
TQString func;
|
|
|
|
return::parseFrame(output, frameNo, func, file, lineNo, address);
|
|
}
|
|
|
|
|
|
bool
|
|
XsldbgDriver::parseBreakList(const char *output,
|
|
std::list < Breakpoint > &brks)
|
|
{
|
|
TRACE("parseBreakList");
|
|
/* skip the first blank line */
|
|
const char *p;
|
|
|
|
// split up a line
|
|
Breakpoint bp;
|
|
char *dummy;
|
|
p = strchr(output, '\n');/* skip the first blank line*/
|
|
|
|
while ((p != 0) && (*p != '\0')) {
|
|
if (*p == '\n')
|
|
p++;
|
|
TQString templateName;
|
|
//tqDebug("Looking at :%s", p);
|
|
if (strncmp(p, " Breakpoint", 11) != 0)
|
|
break;
|
|
p = p + 11;
|
|
if (*p == '\0')
|
|
break;
|
|
|
|
//TRACE(p);
|
|
// get Num
|
|
bp.id = strtol(p, &dummy, 10); /* don't care about overflows */
|
|
|
|
p = dummy;
|
|
if ((p == 0) || (p[1] == '\0'))
|
|
break;
|
|
p++;
|
|
|
|
//TRACE(p);
|
|
// Get breakpoint state ie enabled/disabled
|
|
if (strncmp(p, "enabled", 7) == 0) {
|
|
bp.enabled = true;
|
|
p = p + 7;
|
|
} else {
|
|
if (strncmp(p, "disabled", 8) == 0) {
|
|
p = p + 8;
|
|
bp.enabled = false;
|
|
} else{
|
|
TRACE("Parse error in breakpoint list");
|
|
TRACE(p);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//TRACE("Looking for template");
|
|
//TRACE(p);
|
|
if (strncmp(p, " for template: \"", 16) == 0){
|
|
p = p + 16;
|
|
//TRACE("Looking for template name near");
|
|
//TRACE(p);
|
|
/* get the template name */
|
|
while (p && (*p != '\0') && (*p != '\"')){
|
|
templateName.append(*p);
|
|
p++;
|
|
}
|
|
if (*p == '\"'){
|
|
p++;
|
|
}else{
|
|
TRACE("Error missed \" near");
|
|
TRACE(p);
|
|
}
|
|
}
|
|
|
|
//TRACE("Looking for mode near");
|
|
//TRACE(p);
|
|
if (strncmp(p, " mode: \"", 8) == 0){
|
|
p = p + 8;
|
|
while (p && *p != '\"')
|
|
p++;
|
|
if (p)
|
|
p++;
|
|
}
|
|
|
|
if (strncmp(p, " in file ", 9) != 0){
|
|
TRACE("Parse error in breakpoint list");
|
|
TRACE(p);
|
|
return false;
|
|
}
|
|
|
|
|
|
/* skip ' in file ' */
|
|
p = p + 9;
|
|
// TRACE(p);
|
|
|
|
if (*p == '\"')
|
|
p++;
|
|
/* grab file name */
|
|
TQString file;
|
|
while ((*p != '\"') && !isspace(*p)) {
|
|
file.append(*p);
|
|
p++;
|
|
}
|
|
if (*p == '\"')
|
|
p++;
|
|
if (*p == '\0')
|
|
break;
|
|
|
|
/* skip ' : line ' */
|
|
p = p + 8;
|
|
while (isspace(*p)) {
|
|
p++;
|
|
}
|
|
//TRACE(p);
|
|
TQString lineNo;
|
|
while (isdigit(*p)) {
|
|
lineNo.append(*p);
|
|
p++;
|
|
}
|
|
|
|
// bp.lineNo is zero-based
|
|
bp.lineNo = lineNo.toInt() - 1;
|
|
bp.location = TQString("in %1 at %2:%3").arg(templateName, file, lineNo);
|
|
bp.fileName = file;
|
|
brks.push_back(bp);
|
|
|
|
if (p != 0) {
|
|
p = strchr(p, '\n');
|
|
if (p)
|
|
p++;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
std::list<ThreadInfo>
|
|
XsldbgDriver::parseThreadList(const char */*output*/)
|
|
{
|
|
return std::list<ThreadInfo>();
|
|
}
|
|
|
|
bool
|
|
XsldbgDriver::parseBreakpoint(const char *output, int &id,
|
|
TQString &file, int &lineNo, TQString &address)
|
|
{
|
|
// check for errors
|
|
if ( strncmp(output, "Error:", 6) == 0) {
|
|
return false;
|
|
}
|
|
|
|
char *dummy;
|
|
if (strncmp(output, "Breakpoint ", 11) != 0)
|
|
return false;
|
|
|
|
output += 11;
|
|
if (!isdigit(*output))
|
|
return false;
|
|
|
|
// get Num
|
|
id = strtol(output, &dummy, 10); /* don't care about overflows */
|
|
if (output == dummy)
|
|
return false;
|
|
|
|
// the file name + lineNo will be filled in later from the breakpoint list
|
|
file = address = TQString();
|
|
lineNo = 0;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
XsldbgDriver::parseLocals(const char *output, std::list < ExprValue* > &newVars)
|
|
{
|
|
|
|
/* keep going until error or xsldbg prompt is found */
|
|
while (*output != '\0') {
|
|
ExprValue *variable = parseVar(output);
|
|
|
|
if (variable == 0) {
|
|
break;
|
|
}
|
|
// do not add duplicates
|
|
for (std::list<ExprValue*>::iterator o = newVars.begin(); o != newVars.end(); ++o) {
|
|
if ((*o)->m_name == variable->m_name) {
|
|
delete variable;
|
|
|
|
goto skipDuplicate;
|
|
}
|
|
}
|
|
newVars.push_back(variable);
|
|
skipDuplicate:;
|
|
}
|
|
}
|
|
|
|
|
|
ExprValue *
|
|
XsldbgDriver::parsePrintExpr(const char *output, bool wantErrorValue)
|
|
{
|
|
ExprValue* var = 0;
|
|
// check for error conditions
|
|
if (!parseErrorMessage(output, var, wantErrorValue)) {
|
|
// parse the variable
|
|
var = parseVar(output);
|
|
}
|
|
return var;
|
|
}
|
|
|
|
bool
|
|
XsldbgDriver::parseChangeWD(const char *output, TQString & message)
|
|
{
|
|
bool isGood = false;
|
|
|
|
if (strncmp(output, "Change to directory", 20) == 0) {
|
|
output = output + 20; /* skip 'Change to directory' */
|
|
message = TQString(output).simplifyWhiteSpace();
|
|
if (message.isEmpty()) {
|
|
message = i18n("New working directory: ") + m_programWD;
|
|
isGood = true;
|
|
}
|
|
}
|
|
return isGood;
|
|
}
|
|
|
|
bool
|
|
XsldbgDriver::parseChangeExecutable(const char *output, TQString & message)
|
|
{
|
|
message = output;
|
|
TRACE(TQString("XsldbgDriver::parseChangeExecutable :") + output);
|
|
m_haveCoreFile = false;
|
|
|
|
/*
|
|
* The command is successful if there is no output or the single
|
|
* message (no debugging symbols found)...
|
|
*/
|
|
TQRegExp exp(".*Load of source deferred. Use the run command.*");
|
|
int index = exp.search(output, 0);
|
|
|
|
if (index != -1) {
|
|
TRACE("Parsed stylesheet executable");
|
|
message = "";
|
|
}
|
|
return (output[0] == '\0') || (index != -1);
|
|
}
|
|
|
|
bool
|
|
XsldbgDriver::parseCoreFile(const char *output)
|
|
{
|
|
TRACE("XsldbgDriver::parseCoreFile");
|
|
TRACE(output);
|
|
TQRegExp exp(".*Load of data file deferred. Use the run command.*");
|
|
int index = exp.search(output, 0);
|
|
|
|
if (index != -1) {
|
|
m_haveCoreFile = true;
|
|
TRACE("Parsed data file name");
|
|
}
|
|
|
|
return m_haveCoreFile;
|
|
}
|
|
|
|
uint
|
|
XsldbgDriver::parseProgramStopped(const char *output, TQString & message)
|
|
{
|
|
/* Not sure about this function leave it here for the moment */
|
|
/*
|
|
* return DebuggerDriver::SFrefreshBreak & DebuggerDriver::SFprogramActive;
|
|
*/
|
|
|
|
// go through the output, line by line, checking what we have
|
|
const char *start = output - 1;
|
|
uint flags = SFprogramActive;
|
|
|
|
message = TQString();
|
|
do {
|
|
start++; /* skip '\n' */
|
|
|
|
if (strncmp(start, "Finished stylesheet\n\032\032\n", 21) == 0){
|
|
// flags &= ~SFprogramActive;
|
|
break;
|
|
}
|
|
|
|
// next line, please
|
|
start = strchr(start, '\n');
|
|
} while (start != 0);
|
|
|
|
return flags;
|
|
}
|
|
|
|
TQStringList
|
|
XsldbgDriver::parseSharedLibs(const char */*output*/)
|
|
{
|
|
return TQStringList();
|
|
}
|
|
|
|
bool
|
|
XsldbgDriver::parseFindType(const char */*output*/, TQString & /*type*/)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
std::list<RegisterInfo>
|
|
XsldbgDriver::parseRegisters(const char */*output*/)
|
|
{
|
|
return std::list<RegisterInfo>();
|
|
}
|
|
|
|
bool
|
|
XsldbgDriver::parseInfoLine(const char */*output*/, TQString & /*addrFrom*/,
|
|
TQString & /*addrTo*/)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
std::list<DisassembledCode>
|
|
XsldbgDriver::parseDisassemble(const char */*output*/)
|
|
{
|
|
return std::list<DisassembledCode>();
|
|
}
|
|
|
|
TQString
|
|
XsldbgDriver::parseMemoryDump(const char */*output*/,
|
|
std::list < MemoryDump > &/*memdump*/)
|
|
{
|
|
return i18n("No memory dump available");
|
|
}
|
|
|
|
TQString
|
|
XsldbgDriver::parseSetVariable(const char */*output*/)
|
|
{
|
|
TQString msg;
|
|
return msg;
|
|
}
|
|
|
|
|
|
#include "xsldbgdriver.moc"
|