From 7938f9def974898bb8d05e98c4b59d983a887d79 Mon Sep 17 00:00:00 2001
From: Tobias Hunger <qt-info@nokia.com>
Date: Tue, 10 Nov 2009 17:29:41 +0100
Subject: [PATCH] Improve ABLD build parser for S60.

 * Handle Warnings by the perl build scripts run by ABLD.
 * Handle critical failures in CPP on windows.

Reviewed-By: con
---
 src/plugins/projectexplorer/gccparser.cpp     |  40 +++----
 .../projectexplorerconstants.h                |   1 +
 .../qt4projectmanager/qt-s60/abldparser.cpp   | 102 ++++++++++++++++--
 .../qt4projectmanager/qt-s60/abldparser.h     |   8 ++
 .../qt4projectmanager/qt-s60/qt-s60.pri       |   6 +-
 .../qt-s60/s60buildparserfactory.cpp          |  10 +-
 .../qt4projectmanager/qt-s60/winscwparser.cpp |  99 +++++++++++++++++
 .../qt4projectmanager/qt-s60/winscwparser.h   |  56 ++++++++++
 8 files changed, 287 insertions(+), 35 deletions(-)
 create mode 100644 src/plugins/qt4projectmanager/qt-s60/winscwparser.cpp
 create mode 100644 src/plugins/qt4projectmanager/qt-s60/winscwparser.h

diff --git a/src/plugins/projectexplorer/gccparser.cpp b/src/plugins/projectexplorer/gccparser.cpp
index 378b6b15f22..a3e0e93a16c 100644
--- a/src/plugins/projectexplorer/gccparser.cpp
+++ b/src/plugins/projectexplorer/gccparser.cpp
@@ -30,8 +30,6 @@
 #include "gccparser.h"
 #include "projectexplorerconstants.h"
 
-#include <QDebug>
-
 using namespace ProjectExplorer;
 
 GccParser::GccParser()
@@ -70,14 +68,13 @@ void GccParser::stdOutput(const QString & line)
 void GccParser::stdError(const QString & line)
 {
     QString lne = line.trimmed();
-     if (m_regExpLinker.indexIn(lne) > -1) {
+    if (m_regExpLinker.indexIn(lne) > -1) {
         QString description = m_regExpLinker.cap(2);
         emit addToTaskWindow(
-            m_regExpLinker.cap(1), //filename
-            ProjectExplorer::BuildParserInterface::Error,
-            -1, //linenumber
-            description);
-        //qDebug()<<"m_regExpLinker"<<m_regExpLinker.cap(2);
+                m_regExpLinker.cap(1), //filename
+                ProjectExplorer::BuildParserInterface::Error,
+                -1, //linenumber
+                description);
     } else if (m_regExp.indexIn(lne) > -1) {
         ProjectExplorer::BuildParserInterface::PatternType type;
         if (m_regExp.cap(5) == "warning")
@@ -89,22 +86,25 @@ void GccParser::stdError(const QString & line)
 
         QString description =  m_regExp.cap(6);
 
-        //qDebug()<<"m_regExp"<<m_regExp.cap(1)<<m_regExp.cap(2)<<m_regExp.cap(5);
-
         emit addToTaskWindow(
-            m_regExp.cap(1), //filename
-            type,
-            m_regExp.cap(2).toInt(), //line number
-            description);
+                m_regExp.cap(1), //filename
+                type,
+                m_regExp.cap(2).toInt(), //line number
+                description);
     } else if (m_regExpIncluded.indexIn(lne) > -1) {
         emit addToTaskWindow(
-            m_regExpIncluded.cap(1), //filename
-            ProjectExplorer::BuildParserInterface::Unknown,
-            m_regExpIncluded.cap(2).toInt(), //linenumber
-            lne //description
-            );
-        //qDebug()<<"m_regExpInclude"<<m_regExpIncluded.cap(1)<<m_regExpIncluded.cap(2);
+                m_regExpIncluded.cap(1), //filename
+                ProjectExplorer::BuildParserInterface::Unknown,
+                m_regExpIncluded.cap(2).toInt(), //linenumber
+                lne //description
+                );
     } else if (lne.startsWith(QLatin1String("collect2:"))) {
         emit addToTaskWindow("", ProjectExplorer::BuildParserInterface::Error, -1, lne);
+    } else if (lne.startsWith(QLatin1String("ERROR:"))) {
+        // Triggered by cpp on windows.
+        emit addToTaskWindow(QString(), ProjectExplorer::BuildParserInterface::Error, -1, lne);
+    } else if (lne == QLatin1String("* cpp failed")) {
+        // Triggered by cpp/make on windows.
+        emit addToTaskWindow(QString(), ProjectExplorer::BuildParserInterface::Error, -1, lne);
     }
 }
diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h
index 84d9c32e14a..382004456f2 100644
--- a/src/plugins/projectexplorer/projectexplorerconstants.h
+++ b/src/plugins/projectexplorer/projectexplorerconstants.h
@@ -180,6 +180,7 @@ const char * const RESOURCE_MIMETYPE = "application/vnd.nokia.xml.qt.resource";
 const char * const BUILD_PARSER_MSVC        = "BuildParser.MSVC";
 const char * const BUILD_PARSER_GCC         = "BuildParser.Gcc";
 const char * const BUILD_PARSER_RVCT        = "BuildParser.Rvct";
+const char * const BUILD_PARSER_WINSCW      = "BuildParser.Winscw";
 const char * const BUILD_PARSER_ABLD_GCCE   = "BuildParser.ABLD.Gcce";
 const char * const BUILD_PARSER_ABLD_WINSCW = "BuildParser.ABLD.Winscw";
 const char * const BUILD_PARSER_ABLD_RVCT   = "BuildParser.ABLD.Rvct";
diff --git a/src/plugins/qt4projectmanager/qt-s60/abldparser.cpp b/src/plugins/qt4projectmanager/qt-s60/abldparser.cpp
index 4e1d96b2b2a..9049241403a 100644
--- a/src/plugins/qt4projectmanager/qt-s60/abldparser.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/abldparser.cpp
@@ -35,29 +35,30 @@
 
 #include <extensionsystem/pluginmanager.h>
 
-#include <QDebug>
-
 using namespace Qt4ProjectManager;
 using namespace ProjectExplorer;
 
 AbldParser::AbldParser(const QString &name) :
-    m_name(name)
+    m_name(name),
+    m_currentLine(-1),
+    m_waitingForStdErrContinuation(false),
+    m_waitingForStdOutContinuation(false)
 {
+    m_perlIssue.setPattern("^(WARNING|ERROR):\\s([^\\(\\)]+[^\\d])\\((\\d+)\\) : (.+)$");
+    m_perlIssue.setMinimal(true);
+
     // Now look for new parser
     QList<IBuildParserFactory *> buildParserFactories =
             ExtensionSystem::PluginManager::instance()->getObjects<ProjectExplorer::IBuildParserFactory>();
 
     QString subparser_name;
 
-    if ((m_name == QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_ABLD_GCCE)) ||
-        (m_name == QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_ABLD_WINSCW)))
-    {
+    if ((m_name == QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_ABLD_GCCE)))
         subparser_name = QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_GCC);
-    }
+    else if ((m_name == QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_ABLD_WINSCW)))
+        subparser_name = QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_WINSCW);
     else if (m_name == QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_ABLD_RVCT))
-    {
         subparser_name = QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_RVCT);
-    }
 
     QTC_ASSERT(!subparser_name.isNull(), return);
 
@@ -91,6 +92,8 @@ QString AbldParser::name() const
 
 void AbldParser::stdOutput(const QString &line)
 {
+    m_waitingForStdErrContinuation = false;
+
     QString lne = line.trimmed();
     // possible ABLD.bat errors:
     if (lne.startsWith("Is Perl, version ")) {
@@ -101,6 +104,43 @@ void AbldParser::stdOutput(const QString &line)
                 lne);
         return;
     }
+    if (lne.startsWith("FATAL ERROR:")) {
+        emit addToTaskWindow(QString(), ProjectExplorer::BuildParserInterface::Error,
+                             -1, lne.mid(12));
+        m_waitingForStdOutContinuation = false;
+        return;
+    }
+
+    if (m_perlIssue.indexIn(lne) > -1) {
+        m_waitingForStdOutContinuation = true;
+        ProjectExplorer::BuildParserInterface::PatternType type;
+        if (m_perlIssue.cap(1) == QLatin1String("WARNING"))
+            type = ProjectExplorer::BuildParserInterface::Warning;
+        else if (m_perlIssue.cap(1) == QLatin1String("ERROR"))
+            type = ProjectExplorer::BuildParserInterface::Error;
+        else
+            type = ProjectExplorer::BuildParserInterface::Unknown;
+
+        m_currentFile = m_perlIssue.cap(2);
+        m_currentLine = m_perlIssue.cap(3).toInt();
+
+        emit addToTaskWindow(m_currentFile, type,
+                             m_currentLine, m_perlIssue.cap(4));
+        return;
+    }
+
+    if (lne.isEmpty()) {
+        m_waitingForStdOutContinuation = false;
+        return;
+    }
+
+    if (m_waitingForStdOutContinuation) {
+        emit addToTaskWindow(m_currentFile,
+                             ProjectExplorer::BuildParserInterface::Unknown,
+                             m_currentLine, lne);
+        m_waitingForStdOutContinuation = true;
+        return;
+    }
 
     QTC_ASSERT(0 != m_subparser, return);
     // pass on to compiler output parser:
