From 3cee7dad0a90ff461a86b033c2f87a8f9ff28d7d Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Fri, 23 Jul 2010 16:05:56 +0200
Subject: [PATCH] debugger: make parts of python debugger work again with the
 new states

---
 share/qtcreator/gdbmacros/pdumper.py         | 465 ++++++++++---------
 src/plugins/debugger/pdb/pdbengine.cpp       | 173 ++++---
 src/plugins/debugger/pdb/pdbengine.h         |   9 +-
 src/plugins/debugger/script/scriptengine.cpp |   7 +-
 tests/manual/gdbdebugger/python/math.py      |   4 +-
 5 files changed, 357 insertions(+), 301 deletions(-)

diff --git a/share/qtcreator/gdbmacros/pdumper.py b/share/qtcreator/gdbmacros/pdumper.py
index 874597b3e3d..e0144490abb 100644
--- a/share/qtcreator/gdbmacros/pdumper.py
+++ b/share/qtcreator/gdbmacros/pdumper.py
@@ -3,239 +3,250 @@ import pdb;
 import sys;
 import linecache
 
-
-class qdebug:
-    def __init__(self,
-            options = None,
+def qdebug(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
-        if self.options == "listmodules":
-            self.handleListModules()
-        elif self.options == "listsymbols":
-            self.handleListSymbols(expanded)
-        else:
-            self.handleListVars()
-
-    def put(self, value):
-        sys.stdout.write(value)
-
-    def putField(self, name, value):
-        self.put('%s="%s",' % (name, value))
-
-    def putItemCount(self, count):
-        self.put('value="<%s items>",' % count)
-
-    def putEllipsis(self):
-        self.put('{name="<incomplete>",value="",type="",numchild="0"},')
-
-    def cleanType(self, 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 putType(self, type, priority = 0):
-        self.putField("type", self.cleanType(type))
-
-    def putAddress(self, addr):
-        self.put('addr="%s",' % cleanAddress(addr))
-
-    def putNumChild(self, numchild):
-        self.put('numchild="%s",' % numchild)
-
-    def putValue(self, value, encoding = None, priority = 0):
-        self.putField("value", value)
-
-    def putName(self, name):
-        self.put('name="%s",' % name)
-
-    def isExpanded(self, iname):
-        #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 isExpandedIName(self, iname):
-        return iname in self.expandedINames
-
-    def itemFormat(self, item):
-        format = self.formats.get(str(cleanAddress(item.value.address)))
-        if format is None:
-            format = self.typeformats.get(stripClassTag(str(item.value.type)))
-        return format
-
-    def dumpFrame(self, frame):
-        for var in frame.f_locals.keys():
-            if var == "__file__":
-                continue
-            #if var == "__name__":
-            #    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):
-        t = type(value)
-        tt = self.cleanType(t)
-        if tt == "module" or tt == "function":
-            return
-        if str(value).startswith("<class '"):
-            return
-        # FIXME: Should we?
-        if str(value).startswith("<enum-item "):
-            return
-        self.put("{")
-        self.putField("iname", iname)
-        self.putName(name)
-        self.putType(tt)
-        if tt == "NoneType":
-            self.putValue("None")
-            self.putNumChild(0)
-        elif tt == "list" or tt == "tuple":
-            self.putItemCount(len(value))
-            #self.putValue(value)
-            self.put("children=[")
-            for i in xrange(len(value)):
-                self.dumpValue(value[i], str(i), "%s.%d" % (iname, i))
-            self.put("]")
-        elif tt == "str":
-            v = value
-            self.putValue(v.encode('hex'))
-            self.putField("valueencoded", 6)
-            self.putNumChild(0)
-        elif tt == "unicode":
-            v = value
-            self.putValue(v.encode('hex'))
-            self.putField("valueencoded", 6)
-            self.putNumChild(0)
-        elif tt == "buffer":
-            v = str(value)
-            self.putValue(v.encode('hex'))
-            self.putField("valueencoded", 6)
-            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))
+
+    class QDebug:
+        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 put(self, value):
+            #sys.stdout.write(value)
+            self.buffer += value
+
+        def putField(self, name, value):
+            self.put('%s="%s",' % (name, value))
+
+        def putItemCount(self, count):
+            self.put('value="<%s items>",' % count)
+
+        def putEllipsis(self):
+            self.put('{name="<incomplete>",value="",type="",numchild="0"},')
+
+        def cleanType(self, 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 putType(self, type, priority = 0):
+            self.putField("type", self.cleanType(type))
+
+        def putAddress(self, addr):
+            self.put('addr="%s",' % cleanAddress(addr))
+
+        def putNumChild(self, numchild):
+            self.put('numchild="%s",' % numchild)
+
+        def putValue(self, value, encoding = None, priority = 0):
+            self.putField("value", value)
+
+        def putName(self, name):
+            self.put('name="%s",' % name)
+
+        def isExpanded(self, iname):
+            #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 isExpandedIName(self, iname):
+            return iname in self.expandedINames
+
+        def itemFormat(self, item):
+            format = self.formats.get(str(cleanAddress(item.value.address)))
+            if format is None:
+                format = self.typeformats.get(stripClassTag(str(item.value.type)))
+            return format
+
+        def dumpFrame(self, frame):
+            for var in frame.f_locals.keys():
+                if var == "__file__":
+                    continue
+                #if var == "__name__":
+                #    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):
+            t = type(value)
+            tt = self.cleanType(t)
+            if tt == "module" or tt == "function":
+                return
+            if str(value).startswith("<class '"):
+                return
+            # FIXME: Should we?
+            if str(value).startswith("<enum-item "):
+                return
+            self.put("{")
+            self.putField("iname", iname)
+            self.putName(name)
+            self.putType(tt)
+            if tt == "NoneType":
+                self.putValue("None")
+                self.putNumChild(0)
+            elif tt == "list" or tt == "tuple":
+                self.putItemCount(len(value))
+                #self.putValue(value)
+                self.put("children=[")
+                for i in xrange(len(value)):
+                    self.dumpValue(value[i], str(i), "%s.%d" % (iname, i))
+                self.put("]")
+            elif tt == "str":
+                v = value
+                self.putValue(v.encode('hex'))
+                self.putField("valueencoded", 6)
+                self.putNumChild(0)
+            elif tt == "unicode":
+                v = value
+                self.putValue(v.encode('hex'))
+                self.putField("valueencoded", 6)
+                self.putNumChild(0)
+            elif tt == "buffer":
+                v = str(value)
+                self.putValue(v.encode('hex'))
+                self.putField("valueencoded", 6)
+                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):
                     self.put("children=[")
-                    self.dumpValue(k, "key", "%s.%d.k" % (iname, i))
-                    self.dumpValue(v, "value", "%s.%d.v" % (iname, i))
-                    self.put("]")
+                    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 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("},")
-                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):
-                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 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("]")
-        sys.stdout.flush()
+            #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()
+        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()
+
+    d = QDebug(options, expanded, typeformats, individualformats, watchers)
+    #print d.buffer
+    sys.stdout.write(d.buffer)
+    sys.stdout.flush()
diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp
index 0863a9f0742..abd63b0e7d1 100644
--- a/src/plugins/debugger/pdb/pdbengine.cpp
+++ b/src/plugins/debugger/pdb/pdbengine.cpp
@@ -61,8 +61,8 @@
 #include <QtCore/QVariant>
 
 #include <QtGui/QApplication>
