From e77c2f5a8b843f9f87d0466f619ba204ce4745c5 Mon Sep 17 00:00:00 2001
From: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
Date: Wed, 9 Feb 2011 20:00:44 +0100
Subject: [PATCH] don't give up on parsing errors

instead of erroring out the parse, only error out the evaluation in
exact mode. that way we can do cumulative evaluation even on broken
files.

Task-number: QTCREATORBUG-3093
---
 src/shared/proparser/profileevaluator.cpp |  3 ++
 src/shared/proparser/profileparser.cpp    | 64 ++++++++++++++---------
 src/shared/proparser/proitems.cpp         |  3 +-
 src/shared/proparser/proitems.h           |  4 ++
 4 files changed, 47 insertions(+), 27 deletions(-)

diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp
index e9eabc803cc..7a9c72b4c98 100644
--- a/src/shared/proparser/profileevaluator.cpp
+++ b/src/shared/proparser/profileevaluator.cpp
@@ -1137,6 +1137,9 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProFile(
         ProFile *pro, ProFileEvaluatorHandler::EvalFileType type,
         ProFileEvaluator::LoadFlags flags)
 {
+    if (!m_cumulative && !pro->isOk())
+        return ReturnFalse;
+
     m_handler->aboutToEval(currentProFile(), pro, type);
     m_profileStack.push(pro);
     if (flags & LoadPreFiles) {
diff --git a/src/shared/proparser/profileparser.cpp b/src/shared/proparser/profileparser.cpp
index 977fa1bad1f..eb131ffd456 100644
--- a/src/shared/proparser/profileparser.cpp
+++ b/src/shared/proparser/profileparser.cpp
@@ -310,6 +310,8 @@ bool ProFileParser::read(ProFile *pro, const QString &in)
     ptr += 4;
     ushort *xprPtr = ptr;
 
+    ushort *oldTokPtr = tokPtr;
+
 #define FLUSH_LHS_LITERAL(setSep) \
     do { \
         if ((tlen = ptr - xprPtr)) { \
@@ -356,9 +358,14 @@ bool ProFileParser::read(ProFile *pro, const QString &in)
             c = *cur;
             if (c == '\n') {
                 ++cur;
-                goto flushLine;
+                if (!inError)
+                    goto flushLine;
+                ++m_lineNo;
+                goto freshLine;
             } else if (!c) {
-                goto flushLine;
+                if (!inError)
+                    goto flushLine;
+                goto flushFile;
             } else if (c != ' ' && c != '\t' && c != '\r') {
                 break;
             }
@@ -430,8 +437,11 @@ bool ProFileParser::read(ProFile *pro, const QString &in)
                         }
                         tlen = ptr - xprPtr;
                         if (context == CtxTest) {
-                            if (needSep)
-                                goto extraChars;
+                            if (needSep) {
+                              extraChars:
+                                parseError(fL1S("Extra characters after test expression."));
+                                goto parseErr;
+                            }
                             if (tlen)
                                 finalizeHashStr(xprPtr, tlen);
                             else
@@ -533,7 +543,12 @@ bool ProFileParser::read(ProFile *pro, const QString &in)
                                 parseError(fL1S("Missing %1 terminator [found %2]")
                                     .arg(QChar(term))
                                     .arg(c ? QString(c) : QString::fromLatin1("end-of-line")));
-                                return false;
+                              parseErr:
+                                pro->setOk(false);
+                                xprStack.resize(0);
+                                tokPtr = oldTokPtr;
+                                inError = true;
+                                goto skip;
                             }
                         }
                       joinToken:
@@ -616,8 +631,7 @@ bool ProFileParser::read(ProFile *pro, const QString &in)
                         FLUSH_LHS_LITERAL(false);
                         if (ptr == buf) {
                             parseError(fL1S("Opening parenthesis without prior test name."));
-                            inError = true;
-                            goto skip;
+                            goto parseErr;
                         }
                         *ptr++ = TokTestCall;
                         term = ':';
@@ -690,8 +704,7 @@ bool ProFileParser::read(ProFile *pro, const QString &in)
                         putLineMarker(tokPtr);
                         if (!(tlen = ptr - buf)) {
                             parseError(fL1S("Assignment operator without prior variable name."));
-                            inError = true;
-                            goto skip;
+                            goto parseErr;
                         }
                         putBlock(tokPtr, buf, tlen);
                         putTok(tokPtr, tok);
@@ -743,11 +756,11 @@ bool ProFileParser::read(ProFile *pro, const QString &in)
                 FLUSH_LITERAL(false);
                 if (quote) {
                     parseError(fL1S("Missing closing %1 quote").arg(QChar(quote)));
-                    return false;
+                    goto parseErr;
                 }
                 if (!xprStack.isEmpty()) {
                     parseError(fL1S("Missing closing parenthesis in function call"));
-                    return false;
+                    goto parseErr;
                 }
                 if (context == CtxValue) {
                     tokPtr[-1] = litCount ? litCount + expCount : 0;
@@ -756,17 +769,8 @@ bool ProFileParser::read(ProFile *pro, const QString &in)
                 } else {
                     finalizeCond(tokPtr, buf, ptr);
                 }
-                if (!c) {
-                    flushScopes(tokPtr);
-                    if (m_blockstack.size() > 1)
-                        parseError(fL1S("Missing closing brace(s)."));
-                    while (m_blockstack.size())
-                        leaveScope(tokPtr);
-                    xprBuff.clear();
-                    *pro->itemsRef() =
-                            QString(tokBuff.constData(), tokPtr - (ushort *)tokBuff.constData());
-                    return true;
-                }
+                if (!c)
+                    break;
                 ++m_lineNo;
                 goto freshLine;
             }
@@ -783,13 +787,21 @@ bool ProFileParser::read(ProFile *pro, const QString &in)
         ++m_lineNo;
     }
 