@@ -109,6 +149,8 @@ void AbldParser::stdOutput(const QString &line)
 
 void AbldParser::stdError(const QString &line)
 {
+    m_waitingForStdOutContinuation = false;
+
     QString lne = line.trimmed();
 
     // possible abld.pl errors:
@@ -123,6 +165,48 @@ void AbldParser::stdError(const QString &line)
         return;
     }
 
+    if (lne.startsWith("Died at ")) {
+        emit addToTaskWindow(QString(),
+                             ProjectExplorer::BuildParserInterface::Error,
+                             -1, lne);
+        m_waitingForStdErrContinuation = false;
+        return;
+    }
+
+    if (lne.startsWith("MMPFILE \"")) {
+        m_currentFile = lne.mid(9, lne.size() - 10);
+        m_waitingForStdErrContinuation = false;
+        return;
+    }
+    if (lne.isEmpty()) {
+        m_waitingForStdErrContinuation = false;
+        return;
+    }
+    if (lne.startsWith("WARNING: ")) {
+        QString description = lne.mid(9);
+        emit addToTaskWindow(m_currentFile,
+                             ProjectExplorer::BuildParserInterface::Warning,
+                             -1, description);
+        m_waitingForStdErrContinuation = true;
+        return;
+    }
+    if (lne.startsWith("ERROR: ")) {
+        QString description = lne.mid(7);
+        emit addToTaskWindow(m_currentFile,
+                             ProjectExplorer::BuildParserInterface::Error,
+                             -1, description);
+        m_waitingForStdErrContinuation = true;
+        return;
+    }
+    if (m_waitingForStdErrContinuation)
+    {
+        emit addToTaskWindow(m_currentFile,
+                             ProjectExplorer::BuildParserInterface::Unknown,
+                             -1, lne);
+        m_waitingForStdErrContinuation = true;
+        return;
+    }
+
     QTC_ASSERT(0 != m_subparser, return);
     // pass on to compiler output parser:
     m_subparser->stdError(lne);
diff --git a/src/plugins/qt4projectmanager/qt-s60/abldparser.h b/src/plugins/qt4projectmanager/qt-s60/abldparser.h
index ff162305014..2a5f616ac17 100644
--- a/src/plugins/qt4projectmanager/qt-s60/abldparser.h
+++ b/src/plugins/qt4projectmanager/qt-s60/abldparser.h
@@ -50,6 +50,14 @@ public:
 private:
     ProjectExplorer::BuildParserInterface * m_subparser;
     const QString m_name;
+
+    QRegExp m_perlIssue;
+
+    QString m_currentFile;
+    int m_currentLine;
+
+    bool m_waitingForStdErrContinuation;
+    bool m_waitingForStdOutContinuation;
 };
 
 } // namespace Qt4ProjectExplorer
diff --git a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri
index 4c72bf4aead..c0fd1d72f86 100644
--- a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri
+++ b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri
@@ -14,7 +14,8 @@
         $$PWD/s60runconfigbluetoothstarter.cpp \
         $$PWD/s60buildparserfactory.cpp \
         $$PWD/abldparser.cpp \
-        $$PWD/rvctparser.cpp
+        $$PWD/rvctparser.cpp \
+        $$PWD/winscwparser.cpp
     HEADERS += $$PWD/s60devices.h \
         $$PWD/s60devicespreferencepane.h \
         $$PWD/s60manager.h \
@@ -28,7 +29,8 @@
         $$PWD/s60runconfigbluetoothstarter.h \
         $$PWD/s60buildparserfactory.h \
         $$PWD/abldparser.h \
-        $$PWD/rvctparser.h
+        $$PWD/rvctparser.h \
+        $$PWD/winscwparser.h
     FORMS += $$PWD/s60devicespreferencepane.ui
     OTHER_FILES += $$PWD/qt-s60-todo.txt
     include(../../../shared/trk/trk.pri)||error("could not include trk.pri")
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60buildparserfactory.cpp b/src/plugins/qt4projectmanager/qt-s60/s60buildparserfactory.cpp
index 86657a4a04a..06e650e3945 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60buildparserfactory.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60buildparserfactory.cpp
@@ -30,6 +30,7 @@
 #include "s60buildparserfactory.h"
 #include "abldparser.h"
 #include "rvctparser.h"