-#include <QtGui/QToolTip>
 #include <QtGui/QMessageBox>
+#include <QtGui/QToolTip>
 
 
 #define DEBUG_SCRIPT 1
@@ -94,12 +94,26 @@ PdbEngine::~PdbEngine()
 
 void PdbEngine::executeDebuggerCommand(const QString &command)
 {
-    XSDEBUG("PdbEngine::executeDebuggerCommand:" << command);
+    QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
+    //XSDEBUG("PdbEngine::executeDebuggerCommand:" << command);
     if (state() == DebuggerNotReady) {
         showMessage(_("PDB PROCESS NOT RUNNING, PLAIN CMD IGNORED: ") + command);
         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,
@@ -108,12 +122,14 @@ void PdbEngine::postCommand(const QByteArray &command,
                  const char *callbackName,
                  const QVariant &cookie)
 {
+    QTC_ASSERT(m_pdbProc.state() == QProcess::Running, notifyEngineIll());
     PdbCommand cmd;
     cmd.command = command;
     cmd.callback = callback;
     cmd.callbackName = callbackName;
     cmd.cookie = cookie;
     m_commands.enqueue(cmd);
+    qDebug() << "ENQUEUE: " << command << cmd.callbackName;
     showMessage(_(cmd.command), LogInput);
     m_pdbProc.write(cmd.command + "\n");
 }
@@ -127,7 +143,6 @@ void PdbEngine::shutdownInferior()
 void PdbEngine::shutdownEngine()
 {
     QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
-    SDEBUG("PdbEngine::shutdownEngine()");
     m_pdbProc.kill();
 }
 
@@ -135,24 +150,8 @@ void PdbEngine::setupEngine()
 {
     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
 
-    m_scriptFileName = QFileInfo(startParameters().executable).absoluteFilePath();
-    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");
+    m_pdb = _("python");
     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)),
         SLOT(handlePdbError(QProcess::ProcessError)));