+  flushFile:
+    flushScopes(tokPtr);
+    if (m_blockstack.size() > 1) {
+        parseError(fL1S("Missing closing brace(s)."));
+        pro->setOk(false);
+    }
+    while (m_blockstack.size())
+        leaveScope(tokPtr);
+    xprBuff.clear();
+    *pro->itemsRef() = QString(tokBuff.constData(), tokPtr - (ushort *)tokBuff.constData());
+    return true;
+
 #undef FLUSH_LITERAL
 #undef FLUSH_LHS_LITERAL
 #undef FLUSH_RHS_LITERAL
-
-  extraChars:
-    parseError(fL1S("Extra characters after test expression."));
-    return false;
 }
 
 void ProFileParser::putLineMarker(ushort *&tokPtr)
diff --git a/src/shared/proparser/proitems.cpp b/src/shared/proparser/proitems.cpp
index 3bb2773703a..9d1f8fa5c87 100644
--- a/src/shared/proparser/proitems.cpp
+++ b/src/shared/proparser/proitems.cpp
@@ -336,7 +336,8 @@ void ProStringList::removeDuplicates()
 
 ProFile::ProFile(const QString &fileName)
     : m_refCount(1),
-      m_fileName(fileName)
+      m_fileName(fileName),
+      m_ok(true)
 {
     if (!fileName.startsWith(QLatin1Char('(')))
         m_directoryName = fileName.left(fileName.lastIndexOf(QLatin1Char('/')));
diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h
index 8d7337b695d..02c29a20953 100644
--- a/src/shared/proparser/proitems.h
+++ b/src/shared/proparser/proitems.h
@@ -199,11 +199,15 @@ public:
     void ref() { m_refCount.ref(); }
     void deref() { if (!m_refCount.deref()) delete this; }
 
+    bool isOk() const { return m_ok; }
+    void setOk(bool ok) { m_ok = ok; }
+
 private:
     ProItemRefCount m_refCount;
     QString m_proitems;
     QString m_fileName;
     QString m_directoryName;
+    bool m_ok;
 };
 
 QT_END_NAMESPACE
-- 
GitLab