From 08deb39072e9d598d3b544054272ed39927d2520 Mon Sep 17 00:00:00 2001
From: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
Date: Fri, 18 Mar 2011 20:03:22 +0100
Subject: [PATCH] more exact qmake command line parsing

support -after and -config.
this also moves the actual parsing to ProFileOption, where it belongs.
---
 src/plugins/qt4projectmanager/qmakestep.cpp | 18 +----
 src/shared/proparser/profileevaluator.cpp   | 82 +++++++++++++--------
 src/shared/proparser/profileevaluator.h     |  8 +-
 tests/manual/proparser/main.cpp             |  4 +-
 4 files changed, 60 insertions(+), 52 deletions(-)

diff --git a/src/plugins/qt4projectmanager/qmakestep.cpp b/src/plugins/qt4projectmanager/qmakestep.cpp
index c89955e47d..fa46167afc 100644
--- a/src/plugins/qt4projectmanager/qmakestep.cpp
+++ b/src/plugins/qt4projectmanager/qmakestep.cpp
@@ -34,7 +34,6 @@
 #include "qmakestep.h"
 
 #include <projectexplorer/projectexplorerconstants.h>
-#include <proparser/profileevaluator.h>
 #include "qmakeparser.h"
 #include "qt4buildconfiguration.h"
 #include "qt4project.h"
@@ -370,20 +369,9 @@ void QMakeStep::setLinkQmlDebuggingLibrary(bool enable)
 QStringList QMakeStep::parserArguments()
 {
     QStringList result;
-    for (Utils::QtcProcess::ConstArgIterator ait(allArguments()); ait.next(); ) {
-        const QString &arg = ait.value();
-        if (arg.contains(QLatin1Char('='))) {
-            result << arg;
-        } else {
-            for (int i = 0; i < ProFileOption::modeMapSize; ++i) {
-                // Workaround: Apple GCC does not like ProFileOption::modeMap[i], because the array's bounds are not known
-                if (QLatin1String((&ProFileOption::modeMap[0] + i)->qmakeOption) == arg) {
-                    result << arg;
-                    break;
-                }
-            }
-        }
-    }
+    for (Utils::QtcProcess::ConstArgIterator ait(allArguments()); ait.next(); )
+        if (ait.isSimple())
+            result << ait.value();
     return result;
 }
 
diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp
index 8c5d8625c3..2c6c427f39 100644
--- a/src/shared/proparser/profileevaluator.cpp
+++ b/src/shared/proparser/profileevaluator.cpp
@@ -77,6 +77,8 @@ QT_BEGIN_NAMESPACE
 using namespace ProStringConstants;
 
 
+#define fL1S(s) QString::fromLatin1(s)
+
 ///////////////////////////////////////////////////////////////////////
 //
 // ProFileOption