@@ -163,13 +162,15 @@ void PdbEngine::setupEngine()
     connect(&m_pdbProc, SIGNAL(readyReadStandardError()),
         SLOT(readPdbStandardError()));
 
+    connect(this, SIGNAL(outputReady(QByteArray)),
+        SLOT(handleOutput2(QByteArray)), Qt::QueuedConnection);
+
     // We will stop immediatly, so setup a proper callback.
     PdbCommand cmd;
     cmd.callback = &PdbEngine::handleFirstCommand;
     m_commands.enqueue(cmd);
 
-    m_pdbProc.start(m_pdb, gdbArgs);
-    //qDebug() << "STARTING:" << m_pdb << gdbArgs;
+    m_pdbProc.start(m_pdb, QStringList() << _("-i"));
 
     if (!m_pdbProc.waitForStarted()) {
         const QString msg = tr("Unable to start pdb '%1': %2")
@@ -189,21 +190,33 @@ void PdbEngine::setupEngine()
 void PdbEngine::setupInferior()
 {
     QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
-    attemptBreakpointSynchronization();
 
-    showMessage(_("PDB STARTED, INITIALIZING IT"));
-    const QByteArray dumperSourcePath =
-        Core::ICore::instance()->resourcePath().toLocal8Bit() + "/gdbmacros/";
-    postCommand("execfile('" + dumperSourcePath + "pdumper.py')",
-        CB(handleLoadDumper));
+    QString fileName = QFileInfo(startParameters().executable).absoluteFilePath();
+    QFile scriptFile(fileName);
+    if (!scriptFile.open(QIODevice::ReadOnly|QIODevice::Text)) {
+        showMessageBox(QMessageBox::Critical, tr("Python Error"),
+            _("Cannot open script file %1:\n%2").
+               arg(fileName, scriptFile.errorString()));
+        notifyInferiorSetupFailed();
+        return;
+    }
+    notifyInferiorSetupOk();
 }
 
 void PdbEngine::runEngine()
 {
+    QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
     showStatusMessage(tr("Running requested..."), 5000);
-    SDEBUG("PdbEngine::runEngine()");
-    notifyEngineRunAndInferiorRunOk();
-    postCommand("continue", CB(handleUpdateAll));
+    const QByteArray dumperSourcePath =
+        Core::ICore::instance()->resourcePath().toLocal8Bit() + "/gdbmacros/";
+    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()
@@ -388,7 +401,7 @@ void PdbEngine::loadAllSymbols()
 
 void PdbEngine::reloadModules()
 {
-    postCommand("qdebug('listmodules')", CB(handleListModules));
+    //postCommand("qdebug('listmodules')", CB(handleListModules));
 }
 
 void PdbEngine::handleListModules(const PdbResponse &response)
@@ -549,6 +562,7 @@ void PdbEngine::updateWatchData(const WatchData &data)
 
 void PdbEngine::handlePdbError(QProcess::ProcessError error)
 {
+    qDebug() << "HANDLE PDB ERROR";
     showMessage(_("HANDLE PDB ERROR"));
     switch (error) {
     case QProcess::Crashed:
@@ -595,6 +609,7 @@ QString PdbEngine::errorMessage(QProcess::ProcessError error) const
 
 void PdbEngine::handlePdbFinished(int code, QProcess::ExitStatus type)
 {
+    qDebug() << "PDB FINISHED";
     showMessage(_("PDB PROCESS FINISHED, status %1, code %2").arg(type).arg(code));
     notifyEngineSpontaneousShutdown();
 }
@@ -602,35 +617,57 @@ void PdbEngine::handlePdbFinished(int code, QProcess::ExitStatus type)
 void PdbEngine::readPdbStandardError()
 {
     QByteArray err = m_pdbProc.readAllStandardError();
-    qWarning() << "Unexpected pdb stderr:" << err;
-    showMessage(_("Unexpected pdb stderr: " + err));
+    qDebug() << "\nPDB STDERR" << err;
+    //qWarning() << "Unexpected pdb stderr:" << err;
+    //showMessage(_("Unexpected pdb stderr: " + err));
+    //handleOutput(err);
 }
 
 void PdbEngine::readPdbStandardOutput()
 {
-    m_inbuffer.append(m_pdbProc.readAllStandardOutput());
-    //qDebug() << "BUFFER FROM: '" << m_inbuffer << "'";
-    int pos = 1;
-    while ((pos = m_inbuffer.indexOf("(Pdb)")) != -1) {
-        PdbResponse response;
-        response.data = m_inbuffer.left(pos).trimmed();
-        showMessage(_(response.data));
+    QByteArray out = m_pdbProc.readAllStandardOutput();
+    qDebug() << "\nPDB STDOUT" << out;
+    handleOutput(out);
+}
+
+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);
-        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;
-        }
+        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;
     }
-    //qDebug() << "BUFFER LEFT: '" << m_inbuffer << "'";
 }
-
+/*
 void PdbEngine::handleResponse(const QByteArray &response0)
 {
     QByteArray response = response0;
@@ -649,7 +686,7 @@ void PdbEngine::handleResponse(const QByteArray &response0)
         if (pos1 != -1 && pos2 != -1) {
             int lineNumber = response.mid(pos1 + 1, pos2 - pos1 - 1).toInt();
             QByteArray fileName = response.mid(2, pos1 - 2);
-            qDebug() << " " << pos1 << pos2 << lineNumber << fileName 
+            qDebug() << " " << pos1 << pos2 << lineNumber << fileName
                 << response.mid(pos1 + 1, pos2 - pos1 - 1);
             StackFrame frame;
             frame.file = _(fileName);
@@ -663,6 +700,7 @@ void PdbEngine::handleResponse(const QByteArray &response0)
     }
     qDebug() << "COULD NOT PARSE RESPONSE: '" << response << "'";
 }
+*/
 
 void PdbEngine::handleFirstCommand(const PdbResponse &response)
 {
@@ -677,6 +715,12 @@ void PdbEngine::handleUpdateAll(const PdbResponse &response)
 }
 
 void PdbEngine::updateAll()
+{
+    postCommand("bt", CB(handleBacktrace));
+    //updateLocals();
+}
+
+void PdbEngine::updateLocals()
 {
     WatchHandler *handler = watchHandler();
 
@@ -706,7 +750,6 @@ void PdbEngine::updateAll()
         options += "defaults,";
     options.chop(1);
 
-    postCommand("bt", CB(handleBacktrace));
     postCommand("qdebug('" + options + "','"
         + handler->expansionRequests() + "','"
         + handler->typeFormatRequests() + "','"
@@ -741,7 +784,7 @@ void PdbEngine::handleBacktrace(const PdbResponse &response)
             if (pos1 != -1 && pos2 != -1) {
                 int lineNumber = line.mid(pos1 + 1, pos2 - pos1 - 1).toInt();
                 QByteArray fileName = line.mid(2, pos1 - 2);
-                //qDebug() << " " << pos1 << pos2 << lineNumber << fileName 
+                //qDebug() << " " << pos1 << pos2 << lineNumber << fileName
                 //    << line.mid(pos1 + 1, pos2 - pos1 - 1);
                 StackFrame frame;
                 frame.file = _(fileName);
@@ -758,8 +801,8 @@ void PdbEngine::handleBacktrace(const PdbResponse &response)
         }
     }
     const int frameCount = stackFrames.size();
-    for (int i = 0; i != frameCount; ++i) 
-        stackFrames[i].level = frameCount - stackFrames[i].level - 1; 
+    for (int i = 0; i != frameCount; ++i)
+        stackFrames[i].level = frameCount - stackFrames[i].level - 1;
     stackHandler()->setFrames(stackFrames);
 
     // Select current frame.
@@ -768,6 +811,8 @@ void PdbEngine::handleBacktrace(const PdbResponse &response)
         stackHandler()->setCurrentIndex(currentIndex);
         gotoLocation(stackFrames.at(currentIndex), true);
     }
+
+    updateLocals();
 }
 
 void PdbEngine::handleListLocals(const PdbResponse &response)