+#include "winscwparser.h"
 
 #include <projectexplorer/projectexplorerconstants.h>
 
@@ -43,16 +44,17 @@ bool S60ParserFactory::canCreate(const QString & name) const
 {
     return ((name == QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_ABLD_GCCE)) ||
             (name == QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_ABLD_WINSCW)) ||
-            (name == QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_ABLD_RVCT))  ||
-            (name == QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_RVCT)));
+            (name == QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_ABLD_RVCT)) ||
+            (name == QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_RVCT)) ||
+            (name == QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_WINSCW)));
 }
 
 ProjectExplorer::BuildParserInterface * S60ParserFactory::create(const QString & name) const
 {
     if (name ==  QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_RVCT))
-    {
         return new RvctParser();
-    }
+    if (name == QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_WINSCW))
+        return new WinscwParser();
 
     return new AbldParser(name);
 }
diff --git a/src/plugins/qt4projectmanager/qt-s60/winscwparser.cpp b/src/plugins/qt4projectmanager/qt-s60/winscwparser.cpp
new file mode 100644
index 00000000000..b68c9f54249
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/winscwparser.cpp
@@ -0,0 +1,99 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "winscwparser.h"
+#include <projectexplorer/projectexplorerconstants.h>
+
+using namespace Qt4ProjectManager;
+
+WinscwParser::WinscwParser()
+{
+    // linker problems:
+    m_linkerProblem.setPattern("^(\\S*)\\(\\S+\\):\\s(.+)$");
+    m_linkerProblem.setMinimal(true);
+
+    //make[4]: Entering directory `/home/kkoehne/dev/ide-explorer/src/plugins/qtscripteditor'
+    m_makeDir.setPattern("^make.*: (\\w+) directory .(.+).$");
+    m_makeDir.setMinimal(true);
+}
+
+QString WinscwParser::name() const
+{
+    return QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_RVCT);
+}
+
+void WinscwParser::stdOutput(const QString &line)
+{
+    QString lne = line.trimmed();
+
+    if (m_makeDir.indexIn(lne) > -1) {
+        if (m_makeDir.cap(1) == "Leaving")
+            emit leaveDirectory(m_makeDir.cap(2));
+        else
+            emit enterDirectory(m_makeDir.cap(2));
+    }
+
+    if (!m_fileName.isNull() &&
+        lne.startsWith(m_fileName))
+    {
+        int file_name_size(m_fileName.size());
+        int second_colon = lne.indexOf(':', file_name_size + 1);
+        if (second_colon < 0)
+        {
+            m_fileName = lne + ':';
+            return;
+        }
+
+        QString file_name(lne.left(file_name_size - 1));
+        QString line_info(lne.mid(file_name_size, second_colon - file_name_size));
+        QString description(lne.mid(second_colon + 1));
+
+        emit addToTaskWindow(
+                file_name,
+                ProjectExplorer::BuildParserInterface::Error,
+                line_info.toInt(),
+                description);
+        return;
+    }
+
+    m_fileName = lne + ':';
+}
+
+void WinscwParser::stdError(const QString &line)
+{
+    QString lne = line.trimmed();
+    if (m_linkerProblem.indexIn(lne) > -1) {
+       QString description = m_linkerProblem.cap(2);
+       emit addToTaskWindow(
+           m_linkerProblem.cap(1), //filename
+           ProjectExplorer::BuildParserInterface::Error,
+           -1, //linenumber
+           description);
+   }
+}
diff --git a/src/plugins/qt4projectmanager/qt-s60/winscwparser.h b/src/plugins/qt4projectmanager/qt-s60/winscwparser.h
new file mode 100644
index 00000000000..43369d4a50c
--- /dev/null
+++ b/src/plugins/qt4projectmanager/qt-s60/winscwparser.h
@@ -0,0 +1,56 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef WINSCWPARSER_H
+#define WINSCWPARSER_H
+
+#include <projectexplorer/buildparserinterface.h>
+
+#include <QtCore/QRegExp>
+
+namespace Qt4ProjectManager {
+
+class WinscwParser : public ProjectExplorer::BuildParserInterface
+{
+    Q_OBJECT
+
+public:
+    WinscwParser();
+    QString name() const;
+    virtual void stdOutput(const QString & line);
+    virtual void stdError(const QString & line);
+private:
+    QString m_fileName;
+    QRegExp m_linkerProblem;
+    QRegExp m_makeDir;
+};
+
+} // namespace Qt4ProjectManager
+
+#endif // WINSCWPARSER_H
-- 
GitLab