@@ -106,20 +108,45 @@ ProFileOption::~ProFileOption()
 
 void ProFileOption::setCommandLineArguments(const QStringList &args)
 {
-    cmdargs = args;
+    QStringList _precmds, _preconfigs, _postcmds, _postconfigs;
+    bool after = false;
 
     setHostTargetMode();
-    bool targetModeSet = false;
-    for (int i = args.count() - 1; !targetModeSet && i >= 0; --i) {
-        for (int j = 0; j < modeMapSize; ++j) {
-            const TargetModeMapElement &mapElem = modeMap[j];
-            if (args.at(i) == QLatin1String(mapElem.qmakeOption)) {
-                target_mode = mapElem.targetMode;
-                targetModeSet = true;
-                break;
-            }
+
+    bool isConf = false;
+    foreach (const QString &arg, args) {
+        if (isConf) {
+            isConf = false;
+            if (after)
+                _postconfigs << arg;
+            else
+                _preconfigs << arg;
+        } else if (arg.startsWith(QLatin1Char('-'))) {
+            if (arg == QLatin1String("-after")) {
+                after = true;
+            } else if (arg == QLatin1String("-config")) {
+                isConf = true;
+            } else if (arg == QLatin1String("-win32")) {
+                target_mode = TARG_WIN_MODE;
+            } else if (arg == QLatin1String("-unix")) {
+                target_mode = TARG_UNIX_MODE;
+            } else if (arg == QLatin1String("-macx")) {
+                target_mode = TARG_MACX_MODE;
+            }
+        } else if (arg.contains(QLatin1Char('='))) {
+            if (after)
+                _postcmds << arg;
+            else
+                _precmds << arg;
         }
     }
+
+    if (!_preconfigs.isEmpty())
+        _precmds << (fL1S("CONFIG += ") + _preconfigs.join(fL1S(" ")));
+    precmds = _precmds.join(fL1S("\n"));
+    if (!_postconfigs.isEmpty())
+        _postcmds << (fL1S("CONFIG += ") + _postconfigs.join(fL1S(" ")));
+    postcmds = _postcmds.join(fL1S("\n"));
 }
 
 void ProFileOption::setHostTargetMode()
@@ -135,22 +162,12 @@ void ProFileOption::setHostTargetMode()
 #endif
 }
 
-const struct ProFileOption::TargetModeMapElement ProFileOption::modeMap[] = {
-    { "-unix", TARG_UNIX_MODE },
-    { "-macx", TARG_MACX_MODE },
-    { "-win32", TARG_WIN_MODE }
-};
-const int ProFileOption::modeMapSize
-    = sizeof ProFileOption::modeMap / sizeof ProFileOption::modeMap[0];
-
 ///////////////////////////////////////////////////////////////////////
 //
 // ProFileEvaluator::Private
 //
 ///////////////////////////////////////////////////////////////////////
 
-#define fL1S(s) QString::fromLatin1(s)
-
 class ProFileEvaluator::Private
 {
 public:
@@ -177,6 +194,7 @@ public:
     static ALWAYS_INLINE void skipHashStr(const ushort *&tokPtr);
     void skipExpression(const ushort *&tokPtr);
 
+    void visitCmdLine(const QString &cmds);
     VisitReturn visitProFile(ProFile *pro, ProFileEvaluatorHandler::EvalFileType type,
                              ProFileEvaluator::LoadFlags flags);
     VisitReturn visitProBlock(ProFile *pro, const ushort *tokPtr);
@@ -1149,6 +1167,18 @@ void ProFileEvaluator::Private::visitProVariable(
     }
 }
 
+void ProFileEvaluator::Private::visitCmdLine(const QString &cmds)
+{
+    if (!cmds.isEmpty()) {
+        if (ProFile *pro = m_parser->parsedProBlock(fL1S("(command line)"), cmds)) {
+            m_locationStack.push(m_current);
+            visitProBlock(pro, pro->tokPtr());
+            m_current = m_locationStack.pop();
+            pro->deref();
+        }
+    }
+}
+
 ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProFile(
         ProFile *pro, ProFileEvaluatorHandler::EvalFileType type,
         ProFileEvaluator::LoadFlags flags)
@@ -1310,20 +1340,14 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProFile(
             if (tgt.isEmpty())
                 tgt.append(ProString(QFileInfo(pro->fileName()).baseName(), NoHash));
 
-        if (!m_option->cmdargs.isEmpty()) {
-            if (ProFile *pro = m_parser->parsedProBlock(
-                    fL1S("(command line)"), m_option->cmdargs.join(fL1S("\n")))) {
-                m_locationStack.push(m_current);
-                visitProBlock(pro, pro->tokPtr());
-                m_current = m_locationStack.pop();
-                pro->deref();
-            }
-        }
+        visitCmdLine(m_option->precmds);
     }
 
     visitProBlock(pro, pro->tokPtr());
 
     if (flags & LoadPostFiles) {
+        visitCmdLine(m_option->postcmds);
+
             evaluateFeatureFile(QLatin1String("default_post.prf"));
 
             QSet<QString> processed;
diff --git a/src/shared/proparser/profileevaluator.h b/src/shared/proparser/profileevaluator.h
index 48de5752ea..6b56b043ed 100644
--- a/src/shared/proparser/profileevaluator.h
+++ b/src/shared/proparser/profileevaluator.h
@@ -176,12 +176,6 @@ struct ProFileOption
     //QString pro_ext;
     //QString res_ext;
 
-    static const struct TargetModeMapElement {
-        const char * const qmakeOption;
-        const TARG_MODE targetMode;
-    } modeMap[];
-    static const int modeMapSize;
-
     // -nocache, -cache, -spec, QMAKESPEC
     // -set persistent value
     void setCommandLineArguments(const QStringList &args);
@@ -195,7 +189,7 @@ struct ProFileOption
     ProFileEvaluator::FunctionDefs base_functions;
     QStringList feature_roots;
     QString qmakespec_name;
-    QStringList cmdargs;
+    QString precmds, postcmds;
 #ifdef PROEVALUATOR_THREAD_SAFE
     QMutex mutex;
     QWaitCondition cond;
diff --git a/tests/manual/proparser/main.cpp b/tests/manual/proparser/main.cpp
index 7b3210187d..9afe6f52a9 100644
--- a/tests/manual/proparser/main.cpp
+++ b/tests/manual/proparser/main.cpp
@@ -156,9 +156,11 @@ int main(int argc, char **argv)
     if (args.count() && args.first() == QLatin1String("-v"))
         level = 0, args.removeFirst();
     if (args.count() < 2)
-        qFatal("need at least two arguments: [-v] <cumulative?> <filenme> [<out_pwd>]");
+        qFatal("need at least two arguments: [-v] <cumulative?> <filenme> [<out_pwd> [<qmake options>]]");
 
     ProFileOption option;
+    if (args.count() >= 4)
+        option.setCommandLineArguments(args.mid(3));
     ProFileParser parser(0, &parseHandler);
 
     static const struct {
-- 
GitLab