@@ -792,14 +837,6 @@ void PdbEngine::handleListLocals(const PdbResponse &response)
     handler->insertBulkData(list);
 }
 
-void PdbEngine::handleLoadDumper(const PdbResponse &response)
-{
-    Q_UNUSED(response);
-    //qDebug() << " DUMPERS LOADED '" << response.data << "'";
-    //continueInferior();
-    notifyInferiorSetupOk();
-}
-
 unsigned PdbEngine::debuggerCapabilities() const
 {
     return ReloadModuleCapability;
diff --git a/src/plugins/debugger/pdb/pdbengine.h b/src/plugins/debugger/pdb/pdbengine.h
index d6778b89dc1..e113afb4392 100644
--- a/src/plugins/debugger/pdb/pdbengine.h
+++ b/src/plugins/debugger/pdb/pdbengine.h
@@ -105,6 +105,9 @@ private:
     bool isSynchroneous() const { return true; }
     void updateWatchData(const WatchData &data);
 
+signals:
+    void outputReady(const QByteArray &data);
+
 private:
     QString errorMessage(QProcess::ProcessError error) const;
     unsigned debuggerCapabilities() const;
@@ -113,10 +116,14 @@ private:
     Q_SLOT void handlePdbError(QProcess::ProcessError error);
     Q_SLOT void readPdbStandardOutput();
     Q_SLOT void readPdbStandardError();
+    Q_SLOT void handleOutput2(const QByteArray &data);
     void handleResponse(const QByteArray &ba);
+    void handleOutput(const QByteArray &data);
     void updateAll();
+    void updateLocals();
     void handleUpdateAll(const PdbResponse &response);
     void handleFirstCommand(const PdbResponse &response);
+    void handleExecuteDebuggerCommand(const PdbResponse &response);
 
     typedef void (PdbEngine::*PdbCommandCallback)
         (const PdbResponse &response);
@@ -139,7 +146,6 @@ private:
     void handleListLocals(const PdbResponse &response);
     void handleListModules(const PdbResponse &response);
     void handleListSymbols(const PdbResponse &response);
-    void handleLoadDumper(const PdbResponse &response);
     void handleBreakInsert(const PdbResponse &response);
 
     void handleChildren(const WatchData &data0, const GdbMi &item,
@@ -149,6 +155,7 @@ private:
                      PdbCommandCallback callback = 0,
                      const char *callbackName = 0,
                      const QVariant &cookie = QVariant());
+    void postDirectCommand(const QByteArray &command);
 
     QQueue<PdbCommand> m_commands;
 
diff --git a/src/plugins/debugger/script/scriptengine.cpp b/src/plugins/debugger/script/scriptengine.cpp
index 54f30904646..6301a8302df 100644
--- a/src/plugins/debugger/script/scriptengine.cpp
+++ b/src/plugins/debugger/script/scriptengine.cpp
@@ -327,7 +327,8 @@ void ScriptEngine::importExtensions()
                      "Make sure that the bindings have been built, "
                      "and that this executable and the plugins are "
                      "using compatible Qt libraries.",
-                     qPrintable(failExtensions.join(QLatin1String(", "))), qPrintable(dir.absolutePath()));
+                     qPrintable(failExtensions.join(QLatin1String(", "))),
+                        qPrintable(dir.absolutePath()));
         }
     }
     return; // failExtensions.isEmpty();
