forked from qt-creator/qt-creator
debugger: make parts of python debugger work again with the new states
This commit is contained in:
@@ -3,239 +3,250 @@ import pdb;
|
|||||||
import sys;
|
import sys;
|
||||||
import linecache
|
import linecache
|
||||||
|
|
||||||
|
def qdebug(options = None,
|
||||||
class qdebug:
|
|
||||||
def __init__(self,
|
|
||||||
options = None,
|
|
||||||
expanded = None,
|
expanded = None,
|
||||||
typeformats = None,
|
typeformats = None,
|
||||||
individualformats = None,
|
individualformats = None,
|
||||||
watchers = None):
|
watchers = None):
|
||||||
self.options = options
|
|
||||||
self.expandedINames = expanded
|
|
||||||
self.typeformats = typeformats
|
|
||||||
self.individualformats = individualformats
|
|
||||||
self.watchers = watchers
|
|
||||||
if self.options == "listmodules":
|
|
||||||
self.handleListModules()
|
|
||||||
elif self.options == "listsymbols":
|
|
||||||
self.handleListSymbols(expanded)
|
|
||||||
else:
|
|
||||||
self.handleListVars()
|
|
||||||
|
|
||||||
def put(self, value):
|
class QDebug:
|
||||||
sys.stdout.write(value)
|
def __init__(self,
|
||||||
|
options = None,
|
||||||
|
expanded = None,
|
||||||
|
typeformats = None,
|
||||||
|
individualformats = None,
|
||||||
|
watchers = None):
|
||||||
|
self.options = options
|
||||||
|
self.expandedINames = expanded
|
||||||
|
self.typeformats = typeformats
|
||||||
|
self.individualformats = individualformats
|
||||||
|
self.watchers = watchers
|
||||||
|
self.buffer = ""
|
||||||
|
if self.options == "listmodules":
|
||||||
|
self.handleListModules()
|
||||||
|
elif self.options == "listsymbols":
|
||||||
|
self.handleListSymbols(expanded)
|
||||||
|
else:
|
||||||
|
self.handleListVars()
|
||||||
|
|
||||||
def putField(self, name, value):
|
def put(self, value):
|
||||||
self.put('%s="%s",' % (name, value))
|
#sys.stdout.write(value)
|
||||||
|
self.buffer += value
|
||||||
|
|
||||||
def putItemCount(self, count):
|
def putField(self, name, value):
|
||||||
self.put('value="<%s items>",' % count)
|
self.put('%s="%s",' % (name, value))
|
||||||
|
|
||||||
def putEllipsis(self):
|
def putItemCount(self, count):
|
||||||
self.put('{name="<incomplete>",value="",type="",numchild="0"},')
|
self.put('value="<%s items>",' % count)
|
||||||
|
|
||||||
def cleanType(self, type):
|
def putEllipsis(self):
|
||||||
t = str(type)
|
self.put('{name="<incomplete>",value="",type="",numchild="0"},')
|
||||||
if t.startswith("<type '") and t.endswith("'>"):
|
|
||||||
t = t[7:-2]
|
|
||||||
if t.startswith("<class '") and t.endswith("'>"):
|
|
||||||
t = t[8:-2]
|
|
||||||
return t
|
|
||||||
|
|
||||||
def putType(self, type, priority = 0):
|
def cleanType(self, type):
|
||||||
self.putField("type", self.cleanType(type))
|
t = str(type)
|
||||||
|
if t.startswith("<type '") and t.endswith("'>"):
|
||||||
|
t = t[7:-2]
|
||||||
|
if t.startswith("<class '") and t.endswith("'>"):
|
||||||
|
t = t[8:-2]
|
||||||
|
return t
|
||||||
|
|
||||||
def putAddress(self, addr):
|
def putType(self, type, priority = 0):
|
||||||
self.put('addr="%s",' % cleanAddress(addr))
|
self.putField("type", self.cleanType(type))
|
||||||
|
|
||||||
def putNumChild(self, numchild):
|
def putAddress(self, addr):
|
||||||
self.put('numchild="%s",' % numchild)
|
self.put('addr="%s",' % cleanAddress(addr))
|
||||||
|
|
||||||
def putValue(self, value, encoding = None, priority = 0):
|
def putNumChild(self, numchild):
|
||||||
self.putField("value", value)
|
self.put('numchild="%s",' % numchild)
|
||||||
|
|
||||||
def putName(self, name):
|
def putValue(self, value, encoding = None, priority = 0):
|
||||||
self.put('name="%s",' % name)
|
self.putField("value", value)
|
||||||
|
|
||||||
def isExpanded(self, iname):
|
def putName(self, name):
|
||||||
#self.warn("IS EXPANDED: %s in %s" % (iname, self.expandedINames))
|
self.put('name="%s",' % name)
|
||||||
if iname.startswith("None"):
|
|
||||||
raise "Illegal iname '%s'" % iname
|
|
||||||
#self.warn(" --> %s" % (iname in self.expandedINames))
|
|
||||||
return iname in self.expandedINames
|
|
||||||
|
|
||||||
def isExpandedIName(self, iname):
|
def isExpanded(self, iname):
|
||||||
return iname in self.expandedINames
|
#self.warn("IS EXPANDED: %s in %s" % (iname, self.expandedINames))
|
||||||
|
if iname.startswith("None"):
|
||||||
|
raise "Illegal iname '%s'" % iname
|
||||||
|
#self.warn(" --> %s" % (iname in self.expandedINames))
|
||||||
|
return iname in self.expandedINames
|
||||||
|
|
||||||
def itemFormat(self, item):
|
def isExpandedIName(self, iname):
|
||||||
format = self.formats.get(str(cleanAddress(item.value.address)))
|
return iname in self.expandedINames
|
||||||
if format is None:
|
|
||||||
format = self.typeformats.get(stripClassTag(str(item.value.type)))
|
|
||||||
return format
|
|
||||||
|
|
||||||
def dumpFrame(self, frame):
|
def itemFormat(self, item):
|
||||||
for var in frame.f_locals.keys():
|
format = self.formats.get(str(cleanAddress(item.value.address)))
|
||||||
if var == "__file__":
|
if format is None:
|
||||||
continue
|
format = self.typeformats.get(stripClassTag(str(item.value.type)))
|
||||||
#if var == "__name__":
|
return format
|
||||||
# continue
|
|
||||||
if var == "__package__":
|
|
||||||
continue
|
|
||||||
if var == "qdebug":
|
|
||||||
continue
|
|
||||||
if var != '__builtins__':
|
|
||||||
value = frame.f_locals[var]
|
|
||||||
self.dumpValue(value, var, "local.%s" % var)
|
|
||||||
|
|
||||||
def dumpValue(self, value, name, iname):
|
def dumpFrame(self, frame):
|
||||||
t = type(value)
|
for var in frame.f_locals.keys():
|
||||||
tt = self.cleanType(t)
|
if var == "__file__":
|
||||||
if tt == "module" or tt == "function":
|
continue
|
||||||
return
|
#if var == "__name__":
|
||||||
if str(value).startswith("<class '"):
|
# continue
|
||||||
return
|
if var == "__package__":
|
||||||
# FIXME: Should we?
|
continue
|
||||||
if str(value).startswith("<enum-item "):
|
if var == "qdebug":
|
||||||
return
|
continue
|
||||||
self.put("{")
|
if var != '__builtins__':
|
||||||
self.putField("iname", iname)
|
value = frame.f_locals[var]
|
||||||
self.putName(name)
|
self.dumpValue(value, var, "local.%s" % var)
|
||||||
self.putType(tt)
|
|
||||||
if tt == "NoneType":
|
def dumpValue(self, value, name, iname):
|
||||||
self.putValue("None")
|
t = type(value)
|
||||||
self.putNumChild(0)
|
tt = self.cleanType(t)
|
||||||
elif tt == "list" or tt == "tuple":
|
if tt == "module" or tt == "function":
|
||||||
self.putItemCount(len(value))
|
return
|
||||||
#self.putValue(value)
|
if str(value).startswith("<class '"):
|
||||||
self.put("children=[")
|
return
|
||||||
for i in xrange(len(value)):
|
# FIXME: Should we?
|
||||||
self.dumpValue(value[i], str(i), "%s.%d" % (iname, i))
|
if str(value).startswith("<enum-item "):
|
||||||
self.put("]")
|
return
|
||||||
elif tt == "str":
|
self.put("{")
|
||||||
v = value
|
self.putField("iname", iname)
|
||||||
self.putValue(v.encode('hex'))
|
self.putName(name)
|
||||||
self.putField("valueencoded", 6)
|
self.putType(tt)
|
||||||
self.putNumChild(0)
|
if tt == "NoneType":
|
||||||
elif tt == "unicode":
|
self.putValue("None")
|
||||||
v = value
|
self.putNumChild(0)
|
||||||
self.putValue(v.encode('hex'))
|
elif tt == "list" or tt == "tuple":
|
||||||
self.putField("valueencoded", 6)
|
self.putItemCount(len(value))
|
||||||
self.putNumChild(0)
|
#self.putValue(value)
|
||||||
elif tt == "buffer":
|
self.put("children=[")
|
||||||
v = str(value)
|
for i in xrange(len(value)):
|
||||||
self.putValue(v.encode('hex'))
|
self.dumpValue(value[i], str(i), "%s.%d" % (iname, i))
|
||||||
self.putField("valueencoded", 6)
|
self.put("]")
|
||||||
self.putNumChild(0)
|
elif tt == "str":
|
||||||
elif tt == "xrange":
|
v = value
|
||||||
b = iter(value).next()
|
self.putValue(v.encode('hex'))
|
||||||
e = b + len(value)
|
self.putField("valueencoded", 6)
|
||||||
self.putValue("(%d, %d)" % (b, e))
|
self.putNumChild(0)
|
||||||
self.putNumChild(0)
|
elif tt == "unicode":
|
||||||
elif tt == "dict":
|
v = value
|
||||||
self.putItemCount(len(value))
|
self.putValue(v.encode('hex'))
|
||||||
self.putField("childnumchild", 2)
|
self.putField("valueencoded", 6)
|
||||||
self.put("children=[")
|
self.putNumChild(0)
|
||||||
i = 0
|
elif tt == "buffer":
|
||||||
for (k, v) in value.iteritems():
|
v = str(value)
|
||||||
self.put("{")
|
self.putValue(v.encode('hex'))
|
||||||
self.putType(" ")
|
self.putField("valueencoded", 6)
|
||||||
self.putValue("%s: %s" % (k, v))
|
self.putNumChild(0)
|
||||||
|
elif tt == "xrange":
|
||||||
|
b = iter(value).next()
|
||||||
|
e = b + len(value)
|
||||||
|
self.putValue("(%d, %d)" % (b, e))
|
||||||
|
self.putNumChild(0)
|
||||||
|
elif tt == "dict":
|
||||||
|
self.putItemCount(len(value))
|
||||||
|
self.putField("childnumchild", 2)
|
||||||
|
self.put("children=[")
|
||||||
|
i = 0
|
||||||
|
for (k, v) in value.iteritems():
|
||||||
|
self.put("{")
|
||||||
|
self.putType(" ")
|
||||||
|
self.putValue("%s: %s" % (k, v))
|
||||||
|
if self.isExpanded(iname):
|
||||||
|
self.put("children=[")
|
||||||
|
self.dumpValue(k, "key", "%s.%d.k" % (iname, i))
|
||||||
|
self.dumpValue(v, "value", "%s.%d.v" % (iname, i))
|
||||||
|
self.put("]")
|
||||||
|
self.put("},")
|
||||||
|
i += 1
|
||||||
|
self.put("]")
|
||||||
|
elif tt == "class":
|
||||||
|
pass
|
||||||
|
elif tt == "module":
|
||||||
|
pass
|
||||||
|
elif tt == "function":
|
||||||
|
pass
|
||||||
|
elif str(value).startswith("<enum-item "):
|
||||||
|
# FIXME: Having enums always shown like this is not nice.
|
||||||
|
self.putValue(str(value)[11:-1])
|
||||||
|
self.putNumChild(0)
|
||||||
|
else:
|
||||||
|
v = str(value)
|
||||||
|
p = v.find(" object at ")
|
||||||
|
if p > 1:
|
||||||
|
v = "@" + v[p + 11:-1]
|
||||||
|
self.putValue(v)
|
||||||
if self.isExpanded(iname):
|
if self.isExpanded(iname):
|
||||||
self.put("children=[")
|
self.put("children=[")
|
||||||
self.dumpValue(k, "key", "%s.%d.k" % (iname, i))
|
for child in dir(value):
|
||||||
self.dumpValue(v, "value", "%s.%d.v" % (iname, i))
|
if child == "__dict__":
|
||||||
self.put("]")
|
continue
|
||||||
|
if child == "__doc__":
|
||||||
|
continue
|
||||||
|
if child == "__module__":
|
||||||
|
continue
|
||||||
|
attr = getattr(value, child)
|
||||||
|
if callable(attr):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
self.dumpValue(attr, child, "%s.%s" % (iname, child))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
self.put("],")
|
||||||
|
self.put("},")
|
||||||
|
|
||||||
|
|
||||||
|
def warn(self, msg):
|
||||||
|
self.putField("warning", msg)
|
||||||
|
|
||||||
|
def handleListVars(self):
|
||||||
|
# Trigger error to get a backtrace.
|
||||||
|
frame = None
|
||||||
|
#self.warn("frame: %s" % frame)
|
||||||
|
try:
|
||||||
|
raise ZeroDivisionError
|
||||||
|
except ZeroDivisionError:
|
||||||
|
frame = sys.exc_info()[2].tb_frame.f_back
|
||||||
|
|
||||||
|
limit = 30
|
||||||
|
n = 0
|
||||||
|
isActive = False
|
||||||
|
while frame is not None and n < limit:
|
||||||
|
#self.warn("frame: %s" % frame.f_locals.keys())
|
||||||
|
lineno = frame.f_lineno
|
||||||
|
code = frame.f_code
|
||||||
|
filename = code.co_filename
|
||||||
|
name = code.co_name
|
||||||
|
if isActive:
|
||||||
|
linecache.checkcache(filename)
|
||||||
|
line = linecache.getline(filename, lineno, frame.f_globals)
|
||||||
|
self.dumpFrame(frame)
|
||||||
|
if name == "<module>":
|
||||||
|
isActive = False
|
||||||
|
if name == "trace_dispatch":
|
||||||
|
isActive = True
|
||||||
|
frame = frame.f_back
|
||||||
|
n = n + 1
|
||||||
|
#sys.stdout.flush()
|
||||||
|
|
||||||
|
def handleListModules(self):
|
||||||
|
self.put("modules=[");
|
||||||
|
for name in sys.modules:
|
||||||
|
self.put("{")
|
||||||
|
self.putName(name)
|
||||||
|
self.putValue(sys.modules[name])
|
||||||
self.put("},")
|
self.put("},")
|
||||||
i += 1
|
|
||||||
self.put("]")
|
self.put("]")
|
||||||
elif tt == "class":
|
#sys.stdout.flush()
|
||||||
pass
|
|
||||||
elif tt == "module":
|
|
||||||
pass
|
|
||||||
elif tt == "function":
|
|
||||||
pass
|
|
||||||
elif str(value).startswith("<enum-item "):
|
|
||||||
# FIXME: Having enums always shown like this is not nice.
|
|
||||||
self.putValue(str(value)[11:-1])
|
|
||||||
self.putNumChild(0)
|
|
||||||
else:
|
|
||||||
v = str(value)
|
|
||||||
p = v.find(" object at ")
|
|
||||||
if p > 1:
|
|
||||||
v = "@" + v[p + 11:-1]
|
|
||||||
self.putValue(v)
|
|
||||||
if self.isExpanded(iname):
|
|
||||||
self.put("children=[")
|
|
||||||
for child in dir(value):
|
|
||||||
if child == "__dict__":
|
|
||||||
continue
|
|
||||||
if child == "__doc__":
|
|
||||||
continue
|
|
||||||
if child == "__module__":
|
|
||||||
continue
|
|
||||||
attr = getattr(value, child)
|
|
||||||
if callable(attr):
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
self.dumpValue(attr, child, "%s.%s" % (iname, child))
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
self.put("],")
|
|
||||||
self.put("},")
|
|
||||||
|
|
||||||
|
def handleListSymbols(self, module):
|
||||||
|
#self.put("symbols=%s" % dir(sys.modules[module]))
|
||||||
|
self.put("symbols=[");
|
||||||
|
for name in sys.modules:
|
||||||
|
self.put("{")
|
||||||
|
self.putName(name)
|
||||||
|
#self.putValue(sys.modules[name])
|
||||||
|
self.put("},")
|
||||||
|
self.put("]")
|
||||||
|
#sys.stdout.flush()
|
||||||
|
|
||||||
def warn(self, msg):
|
d = QDebug(options, expanded, typeformats, individualformats, watchers)
|
||||||
self.putField("warning", msg)
|
#print d.buffer
|
||||||
|
sys.stdout.write(d.buffer)
|
||||||
def handleListVars(self):
|
sys.stdout.flush()
|
||||||
# Trigger error to get a backtrace.
|
|
||||||
frame = None
|
|
||||||
#self.warn("frame: %s" % frame)
|
|
||||||
try:
|
|
||||||
raise ZeroDivisionError
|
|
||||||
except ZeroDivisionError:
|
|
||||||
frame = sys.exc_info()[2].tb_frame.f_back
|
|
||||||
|
|
||||||
limit = 30
|
|
||||||
n = 0
|
|
||||||
isActive = False
|
|
||||||
while frame is not None and n < limit:
|
|
||||||
#self.warn("frame: %s" % frame.f_locals.keys())
|
|
||||||
lineno = frame.f_lineno
|
|
||||||
code = frame.f_code
|
|
||||||
filename = code.co_filename
|
|
||||||
name = code.co_name
|
|
||||||
if isActive:
|
|
||||||
linecache.checkcache(filename)
|
|
||||||
line = linecache.getline(filename, lineno, frame.f_globals)
|
|
||||||
self.dumpFrame(frame)
|
|
||||||
if name == "<module>":
|
|
||||||
isActive = False
|
|
||||||
if name == "trace_dispatch":
|
|
||||||
isActive = True
|
|
||||||
frame = frame.f_back
|
|
||||||
n = n + 1
|
|
||||||
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
def handleListModules(self):
|
|
||||||
self.put("modules=[");
|
|
||||||
for name in sys.modules:
|
|
||||||
self.put("{")
|
|
||||||
self.putName(name)
|
|
||||||
self.putValue(sys.modules[name])
|
|
||||||
self.put("},")
|
|
||||||
self.put("]")
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
def handleListSymbols(self, module):
|
|
||||||
#self.put("symbols=%s" % dir(sys.modules[module]))
|
|
||||||
self.put("symbols=[");
|
|
||||||
for name in sys.modules:
|
|
||||||
self.put("{")
|
|
||||||
self.putName(name)
|
|
||||||
#self.putValue(sys.modules[name])
|
|
||||||
self.put("},")
|
|
||||||
self.put("]")
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|||||||
@@ -61,8 +61,8 @@
|
|||||||
#include <QtCore/QVariant>
|
#include <QtCore/QVariant>
|
||||||
|
|
||||||
#include <QtGui/QApplication>
|
#include <QtGui/QApplication>
|
||||||
#include <QtGui/QToolTip>
|
|
||||||
#include <QtGui/QMessageBox>
|
#include <QtGui/QMessageBox>
|
||||||
|
#include <QtGui/QToolTip>
|
||||||
|
|
||||||
|
|
||||||
#define DEBUG_SCRIPT 1
|
#define DEBUG_SCRIPT 1
|
||||||
@@ -94,12 +94,26 @@ PdbEngine::~PdbEngine()
|
|||||||
|
|
||||||
void PdbEngine::executeDebuggerCommand(const QString &command)
|
void PdbEngine::executeDebuggerCommand(const QString &command)
|
||||||
{
|
{
|
||||||
XSDEBUG("PdbEngine::executeDebuggerCommand:" << command);
|
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
|
||||||
|
//XSDEBUG("PdbEngine::executeDebuggerCommand:" << command);
|
||||||
if (state() == DebuggerNotReady) {
|
if (state() == DebuggerNotReady) {
|
||||||
showMessage(_("PDB PROCESS NOT RUNNING, PLAIN CMD IGNORED: ") + command);
|
showMessage(_("PDB PROCESS NOT RUNNING, PLAIN CMD IGNORED: ") + command);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_pdbProc.write(command.toLatin1() + "\n");
|
QTC_ASSERT(m_pdbProc.state() == QProcess::Running, notifyEngineIll());
|
||||||
|
postCommand(command.toLatin1(), CB(handleExecuteDebuggerCommand));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PdbEngine::handleExecuteDebuggerCommand(const PdbResponse &response)
|
||||||
|
{
|
||||||
|
Q_UNUSED(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PdbEngine::postDirectCommand(const QByteArray &command)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_pdbProc.state() == QProcess::Running, notifyEngineIll());
|
||||||
|
showMessage(_(command), LogInput);
|
||||||
|
m_pdbProc.write(command + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdbEngine::postCommand(const QByteArray &command,
|
void PdbEngine::postCommand(const QByteArray &command,
|
||||||
@@ -108,12 +122,14 @@ void PdbEngine::postCommand(const QByteArray &command,
|
|||||||
const char *callbackName,
|
const char *callbackName,
|
||||||
const QVariant &cookie)
|
const QVariant &cookie)
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(m_pdbProc.state() == QProcess::Running, notifyEngineIll());
|
||||||
PdbCommand cmd;
|
PdbCommand cmd;
|
||||||
cmd.command = command;
|
cmd.command = command;
|
||||||
cmd.callback = callback;
|
cmd.callback = callback;
|
||||||
cmd.callbackName = callbackName;
|
cmd.callbackName = callbackName;
|
||||||
cmd.cookie = cookie;
|
cmd.cookie = cookie;
|
||||||
m_commands.enqueue(cmd);
|
m_commands.enqueue(cmd);
|
||||||
|
qDebug() << "ENQUEUE: " << command << cmd.callbackName;
|
||||||
showMessage(_(cmd.command), LogInput);
|
showMessage(_(cmd.command), LogInput);
|
||||||
m_pdbProc.write(cmd.command + "\n");
|
m_pdbProc.write(cmd.command + "\n");
|
||||||
}
|
}
|
||||||
@@ -127,7 +143,6 @@ void PdbEngine::shutdownInferior()
|
|||||||
void PdbEngine::shutdownEngine()
|
void PdbEngine::shutdownEngine()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
|
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
|
||||||
SDEBUG("PdbEngine::shutdownEngine()");
|
|
||||||
m_pdbProc.kill();
|
m_pdbProc.kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,24 +150,8 @@ void PdbEngine::setupEngine()
|
|||||||
{
|
{
|
||||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||||
|
|
||||||
m_scriptFileName = QFileInfo(startParameters().executable).absoluteFilePath();
|
m_pdb = _("python");
|
||||||
QFile scriptFile(m_scriptFileName);
|
|
||||||
if (!scriptFile.open(QIODevice::ReadOnly|QIODevice::Text)) {
|
|
||||||
//showMessage("STARTING " +m_scriptFileName + "FAILED");
|
|
||||||
showMessage(QString::fromLatin1("Cannot open %1: %2").
|
|
||||||
arg(m_scriptFileName, scriptFile.errorString()), LogError);
|
|
||||||
notifyEngineSetupFailed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_pdbProc.disconnect(); // From any previous runs
|
|
||||||
|
|
||||||
m_pdb = _("/usr/bin/python");
|
|
||||||
showMessage(_("STARTING PDB ") + m_pdb);
|
showMessage(_("STARTING PDB ") + m_pdb);
|
||||||
QStringList gdbArgs;
|
|
||||||
gdbArgs += _("-i");
|
|
||||||
gdbArgs += _("/usr/bin/pdb");
|
|
||||||
gdbArgs += m_scriptFileName;
|
|
||||||
//gdbArgs += args;
|
|
||||||
|
|
||||||
connect(&m_pdbProc, SIGNAL(error(QProcess::ProcessError)),
|
connect(&m_pdbProc, SIGNAL(error(QProcess::ProcessError)),
|
||||||
SLOT(handlePdbError(QProcess::ProcessError)));
|
SLOT(handlePdbError(QProcess::ProcessError)));
|
||||||
@@ -163,13 +162,15 @@ void PdbEngine::setupEngine()
|
|||||||
connect(&m_pdbProc, SIGNAL(readyReadStandardError()),
|
connect(&m_pdbProc, SIGNAL(readyReadStandardError()),
|
||||||
SLOT(readPdbStandardError()));
|
SLOT(readPdbStandardError()));
|
||||||
|
|
||||||
|
connect(this, SIGNAL(outputReady(QByteArray)),
|
||||||
|
SLOT(handleOutput2(QByteArray)), Qt::QueuedConnection);
|
||||||
|
|
||||||
// We will stop immediatly, so setup a proper callback.
|
// We will stop immediatly, so setup a proper callback.
|
||||||
PdbCommand cmd;
|
PdbCommand cmd;
|
||||||
cmd.callback = &PdbEngine::handleFirstCommand;
|
cmd.callback = &PdbEngine::handleFirstCommand;
|
||||||
m_commands.enqueue(cmd);
|
m_commands.enqueue(cmd);
|
||||||
|
|
||||||
m_pdbProc.start(m_pdb, gdbArgs);
|
m_pdbProc.start(m_pdb, QStringList() << _("-i"));
|
||||||
//qDebug() << "STARTING:" << m_pdb << gdbArgs;
|
|
||||||
|
|
||||||
if (!m_pdbProc.waitForStarted()) {
|
if (!m_pdbProc.waitForStarted()) {
|
||||||
const QString msg = tr("Unable to start pdb '%1': %2")
|
const QString msg = tr("Unable to start pdb '%1': %2")
|
||||||
@@ -189,21 +190,33 @@ void PdbEngine::setupEngine()
|
|||||||
void PdbEngine::setupInferior()
|
void PdbEngine::setupInferior()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||||
attemptBreakpointSynchronization();
|
|
||||||
|
|
||||||
showMessage(_("PDB STARTED, INITIALIZING IT"));
|
QString fileName = QFileInfo(startParameters().executable).absoluteFilePath();
|
||||||
const QByteArray dumperSourcePath =
|
QFile scriptFile(fileName);
|
||||||
Core::ICore::instance()->resourcePath().toLocal8Bit() + "/gdbmacros/";
|
if (!scriptFile.open(QIODevice::ReadOnly|QIODevice::Text)) {
|
||||||
postCommand("execfile('" + dumperSourcePath + "pdumper.py')",
|
showMessageBox(QMessageBox::Critical, tr("Python Error"),
|
||||||
CB(handleLoadDumper));
|
_("Cannot open script file %1:\n%2").
|
||||||
|
arg(fileName, scriptFile.errorString()));
|
||||||
|
notifyInferiorSetupFailed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
notifyInferiorSetupOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdbEngine::runEngine()
|
void PdbEngine::runEngine()
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
||||||
showStatusMessage(tr("Running requested..."), 5000);
|
showStatusMessage(tr("Running requested..."), 5000);
|
||||||
SDEBUG("PdbEngine::runEngine()");
|
const QByteArray dumperSourcePath =
|
||||||
notifyEngineRunAndInferiorRunOk();
|
Core::ICore::instance()->resourcePath().toLocal8Bit() + "/gdbmacros/";
|
||||||
postCommand("continue", CB(handleUpdateAll));
|
QString fileName = QFileInfo(startParameters().executable).absoluteFilePath();
|
||||||
|
postDirectCommand("import sys");
|
||||||
|
postDirectCommand("sys.argv.append('" + fileName.toLocal8Bit() + "')");
|
||||||
|
postDirectCommand("execfile('/usr/bin/pdb')");
|
||||||
|
postDirectCommand("execfile('" + dumperSourcePath + "pdumper.py')");
|
||||||
|
attemptBreakpointSynchronization();
|
||||||
|
notifyEngineRunAndInferiorStopOk();
|
||||||
|
continueInferior();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdbEngine::interruptInferior()
|
void PdbEngine::interruptInferior()
|
||||||
@@ -388,7 +401,7 @@ void PdbEngine::loadAllSymbols()
|
|||||||
|
|
||||||
void PdbEngine::reloadModules()
|
void PdbEngine::reloadModules()
|
||||||
{
|
{
|
||||||
postCommand("qdebug('listmodules')", CB(handleListModules));
|
//postCommand("qdebug('listmodules')", CB(handleListModules));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdbEngine::handleListModules(const PdbResponse &response)
|
void PdbEngine::handleListModules(const PdbResponse &response)
|
||||||
@@ -549,6 +562,7 @@ void PdbEngine::updateWatchData(const WatchData &data)
|
|||||||
|
|
||||||
void PdbEngine::handlePdbError(QProcess::ProcessError error)
|
void PdbEngine::handlePdbError(QProcess::ProcessError error)
|
||||||
{
|
{
|
||||||
|
qDebug() << "HANDLE PDB ERROR";
|
||||||
showMessage(_("HANDLE PDB ERROR"));
|
showMessage(_("HANDLE PDB ERROR"));
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case QProcess::Crashed:
|
case QProcess::Crashed:
|
||||||
@@ -595,6 +609,7 @@ QString PdbEngine::errorMessage(QProcess::ProcessError error) const
|
|||||||
|
|
||||||
void PdbEngine::handlePdbFinished(int code, QProcess::ExitStatus type)
|
void PdbEngine::handlePdbFinished(int code, QProcess::ExitStatus type)
|
||||||
{
|
{
|
||||||
|
qDebug() << "PDB FINISHED";
|
||||||
showMessage(_("PDB PROCESS FINISHED, status %1, code %2").arg(type).arg(code));
|
showMessage(_("PDB PROCESS FINISHED, status %1, code %2").arg(type).arg(code));
|
||||||
notifyEngineSpontaneousShutdown();
|
notifyEngineSpontaneousShutdown();
|
||||||
}
|
}
|
||||||
@@ -602,35 +617,57 @@ void PdbEngine::handlePdbFinished(int code, QProcess::ExitStatus type)
|
|||||||
void PdbEngine::readPdbStandardError()
|
void PdbEngine::readPdbStandardError()
|
||||||
{
|
{
|
||||||
QByteArray err = m_pdbProc.readAllStandardError();
|
QByteArray err = m_pdbProc.readAllStandardError();
|
||||||
qWarning() << "Unexpected pdb stderr:" << err;
|
qDebug() << "\nPDB STDERR" << err;
|
||||||
showMessage(_("Unexpected pdb stderr: " + err));
|
//qWarning() << "Unexpected pdb stderr:" << err;
|
||||||
|
//showMessage(_("Unexpected pdb stderr: " + err));
|
||||||
|
//handleOutput(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdbEngine::readPdbStandardOutput()
|
void PdbEngine::readPdbStandardOutput()
|
||||||
{
|
{
|
||||||
m_inbuffer.append(m_pdbProc.readAllStandardOutput());
|
QByteArray out = m_pdbProc.readAllStandardOutput();
|
||||||
//qDebug() << "BUFFER FROM: '" << m_inbuffer << "'";
|
qDebug() << "\nPDB STDOUT" << out;
|
||||||
int pos = 1;
|
handleOutput(out);
|
||||||
while ((pos = m_inbuffer.indexOf("(Pdb)")) != -1) {
|
|
||||||
PdbResponse response;
|
|
||||||
response.data = m_inbuffer.left(pos).trimmed();
|
|
||||||
showMessage(_(response.data));
|
|
||||||
m_inbuffer = m_inbuffer.mid(pos + 6);
|
|
||||||
QTC_ASSERT(!m_commands.isEmpty(),
|
|
||||||
qDebug() << "RESPONSE: " << response.data; return)
|
|
||||||
PdbCommand cmd = m_commands.dequeue();
|
|
||||||
response.cookie = cmd.cookie;
|
|
||||||
if (cmd.callback) {
|
|
||||||
//qDebug() << "EXECUTING CALLBACK " << cmd.callbackName
|
|
||||||
// << " RESPONSE: " << response.data;
|
|
||||||
(this->*cmd.callback)(response);
|
|
||||||
} else {
|
|
||||||
qDebug() << "NO CALLBACK FOR RESPONSE: " << response.data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//qDebug() << "BUFFER LEFT: '" << m_inbuffer << "'";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PdbEngine::handleOutput(const QByteArray &data)
|
||||||
|
{
|
||||||
|
//qDebug() << "READ: " << data;
|
||||||
|
m_inbuffer.append(data);
|
||||||
|
qDebug() << "BUFFER FROM: '" << m_inbuffer << "'";
|
||||||
|
while (true) {
|
||||||
|
int pos = m_inbuffer.indexOf("(Pdb)");
|
||||||
|
if (pos == -1)
|
||||||
|
pos = m_inbuffer.indexOf(">>>");
|
||||||
|
if (pos == -1)
|
||||||
|
break;
|
||||||
|
QByteArray response = m_inbuffer.left(pos).trimmed();
|
||||||
|
m_inbuffer = m_inbuffer.mid(pos + 6);
|
||||||
|
emit outputReady(response);
|
||||||
|
}
|
||||||
|
qDebug() << "BUFFER LEFT: '" << m_inbuffer << "'";
|
||||||
|
//m_inbuffer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PdbEngine::handleOutput2(const QByteArray &data)
|
||||||
|
{
|
||||||
|
PdbResponse response;
|
||||||
|
response.data = data;
|
||||||
|
showMessage(_(data));
|
||||||
|
QTC_ASSERT(!m_commands.isEmpty(), qDebug() << "RESPONSE: " << data; return)
|
||||||
|
PdbCommand cmd = m_commands.dequeue();
|
||||||
|
response.cookie = cmd.cookie;
|
||||||
|
qDebug() << "DEQUE: " << cmd.command << cmd.callbackName;
|
||||||
|
if (cmd.callback) {
|
||||||
|
//qDebug() << "EXECUTING CALLBACK " << cmd.callbackName
|
||||||
|
// << " RESPONSE: " << response.data;
|
||||||
|
(this->*cmd.callback)(response);
|
||||||
|
} else {
|
||||||
|
qDebug() << "NO CALLBACK FOR RESPONSE: " << response.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
void PdbEngine::handleResponse(const QByteArray &response0)
|
void PdbEngine::handleResponse(const QByteArray &response0)
|
||||||
{
|
{
|
||||||
QByteArray response = response0;
|
QByteArray response = response0;
|
||||||
@@ -663,6 +700,7 @@ void PdbEngine::handleResponse(const QByteArray &response0)
|
|||||||
}
|
}
|
||||||
qDebug() << "COULD NOT PARSE RESPONSE: '" << response << "'";
|
qDebug() << "COULD NOT PARSE RESPONSE: '" << response << "'";
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void PdbEngine::handleFirstCommand(const PdbResponse &response)
|
void PdbEngine::handleFirstCommand(const PdbResponse &response)
|
||||||
{
|
{
|
||||||
@@ -677,6 +715,12 @@ void PdbEngine::handleUpdateAll(const PdbResponse &response)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PdbEngine::updateAll()
|
void PdbEngine::updateAll()
|
||||||
|
{
|
||||||
|
postCommand("bt", CB(handleBacktrace));
|
||||||
|
//updateLocals();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PdbEngine::updateLocals()
|
||||||
{
|
{
|
||||||
WatchHandler *handler = watchHandler();
|
WatchHandler *handler = watchHandler();
|
||||||
|
|
||||||
@@ -706,7 +750,6 @@ void PdbEngine::updateAll()
|
|||||||
options += "defaults,";
|
options += "defaults,";
|
||||||
options.chop(1);
|
options.chop(1);
|
||||||
|
|
||||||
postCommand("bt", CB(handleBacktrace));
|
|
||||||
postCommand("qdebug('" + options + "','"
|
postCommand("qdebug('" + options + "','"
|
||||||
+ handler->expansionRequests() + "','"
|
+ handler->expansionRequests() + "','"
|
||||||
+ handler->typeFormatRequests() + "','"
|
+ handler->typeFormatRequests() + "','"
|
||||||
@@ -768,6 +811,8 @@ void PdbEngine::handleBacktrace(const PdbResponse &response)
|
|||||||
stackHandler()->setCurrentIndex(currentIndex);
|
stackHandler()->setCurrentIndex(currentIndex);
|
||||||
gotoLocation(stackFrames.at(currentIndex), true);
|
gotoLocation(stackFrames.at(currentIndex), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateLocals();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdbEngine::handleListLocals(const PdbResponse &response)
|
void PdbEngine::handleListLocals(const PdbResponse &response)
|
||||||
@@ -792,14 +837,6 @@ void PdbEngine::handleListLocals(const PdbResponse &response)
|
|||||||
handler->insertBulkData(list);
|
handler->insertBulkData(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdbEngine::handleLoadDumper(const PdbResponse &response)
|
|
||||||
{
|
|
||||||
Q_UNUSED(response);
|
|
||||||
//qDebug() << " DUMPERS LOADED '" << response.data << "'";
|
|
||||||
//continueInferior();
|
|
||||||
notifyInferiorSetupOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned PdbEngine::debuggerCapabilities() const
|
unsigned PdbEngine::debuggerCapabilities() const
|
||||||
{
|
{
|
||||||
return ReloadModuleCapability;
|
return ReloadModuleCapability;
|
||||||
|
|||||||
@@ -105,6 +105,9 @@ private:
|
|||||||
bool isSynchroneous() const { return true; }
|
bool isSynchroneous() const { return true; }
|
||||||
void updateWatchData(const WatchData &data);
|
void updateWatchData(const WatchData &data);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void outputReady(const QByteArray &data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString errorMessage(QProcess::ProcessError error) const;
|
QString errorMessage(QProcess::ProcessError error) const;
|
||||||
unsigned debuggerCapabilities() const;
|
unsigned debuggerCapabilities() const;
|
||||||
@@ -113,10 +116,14 @@ private:
|
|||||||
Q_SLOT void handlePdbError(QProcess::ProcessError error);
|
Q_SLOT void handlePdbError(QProcess::ProcessError error);
|
||||||
Q_SLOT void readPdbStandardOutput();
|
Q_SLOT void readPdbStandardOutput();
|
||||||
Q_SLOT void readPdbStandardError();
|
Q_SLOT void readPdbStandardError();
|
||||||
|
Q_SLOT void handleOutput2(const QByteArray &data);
|
||||||
void handleResponse(const QByteArray &ba);
|
void handleResponse(const QByteArray &ba);
|
||||||
|
void handleOutput(const QByteArray &data);
|
||||||
void updateAll();
|
void updateAll();
|
||||||
|
void updateLocals();
|
||||||
void handleUpdateAll(const PdbResponse &response);
|
void handleUpdateAll(const PdbResponse &response);
|
||||||
void handleFirstCommand(const PdbResponse &response);
|
void handleFirstCommand(const PdbResponse &response);
|
||||||
|
void handleExecuteDebuggerCommand(const PdbResponse &response);
|
||||||
|
|
||||||
typedef void (PdbEngine::*PdbCommandCallback)
|
typedef void (PdbEngine::*PdbCommandCallback)
|
||||||
(const PdbResponse &response);
|
(const PdbResponse &response);
|
||||||
@@ -139,7 +146,6 @@ private:
|
|||||||
void handleListLocals(const PdbResponse &response);
|
void handleListLocals(const PdbResponse &response);
|
||||||
void handleListModules(const PdbResponse &response);
|
void handleListModules(const PdbResponse &response);
|
||||||
void handleListSymbols(const PdbResponse &response);
|
void handleListSymbols(const PdbResponse &response);
|
||||||
void handleLoadDumper(const PdbResponse &response);
|
|
||||||
void handleBreakInsert(const PdbResponse &response);
|
void handleBreakInsert(const PdbResponse &response);
|
||||||
|
|
||||||
void handleChildren(const WatchData &data0, const GdbMi &item,
|
void handleChildren(const WatchData &data0, const GdbMi &item,
|
||||||
@@ -149,6 +155,7 @@ private:
|
|||||||
PdbCommandCallback callback = 0,
|
PdbCommandCallback callback = 0,
|
||||||
const char *callbackName = 0,
|
const char *callbackName = 0,
|
||||||
const QVariant &cookie = QVariant());
|
const QVariant &cookie = QVariant());
|
||||||
|
void postDirectCommand(const QByteArray &command);
|
||||||
|
|
||||||
QQueue<PdbCommand> m_commands;
|
QQueue<PdbCommand> m_commands;
|
||||||
|
|
||||||
|
|||||||
@@ -327,7 +327,8 @@ void ScriptEngine::importExtensions()
|
|||||||
"Make sure that the bindings have been built, "
|
"Make sure that the bindings have been built, "
|
||||||
"and that this executable and the plugins are "
|
"and that this executable and the plugins are "
|
||||||
"using compatible Qt libraries.",
|
"using compatible Qt libraries.",
|
||||||
qPrintable(failExtensions.join(QLatin1String(", "))), qPrintable(dir.absolutePath()));
|
qPrintable(failExtensions.join(QLatin1String(", "))),
|
||||||
|
qPrintable(dir.absolutePath()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return; // failExtensions.isEmpty();
|
return; // failExtensions.isEmpty();
|
||||||
@@ -336,12 +337,12 @@ void ScriptEngine::importExtensions()
|
|||||||
void ScriptEngine::runEngine()
|
void ScriptEngine::runEngine()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
||||||
SDEBUG("ScriptEngine::runEngine()");
|
|
||||||
notifyEngineRunAndInferiorRunOk();
|
notifyEngineRunAndInferiorRunOk();
|
||||||
showStatusMessage(tr("Running requested..."), 5000);
|
showStatusMessage(tr("Running requested..."), 5000);
|
||||||
showMessage(QLatin1String("Running: ") + m_scriptFileName, LogMisc);
|
showMessage(QLatin1String("Running: ") + m_scriptFileName, LogMisc);
|
||||||
importExtensions();
|
importExtensions();
|
||||||
const QScriptValue result = m_scriptEngine->evaluate(m_scriptContents, m_scriptFileName);
|
const QScriptValue result =
|
||||||
|
m_scriptEngine->evaluate(m_scriptContents, m_scriptFileName);
|
||||||
QString msg;
|
QString msg;
|
||||||
if (m_scriptEngine->hasUncaughtException()) {
|
if (m_scriptEngine->hasUncaughtException()) {
|
||||||
msg = _("An exception occurred during execution at line: %1\n%2\n")
|
msg = _("An exception occurred during execution at line: %1\n%2\n")
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ def testMath():
|
|||||||
print cube(5)
|
print cube(5)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
#testMath()
|
testMath()
|
||||||
testApp()
|
#testApp()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
Reference in New Issue
Block a user