From 745ee20fcc903d40c831d1f3ad803f6e1ec829d7 Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Thu, 14 May 2009 10:10:38 +0200
Subject: [PATCH] debugger: work on tcf response parsing

---
 src/plugins/debugger/tcfengine.cpp | 115 +++++++++++++++++++++--------
 src/plugins/debugger/tcfengine.h   |  31 +++-----
 2 files changed, 93 insertions(+), 53 deletions(-)

diff --git a/src/plugins/debugger/tcfengine.cpp b/src/plugins/debugger/tcfengine.cpp
index 20d2e98b097..32f2d96bb0f 100644
--- a/src/plugins/debugger/tcfengine.cpp
+++ b/src/plugins/debugger/tcfengine.cpp
@@ -40,6 +40,7 @@
 #include "watchhandler.h"
 #include "watchutils.h"
 #include "moduleshandler.h"
+#include "gdbmi.h"
 
 #include <utils/qtcassert.h>
 
@@ -74,6 +75,21 @@ using namespace Debugger::Constants;
 #define STRINGIFY(x) STRINGIFY_INTERNAL(x)
 #define CB(callback) &TcfEngine::callback, STRINGIFY(callback)
 
+
+///////////////////////////////////////////////////////////////////////
+//
+// TcfData
+//
+///////////////////////////////////////////////////////////////////////
+
+
+TcfData::TcfData(const QByteArray &data)
+{
+    fromString(data);
+    qDebug() << "TCF RESPONSE: " << data << " -> " << toString();
+}
+
+
 ///////////////////////////////////////////////////////////////////////
 //
 // TcfEngine
@@ -119,8 +135,15 @@ void TcfEngine::socketReadyRead()
 {
     //XSDEBUG("TcfEngine::socketReadyRead()");
     m_inbuffer.append(m_socket->readAll());
-    //handleResponse(QByteArray::fromRawData(m_inbuffer.constData() + start, end - start));
-    handleResponse(m_inbuffer);
+    int pos = 0;
+    while (1) {
+        int next = m_inbuffer.indexOf("\3\1", pos);
+        //qDebug() << "pos: " << pos << "next: " << next;
+        if (next == -1)
+            break;
+        handleResponse(m_inbuffer.mid(pos, next - pos));
+        pos = next + 2; 
+    }
     m_inbuffer.clear();
 }
 
@@ -268,28 +291,61 @@ QList<Symbol> TcfEngine::moduleSymbols(const QString & /*moduleName*/)
 }
 
 