@@ -336,12 +337,12 @@ void ScriptEngine::importExtensions()
 void ScriptEngine::runEngine()
 {
     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
-    SDEBUG("ScriptEngine::runEngine()");
     notifyEngineRunAndInferiorRunOk();
     showStatusMessage(tr("Running requested..."), 5000);
     showMessage(QLatin1String("Running: ") + m_scriptFileName, LogMisc);
     importExtensions();
-    const QScriptValue result = m_scriptEngine->evaluate(m_scriptContents, m_scriptFileName);
+    const QScriptValue result =
+        m_scriptEngine->evaluate(m_scriptContents, m_scriptFileName);
     QString msg;
     if (m_scriptEngine->hasUncaughtException()) {
         msg = _("An exception occurred during execution at line: %1\n%2\n")
diff --git a/tests/manual/gdbdebugger/python/math.py b/tests/manual/gdbdebugger/python/math.py
index 52f0cb58a7b..0bd111e386a 100644
--- a/tests/manual/gdbdebugger/python/math.py
+++ b/tests/manual/gdbdebugger/python/math.py
@@ -46,8 +46,8 @@ def testMath():
     print cube(5)
 
 def main():
-    #testMath()
-    testApp()
+    testMath()
+    #testApp()
     return 0
 
 if __name__ == '__main__':
-- 
GitLab