From 5afeaa720dd193ea4f9f48fac11e9ae28393d372 Mon Sep 17 00:00:00 2001 From: hjk <qtc-committer@nokia.com> Date: Thu, 27 May 2010 15:41:52 +0200 Subject: [PATCH] debugger: more robust version string parsing Fix for QTCREATORBUG-1490 Reviewed-By: Friedemann Kleint --- src/plugins/debugger/gdb/gdbengine.cpp | 58 ++---------------- src/plugins/debugger/gdb/gdbmi.cpp | 46 +++++++++++++++ src/plugins/debugger/gdb/gdbmi.h | 3 + tests/auto/debugger/debugger.pro | 2 +- tests/auto/debugger/tst_version.cpp | 82 ++++++++++++++++++++++++++ tests/auto/debugger/version.pro | 15 +++++ 6 files changed, 152 insertions(+), 54 deletions(-) create mode 100644 tests/auto/debugger/tst_version.cpp create mode 100644 tests/auto/debugger/version.pro diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 166e5de6c7b..12f9d8cbdf5 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1470,70 +1470,22 @@ void GdbEngine::handleInfoProc(const GdbResponse &response) void GdbEngine::handleShowVersion(const GdbResponse &response) { - //qDebug () << "VERSION 2:" << response.data.findChild("consolestreamoutput").data(); - //qDebug () << "VERSION:" << response.toString(); - debugMessage(_("VERSION: " + response.toString())); + debugMessage(_("PARSING VERSION: " + response.toString())); if (response.resultClass == GdbResultDone) { m_gdbVersion = 100; m_gdbBuildVersion = -1; m_isMacGdb = false; GdbMi version = response.data.findChild("consolestreamoutput"); QString msg = QString::fromLocal8Bit(version.data()); - - bool foundIt = false; - - QRegExp supported(_("GNU gdb(.*) (\\d+)\\.(\\d+)(\\.(\\d+))?(-(\\d+))?")); - if (supported.indexIn(msg) >= 0) { + extractGdbVersion(msg, + &m_gdbVersion, &m_gdbBuildVersion, &m_isMacGdb); + if (m_gdbVersion > 60500 && m_gdbVersion < 200000) debugMessage(_("SUPPORTED GDB VERSION ") + msg); - m_gdbVersion = 10000 * supported.cap(2).toInt() - + 100 * supported.cap(3).toInt() - + 1 * supported.cap(5).toInt(); - m_gdbBuildVersion = supported.cap(7).toInt(); - m_isMacGdb = msg.contains(__("Apple version")); - foundIt = true; - } - - // OpenSUSE managed to ship "GNU gdb (GDB) SUSE (6.8.91.20090930-2.4). - if (!foundIt && msg.startsWith(_("GNU gdb (GDB) SUSE "))) { - supported.setPattern(_("[^\\d]*(\\d+).(\\d+).(\\d+).*")); - if (supported.indexIn(msg) >= 0) { - debugMessage(_("SUSE PATCHED GDB VERSION ") + msg); - m_gdbVersion = 10000 * supported.cap(1).toInt() - + 100 * supported.cap(2).toInt() - + 1 * supported.cap(3).toInt(); - m_gdbBuildVersion = -1; - m_isMacGdb = false; - foundIt = true; - } else { - debugMessage(_("UNPARSABLE SUSE PATCHED GDB VERSION ") + msg); - } - } - - if (!foundIt) { + else debugMessage(_("UNSUPPORTED GDB VERSION ") + msg); -#if 0 - QStringList list = msg.split(_c('\n')); - while (list.size() > 2) - list.removeLast(); - msg = tr("The debugger you are using identifies itself as:") - + _("<p><p>") + list.join(_("<br>")) + _("<p><p>") - + tr("This version is not officially supported by Qt Creator.\n" - "Debugging will most likely not work well.\n" - "Using gdb 7.1 or later is strongly recommended."); -#if 0 - // ugly, but 'Show again' check box... - static QErrorMessage *err = new QErrorMessage(mainWindow()); - err->setMinimumSize(400, 300); - err->showMessage(msg); -#else - //showMessageBox(QMessageBox::Information, tr("Warning"), msg); -#endif -#endif - } debugMessage(_("USING GDB VERSION: %1, BUILD: %2%3").arg(m_gdbVersion) .arg(m_gdbBuildVersion).arg(_(m_isMacGdb ? " (APPLE)" : ""))); - //qDebug () << "VERSION 3:" << m_gdbVersion << m_gdbBuildVersion; } } diff --git a/src/plugins/debugger/gdb/gdbmi.cpp b/src/plugins/debugger/gdb/gdbmi.cpp index c34d81124d2..158a1fc2b99 100644 --- a/src/plugins/debugger/gdb/gdbmi.cpp +++ b/src/plugins/debugger/gdb/gdbmi.cpp @@ -32,6 +32,7 @@ #include <utils/qtcassert.h> #include <QtCore/QByteArray> +#include <QtCore/QRegExp> #include <QtCore/QTextStream> #include <ctype.h> @@ -400,5 +401,50 @@ QByteArray GdbResponse::toString() const return result; } + +////////////////////////////////////////////////////////////////////////////////// +// +// GdbResponse +// +////////////////////////////////////////////////////////////////////////////////// + +void extractGdbVersion(const QString &msg, + int *gdbVersion, int *gdbBuildVersion, bool *isMacGdb) +{ + const QChar dot(QLatin1Char('.')); + + QString cleaned; + QString build; + bool inClean = true; + foreach (QChar c, msg) { + if (inClean && !cleaned.isEmpty() && c != dot && (c.isPunct() || c.isSpace())) + inClean = false; + if (inClean) { + if (c.isDigit()) + cleaned.append(c); + else if (!cleaned.isEmpty() && !cleaned.endsWith(dot)) + cleaned.append(dot); + } else { + if (c.isDigit()) + build.append(c); + else if (!build.isEmpty() && !build.endsWith(dot)) + build.append(dot); + } + } + + *isMacGdb = msg.contains(QLatin1String("Apple version")); + + *gdbVersion = 10000 * cleaned.section(dot, 0, 0).toInt() + + 100 * cleaned.section(dot, 1, 1).toInt() + + 1 * cleaned.section(dot, 2, 2).toInt(); + if (cleaned.count(dot) >= 3) + *gdbBuildVersion = cleaned.section(dot, 3, 3).toInt(); + else + *gdbBuildVersion = build.section(dot, 0, 0).toInt(); + + if (*isMacGdb) + *gdbBuildVersion = build.section(dot, 1, 1).toInt(); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/gdb/gdbmi.h b/src/plugins/debugger/gdb/gdbmi.h index ce484c8cd67..7803d71ce54 100644 --- a/src/plugins/debugger/gdb/gdbmi.h +++ b/src/plugins/debugger/gdb/gdbmi.h @@ -168,6 +168,9 @@ public: QVariant cookie; }; +void extractGdbVersion(const QString &msg, + int *gdbVersion, int *gdbBuildVersion, bool *isMacGdb); + } // namespace Internal } // namespace Debugger diff --git a/tests/auto/debugger/debugger.pro b/tests/auto/debugger/debugger.pro index ef1547f9ce6..84ad7990841 100644 --- a/tests/auto/debugger/debugger.pro +++ b/tests/auto/debugger/debugger.pro @@ -1,5 +1,5 @@ TEMPLATE = subdirs -SUBDIRS = dumpers.pro plugin.pro gdb.pro +SUBDIRS = dumpers.pro plugin.pro gdb.pro version.pro diff --git a/tests/auto/debugger/tst_version.cpp b/tests/auto/debugger/tst_version.cpp new file mode 100644 index 00000000000..cfac4f14de3 --- /dev/null +++ b/tests/auto/debugger/tst_version.cpp @@ -0,0 +1,82 @@ + +#include "gdb/gdbmi.h" + +#include <QtTest> + + +class tst_Version : public QObject +{ + Q_OBJECT + +public: + tst_Version() {} + +private slots: + void version(); + void version_data(); +}; + +void tst_Version::version() +{ + QFETCH(QString, msg); + QFETCH(int, gdbVersion); + QFETCH(int, gdbBuildVersion); + QFETCH(bool, isMacGdb); + int v = 0, bv = 0; + bool mac = true; + Debugger::Internal::extractGdbVersion(msg, &v, &bv, &mac); + qDebug() << msg << " -> " << v << bv << mac; + QCOMPARE(v, gdbVersion); + QCOMPARE(bv, gdbBuildVersion); + QCOMPARE(mac, isMacGdb); +} + +void tst_Version::version_data() +{ + QTest::addColumn<QString>("msg"); + QTest::addColumn<int>("gdbVersion"); + QTest::addColumn<int>("gdbBuildVersion"); + QTest::addColumn<bool>("isMacGdb"); + + QTest::newRow("Debian") + << "GNU gdb (GDB) 7.0.1-debian" + << 70001 << 0 << false; + + QTest::newRow("CVS 7.0.90") + << "GNU gdb (GDB) 7.0.90.20100226-cvs" + << 70090 << 20100226 << false; + + QTest::newRow("Ubuntu Lucid") + << "GNU gdb (GDB) 7.1-ubuntu" + << 70100 << 0 << false; + + QTest::newRow("Fedora 13") + << "GNU gdb (GDB) Fedora (7.1-22.fc13)" + << 70100 << 22 << false; + + QTest::newRow("Gentoo") + << "GNU gdb (Gentoo 7.1 p1) 7.1" + << 70100 << 1 << false; + + QTest::newRow("Fedora EL5") + << "GNU gdb Fedora (6.8-37.el5)" + << 60800 << 37 << false; + + QTest::newRow("SUSE") + << "GNU gdb (GDB) SUSE (6.8.91.20090930-2.4)" + << 60891 << 20090930 << false; + + QTest::newRow("Apple") + << "GNU gdb 6.3.50-20050815 (Apple version gdb-1461.2)" + << 60350 << 1461 << true; +} + + +int main(int argc, char *argv[]) +{ + tst_Version test; + return QTest::qExec(&test, argc, argv); +} + +#include "tst_version.moc" + diff --git a/tests/auto/debugger/version.pro b/tests/auto/debugger/version.pro new file mode 100644 index 00000000000..78d3f0f77c5 --- /dev/null +++ b/tests/auto/debugger/version.pro @@ -0,0 +1,15 @@ +QT += testlib +QT -= gui + +UTILSDIR = ../../../src/libs + +DEBUGGERDIR = ../../../src/plugins/debugger + +INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR + +SOURCES += \ + tst_version.cpp \ + $$DEBUGGERDIR/gdb/gdbmi.cpp \ + +TARGET = tst_$$TARGET + -- GitLab