summaryrefslogtreecommitdiffstats
path: root/qmake/library/qmakeparser.cpp
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@nokia.com>2012-09-11 19:30:29 +0200
committerQt by Nokia <qt-info@nokia.com>2012-09-13 03:42:44 +0200
commit8400896cfe3fbef7666329a2920bd0dbdd5890af (patch)
tree4aeef74d80fcf6d7443c3790dcacf43a016c00e9 /qmake/library/qmakeparser.cpp
parentae3f95a951334dee001e37c305e4d7bf91c0d1b3 (diff)
don't pretend that break()/next()/return() are functions
it's a pretty braindead thing to implement control flow statements as (built-in) functions. as a "side effect", this fixes return() value handling for lists. (cherry picked from qtcreator/f53ed6c4b3feca59a94d4f0de8b1a7411122e30e) (cherry picked from qtcreator/f529e22ec38fb9a656d74394e484d2453cf42c69) Change-Id: I59c8efa0e4d65329327115f7f8ed20719e7f7546 Reviewed-by: Qt Doc Bot <qt_docbot@qt-project.org> Reviewed-by: Joerg Bornemann <joerg.bornemann@nokia.com> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
Diffstat (limited to 'qmake/library/qmakeparser.cpp')
-rw-r--r--qmake/library/qmakeparser.cpp47
1 files changed, 47 insertions, 0 deletions
diff --git a/qmake/library/qmakeparser.cpp b/qmake/library/qmakeparser.cpp
index 660f93517d..04558b8e9b 100644
--- a/qmake/library/qmakeparser.cpp
+++ b/qmake/library/qmakeparser.cpp
@@ -108,6 +108,9 @@ static struct {
QString strdefineTest;
QString strdefineReplace;
QString stroption;
+ QString strreturn;
+ QString strnext;
+ QString strbreak;
QString strhost_build;
QString strLINE;
QString strFILE;
@@ -128,6 +131,9 @@ void QMakeParser::initialize()
statics.strdefineTest = QLatin1String("defineTest");
statics.strdefineReplace = QLatin1String("defineReplace");
statics.stroption = QLatin1String("option");
+ statics.strreturn = QLatin1String("return");
+ statics.strnext = QLatin1String("next");
+ statics.strbreak = QLatin1String("break");
statics.strhost_build = QLatin1String("host_build");
statics.strLINE = QLatin1String("_LINE_");
statics.strFILE = QLatin1String("_FILE_");
@@ -884,9 +890,11 @@ void QMakeParser::putLineMarker(ushort *&tokPtr)
void QMakeParser::enterScope(ushort *&tokPtr, bool special, ScopeState state)
{
+ uchar nest = m_blockstack.top().nest;
m_blockstack.resize(m_blockstack.size() + 1);
m_blockstack.top().special = special;
m_blockstack.top().start = tokPtr;
+ m_blockstack.top().nest = nest;
tokPtr += 2;
m_state = state;
m_canElse = false;
@@ -1026,6 +1034,7 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg
m_tmp.setRawData((QChar *)uc + 4, nlen);
const QString *defName;
ushort defType;
+ uchar nest;
if (m_tmp == statics.strfor) {
if (m_invert || m_operator == OrOperator) {
// '|' could actually work reasonably, but qmake does nonsense here.
@@ -1048,6 +1057,7 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg
didFor:
putTok(tokPtr, TokValueTerminator);
enterScope(tokPtr, true, StCtrl);
+ m_blockstack.top().nest |= NestLoop;
return;
} else if (*uc == TokArgSeparator && argc == 2) {
// for(var, something)
@@ -1094,11 +1104,48 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg
putTok(tokPtr, defType);
putHashStr(tokPtr, uce + 2, nlen);
enterScope(tokPtr, true, StCtrl);
+ m_blockstack.top().nest = NestFunction;
return;
}
}
parseError(fL1S("%1(function) requires one literal argument.").arg(*defName));
return;
+ } else if (m_tmp == statics.strreturn) {
+ if (argc > 1) {
+ parseError(fL1S("return() requires zero or one argument."));
+ bogusTest(tokPtr);
+ return;
+ }
+ defType = TokReturn;
+ nest = NestFunction;
+ goto ctrlstm2;
+ } else if (m_tmp == statics.strnext) {
+ defType = TokNext;
+ goto ctrlstm;
+ } else if (m_tmp == statics.strbreak) {
+ defType = TokBreak;
+ ctrlstm:
+ if (*uce != TokFuncTerminator) {
+ parseError(fL1S("%1() requires zero arguments.").arg(m_tmp));
+ bogusTest(tokPtr);
+ return;
+ }
+ nest = NestLoop;
+ ctrlstm2:
+ if (m_invert) {
+ parseError(fL1S("Unexpected NOT operator in front of %1().").arg(m_tmp));
+ bogusTest(tokPtr);
+ return;
+ }
+ if (!(m_blockstack.top().nest & nest)) {
+ parseError(fL1S("Unexpected %1().").arg(m_tmp));
+ bogusTest(tokPtr);
+ return;
+ }
+ finalizeTest(tokPtr);
+ putBlock(tokPtr, uce, ptr - uce - 1); // Only for TokReturn
+ putTok(tokPtr, defType);
+ return;
} else if (m_tmp == statics.stroption) {
if (m_state != StNew || m_blockstack.top().braceLevel || m_blockstack.size() > 1
|| m_invert || m_operator != NoOperator) {