-void TcfEngine::handleResponse(const QByteArray &buf)
+void TcfEngine::handleResponse(const QByteArray &response)
 {
     static QTime lastTime;
 
     //emit tcfOutputAvailable(_("            "), currentTime());
-    TcfResponse response;
-    QList<QByteArray> parts = buf.split('\0');
+    QList<QByteArray> parts = response.split('\0');
+    if (parts.size() < 2 || !parts.last().isEmpty()) {
+        qDebug() << "Wrong response packet layout"
+            << quoteUnprintableLatin1(response);
+        return;
+    }
+    parts.removeLast(); // always empty
+    QByteArray tag = parts.at(0);
     int n = parts.size();
-    if (n >= 1)
-        response.tag = parts.at(0);
-    if (n >= 2)
-        response.service = parts.at(1);
-    if (n >= 3)
-        response.cmd = parts.at(2);
-    if (n >= 4)
-        response.data = parts.at(3);
-    if (response.cmd != "peerHeartBeat")
-        emit tcfOutputAvailable(_("\ntcf:"), quoteUnprintableLatin1(buf));
-    //emit tcfOutputAvailable(_("\ntcf:"), response.toString());
-    qDebug() << response.toString();
-
-    if (response.service == "Locator" && response.cmd == "Hello") {
+    if (n == 1 && tag == "N") { // unidentified command
+        qDebug() << "Command not recognized.";
+    } else if (n == 2 && tag == "N") { // flow control
+        int congestion = parts.at(1).toInt();
+        qDebug() << "Congestion: " << congestion;
+    } else if (n == 4 && tag == "R") { // result data
+        int token = parts.at(1).toInt();
+        QByteArray message = parts.at(2);
+        TcfData data(parts.at(3));
+        emit tcfOutputAvailable(_("\ntcf R:"), quoteUnprintableLatin1(response));
+        TcfCommand tcf = m_cookieForToken[token];
+        TcfData result(data);
+        //qDebug() << "Good response: " << quoteUnprintableLatin1(response);
+        if (tcf.callback)
+            (this->*(tcf.callback))(result, tcf.cookie);
+    } else if (n == 3 && tag == "P") { // progress data (partial result)
+        //int token = parts.at(1).toInt();
+        QByteArray data = parts.at(2);
+        emit tcfOutputAvailable(_("\ntcf P:"), quoteUnprintableLatin1(response));
+    } else if (n == 4 && tag == "E") { // an event
+        QByteArray service = parts.at(1);
+        QByteArray eventName = parts.at(2);
+        TcfData data(parts.at(3));
+        if (eventName != "peerHeartBeat")
+            emit tcfOutputAvailable(_("\ntcf E:"), quoteUnprintableLatin1(response));
+        if (service == "Locator" && eventName == "Hello") {
+            m_services.clear();
+            foreach (const GdbMi &service, data.children()) {
+                qDebug() << "Found service: " << service.data();
+                m_services.append(service.data());
+            }
+            QTimer::singleShot(0, this, SLOT(startDebugging()));
+        }
+    } else {
+        qDebug() << "Unknown response packet"
+            << quoteUnprintableLatin1(response) << parts;
+    }
+}
+
+void TcfEngine::startDebugging()
+{
         //postCommand('C', CB(handleRunControlSuspend),
         //    "RunControl", "suspend", "\"Thread1\"");
         //postCommand('C', CB(handleRunControlSuspend),
@@ -304,12 +360,6 @@ void TcfEngine::handleResponse(const QByteArray &buf)
         //postCommand('E', "Locator", "Hello", "");
         //postCommand('C', "Locator", "sync", "");
         //postCommand("Locator", "redirect", "ID");
-        return;
-    }
-
-    TcfCommand tcf = m_cookieForToken[1];
-    if (tcf.callback)
-        (this->*(tcf.callback))(response, tcf.cookie);
 }
 
 void TcfEngine::postCommand(char tag,
@@ -319,7 +369,7 @@ void TcfEngine::postCommand(char tag,
     const QByteArray &cmd,
     const QByteArray &args)
 {
-    static int token;
+    static int token = 50;
     ++token;
     
     const char delim = 0;
@@ -330,7 +380,7 @@ void TcfEngine::postCommand(char tag,
     QByteArray ba;
     ba.append(tag);
     ba.append(delim);
-    ba.append(QString::number(token).toLatin1());
+    ba.append(QByteArray::number(token));
     ba.append(delim);
     ba.append(service);
     ba.append(delim);
@@ -353,21 +403,22 @@ void TcfEngine::postCommand(char tag,
     emit tcfInputAvailable("send", QString::number(result));
 }
 
-void TcfEngine::handleRunControlSuspend(const TcfResponse &response, const QVariant &)
+void TcfEngine::handleRunControlSuspend(const TcfData &data, const QVariant &)
 {
     qDebug() << "HANDLE RESULT";
 }
 
-void TcfEngine::handleRunControlGetChildren(const TcfResponse &response, const QVariant &)
+void TcfEngine::handleRunControlGetChildren(const TcfData &data, const QVariant &)
 {
-    qDebug() << "HANDLE RESULT" << response.toString();
+    qDebug() << "HANDLE RUN CONTROL GET CHILDREN" << data.toString();
 }
 
-void TcfEngine::handleSysMonitorGetChildren(const TcfResponse &response, const QVariant &)
+void TcfEngine::handleSysMonitorGetChildren(const TcfData &data, const QVariant &)
 {
-    qDebug() << "HANDLE RESULT" << response.toString();
+    qDebug() << "HANDLE RUN CONTROL GET CHILDREN" << data.toString();
 }
 
+
 //////////////////////////////////////////////////////////////////////
 //
 // Tooltip specific stuff
diff --git a/src/plugins/debugger/tcfengine.h b/src/plugins/debugger/tcfengine.h
index c80411f1435..eb965d1bc70 100644
--- a/src/plugins/debugger/tcfengine.h
+++ b/src/plugins/debugger/tcfengine.h
@@ -47,6 +47,7 @@ QT_END_NAMESPACE
 
 #include "idebuggerengine.h"
 #include "debuggermanager.h"
+#include "gdbmi.h"
 
 namespace Debugger {
 namespace Internal {
@@ -56,25 +57,10 @@ class IDebuggerManagerAccessForEngines;
 class ScriptAgent;
 class WatchData;
 
-class TcfResponse
+class TcfData : public GdbMi
 {
 public:
-    enum ResponseType
-    {
-        HelloResponse,
-        HeartBeatResponse
-    };
-
-    QString toString() const
-    {
-        return _("TAG: " + tag + "  SERVICE: " + service
-            + "  CMD: " + cmd + "  DATA: " + data);
-    }
-
-    QByteArray tag;
-    QByteArray service;
-    QByteArray cmd;
-    QByteArray data;
+    TcfData(const QByteArray &data);
 };
 
 class TcfEngine : public IDebuggerEngine
@@ -140,13 +126,15 @@ private:
     Q_SLOT void socketReadyRead();
 
     void handleResponse(const QByteArray &ba);
-    void handleRunControlSuspend(const TcfResponse &response, const QVariant &);
-    void handleRunControlGetChildren(const TcfResponse &response, const QVariant &);
-    void handleSysMonitorGetChildren(const TcfResponse &response, const QVariant &);
+    void handleRunControlSuspend(const TcfData &response, const QVariant &);
+    void handleRunControlGetChildren(const TcfData &response, const QVariant &);
+    void handleSysMonitorGetChildren(const TcfData &response, const QVariant &);
 
 private:
+    Q_SLOT void startDebugging();
+
     typedef void (TcfEngine::*TcfCommandCallback)
-        (const TcfResponse &record, const QVariant &cookie);
+        (const TcfData &record, const QVariant &cookie);
 
     struct TcfCommand
     {
@@ -171,6 +159,7 @@ private:
     IDebuggerManagerAccessForEngines *qq;
     QTcpSocket *m_socket;
     QByteArray m_inbuffer;
+    QStringList m_services;
 };
 
 } // namespace Internal
-- 
GitLab