From c9a7a799705c87438dfdb6d075c49d1b6cc3231d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 11 Dec 2015 12:08:47 +0100 Subject: make write_file() capable of making files (not) executable Change-Id: I9ca96bc3408160261781697a3471c1f446c86c3a Reviewed-by: Joerg Bornemann (cherry picked from qtbase/57ca8d2698f1eaf30f1110ba47445c04d2bcd0f7) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 27 +++++++++++++++++++-------- src/shared/proparser/qmakeevaluator.h | 2 +- src/shared/proparser/qmakevfs.cpp | 18 +++++++++++++++--- src/shared/proparser/qmakevfs.h | 2 +- 4 files changed, 36 insertions(+), 13 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index a8a2b2dacb5..bae84e9e4fd 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -350,10 +350,10 @@ static QMakeEvaluator::VisitReturn parseJsonInto(const QByteArray &json, const Q QMakeEvaluator::VisitReturn QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, - const QString &contents) + bool exe, const QString &contents) { QString errStr; - if (!m_vfs->writeFile(fn, mode, contents, &errStr)) { + if (!m_vfs->writeFile(fn, mode, exe, contents, &errStr)) { evalError(fL1S("Cannot write %1file %2: %3") .arg(ctx, QDir::toNativeSeparators(fn), errStr)); return ReturnFalse; @@ -1541,22 +1541,33 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } case T_WRITE_FILE: { if (args.count() > 3) { - evalError(fL1S("write_file(name, [content var, [append]]) requires one to three arguments.")); + evalError(fL1S("write_file(name, [content var, [append] [exe]]) requires one to three arguments.")); return ReturnFalse; } QIODevice::OpenMode mode = QIODevice::Truncate; + bool exe = false; QString contents; if (args.count() >= 2) { const ProStringList &vals = values(args.at(1).toKey()); if (!vals.isEmpty()) contents = vals.join(QLatin1Char('\n')) + QLatin1Char('\n'); - if (args.count() >= 3) - if (!args.at(2).toQString(m_tmp1).compare(fL1S("append"), Qt::CaseInsensitive)) - mode = QIODevice::Append; + if (args.count() >= 3) { + foreach (const ProString &opt, split_value_list(args.at(2).toQString(m_tmp2))) { + opt.toQString(m_tmp3); + if (m_tmp3 == QLatin1String("append")) { + mode = QIODevice::Append; + } else if (m_tmp3 == QLatin1String("exe")) { + exe = true; + } else { + evalError(fL1S("write_file(): invalid flag %1.").arg(m_tmp3)); + return ReturnFalse; + } + } + } } QString path = resolvePath(args.at(0).toQString(m_tmp1)); path.detach(); // make sure to not leak m_tmp1 into the map of written files. - return writeFile(QString(), path, mode, contents); + return writeFile(QString(), path, mode, exe, contents); } case T_TOUCH: { if (args.count() != 2) { @@ -1767,7 +1778,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn); } } - return writeFile(fL1S("cache "), fn, QIODevice::Append, varstr); + return writeFile(fL1S("cache "), fn, QIODevice::Append, false, varstr); } default: evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1))); diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h index 7bb673cb897..7cd2a82abee 100644 --- a/src/shared/proparser/qmakeevaluator.h +++ b/src/shared/proparser/qmakeevaluator.h @@ -229,7 +229,7 @@ public: QMultiMap &rootSet) const; VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, - const QString &contents); + bool exe, const QString &contents); #ifndef QT_BOOTSTRAPPED void runProcess(QProcess *proc, const QString &command) const; #endif diff --git a/src/shared/proparser/qmakevfs.cpp b/src/shared/proparser/qmakevfs.cpp index 7eb35bebcaa..0231fa9a46f 100644 --- a/src/shared/proparser/qmakevfs.cpp +++ b/src/shared/proparser/qmakevfs.cpp @@ -44,8 +44,8 @@ QMakeVfs::QMakeVfs() { } -bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, const QString &contents, - QString *errStr) +bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, + const QString &contents, QString *errStr) { #ifndef PROEVALUATOR_FULL # ifdef PROEVALUATOR_THREAD_SAFE @@ -57,6 +57,7 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, const QStr else *cont = contents; Q_UNUSED(errStr) + Q_UNUSED(exe) return true; #else QFileInfo qfi(fn); @@ -67,8 +68,16 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, const QStr QByteArray bytes = contents.toLocal8Bit(); QFile cfile(fn); if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) { - if (cfile.readAll() == bytes) + if (cfile.readAll() == bytes) { + if (exe) { + cfile.setPermissions(cfile.permissions() + | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther); + } else { + cfile.setPermissions(cfile.permissions() + & ~(QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther)); + } return true; + } cfile.close(); } if (!cfile.open(mode | QIODevice::WriteOnly | QIODevice::Text)) { @@ -81,6 +90,9 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, const QStr *errStr = cfile.errorString(); return false; } + if (exe) + cfile.setPermissions(cfile.permissions() + | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther); return true; #endif } diff --git a/src/shared/proparser/qmakevfs.h b/src/shared/proparser/qmakevfs.h index 8c387fe29d5..3ffe67c1bac 100644 --- a/src/shared/proparser/qmakevfs.h +++ b/src/shared/proparser/qmakevfs.h @@ -43,7 +43,7 @@ class QMAKE_EXPORT QMakeVfs public: QMakeVfs(); - bool writeFile(const QString &fn, QIODevice::OpenMode mode, const QString &contents, QString *errStr); + bool writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, const QString &contents, QString *errStr); bool readFile(const QString &fn, QString *contents, QString *errStr); bool exists(const QString &fn); -- cgit v1.2.3 From 73fead33dcb406a01f1ab91777546a329c056b54 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Tue, 19 Jan 2016 10:55:32 +0300 Subject: QMake: replace QStringLiteral with QLatin1String ... in string comparisons. It's more efficient. Change-Id: I5d54ab7777a0838455eaaac671e735eb37bfe243 Reviewed-by: Oswald Buddenhagen (cherry picked from qtbase/f384c3097911c523e67620b77b1086e4788cd209) Reviewed-by: Jake Petroules Reviewed-by: Anton Kudryavtsev --- src/shared/proparser/qmakeevaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index dafb56244a0..606e9008f56 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -949,7 +949,7 @@ static ProString msvcBinDirToQMakeArch(QString subdir) if (idx >= 0) subdir.remove(0, idx + 1); subdir = subdir.toLower(); - if (subdir == QStringLiteral("amd64")) + if (subdir == QLatin1String("amd64")) return ProString("x86_64"); return ProString(subdir); } -- cgit v1.2.3 From bbb353b113277760790fe82a6b2c065c0ab51dec Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 7 Mar 2016 15:29:44 +0100 Subject: qmake: fix UB in QMakeParser::putHashStr() Found by UBSan: qmake/library/qmakeparser.cpp:278:33: runtime error: null pointer passed as argument 2, which is declared to never be null Guard the call. Change-Id: I99341ab439a511f366dae9344ddcc8727c33b9b6 Reviewed-by: Oswald Buddenhagen (cherry picked from qtbase/1fd0d57ce3da83631423d17faadf97133f5c7835) Reviewed-by: Marc Mutz Reviewed-by: Jake Petroules --- src/shared/proparser/qmakeparser.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakeparser.cpp b/src/shared/proparser/qmakeparser.cpp index 59dc289548c..f22d47450ac 100644 --- a/src/shared/proparser/qmakeparser.cpp +++ b/src/shared/proparser/qmakeparser.cpp @@ -272,7 +272,8 @@ void QMakeParser::putHashStr(ushort *&pTokPtr, const ushort *buf, uint len) *tokPtr++ = (ushort)hash; *tokPtr++ = (ushort)(hash >> 16); *tokPtr++ = (ushort)len; - memcpy(tokPtr, buf, len * 2); + if (len) // buf may be nullptr; don't pass that to memcpy (-> undefined behavior) + memcpy(tokPtr, buf, len * 2); pTokPtr = tokPtr + len; } -- cgit v1.2.3 From 27853f823442059794231ab94d5bd349381ea06d Mon Sep 17 00:00:00 2001 From: Mat Sutcliffe Date: Thu, 16 Jun 2016 14:38:22 +0100 Subject: qmake: Fix missing newlines in generated vcxproj files Sync up with qmake - this doesn't actually do anything in qtc. Change-Id: I792599a4cd7822f109fa921f02207fb1b144b1d1 Reviewed-by: Oswald Buddenhagen (cherry picked from qtbase/23bce6b169ca14ff72b672965ed5f89424c2d8fe) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 7 ++++++- src/shared/proparser/qmakeglobals.cpp | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index bae84e9e4fd..e6f7bab2192 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -64,9 +64,11 @@ #ifdef Q_OS_WIN32 #define QT_POPEN _popen +#define QT_POPEN_READ "rb" #define QT_PCLOSE _pclose #else #define QT_POPEN popen +#define QT_POPEN_READ "r" #define QT_PCLOSE pclose #endif @@ -407,7 +409,7 @@ QByteArray QMakeEvaluator::getCommandOutput(const QString &args) const #else if (FILE *proc = QT_POPEN(QString(QLatin1String("cd ") + IoUtils::shellQuote(QDir::toNativeSeparators(currentDirectory())) - + QLatin1String(" && ") + args).toLocal8Bit().constData(), "r")) { + + QLatin1String(" && ") + args).toLocal8Bit().constData(), QT_POPEN_READ)) { while (!feof(proc)) { char buff[10 * 1024]; int read_in = int(fread(buff, 1, sizeof(buff), proc)); @@ -417,6 +419,9 @@ QByteArray QMakeEvaluator::getCommandOutput(const QString &args) const } QT_PCLOSE(proc); } +# ifdef Q_OS_WIN + out.replace("\r\n", "\n"); +# endif #endif return out; } diff --git a/src/shared/proparser/qmakeglobals.cpp b/src/shared/proparser/qmakeglobals.cpp index 2231391f9ad..d9c9ff16678 100644 --- a/src/shared/proparser/qmakeglobals.cpp +++ b/src/shared/proparser/qmakeglobals.cpp @@ -56,9 +56,11 @@ #ifdef Q_OS_WIN32 #define QT_POPEN _popen +#define QT_POPEN_READ "rb" #define QT_PCLOSE _pclose #else #define QT_POPEN popen +#define QT_POPEN_READ "r" #define QT_PCLOSE pclose #endif @@ -299,7 +301,7 @@ bool QMakeGlobals::initProperties() data = proc.readAll(); #else if (FILE *proc = QT_POPEN(QString(QMakeInternal::IoUtils::shellQuote(qmake_abslocation) - + QLatin1String(" -query")).toLocal8Bit(), "r")) { + + QLatin1String(" -query")).toLocal8Bit(), QT_POPEN_READ)) { char buff[1024]; while (!feof(proc)) data.append(buff, int(fread(buff, 1, 1023, proc))); -- cgit v1.2.3 From fcbaf241816045389451e99051443feed672425a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 30 Jun 2016 14:13:48 +0200 Subject: nuke dead expandVariableReferences() overload prototype Change-Id: I0c6fceac0b984e4613932b8507a632dd83d0e79b Reviewed-by: Joerg Bornemann (cherry picked from qtbase/d0055e9fd7825f9033b26f9aa421e218e44dadde) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakeevaluator.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h index 7cd2a82abee..0e0ba95026a 100644 --- a/src/shared/proparser/qmakeevaluator.h +++ b/src/shared/proparser/qmakeevaluator.h @@ -173,7 +173,6 @@ public: void setTemplate(); ProStringList split_value_list(const QString &vals, const ProFile *source = 0); - ProStringList expandVariableReferences(const ProString &value, int *pos = 0, bool joined = false); ProStringList expandVariableReferences(const ushort *&tokPtr, int sizeHint = 0, bool joined = false); QString currentFileName() const; -- cgit v1.2.3 From b4ac7f6d2c38af2ba518d96b8908a19f6202f1dd Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 29 Jun 2016 15:40:17 +0200 Subject: fix error() not propagating through if() if() would simply "downgrade" a fatal error to a false condition, which is certainly not expected. Change-Id: Ie9c54f2bddf588856498bf795007b341b7c9363a Reviewed-by: Joerg Bornemann (cherry picked from qtbase/b27d4835c2ae0d8767ca914acb72a4bdcea6fc85) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 4 ++-- src/shared/proparser/qmakeevaluator.cpp | 9 +++++---- src/shared/proparser/qmakeevaluator.h | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index e6f7bab2192..1bc2ba489f1 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -1215,8 +1215,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( evalError(fL1S("if(condition) requires one argument.")); return ReturnFalse; } - return returnBool(evaluateConditional(args.at(0).toQString(), - m_current.pro->fileName(), m_current.line)); + return evaluateConditional(args.at(0).toQString(), + m_current.pro->fileName(), m_current.line); } case T_CONFIG: { if (args.count() < 1 || args.count() > 2) { diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index 606e9008f56..9c73857c1c4 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -1750,13 +1750,14 @@ ProStringList QMakeEvaluator::evaluateExpandFunction( return ProStringList(); } -bool QMakeEvaluator::evaluateConditional(const QString &cond, const QString &where, int line) +QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditional( + const QString &cond, const QString &where, int line) { - bool ret = false; + VisitReturn ret = ReturnFalse; ProFile *pro = m_parser->parsedProBlock(cond, where, line, QMakeParser::TestGrammar); if (pro->isOk()) { m_locationStack.push(m_current); - ret = visitProBlock(pro, pro->tokPtr()) == ReturnTrue; + ret = visitProBlock(pro, pro->tokPtr()); m_current = m_locationStack.pop(); } pro->deref(); @@ -1768,7 +1769,7 @@ void QMakeEvaluator::checkRequirements(const ProStringList &deps) { ProStringList &failed = valuesRef(ProKey("QMAKE_FAILED_REQUIREMENTS")); foreach (const ProString &dep, deps) - if (!evaluateConditional(dep.toQString(), m_current.pro->fileName(), m_current.line)) + if (evaluateConditional(dep.toQString(), m_current.pro->fileName(), m_current.line) != ReturnTrue) failed << dep; } #endif diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h index 0e0ba95026a..0fa12ede642 100644 --- a/src/shared/proparser/qmakeevaluator.h +++ b/src/shared/proparser/qmakeevaluator.h @@ -211,7 +211,7 @@ public: ProStringList evaluateBuiltinExpand(int func_t, const ProKey &function, const ProStringList &args); VisitReturn evaluateBuiltinConditional(int func_t, const ProKey &function, const ProStringList &args); - bool evaluateConditional(const QString &cond, const QString &where, int line = -1); + VisitReturn evaluateConditional(const QString &cond, const QString &where, int line = -1); #ifdef PROEVALUATOR_FULL void checkRequirements(const ProStringList &deps); #endif -- cgit v1.2.3 From 3fe303ebfeffe3ea195836db577621b6aff9d99e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 29 Jun 2016 16:56:57 +0200 Subject: make error() propagate from custom replace functions it didn't, which is rather unexpected. Change-Id: I8cdb7b1490a8c2207809812b93cc65fbe23a1b98 Reviewed-by: Joerg Bornemann (cherry picked from qtbase/339b9706ccbed4063a92337c9994731793558b0a) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakeevaluator.cpp | 110 +++++++++++++++++++------------- src/shared/proparser/qmakeevaluator.h | 14 ++-- 2 files changed, 73 insertions(+), 51 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index 9c73857c1c4..7f3b9571e4b 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -401,7 +401,7 @@ static ALWAYS_INLINE void addStrList( } } -void QMakeEvaluator::evaluateExpression( +QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateExpression( const ushort *&tokPtr, ProStringList *ret, bool joined) { debugMsg(2, joined ? "evaluating joined expression" : "evaluating expression"); @@ -451,12 +451,15 @@ void QMakeEvaluator::evaluateExpression( case TokFuncName: { const ProKey &func = pro->getHashStr(tokPtr); debugMsg(2, "function %s", dbgKey(func)); - addStrList(evaluateExpandFunction(func, tokPtr), tok, ret, pending, joined); + ProStringList val; + if (evaluateExpandFunction(func, tokPtr, &val) == ReturnError) + return ReturnError; + addStrList(val, tok, ret, pending, joined); break; } default: debugMsg(2, "evaluated expression => %s", dbgStrList(*ret)); tokPtr--; - return; + return ReturnTrue; } } } @@ -528,7 +531,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock( case TokAppendUnique: case TokRemove: case TokReplace: - visitProVariable(tok, curr, tokPtr); + ret = visitProVariable(tok, curr, tokPtr); + if (ret == ReturnError) + break; curr.clear(); continue; case TokBranch: @@ -688,9 +693,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock( continue; default: { const ushort *oTokPtr = --tokPtr; - evaluateExpression(tokPtr, &curr, false); - if (tokPtr != oTokPtr) - continue; + ret = evaluateExpression(tokPtr, &curr, false); + if (ret == ReturnError || tokPtr != oTokPtr) + break; } Q_ASSERT_X(false, "visitProBlock", "unexpected item type"); continue; @@ -723,7 +728,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProLoop( int index = 0; ProKey variable; ProStringList oldVarVal; - ProString it_list = expandVariableReferences(exprPtr, 0, true).at(0); + ProStringList it_list_out; + if (expandVariableReferences(exprPtr, 0, &it_list_out, true) == ReturnError) + return ReturnError; + ProString it_list = it_list_out.at(0); if (_variable.isEmpty()) { if (it_list != statics.strever) { evalError(fL1S("Invalid loop expression.")); @@ -820,7 +828,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProLoop( return ret; } -void QMakeEvaluator::visitProVariable( +QMakeEvaluator::VisitReturn QMakeEvaluator::visitProVariable( ushort tok, const ProStringList &curr, const ushort *&tokPtr) { int sizeHint = *tokPtr++; @@ -829,24 +837,26 @@ void QMakeEvaluator::visitProVariable( skipExpression(tokPtr); if (!m_cumulative || !curr.isEmpty()) evalError(fL1S("Left hand side of assignment must expand to exactly one word.")); - return; + return ReturnTrue; } const ProKey &varName = map(curr.first()); if (tok == TokReplace) { // ~= // DEFINES ~= s/a/b/?[gqi] - const ProStringList &varVal = expandVariableReferences(tokPtr, sizeHint, true); + ProStringList varVal; + if (expandVariableReferences(tokPtr, sizeHint, &varVal, true) == ReturnError) + return ReturnError; const QString &val = varVal.at(0).toQString(m_tmp1); if (val.length() < 4 || val.at(0) != QLatin1Char('s')) { evalError(fL1S("The ~= operator can handle only the s/// function.")); - return; + return ReturnTrue; } QChar sep = val.at(1); QStringList func = val.split(sep); if (func.count() < 3 || func.count() > 4) { evalError(fL1S("The s/// function expects 3 or 4 arguments.")); - return; + return ReturnTrue; } bool global = false, quote = false, case_sense = false; @@ -867,7 +877,9 @@ void QMakeEvaluator::visitProVariable( replaceInList(&valuesRef(varName), regexp, replace, global, m_tmp2); debugMsg(2, "replaced %s with %s", dbgQStr(pattern), dbgQStr(replace)); } else { - ProStringList varVal = expandVariableReferences(tokPtr, sizeHint); + ProStringList varVal; + if (expandVariableReferences(tokPtr, sizeHint, &varVal, false) == ReturnError) + return ReturnError; switch (tok) { default: // whatever - cannot happen case TokAssign: // = @@ -915,6 +927,8 @@ void QMakeEvaluator::visitProVariable( else if (varName == statics.strREQUIRES) checkRequirements(values(varName)); #endif + + return ReturnTrue; } void QMakeEvaluator::setTemplate() @@ -1602,18 +1616,18 @@ bool QMakeEvaluator::isActiveConfig(const QString &config, bool regex) return false; } -ProStringList QMakeEvaluator::expandVariableReferences( - const ushort *&tokPtr, int sizeHint, bool joined) +QMakeEvaluator::VisitReturn QMakeEvaluator::expandVariableReferences( + const ushort *&tokPtr, int sizeHint, ProStringList *ret, bool joined) { - ProStringList ret; - ret.reserve(sizeHint); + ret->reserve(sizeHint); forever { - evaluateExpression(tokPtr, &ret, joined); + if (evaluateExpression(tokPtr, ret, joined) == ReturnError) + return ReturnError; switch (*tokPtr) { case TokValueTerminator: case TokFuncTerminator: tokPtr++; - return ret; + return ReturnTrue; case TokArgSeparator: if (joined) { tokPtr++; @@ -1627,28 +1641,28 @@ ProStringList QMakeEvaluator::expandVariableReferences( } } -QList QMakeEvaluator::prepareFunctionArgs(const ushort *&tokPtr) +QMakeEvaluator::VisitReturn QMakeEvaluator::prepareFunctionArgs( + const ushort *&tokPtr, QList *ret) { - QList args_list; if (*tokPtr != TokFuncTerminator) { for (;; tokPtr++) { ProStringList arg; - evaluateExpression(tokPtr, &arg, false); - args_list << arg; + if (evaluateExpression(tokPtr, &arg, false) == ReturnError) + return ReturnError; + *ret << arg; if (*tokPtr == TokFuncTerminator) break; Q_ASSERT(*tokPtr == TokArgSeparator); } } tokPtr++; - return args_list; + return ReturnTrue; } -ProStringList QMakeEvaluator::evaluateFunction( - const ProFunctionDef &func, const QList &argumentsList, VisitReturn *ok) +QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFunction( + const ProFunctionDef &func, const QList &argumentsList, ProStringList *ret) { VisitReturn vr; - ProStringList ret; if (m_valuemapStack.count() >= 100) { evalError(fL1S("Ran into infinite recursion (depth > 100).")); @@ -1667,25 +1681,22 @@ ProStringList QMakeEvaluator::evaluateFunction( vr = visitProBlock(func.pro(), func.tokPtr()); if (vr == ReturnReturn) vr = ReturnTrue; - ret = m_returnValue; + if (vr == ReturnTrue) + *ret = m_returnValue; m_returnValue.clear(); m_current = m_locationStack.pop(); m_valuemapStack.pop(); } - if (ok) - *ok = vr; - if (vr == ReturnTrue) - return ret; - return ProStringList(); + return vr; } QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBoolFunction( const ProFunctionDef &func, const QList &argumentsList, const ProString &function) { - VisitReturn vr; - ProStringList ret = evaluateFunction(func, argumentsList, &vr); + ProStringList ret; + VisitReturn vr = evaluateFunction(func, argumentsList, &ret); if (vr == ReturnTrue) { if (ret.isEmpty()) return ReturnTrue; @@ -1713,13 +1724,18 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction( { if (int func_t = statics.functions.value(func)) { //why don't the builtin functions just use args_list? --Sam - return evaluateBuiltinConditional(func_t, func, expandVariableReferences(tokPtr, 5, true)); + ProStringList args; + if (expandVariableReferences(tokPtr, 5, &args, true) == ReturnError) + return ReturnError; + return evaluateBuiltinConditional(func_t, func, args); } QHash::ConstIterator it = m_functionDefs.testFunctions.constFind(func); if (it != m_functionDefs.testFunctions.constEnd()) { - const QList args = prepareFunctionArgs(tokPtr); + QList args; + if (prepareFunctionArgs(tokPtr, &args) == ReturnError) + return ReturnError; traceMsg("calling %s(%s)", dbgKey(func), dbgStrListList(args)); return evaluateBoolFunction(*it, args, func); } @@ -1729,25 +1745,31 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction( return ReturnFalse; } -ProStringList QMakeEvaluator::evaluateExpandFunction( - const ProKey &func, const ushort *&tokPtr) +QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateExpandFunction( + const ProKey &func, const ushort *&tokPtr, ProStringList *ret) { if (int func_t = statics.expands.value(func)) { //why don't the builtin functions just use args_list? --Sam - return evaluateBuiltinExpand(func_t, func, expandVariableReferences(tokPtr, 5, true)); + ProStringList args; + if (expandVariableReferences(tokPtr, 5, &args, true) == ReturnError) + return ReturnError; + *ret = evaluateBuiltinExpand(func_t, func, args); + return ReturnTrue; } QHash::ConstIterator it = m_functionDefs.replaceFunctions.constFind(func); if (it != m_functionDefs.replaceFunctions.constEnd()) { - const QList args = prepareFunctionArgs(tokPtr); + QList args; + if (prepareFunctionArgs(tokPtr, &args) == ReturnError) + return ReturnError; traceMsg("calling $$%s(%s)", dbgKey(func), dbgStrListList(args)); - return evaluateFunction(*it, args, 0); + return evaluateFunction(*it, args, ret); } skipExpression(tokPtr); evalError(fL1S("'%1' is not a recognized replace function.").arg(func.toQString(m_tmp1))); - return ProStringList(); + return ReturnFalse; } QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditional( diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h index 0fa12ede642..27add611461 100644 --- a/src/shared/proparser/qmakeevaluator.h +++ b/src/shared/proparser/qmakeevaluator.h @@ -144,7 +144,7 @@ public: { return b ? ReturnTrue : ReturnFalse; } static ALWAYS_INLINE uint getBlockLen(const ushort *&tokPtr); - void evaluateExpression(const ushort *&tokPtr, ProStringList *ret, bool joined); + VisitReturn evaluateExpression(const ushort *&tokPtr, ProStringList *ret, bool joined); static ALWAYS_INLINE void skipStr(const ushort *&tokPtr); static ALWAYS_INLINE void skipHashStr(const ushort *&tokPtr); void skipExpression(const ushort *&tokPtr); @@ -164,7 +164,7 @@ public: VisitReturn visitProLoop(const ProKey &variable, const ushort *exprPtr, const ushort *tokPtr); void visitProFunctionDef(ushort tok, const ProKey &name, const ushort *tokPtr); - void visitProVariable(ushort tok, const ProStringList &curr, const ushort *&tokPtr); + VisitReturn visitProVariable(ushort tok, const ProStringList &curr, const ushort *&tokPtr); ALWAYS_INLINE const ProKey &map(const ProString &var) { return map(var.toKey()); } const ProKey &map(const ProKey &var); @@ -173,7 +173,7 @@ public: void setTemplate(); ProStringList split_value_list(const QString &vals, const ProFile *source = 0); - ProStringList expandVariableReferences(const ushort *&tokPtr, int sizeHint = 0, bool joined = false); + VisitReturn expandVariableReferences(const ushort *&tokPtr, int sizeHint, ProStringList *ret, bool joined); QString currentFileName() const; QString currentDirectory() const; @@ -198,14 +198,14 @@ public: void deprecationWarning(const QString &msg) const { message(QMakeHandler::EvalWarnDeprecated, msg); } - QList prepareFunctionArgs(const ushort *&tokPtr); - ProStringList evaluateFunction(const ProFunctionDef &func, - const QList &argumentsList, VisitReturn *ok); + VisitReturn prepareFunctionArgs(const ushort *&tokPtr, QList *ret); + VisitReturn evaluateFunction(const ProFunctionDef &func, + const QList &argumentsList, ProStringList *ret); VisitReturn evaluateBoolFunction(const ProFunctionDef &func, const QList &argumentsList, const ProString &function); - ProStringList evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr); + VisitReturn evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr, ProStringList *ret); VisitReturn evaluateConditionalFunction(const ProKey &function, const ushort *&tokPtr); ProStringList evaluateBuiltinExpand(int func_t, const ProKey &function, const ProStringList &args); -- cgit v1.2.3 From 32f3eccade765e79563fdb1e2073e58f6ca00080 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 30 Jun 2016 16:02:29 +0200 Subject: make error() propagate from requires() and REQUIRES= that can make sense if a function which determines the availability of a dependency fails to do so for unexpected reasons. Change-Id: If6cd113df25aee66830c120a2fab067c822a4543 Reviewed-by: Joerg Bornemann (cherry picked from qtbase/1b4ea11332f74984a62a4cc4597ad49f5b5269dc) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 3 ++- src/shared/proparser/qmakeevaluator.cpp | 13 +++++++++---- src/shared/proparser/qmakeevaluator.h | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index 1bc2ba489f1..f9700b9bc06 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -1194,7 +1194,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( return ReturnFalse; case T_REQUIRES: #ifdef PROEVALUATOR_FULL - checkRequirements(args); + if (checkRequirements(args) == ReturnError) + return ReturnError; #endif return ReturnFalse; // Another qmake breakage case T_EVAL: { diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index 7f3b9571e4b..c88a0e55b11 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -925,7 +925,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProVariable( } #ifdef PROEVALUATOR_FULL else if (varName == statics.strREQUIRES) - checkRequirements(values(varName)); + return checkRequirements(values(varName)); #endif return ReturnTrue; @@ -1787,12 +1787,17 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditional( } #ifdef PROEVALUATOR_FULL -void QMakeEvaluator::checkRequirements(const ProStringList &deps) +QMakeEvaluator::VisitReturn QMakeEvaluator::checkRequirements(const ProStringList &deps) { ProStringList &failed = valuesRef(ProKey("QMAKE_FAILED_REQUIREMENTS")); - foreach (const ProString &dep, deps) - if (evaluateConditional(dep.toQString(), m_current.pro->fileName(), m_current.line) != ReturnTrue) + foreach (const ProString &dep, deps) { + VisitReturn vr = evaluateConditional(dep.toQString(), m_current.pro->fileName(), m_current.line); + if (vr == ReturnError) + return ReturnError; + if (vr != ReturnTrue) failed << dep; + } + return ReturnTrue; } #endif diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h index 27add611461..672a36b7b7a 100644 --- a/src/shared/proparser/qmakeevaluator.h +++ b/src/shared/proparser/qmakeevaluator.h @@ -213,7 +213,7 @@ public: VisitReturn evaluateConditional(const QString &cond, const QString &where, int line = -1); #ifdef PROEVALUATOR_FULL - void checkRequirements(const ProStringList &deps); + VisitReturn checkRequirements(const ProStringList &deps); #endif void updateMkspecPaths(); -- cgit v1.2.3 From 1a58cd361a3c5c20018ade322820e18989fb7700 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 30 Jun 2016 17:26:01 +0200 Subject: fix custom functions inheriting other functions' arguments Task-number: QTBUG-41830 Change-Id: Iba3eee4975a1ee671b7190e52c0efc9a18147c62 Reviewed-by: Joerg Bornemann Reviewed-by: Lars Knoll Reviewed-by: Oswald Buddenhagen (cherry picked from qtbase/dacf3994ba29106132c3a377dba303acdb74daca) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakeevaluator.cpp | 56 +++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 17 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index c88a0e55b11..8f0ed9c6422 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -1801,19 +1801,35 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::checkRequirements(const ProStringLis } #endif +static bool isFunctParam(const ProKey &variableName) +{ + const int len = variableName.size(); + const QChar *data = variableName.constData(); + for (int i = 0; i < len; i++) { + ushort c = data[i].unicode(); + if (c < '0' || c > '9') + return false; + } + return true; +} + ProValueMap *QMakeEvaluator::findValues(const ProKey &variableName, ProValueMap::Iterator *rit) { ProValueMapStack::Iterator vmi = m_valuemapStack.end(); - do { + for (bool first = true; ; first = false) { --vmi; ProValueMap::Iterator it = (*vmi).find(variableName); if (it != (*vmi).end()) { if (it->constBegin() == statics.fakeValue.constBegin()) - return 0; + break; *rit = it; return &(*vmi); } - } while (vmi != m_valuemapStack.begin()); + if (vmi == m_valuemapStack.begin()) + break; + if (first && isFunctParam(variableName)) + break; + } return 0; } @@ -1825,18 +1841,20 @@ ProStringList &QMakeEvaluator::valuesRef(const ProKey &variableName) it->clear(); return *it; } - ProValueMapStack::Iterator vmi = m_valuemapStack.end(); - if (--vmi != m_valuemapStack.begin()) { - do { - --vmi; - ProValueMap::ConstIterator it = (*vmi).constFind(variableName); - if (it != (*vmi).constEnd()) { - ProStringList &ret = m_valuemapStack.top()[variableName]; - if (it->constBegin() != statics.fakeValue.constBegin()) - ret = *it; - return ret; - } - } while (vmi != m_valuemapStack.begin()); + if (!isFunctParam(variableName)) { + ProValueMapStack::Iterator vmi = m_valuemapStack.end(); + if (--vmi != m_valuemapStack.begin()) { + do { + --vmi; + ProValueMap::ConstIterator it = (*vmi).constFind(variableName); + if (it != (*vmi).constEnd()) { + ProStringList &ret = m_valuemapStack.top()[variableName]; + if (it->constBegin() != statics.fakeValue.constBegin()) + ret = *it; + return ret; + } + } while (vmi != m_valuemapStack.begin()); + } } return m_valuemapStack.top()[variableName]; } @@ -1844,7 +1862,7 @@ ProStringList &QMakeEvaluator::valuesRef(const ProKey &variableName) ProStringList QMakeEvaluator::values(const ProKey &variableName) const { ProValueMapStack::ConstIterator vmi = m_valuemapStack.constEnd(); - do { + for (bool first = true; ; first = false) { --vmi; ProValueMap::ConstIterator it = (*vmi).constFind(variableName); if (it != (*vmi).constEnd()) { @@ -1852,7 +1870,11 @@ ProStringList QMakeEvaluator::values(const ProKey &variableName) const break; return *it; } - } while (vmi != m_valuemapStack.constBegin()); + if (vmi == m_valuemapStack.constBegin()) + break; + if (first && isFunctParam(variableName)) + break; + } return ProStringList(); } -- cgit v1.2.3 From bb1ce1cd56463b0748c153d2c80c988dab169b04 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 5 Jul 2016 20:00:17 +0200 Subject: fix calculations of worst-case size requirements for token buffer Task-nubmer: QTCREATORBUG-16508 Change-Id: I3aa4c736acec44f95a0a33c7baae9276568f684f Reviewed-by: Joerg Bornemann Reviewed-by: Oswald Buddenhagen (cherry picked from qtbase/d459a6b0e0d4f128caceaafe981ecf374bb3e420) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakeparser.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakeparser.cpp b/src/shared/proparser/qmakeparser.cpp index f22d47450ac..777402068f5 100644 --- a/src/shared/proparser/qmakeparser.cpp +++ b/src/shared/proparser/qmakeparser.cpp @@ -296,27 +296,30 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra // Worst-case size calculations: // - line marker adds 1 (2-nl) to 1st token of each line // - empty assignment "A=":2 => - // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + 0(1) + + // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + size_hint(1) + // TokValueTerminator(1) == 8 (9) // - non-empty assignment "A=B C":5 => - // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + 2(1) + + // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + size_hint(1) + // TokLiteral(1) + len(1) + "B"(1) + // TokLiteral(1) + len(1) + "C"(1) + TokValueTerminator(1) == 14 (15) // - variable expansion: "$$f":3 => // TokVariable(1) + hash(2) + len(1) + "f"(1) = 5 // - function expansion: "$$f()":5 => // TokFuncName(1) + hash(2) + len(1) + "f"(1) + TokFuncTerminator(1) = 6 + // - test literal: "X":1 => + // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokCondition(1) = 6 (7) // - scope: "X:":2 => // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokCondition(1) + - // TokBranch(1) + len(2) + ... + len(2) + ... == 10 - // - test: "X():":4 => + // TokBranch(1) + len(2) + ... + len(2) + ... == 11 (12) + // - test call: "X():":4 => // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokTestCall(1) + TokFuncTerminator(1) + - // TokBranch(1) + len(2) + ... + len(2) + ... == 11 + // TokBranch(1) + len(2) + ... + len(2) + ... == 12 (13) // - "for(A,B):":9 => // TokForLoop(1) + hash(2) + len(1) + "A"(1) + // len(2) + TokLiteral(1) + len(1) + "B"(1) + TokValueTerminator(1) + // len(2) + ... + TokTerminator(1) == 14 (15) - tokBuff.reserve((in.size() + 1) * 5); + // One extra for possibly missing trailing newline. + tokBuff.reserve((in.size() + 1) * 7); ushort *tokPtr = (ushort *)tokBuff.constData(); // Current writing position // Expression precompiler buffer. -- cgit v1.2.3 From e1cee308a98252d902a73db849646c8aadc864d2 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 5 Jul 2016 18:07:14 +0200 Subject: fix raw data leak in $$absolute_path() when the file name is empty, the path will be returned verbatim. this must be considered when constructing the return value. Task-number: QTBUG-54550 Change-Id: Ie108ed52275e66a154ef63bd6f7193f55b3e0454 Reviewed-by: Joerg Bornemann (cherry picked from qtbase/3c8134958c66f40bb86588aa91b83bf58b5de0c9) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index f9700b9bc06..996a5afa394 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -1021,7 +1021,11 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( QString rstr = QDir::cleanPath( QDir(args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory()) .absoluteFilePath(args.at(0).toQString(m_tmp1))); - ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0))); + ret << (rstr.isSharedWith(m_tmp1) + ? args.at(0) + : args.count() > 1 && rstr.isSharedWith(m_tmp2) + ? args.at(1) + : ProString(rstr).setSource(args.at(0))); } break; case E_RELATIVE_PATH: -- cgit v1.2.3 From fb9e43ba444e15e76532f97e778d0149c4514340 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 14 Jul 2016 18:10:50 +0200 Subject: terminate when command called by system() got SIGINT or SIGQUIT sync up with qmake - this doesn't actually do anything in qtc. Change-Id: I5e5df9f6d136601f0f36a8d645f90a1cab9995ad Reviewed-by: Lars Knoll (cherry picked from qtbase/f8ef7e1d2619e6d394c57561bb275767f0517b24) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index 996a5afa394..d3fd28184ca 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -54,6 +54,8 @@ #include #include #include +#include +#include #include #include #else @@ -1498,9 +1500,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( runProcess(&proc, args.at(0).toQString(m_tmp2)); return returnBool(proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0); #else - return returnBool(system((QLatin1String("cd ") - + IoUtils::shellQuote(QDir::toNativeSeparators(currentDirectory())) - + QLatin1String(" && ") + args.at(0)).toLocal8Bit().constData()) == 0); + int ec = system((QLatin1String("cd ") + + IoUtils::shellQuote(QDir::toNativeSeparators(currentDirectory())) + + QLatin1String(" && ") + args.at(0)).toLocal8Bit().constData()); +# ifdef Q_OS_UNIX + if (ec != -1 && WIFSIGNALED(ec) && (WTERMSIG(ec) == SIGQUIT || WTERMSIG(ec) == SIGINT)) + raise(WTERMSIG(ec)); +# endif + return returnBool(ec == 0); #endif #else return ReturnTrue; -- cgit v1.2.3 From 69088860eb177a08444c199f21b2f74a95bc7ca3 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 13 Jul 2015 11:21:22 +0200 Subject: QMake: Add option to set qt.conf file Change-Id: Ie5db11892ccf2d357773a4db6a0464bf27be9a26 Reviewed-by: Oswald Buddenhagen (cherry picked from qtbase/dbf1c2eb9f4e1feb24a58699b7b550016802e386) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakeevaluator.cpp | 2 ++ src/shared/proparser/qmakeglobals.cpp | 7 ++++++- src/shared/proparser/qmakeglobals.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index 8f0ed9c6422..6859b8faf96 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -1006,6 +1006,8 @@ void QMakeEvaluator::loadDefaults() vars[ProKey("QMAKE_QMAKE")] << ProString(m_option->qmake_abslocation); if (!m_option->qmake_args.isEmpty()) vars[ProKey("QMAKE_ARGS")] = ProStringList(m_option->qmake_args); + if (!m_option->qtconf.isEmpty()) + vars[ProKey("QMAKE_QTCONF")] = ProString(m_option->qtconf); vars[ProKey("QMAKE_HOST.cpu_count")] = ProString(QString::number(idealThreadCount())); #if defined(Q_OS_WIN32) vars[ProKey("QMAKE_HOST.os")] << ProString("Windows"); diff --git a/src/shared/proparser/qmakeglobals.cpp b/src/shared/proparser/qmakeglobals.cpp index d9c9ff16678..23cee427aea 100644 --- a/src/shared/proparser/qmakeglobals.cpp +++ b/src/shared/proparser/qmakeglobals.cpp @@ -103,7 +103,7 @@ QString QMakeGlobals::cleanSpec(QMakeCmdLineParserState &state, const QString &s QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments( QMakeCmdLineParserState &state, QStringList &args, int *pos) { - enum { ArgNone, ArgConfig, ArgSpec, ArgXSpec, ArgTmpl, ArgTmplPfx, ArgCache } argState = ArgNone; + enum { ArgNone, ArgConfig, ArgSpec, ArgXSpec, ArgTmpl, ArgTmplPfx, ArgCache, ArgQtConf } argState = ArgNone; for (; *pos < args.count(); (*pos)++) { QString arg = args.at(*pos); switch (argState) { @@ -128,6 +128,9 @@ QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments( case ArgCache: cachefile = args[*pos] = QDir::cleanPath(QDir(state.pwd).absoluteFilePath(arg)); break; + case ArgQtConf: + qtconf = args[*pos] = QDir::cleanPath(QDir(state.pwd).absoluteFilePath(arg)); + break; default: if (arg.startsWith(QLatin1Char('-'))) { if (arg == QLatin1String("-after")) @@ -138,6 +141,8 @@ QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments( do_cache = false; else if (arg == QLatin1String("-cache")) argState = ArgCache; + else if (arg == QLatin1String("-qtconf")) + argState = ArgQtConf; else if (arg == QLatin1String("-platform") || arg == QLatin1String("-spec")) argState = ArgSpec; else if (arg == QLatin1String("-xplatform") || arg == QLatin1String("-xspec")) diff --git a/src/shared/proparser/qmakeglobals.h b/src/shared/proparser/qmakeglobals.h index 33a5bdb8318..c931e8e9435 100644 --- a/src/shared/proparser/qmakeglobals.h +++ b/src/shared/proparser/qmakeglobals.h @@ -103,6 +103,7 @@ public: QString qmake_abslocation; QStringList qmake_args; + QString qtconf; QString qmakespec, xqmakespec; QString user_template, user_template_prefix; QString precmds, postcmds; -- cgit v1.2.3 From 5c812f77e2eb87365235ea310f05e5daaa86d972 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 26 Jan 2016 19:33:30 +0100 Subject: qmake: replace a Q_FOREACH loop with QList::op+= Change-Id: Ibaa49f0d6ea5cbcb5d4d305ec9c55286eac5046e Reviewed-by: Lars Knoll (cherry picked from qtbase/dce2612a7c511e85c5a1b46d1e76b88b56be4c99) Reviewed-by: Marc Mutz Reviewed-by: Jake Petroules --- src/shared/proparser/qmakeevaluator.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index 6859b8faf96..4272d4a700f 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -1483,11 +1483,8 @@ void QMakeEvaluator::updateFeaturePaths() QStringList feature_roots; - foreach (const QString &f, m_option->getPathListEnv(QLatin1String("QMAKEFEATURES"))) - feature_roots += f; - + feature_roots += m_option->getPathListEnv(QLatin1String("QMAKEFEATURES")); feature_roots += m_qmakefeatures; - feature_roots += m_option->splitPathList( m_option->propertyValue(ProKey("QMAKEFEATURES")).toQString(m_mtmp)); -- cgit v1.2.3 From ccdcbc55caec3e7142c15c9c492afa4be174d730 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 26 Jan 2016 19:45:58 +0100 Subject: qmake: don't iterate over .keys() ... iterate over the container itself instead. Avoids temporary QList creation as well as the lookup cost when actually calling value(key). Change-Id: Icac867c30e63863cfa44a382eedd4d6df2070a59 Reviewed-by: Lars Knoll (cherry picked from qtbase/c9cb20c01a0f3fa93ff9f79fd7ea3f53939497c4) Reviewed-by: Marc Mutz Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index d3fd28184ca..aca42342b50 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -303,8 +303,8 @@ static void addJsonArray(const QJsonArray &array, const QString &keyPrefix, ProV static void addJsonObject(const QJsonObject &object, const QString &keyPrefix, ProValueMap *map) { - foreach (const QString &key, object.keys()) - addJsonValue(object.value(key), keyPrefix + key, map); + for (auto it = object.begin(), end = object.end(); it != end; ++it) + addJsonValue(it.value(), keyPrefix + it.key(), map); insertJsonKeyValue(keyPrefix + QLatin1String("_KEYS_"), object.keys(), map); } -- cgit v1.2.3 From 1a4f0f1dada33d09974dfdd7ba6dd5fad45d6ead Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 26 Jan 2016 14:38:54 +0100 Subject: qmake: eradicate Q_FOREACH loops [rvalues] ... by replacing them with C++11 range-for loops. This is the simplest of the patch series: Q_FOREACH took a copy, so we do, too. Except we don't, since we're just catching the return value that comes out of the function (RVO). We can't feed the rvalues into range-for, because they are non-const and would thus detach. Change-Id: I5834620bf82f3442da7b2838363d351a0fb960a0 Reviewed-by: Lars Knoll (cherry picked from qtbase/8d7e913248aa1cad23447668d98911bba01faf4b) Reviewed-by: Marc Mutz Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 30 ++++++++++++++++++++---------- src/shared/proparser/qmakeevaluator.cpp | 18 ++++++++++++------ src/shared/proparser/qmakeglobals.cpp | 3 ++- 3 files changed, 34 insertions(+), 17 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index aca42342b50..5bcbecba0c7 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -493,14 +493,15 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( } } if (!var.isEmpty()) { + const auto strings = values(map(var)); if (regexp) { QRegExp sepRx(sep); - foreach (const ProString &str, values(map(var))) { + for (const ProString &str : strings) { const QString &rstr = str.toQString(m_tmp1).section(sepRx, beg, end); ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr).setSource(str)); } } else { - foreach (const ProString &str, values(map(var))) { + for (const ProString &str : strings) { const QString &rstr = str.toQString(m_tmp1).section(sep, beg, end); ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr).setSource(str)); } @@ -529,7 +530,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( bool leftalign = false; enum { DefaultSign, PadSign, AlwaysSign } sign = DefaultSign; if (args.count() >= 2) { - foreach (const ProString &opt, split_value_list(args.at(1).toQString(m_tmp2))) { + const auto opts = split_value_list(args.at(1).toQString(m_tmp2)); + for (const ProString &opt : opts) { opt.toQString(m_tmp3); if (m_tmp3.startsWith(QLatin1String("ibase="))) { ibase = m_tmp3.mid(6).toInt(); @@ -618,9 +620,12 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( evalError(fL1S("split(var, sep) requires one or two arguments.")); } else { const QString &sep = (args.count() == 2) ? args.at(1).toQString(m_tmp1) : statics.field_sep; - foreach (const ProString &var, values(map(args.at(0)))) - foreach (const QString &splt, var.toQString(m_tmp2).split(sep)) + const auto vars = values(map(args.at(0))); + for (const ProString &var : vars) { + const auto splits = var.toQString(m_tmp2).split(sep); + for (const QString &splt : splits) ret << (splt.isSharedWith(m_tmp2) ? var : ProString(splt).setSource(var)); + } } break; case E_MEMBER: @@ -761,7 +766,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( } else { QRegExp regx(args.at(1).toQString()); int t = 0; - foreach (const ProString &val, values(map(args.at(0)))) { + const auto vals = values(map(args.at(0))); + for (const ProString &val : vals) { if (regx.indexIn(val.toQString(m_tmp[t])) != -1) ret += val; t ^= 1; @@ -958,7 +964,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( } else { const QRegExp before(args.at(1).toQString()); const QString &after(args.at(2).toQString(m_tmp2)); - foreach (const ProString &val, values(map(args.at(0)))) { + const auto vals = values(map(args.at(0))); + for (const ProString &val : vals) { QString rstr = val.toQString(m_tmp1); QString copy = rstr; // Force a detach on modify rstr.replace(before, after); @@ -1191,7 +1198,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( regx.setPattern(copy); } int t = 0; - foreach (const ProString &s, vars.value(map(args.at(1)))) { + const auto strings = vars.value(map(args.at(1))); + for (const ProString &s : strings) { if ((!regx.isEmpty() && regx.exactMatch(s.toQString(m_tmp[t]))) || s == qry) return ReturnTrue; t ^= 1; @@ -1569,7 +1577,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( if (!vals.isEmpty()) contents = vals.join(QLatin1Char('\n')) + QLatin1Char('\n'); if (args.count() >= 3) { - foreach (const ProString &opt, split_value_list(args.at(2).toQString(m_tmp2))) { + const auto opts = split_value_list(args.at(2).toQString(m_tmp2)); + for (const ProString &opt : opts) { opt.toQString(m_tmp3); if (m_tmp3 == QLatin1String("append")) { mode = QIODevice::Append; @@ -1641,7 +1650,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( enum { CacheSet, CacheAdd, CacheSub } mode = CacheSet; ProKey srcvar; if (args.count() >= 2) { - foreach (const ProString &opt, split_value_list(args.at(1).toQString(m_tmp2))) { + const auto opts = split_value_list(args.at(1).toQString(m_tmp2)); + for (const ProString &opt : opts) { opt.toQString(m_tmp3); if (m_tmp3 == QLatin1String("transient")) { persist = false; diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index 4272d4a700f..7e996d2bc2f 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -984,7 +984,8 @@ static ProString msvcArchitecture(const QString &vcInstallDir, const QString &pa QString vcBinDir = vcInstallDir; if (vcBinDir.endsWith(QLatin1Char('\\'))) vcBinDir.chop(1); - foreach (const QString &dir, pathVar.split(QLatin1Char(';'))) { + const auto dirs = pathVar.split(QLatin1Char(';')); + for (const QString &dir : dirs) { if (!dir.startsWith(vcBinDir, Qt::CaseInsensitive)) continue; const ProString arch = msvcBinDirToQMakeArch(dir.mid(vcBinDir.length() + 1)); @@ -1458,7 +1459,8 @@ void QMakeEvaluator::updateMkspecPaths() QStringList ret; const QString concat = QLatin1String("/mkspecs"); - foreach (const QString &it, m_option->getPathListEnv(QLatin1String("QMAKEPATH"))) + const auto paths = m_option->getPathListEnv(QLatin1String("QMAKEPATH")); + for (const QString &it : paths) ret << it + concat; foreach (const QString &it, m_qmakepath) @@ -1498,7 +1500,8 @@ void QMakeEvaluator::updateFeaturePaths() feature_bases << m_sourceRoot; } - foreach (const QString &item, m_option->getPathListEnv(QLatin1String("QMAKEPATH"))) + const auto items = m_option->getPathListEnv(QLatin1String("QMAKEPATH")); + for (const QString &item : items) feature_bases << (item + mkspecs_concat); foreach (const QString &item, m_qmakepath) @@ -1524,7 +1527,8 @@ void QMakeEvaluator::updateFeaturePaths() feature_bases << (m_option->propertyValue(ProKey("QT_HOST_DATA/src")) + mkspecs_concat); foreach (const QString &fb, feature_bases) { - foreach (const ProString &sfx, values(ProKey("QMAKE_PLATFORM"))) + const auto sfxs = values(ProKey("QMAKE_PLATFORM")); + for (const ProString &sfx : sfxs) feature_roots << (fb + features_concat + sfx + QLatin1Char('/')); feature_roots << (fb + features_concat); } @@ -1597,7 +1601,8 @@ bool QMakeEvaluator::isActiveConfig(const QString &config, bool regex) // CONFIG variable int t = 0; - foreach (const ProString &configValue, values(statics.strCONFIG)) { + const auto configValues = values(statics.strCONFIG); + for (const ProString &configValue : configValues) { if (re.exactMatch(configValue.toQString(m_tmp[t]))) return true; t ^= 1; @@ -2016,7 +2021,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFileInto( *values = visitor.m_valuemapStack.top(); ProKey qiif("QMAKE_INTERNAL_INCLUDED_FILES"); ProStringList &iif = m_valuemapStack.first()[qiif]; - foreach (const ProString &ifn, values->value(qiif)) + const auto ifns = values->value(qiif); + for (const ProString &ifn : ifns) if (!iif.contains(ifn)) iif << ifn; return ReturnTrue; diff --git a/src/shared/proparser/qmakeglobals.cpp b/src/shared/proparser/qmakeglobals.cpp index 23cee427aea..448a27f0f58 100644 --- a/src/shared/proparser/qmakeglobals.cpp +++ b/src/shared/proparser/qmakeglobals.cpp @@ -313,7 +313,8 @@ bool QMakeGlobals::initProperties() QT_PCLOSE(proc); } #endif - foreach (QByteArray line, data.split('\n')) { + const auto lines = data.split('\n'); + for (QByteArray line : lines) { int off = line.indexOf(':'); if (off < 0) // huh? continue; -- cgit v1.2.3 From d882ae9cb7ac8b1784682266260c2a04c5c12689 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 26 Jan 2016 14:38:54 +0100 Subject: qmake: eradicate Q_FOREACH loops [already const] (or trivially marked const) ... by replacing them with C++11 range-for loops. Change-Id: I1522e220a57ecb1c5ee0d4281233b3c3931a2ff8 Reviewed-by: Lars Knoll (cherry picked from qtbase/d9229d849f44cf94e4ee19fac390811b474127d2) Reviewed-by: Marc Mutz Reviewed-by: Jake Petroules --- src/shared/proparser/proitems.cpp | 10 +++++----- src/shared/proparser/qmakebuiltins.cpp | 12 ++++++------ src/shared/proparser/qmakeevaluator.cpp | 10 +++++----- src/shared/proparser/qmakeglobals.cpp | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/proitems.cpp b/src/shared/proparser/proitems.cpp index 1a22a3c50b8..126f0371e5b 100644 --- a/src/shared/proparser/proitems.cpp +++ b/src/shared/proparser/proitems.cpp @@ -388,7 +388,7 @@ void ProStringList::removeAll(const char *str) void ProStringList::removeEach(const ProStringList &value) { - foreach (const ProString &str, value) + for (const ProString &str : value) if (!str.isEmpty()) removeAll(str); } @@ -421,7 +421,7 @@ void ProStringList::removeDuplicates() void ProStringList::insertUnique(const ProStringList &value) { - foreach (const ProString &str, value) + for (const ProString &str : value) if (!str.isEmpty() && !contains(str)) append(str); } @@ -429,7 +429,7 @@ void ProStringList::insertUnique(const ProStringList &value) ProStringList::ProStringList(const QStringList &list) { reserve(list.size()); - foreach (const QString &str, list) + for (const QString &str : list) *this << ProString(str); } @@ -437,8 +437,8 @@ QStringList ProStringList::toQStringList() const { QStringList ret; ret.reserve(size()); - for (int i = 0; i < size(); i++) // foreach causes MSVC2010 ICE - ret << at(i).toQString(); + for (const auto &e : *this) + ret.append(e.toQString()); return ret; } diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index 5bcbecba0c7..6a064a7ab6a 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -434,11 +434,11 @@ void QMakeEvaluator::populateDeps( QHash > &dependencies, ProValueMap &dependees, QMultiMap &rootSet) const { - foreach (const ProString &item, deps) + for (const ProString &item : deps) if (!dependencies.contains(item.toKey())) { QSet &dset = dependencies[item.toKey()]; // Always create entry ProStringList depends; - foreach (const ProString &suffix, suffixes) + for (const ProString &suffix : suffixes) depends += values(ProKey(prefix + item + suffix)); if (depends.isEmpty()) { rootSet.insert(first(ProKey(prefix + item + priosfx)).toInt(), item); @@ -605,7 +605,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( const ProStringList &var = values(map(args.at(0))); if (!var.isEmpty()) { const ProFile *src = currentProFile(); - foreach (const ProString &v, var) + for (const ProString &v : var) if (const ProFile *s = v.sourceFile()) { src = s; break; @@ -756,7 +756,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( tmp.sprintf(".QMAKE_INTERNAL_TMP_variableName_%d", m_listCount++); ret = ProStringList(ProString(tmp)); ProStringList lst; - foreach (const ProString &arg, args) + for (const ProString &arg : args) lst += split_value_list(arg.toQString(m_tmp1), arg.sourceFile()); // Relies on deep copy m_valuemapStack.top()[ret.at(0).toKey()] = lst; break; } @@ -876,7 +876,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( } else { const ProStringList &vals = values(args.at(0).toKey()); ret.reserve(vals.size()); - foreach (const ProString &str, vals) + for (const ProString &str : vals) ret += ProString(quoteValue(str)); } break; @@ -1769,7 +1769,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( varstr += QLatin1Char(' '); varstr += quoteValue(diffval.at(0)); } else if (!diffval.isEmpty()) { - foreach (const ProString &vval, diffval) { + for (const ProString &vval : diffval) { varstr += QLatin1String(" \\\n "); varstr += quoteValue(vval); } diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index 7e996d2bc2f..448139129b6 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -1794,7 +1794,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditional( QMakeEvaluator::VisitReturn QMakeEvaluator::checkRequirements(const ProStringList &deps) { ProStringList &failed = valuesRef(ProKey("QMAKE_FAILED_REQUIREMENTS")); - foreach (const ProString &dep, deps) { + for (const ProString &dep : deps) { VisitReturn vr = evaluateConditional(dep.toQString(), m_current.pro->fileName(), m_current.line); if (vr == ReturnError) return ReturnError; @@ -1918,9 +1918,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFileChecked( { if (fileName.isEmpty()) return ReturnFalse; - QMakeEvaluator *ref = this; + const QMakeEvaluator *ref = this; do { - foreach (const ProFile *pf, ref->m_profileStack) + for (const ProFile *pf : ref->m_profileStack) if (pf->fileName() == fileName) { evalError(fL1S("Circular inclusion of %1.").arg(fileName)); return ReturnFalse; @@ -2121,7 +2121,7 @@ QString QMakeEvaluator::formatValueList(const ProStringList &vals, bool commas) { QString ret; - foreach (const ProString &str, vals) { + for (const ProString &str : vals) { if (!ret.isEmpty()) { if (commas) ret += QLatin1Char(','); @@ -2136,7 +2136,7 @@ QString QMakeEvaluator::formatValueListList(const QList &lists) { QString ret; - foreach (const ProStringList &list, lists) { + for (const ProStringList &list : lists) { if (!ret.isEmpty()) ret += QLatin1String(", "); ret += formatValueList(list); diff --git a/src/shared/proparser/qmakeglobals.cpp b/src/shared/proparser/qmakeglobals.cpp index 448a27f0f58..c7bbe9c1d42 100644 --- a/src/shared/proparser/qmakeglobals.cpp +++ b/src/shared/proparser/qmakeglobals.cpp @@ -247,9 +247,9 @@ QStringList QMakeGlobals::splitPathList(const QString &val) const QStringList ret; if (!val.isEmpty()) { QDir bdir; - QStringList vals = val.split(dirlist_sep); + const QStringList vals = val.split(dirlist_sep); ret.reserve(vals.length()); - foreach (const QString &it, vals) + for (const QString &it : vals) ret << QDir::cleanPath(bdir.absoluteFilePath(it)); } return ret; -- cgit v1.2.3 From 3f4e40e3c1cbe2972f9c9413c63db477c17080fa Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Mon, 1 Feb 2016 11:49:22 +0300 Subject: qmake: use reserve to optimize memory allocation Change-Id: I6ace338512c24fd9dc11c767a28f0a63454076fa Reviewed-by: Oswald Buddenhagen (cherry picked from qtbase/1d3503b8f3b49b0f684e1caa504deb0d05f2c60a) Reviewed-by: Jake Petroules Reviewed-by: Anton Kudryavtsev --- src/shared/proparser/qmakebuiltins.cpp | 2 ++ src/shared/proparser/qmakeevaluator.cpp | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index 6a064a7ab6a..035a18493aa 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -146,6 +146,7 @@ void QMakeEvaluator::initFunctionStatics() { "shell_quote", E_SHELL_QUOTE }, { "getenv", E_GETENV }, }; + statics.expands.reserve((int)(sizeof(expandInits)/sizeof(expandInits[0]))); for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i) statics.expands.insert(ProKey(expandInits[i].name), expandInits[i].func); @@ -187,6 +188,7 @@ void QMakeEvaluator::initFunctionStatics() { "touch", T_TOUCH }, { "cache", T_CACHE }, }; + statics.functions.reserve((int)(sizeof(testInits)/sizeof(testInits[0]))); for (unsigned i = 0; i < sizeof(testInits)/sizeof(testInits[0]); ++i) statics.functions.insert(ProKey(testInits[i].name), testInits[i].func); } diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index 448139129b6..2429e099128 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -183,6 +183,7 @@ void QMakeEvaluator::initStatics() { "IN_PWD", "PWD" }, { "DEPLOYMENT", "INSTALLS" } }; + statics.varMap.reserve((int)(sizeof(mapInits)/sizeof(mapInits[0]))); for (unsigned i = 0; i < sizeof(mapInits)/sizeof(mapInits[0]); ++i) statics.varMap.insert(ProKey(mapInits[i].oldname), ProKey(mapInits[i].newname)); } @@ -760,12 +761,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProLoop( if (ok) { int end = itl.mid(dotdot+2).toInt(&ok); if (ok) { - if (m_cumulative && qAbs(end - start) > 100) { + const int absDiff = qAbs(end - start); + if (m_cumulative && absDiff > 100) { // Such a loop is unlikely to contribute something useful to the // file collection, and may cause considerable delay. traceMsg("skipping excessive loop in cumulative mode"); return ReturnFalse; } + list.reserve(absDiff + 1); if (start < end) { for (int i = start; i <= end; i++) list << ProString(QString::number(i)); -- cgit v1.2.3 From f71bc5ad9ea580261a85a2bdbffa83090f3c57a1 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Mon, 1 Feb 2016 10:42:04 +0300 Subject: qmake: optimize container usage in the json handling Iterate only once over QJsonObject, create key list by existing loop instead of create by QJsonObject::keys(), which contains internal loop. In common case if loop's statement is lightweight, then effect of optimization is significant, and vice versa. Also make addJsonArray() and addJsonObject() functions more homogeneous. Use reserve to optimize memory allocation. Change-Id: Id122cd1becfd34bb06640876b1c79e1d396d2a6b Reviewed-by: Oswald Buddenhagen (cherry picked from qtbase/69ab28031549ff1c9ceecdcb29197900e9bc4328) Reviewed-by: Jake Petroules Reviewed-by: Anton Kudryavtsev --- src/shared/proparser/qmakebuiltins.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index 035a18493aa..203597aed44 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -296,7 +296,9 @@ static void insertJsonKeyValue(const QString &key, const QStringList &values, Pr static void addJsonArray(const QJsonArray &array, const QString &keyPrefix, ProValueMap *map) { QStringList keys; - for (int i = 0; i < array.count(); ++i) { + const int size = array.count(); + keys.reserve(size); + for (int i = 0; i < size; ++i) { keys.append(QString::number(i)); addJsonValue(array.at(i), keyPrefix + QString::number(i), map); } @@ -305,10 +307,14 @@ static void addJsonArray(const QJsonArray &array, const QString &keyPrefix, ProV static void addJsonObject(const QJsonObject &object, const QString &keyPrefix, ProValueMap *map) { - for (auto it = object.begin(), end = object.end(); it != end; ++it) - addJsonValue(it.value(), keyPrefix + it.key(), map); - - insertJsonKeyValue(keyPrefix + QLatin1String("_KEYS_"), object.keys(), map); + QStringList keys; + keys.reserve(object.size()); + for (auto it = object.begin(), end = object.end(); it != end; ++it) { + const QString key = it.key(); + keys.append(key); + addJsonValue(it.value(), keyPrefix + key, map); + } + insertJsonKeyValue(keyPrefix + QLatin1String("_KEYS_"), keys, map); } static void addJsonValue(const QJsonValue &value, const QString &keyPrefix, ProValueMap *map) -- cgit v1.2.3 From 973cabd5c5c6a18f0f9d396be6c13bb0170fb843 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Mon, 8 Feb 2016 12:27:28 +0300 Subject: qmake: de-duplicate QString::number() calls with same arg Change-Id: I6e05b9ad3350bd0da5b8a6dc1389ae05315a33df Reviewed-by: Marc Mutz (cherry picked from qtbase/27de4ea4d672d9f1b3a733f803f8605f81311d0a) Reviewed-by: Anton Kudryavtsev --- src/shared/proparser/qmakebuiltins.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index 203597aed44..da860a8db85 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -299,8 +299,9 @@ static void addJsonArray(const QJsonArray &array, const QString &keyPrefix, ProV const int size = array.count(); keys.reserve(size); for (int i = 0; i < size; ++i) { - keys.append(QString::number(i)); - addJsonValue(array.at(i), keyPrefix + QString::number(i), map); + const QString number = QString::number(i); + keys.append(number); + addJsonValue(array.at(i), keyPrefix + number, map); } insertJsonKeyValue(keyPrefix + QLatin1String("_KEYS_"), keys, map); } -- cgit v1.2.3 From bf5cc934ea8fba4f3516b9f00f44db70becd5bbd Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 10 Feb 2016 15:43:15 +0100 Subject: qmake: restore nothrow move special members The user-defined copy assignment, copy constructor and dtor inhibit the move special member functions. Implement them manually. Change-Id: I0d38d7cf6c9611e13b5b081d734d01d6fe4d5276 Reviewed-by: Oswald Buddenhagen Reviewed-by: Marc Mutz (cherry picked from qtbase/9c63ad562bf0a44807f41ce49e4fe1b5ff181a63) Reviewed-by: Jake Petroules --- src/shared/proparser/proitems.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h index d6bc4fe1cbf..e1f3608f8be 100644 --- a/src/shared/proparser/proitems.h +++ b/src/shared/proparser/proitems.h @@ -360,6 +360,8 @@ class ProFunctionDef { public: ProFunctionDef(ProFile *pro, int offset) : m_pro(pro), m_offset(offset) { m_pro->ref(); } ProFunctionDef(const ProFunctionDef &o) : m_pro(o.m_pro), m_offset(o.m_offset) { m_pro->ref(); } + ProFunctionDef(ProFunctionDef &&other) Q_DECL_NOTHROW + : m_pro(other.m_pro), m_offset(other.m_offset) { other.m_pro = nullptr; } ~ProFunctionDef() { m_pro->deref(); } ProFunctionDef &operator=(const ProFunctionDef &o) { @@ -371,6 +373,18 @@ public: } return *this; } + ProFunctionDef &operator=(ProFunctionDef &&other) Q_DECL_NOTHROW + { + ProFunctionDef moved(std::move(other)); + swap(moved); + return *this; + } + void swap(ProFunctionDef &other) Q_DECL_NOTHROW + { + qSwap(m_pro, other.m_pro); + qSwap(m_offset, other.m_offset); + } + ProFile *pro() const { return m_pro; } const ushort *tokPtr() const { return m_pro->tokPtr() + m_offset; } private: -- cgit v1.2.3 From d549e8571233679a28a6708d582c9fd2621fb619 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 12 May 2016 21:15:58 +0200 Subject: optimize ProString::toInt()/toShort() QStringRef has respective overloads now. Change-Id: I9b94c53092ef3fdd62a68f5d3c5bacb98a14d8ec Reviewed-by: Joerg Bornemann (cherry picked from qtbase/e8bdca74b513b58d3db892d838b3a499365ca7e2) Reviewed-by: Jake Petroules --- src/shared/proparser/proitems.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h index e1f3608f8be..522840cfc43 100644 --- a/src/shared/proparser/proitems.h +++ b/src/shared/proparser/proitems.h @@ -126,8 +126,8 @@ public: bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(s, 0, cs) >= 0; } bool contains(const char *s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(QLatin1String(s), 0, cs) >= 0; } bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(c, 0, cs) >= 0; } - int toInt(bool *ok = 0, int base = 10) const { return toQString().toInt(ok, base); } // XXX optimize - short toShort(bool *ok = 0, int base = 10) const { return toQString().toShort(ok, base); } // XXX optimize + int toInt(bool *ok = 0, int base = 10) const { return toQStringRef().toInt(ok, base); } + short toShort(bool *ok = 0, int base = 10) const { return toQStringRef().toShort(ok, base); } uint hash() const { return m_hash; } static uint hash(const QChar *p, int n); -- cgit v1.2.3 From 5da274828aeaea10d876a16c3198a421957b62ef Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 13 May 2016 13:44:42 +0200 Subject: remove pointless conversions to QString when converting to int this doesn't change a lot, but is cleaner. Change-Id: Ia89c399d6df7cc6264954cf309d2c971a5592d6b Reviewed-by: Joerg Bornemann (cherry picked from qtbase/a7a3cd643a554c717ad8fb2bdad3e941dfd94cec) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index da860a8db85..adaa17c8d11 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -484,9 +484,9 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( } else { var = args[0]; sep = args.at(1).toQString(); - beg = args.at(2).toQString(m_tmp2).toInt(); + beg = args.at(2).toInt(); if (args.count() == 4) - end = args.at(3).toQString(m_tmp2).toInt(); + end = args.at(3).toInt(); } } else { if (args.count() != 1) { @@ -645,7 +645,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( const ProStringList &var = values(map(args.at(0))); int start = 0, end = 0; if (args.count() >= 2) { - const QString &start_str = args.at(1).toQString(m_tmp1); + const ProString &start_str = args.at(1); start = start_str.toInt(&ok); if (!ok) { if (args.count() == 2) { @@ -658,11 +658,11 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( } if (!ok) evalError(fL1S("member() argument 2 (start) '%2' invalid.") - .arg(start_str)); + .arg(start_str.toQString(m_tmp1))); } else { end = start; if (args.count() == 3) - end = args.at(2).toQString(m_tmp1).toInt(&ok); + end = args.at(2).toInt(&ok); if (!ok) evalError(fL1S("member() argument 3 (end) '%2' invalid.") .arg(args.at(2).toQString(m_tmp1))); @@ -1303,7 +1303,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( return ReturnFalse; } int cnt = values(map(args.at(0))).count(); - int val = args.at(1).toQString(m_tmp1).toInt(); + int val = args.at(1).toInt(); if (args.count() == 3) { const ProString &comp = args.at(2); if (comp == QLatin1String(">") || comp == QLatin1String("greaterThan")) { -- cgit v1.2.3 From c4382290f018ac7ad62640069c23eef223f2eea1 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 13 May 2016 13:45:48 +0200 Subject: remove pointless conversion to QString in isTrue() Change-Id: I7766672018dd4acf9b9fb89acfe664671de4bc3d Reviewed-by: Joerg Bornemann (cherry picked from qtbase/7931395d5bf30d783449e1696edf8d59b81462ed) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index adaa17c8d11..663d0c8b4b0 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -193,9 +193,8 @@ void QMakeEvaluator::initFunctionStatics() statics.functions.insert(ProKey(testInits[i].name), testInits[i].func); } -static bool isTrue(const ProString &_str, QString &tmp) +static bool isTrue(const ProString &str) { - const QString &str = _str.toQString(tmp); return !str.compare(statics.strtrue, Qt::CaseInsensitive) || str.toInt(); } @@ -910,7 +909,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( } else { bool recursive = false; if (args.count() == 2) - recursive = isTrue(args.at(1), m_tmp2); + recursive = isTrue(args.at(1)); QStringList dirs; QString r = m_option->expandEnvVars(args.at(0).toQString(m_tmp1)) .replace(QLatin1Char('\\'), QLatin1Char('/')); @@ -1414,7 +1413,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( flags = LoadSilent; if (args.count() >= 2) { parseInto = args.at(1).toQString(m_tmp2); - if (args.count() >= 3 && isTrue(args.at(2), m_tmp3)) + if (args.count() >= 3 && isTrue(args.at(2))) flags = LoadSilent; } QString fn = resolvePath(m_option->expandEnvVars(args.at(0).toQString(m_tmp1))); @@ -1452,7 +1451,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( case T_LOAD: { bool ignore_error = false; if (args.count() == 2) { - ignore_error = isTrue(args.at(1), m_tmp2); + ignore_error = isTrue(args.at(1)); } else if (args.count() != 1) { evalError(fL1S("load(feature) requires one or two arguments.")); return ReturnFalse; -- cgit v1.2.3 From ca1f4a265dab55f178d2a798f7ba08f24e55aa6b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 13 May 2016 13:42:15 +0200 Subject: add ProString::toLongLong() and make use of it this is just a bit cleaner. Change-Id: I03e628aca9e2e53c602a4db724da277a0e2c2486 Reviewed-by: Joerg Bornemann (cherry picked from qtbase/e6b755e702fd6d8ebeb25ecd7a5059e62da6c971) Reviewed-by: Jake Petroules --- src/shared/proparser/proitems.h | 1 + src/shared/proparser/qmakebuiltins.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h index 522840cfc43..e4eab85de64 100644 --- a/src/shared/proparser/proitems.h +++ b/src/shared/proparser/proitems.h @@ -126,6 +126,7 @@ public: bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(s, 0, cs) >= 0; } bool contains(const char *s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(QLatin1String(s), 0, cs) >= 0; } bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(c, 0, cs) >= 0; } + int toLongLong(bool *ok = 0, int base = 10) const { return toQStringRef().toLongLong(ok, base); } int toInt(bool *ok = 0, int base = 10) const { return toQStringRef().toInt(ok, base); } short toShort(bool *ok = 0, int base = 10) const { return toQStringRef().toShort(ok, base); } diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index 663d0c8b4b0..0dd2f099764 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -567,7 +567,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( break; } bool ok; - qlonglong num = m_tmp3.toLongLong(&ok, ibase); + qlonglong num = args.at(0).toLongLong(&ok, ibase); if (!ok) { evalError(fL1S("format_number(): malformed number %2 for base %1.") .arg(ibase).arg(m_tmp3)); -- cgit v1.2.3 From ddd749b130f44ba48a76a984a602f0e1cea60532 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 12 May 2016 17:50:17 +0200 Subject: introduce a new way to pass arbitrary arguments to the project file this is done by recognizing the -- option and putting everything that follows it into the QMAKE_EXTRA_ARGS variable. the purpose of this is being able to pass "alien" arguments (for example configure options) without having to marshal them into a qmake variable assignment manually. this is expected to greatly enhance the convenience when no wrapper script (i.e., configure itself) is used (which will be the case outside qtbase). Change-Id: I47735bdab2811d17d7d394fbf638ebd14332ea73 Reviewed-by: Lars Knoll (cherry picked from qtbase/26d44fce3dfb9dbd3b5be2a031fff8c1bb903960) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakeglobals.cpp | 11 +++++++++++ src/shared/proparser/qmakeglobals.h | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakeglobals.cpp b/src/shared/proparser/qmakeglobals.cpp index c7bbe9c1d42..f3600b33e0e 100644 --- a/src/shared/proparser/qmakeglobals.cpp +++ b/src/shared/proparser/qmakeglobals.cpp @@ -133,6 +133,11 @@ QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments( break; default: if (arg.startsWith(QLatin1Char('-'))) { + if (arg == QLatin1String("--")) { + state.extraargs = args.mid(*pos + 1); + *pos = args.size(); + return ArgumentsOk; + } if (arg == QLatin1String("-after")) state.after = true; else if (arg == QLatin1String("-config")) @@ -178,6 +183,12 @@ void QMakeGlobals::commitCommandLineArguments(QMakeCmdLineParserState &state) { if (!state.preconfigs.isEmpty()) state.precmds << (fL1S("CONFIG += ") + state.preconfigs.join(QLatin1Char(' '))); + if (!state.extraargs.isEmpty()) { + QString extra = fL1S("QMAKE_EXTRA_ARGS ="); + foreach (const QString &ea, state.extraargs) + extra += QLatin1Char(' ') + QMakeEvaluator::quoteValue(ProString(ea)); + state.precmds << extra; + } precmds = state.precmds.join(QLatin1Char('\n')); if (!state.postconfigs.isEmpty()) state.postcmds << (fL1S("CONFIG += ") + state.postconfigs.join(QLatin1Char(' '))); diff --git a/src/shared/proparser/qmakeglobals.h b/src/shared/proparser/qmakeglobals.h index c931e8e9435..9942113681b 100644 --- a/src/shared/proparser/qmakeglobals.h +++ b/src/shared/proparser/qmakeglobals.h @@ -81,7 +81,7 @@ class QMAKE_EXPORT QMakeCmdLineParserState public: QMakeCmdLineParserState(const QString &_pwd) : pwd(_pwd), after(false) {} QString pwd; - QStringList precmds, preconfigs, postcmds, postconfigs; + QStringList precmds, preconfigs, postcmds, postconfigs, extraargs; bool after; void flush() { after = false; } -- cgit v1.2.3 From 50b87b3a8d43d1dc2895c4d836a4e35cfd5ffc67 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 13 May 2016 15:21:05 +0200 Subject: add ProStringList::join(ProString) overload and make use of it Change-Id: Ic3919a1fa9419bbb3b57dd1aa7eb95643ee59e53 Reviewed-by: Joerg Bornemann (cherry picked from qtbase/e45a9fe457a4e5e70bf4e62092b253675dc97819) Reviewed-by: Jake Petroules --- src/shared/proparser/proitems.cpp | 5 +++++ src/shared/proparser/proitems.h | 1 + src/shared/proparser/qmakebuiltins.cpp | 5 ++--- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/proitems.cpp b/src/shared/proparser/proitems.cpp index 126f0371e5b..795b8b4564a 100644 --- a/src/shared/proparser/proitems.cpp +++ b/src/shared/proparser/proitems.cpp @@ -362,6 +362,11 @@ static QString ProStringList_join(const ProStringList &this_, const QChar *sep, return res; } +QString ProStringList::join(const ProString &sep) const +{ + return ProStringList_join(*this, sep.constData(), sep.size()); +} + QString ProStringList::join(const QString &sep) const { return ProStringList_join(*this, sep.constData(), sep.size()); diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h index e4eab85de64..0f59ee16f22 100644 --- a/src/shared/proparser/proitems.h +++ b/src/shared/proparser/proitems.h @@ -229,6 +229,7 @@ public: int length() const { return size(); } + QString join(const ProString &sep) const; QString join(const QString &sep) const; QString join(QChar sep) const; diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index 0dd2f099764..ed920ea8ac0 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -602,10 +602,9 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( if (args.count() < 1 || args.count() > 4) { evalError(fL1S("join(var, glue, before, after) requires one to four arguments.")); } else { - QString glue; - ProString before, after; + ProString glue, before, after; if (args.count() >= 2) - glue = args.at(1).toQString(m_tmp1); + glue = args.at(1); if (args.count() >= 3) before = args[2]; if (args.count() == 4) -- cgit v1.2.3 From b7706cdfebf9b944cccbffff285873c347389d7f Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 13 May 2016 15:32:50 +0200 Subject: make QMakeParser take a QStringRef as input the only place where this actually saves a deep copy is the evaluation of if(), but as a side effect the parser is now able to deal with not null-terminated strings, which is kinda nice as well. Change-Id: Ib6d08617aa79d2f9eaecd4906d4d548f34bf377d Reviewed-by: Joerg Bornemann Reviewed-by: Oswald Buddenhagen (cherry picked from qtbase/ad17a35853fe21a93fc34f7b2d9262c5ac992b29) Reviewed-by: Jake Petroules --- src/shared/proparser/prowriter.cpp | 2 +- src/shared/proparser/qmakebuiltins.cpp | 5 +++-- src/shared/proparser/qmakeevaluator.cpp | 6 +++--- src/shared/proparser/qmakeevaluator.h | 2 +- src/shared/proparser/qmakeparser.cpp | 36 +++++++++++++++++---------------- src/shared/proparser/qmakeparser.h | 6 +++--- 6 files changed, 30 insertions(+), 27 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/prowriter.cpp b/src/shared/proparser/prowriter.cpp index 700e134c1b6..d49c3aa8645 100644 --- a/src/shared/proparser/prowriter.cpp +++ b/src/shared/proparser/prowriter.cpp @@ -175,7 +175,7 @@ QString ProWriter::compileScope(const QString &scope) if (scope.isEmpty()) return QString(); QMakeParser parser(0, 0, 0); - ProFile *includeFile = parser.parsedProBlock(scope, QLatin1String("no-file"), 1); + ProFile *includeFile = parser.parsedProBlock(QStringRef(&scope), QLatin1String("no-file"), 1); if (!includeFile) return QString(); QString result = includeFile->items(); diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index ed920ea8ac0..ca0f7175193 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -1221,7 +1221,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( return ReturnFalse; // Another qmake breakage case T_EVAL: { VisitReturn ret = ReturnFalse; - ProFile *pro = m_parser->parsedProBlock(args.join(statics.field_sep), + QString contents = args.join(statics.field_sep); + ProFile *pro = m_parser->parsedProBlock(QStringRef(&contents), m_current.pro->fileName(), m_current.line); if (m_cumulative || pro->isOk()) { m_locationStack.push(m_current); @@ -1237,7 +1238,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( evalError(fL1S("if(condition) requires one argument.")); return ReturnFalse; } - return evaluateConditional(args.at(0).toQString(), + return evaluateConditional(args.at(0).toQStringRef(), m_current.pro->fileName(), m_current.line); } case T_CONFIG: { diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index 2429e099128..f2a71e92523 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -1288,7 +1288,7 @@ void QMakeEvaluator::setupProject() void QMakeEvaluator::evaluateCommand(const QString &cmds, const QString &where) { if (!cmds.isEmpty()) { - ProFile *pro = m_parser->parsedProBlock(cmds, where, -1); + ProFile *pro = m_parser->parsedProBlock(QStringRef(&cmds), where, -1); if (pro->isOk()) { m_locationStack.push(m_current); visitProBlock(pro, pro->tokPtr()); @@ -1780,7 +1780,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateExpandFunction( } QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditional( - const QString &cond, const QString &where, int line) + const QStringRef &cond, const QString &where, int line) { VisitReturn ret = ReturnFalse; ProFile *pro = m_parser->parsedProBlock(cond, where, line, QMakeParser::TestGrammar); @@ -1798,7 +1798,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::checkRequirements(const ProStringLis { ProStringList &failed = valuesRef(ProKey("QMAKE_FAILED_REQUIREMENTS")); for (const ProString &dep : deps) { - VisitReturn vr = evaluateConditional(dep.toQString(), m_current.pro->fileName(), m_current.line); + VisitReturn vr = evaluateConditional(dep.toQStringRef(), m_current.pro->fileName(), m_current.line); if (vr == ReturnError) return ReturnError; if (vr != ReturnTrue) diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h index 672a36b7b7a..9426445810d 100644 --- a/src/shared/proparser/qmakeevaluator.h +++ b/src/shared/proparser/qmakeevaluator.h @@ -211,7 +211,7 @@ public: ProStringList evaluateBuiltinExpand(int func_t, const ProKey &function, const ProStringList &args); VisitReturn evaluateBuiltinConditional(int func_t, const ProKey &function, const ProStringList &args); - VisitReturn evaluateConditional(const QString &cond, const QString &where, int line = -1); + VisitReturn evaluateConditional(const QStringRef &cond, const QString &where, int line = -1); #ifdef PROEVALUATOR_FULL VisitReturn checkRequirements(const ProStringList &deps); #endif diff --git a/src/shared/proparser/qmakeparser.cpp b/src/shared/proparser/qmakeparser.cpp index 777402068f5..7751265e916 100644 --- a/src/shared/proparser/qmakeparser.cpp +++ b/src/shared/proparser/qmakeparser.cpp @@ -221,7 +221,7 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags) } ProFile *QMakeParser::parsedProBlock( - const QString &contents, const QString &name, int line, SubGrammar grammar) + const QStringRef &contents, const QString &name, int line, SubGrammar grammar) { ProFile *pro = new ProFile(name); read(pro, contents, line, grammar); @@ -244,7 +244,7 @@ bool QMakeParser::read(ProFile *pro, ParseFlags flags) fL1S("Cannot read %1: %2").arg(pro->fileName(), errStr)); return false; } - read(pro, content, 1, FullGrammar); + read(pro, QStringRef(&content), 1, FullGrammar); return true; } @@ -286,7 +286,7 @@ void QMakeParser::finalizeHashStr(ushort *buf, uint len) buf[-2] = (ushort)(hash >> 16); } -void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar grammar) +void QMakeParser::read(ProFile *pro, const QStringRef &in, int line, SubGrammar grammar) { m_proFile = pro; m_lineNo = line; @@ -334,8 +334,8 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra QStack xprStack; xprStack.reserve(10); - // We rely on QStrings being null-terminated, so don't maintain a global end pointer. const ushort *cur = (const ushort *)in.unicode(); + const ushort *inend = cur + in.length(); m_canElse = false; freshLine: m_state = StNew; @@ -418,7 +418,7 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra int indent; if (context == CtxPureValue) { - end = (const ushort *)in.unicode() + in.length(); + end = inend; cptr = 0; lineCont = false; indent = 0; // just gcc being stupid @@ -430,24 +430,30 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra // First, skip leading whitespace for (indent = 0; ; ++cur, ++indent) { + if (cur == inend) { + cur = 0; + goto flushLine; + } c = *cur; if (c == '\n') { ++cur; goto flushLine; - } else if (!c) { - cur = 0; - goto flushLine; - } else if (c != ' ' && c != '\t' && c != '\r') { - break; } + if (c != ' ' && c != '\t' && c != '\r') + break; } // Then strip comments. Yep - no escaping is possible. for (cptr = cur;; ++cptr) { + if (cptr == inend) { + end = cptr; + break; + } c = *cptr; if (c == '#') { - for (end = cptr; (c = *++cptr);) { - if (c == '\n') { + end = cptr; + while (++cptr < inend) { + if (*cptr == '\n') { ++cptr; break; } @@ -460,10 +466,6 @@ void QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar gra } break; } - if (!c) { - end = cptr; - break; - } if (c == '\n') { end = cptr++; break; @@ -1215,7 +1217,7 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg bool QMakeParser::resolveVariable(ushort *xprPtr, int tlen, int needSep, ushort **ptr, ushort **buf, QString *xprBuff, ushort **tokPtr, QString *tokBuff, - const ushort *cur, const QString &in) + const ushort *cur, const QStringRef &in) { QString out; m_tmp.setRawData((const QChar *)xprPtr, tlen); diff --git a/src/shared/proparser/qmakeparser.h b/src/shared/proparser/qmakeparser.h index d44523d0248..d370d17cbba 100644 --- a/src/shared/proparser/qmakeparser.h +++ b/src/shared/proparser/qmakeparser.h @@ -83,7 +83,7 @@ public: enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar }; // fileName is expected to be absolute and cleanPath()ed. ProFile *parsedProFile(const QString &fileName, ParseFlags flags = ParseDefault); - ProFile *parsedProBlock(const QString &contents, const QString &name, int line = 0, + ProFile *parsedProBlock(const QStringRef &contents, const QString &name, int line = 0, SubGrammar grammar = FullGrammar); void discardFileFromCache(const QString &fileName); @@ -126,7 +126,7 @@ private: }; bool read(ProFile *pro, ParseFlags flags); - void read(ProFile *pro, const QString &content, int line, SubGrammar grammar); + void read(ProFile *pro, const QStringRef &content, int line, SubGrammar grammar); ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok); ALWAYS_INLINE void putBlockLen(ushort *&tokPtr, uint len); @@ -137,7 +137,7 @@ private: ALWAYS_INLINE bool resolveVariable(ushort *xprPtr, int tlen, int needSep, ushort **ptr, ushort **buf, QString *xprBuff, ushort **tokPtr, QString *tokBuff, - const ushort *cur, const QString &in); + const ushort *cur, const QStringRef &in); void finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr, int wordCount); void finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int argc); void warnOperator(const char *msg); -- cgit v1.2.3 From 1d8ae55a570217f424e5a1c314c4a6898c33c048 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 13 May 2016 15:40:00 +0200 Subject: make split_value_list() take a QStringRef as input this also saves some of the cheap but ugly toQString() calls. Change-Id: Iebe644986501db3878306521c76e4ba2c2fb97b4 Reviewed-by: Joerg Bornemann (cherry picked from qtbase/981f8ad2e4bc46d9a06dab0cbc32a7da755ececb) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 18 ++++++++++-------- src/shared/proparser/qmakeevaluator.cpp | 2 +- src/shared/proparser/qmakeevaluator.h | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index ca0f7175193..b89f8793f9f 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -538,7 +538,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( bool leftalign = false; enum { DefaultSign, PadSign, AlwaysSign } sign = DefaultSign; if (args.count() >= 2) { - const auto opts = split_value_list(args.at(1).toQString(m_tmp2)); + const auto opts = split_value_list(args.at(1).toQStringRef()); for (const ProString &opt : opts) { opt.toQString(m_tmp3); if (m_tmp3.startsWith(QLatin1String("ibase="))) { @@ -732,7 +732,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( if (lines) { ret += ProString(stream.readLine()); } else { - ret += split_value_list(stream.readLine().trimmed()); + const QString &line = stream.readLine(); + ret += split_value_list(QStringRef(&line).trimmed()); if (!singleLine) ret += ProString("\n"); } @@ -764,7 +765,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( ret = ProStringList(ProString(tmp)); ProStringList lst; for (const ProString &arg : args) - lst += split_value_list(arg.toQString(m_tmp1), arg.sourceFile()); // Relies on deep copy + lst += split_value_list(arg.toQStringRef(), arg.sourceFile()); // Relies on deep copy m_valuemapStack.top()[ret.at(0).toKey()] = lst; break; } case E_FIND: @@ -811,7 +812,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( output.replace(QLatin1Char('\t'), QLatin1Char(' ')); if (singleLine) output.replace(QLatin1Char('\n'), QLatin1Char(' ')); - ret += split_value_list(output); + ret += split_value_list(QStringRef(&output)); } } } @@ -960,7 +961,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( QFile qfile; if (qfile.open(stdin, QIODevice::ReadOnly)) { QTextStream t(&qfile); - ret = split_value_list(t.readLine()); + const QString &line = t.readLine(); + ret = split_value_list(QStringRef(&line)); } } break; } @@ -994,7 +996,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( ProString priosfx = args.count() < 4 ? ProString(".priority") : args.at(3); populateDeps(orgList, prefix, args.count() < 3 ? ProStringList(ProString(".depends")) - : split_value_list(args.at(2).toQString(m_tmp2)), + : split_value_list(args.at(2).toQStringRef()), priosfx, dependencies, dependees, rootSet); while (!rootSet.isEmpty()) { QMultiMap::iterator it = rootSet.begin(); @@ -1585,7 +1587,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( if (!vals.isEmpty()) contents = vals.join(QLatin1Char('\n')) + QLatin1Char('\n'); if (args.count() >= 3) { - const auto opts = split_value_list(args.at(2).toQString(m_tmp2)); + const auto opts = split_value_list(args.at(2).toQStringRef()); for (const ProString &opt : opts) { opt.toQString(m_tmp3); if (m_tmp3 == QLatin1String("append")) { @@ -1658,7 +1660,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( enum { CacheSet, CacheAdd, CacheSub } mode = CacheSet; ProKey srcvar; if (args.count() >= 2) { - const auto opts = split_value_list(args.at(1).toQString(m_tmp2)); + const auto opts = split_value_list(args.at(1).toQStringRef()); for (const ProString &opt : opts) { opt.toQString(m_tmp3); if (m_tmp3 == QLatin1String("transient")) { diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index f2a71e92523..7d43610a31c 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -267,7 +267,7 @@ void QMakeEvaluator::skipHashStr(const ushort *&tokPtr) // FIXME: this should not build new strings for direct sections. // Note that the E_SPRINTF and E_LIST implementations rely on the deep copy. -ProStringList QMakeEvaluator::split_value_list(const QString &vals, const ProFile *source) +ProStringList QMakeEvaluator::split_value_list(const QStringRef &vals, const ProFile *source) { QString build; ProStringList ret; diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h index 9426445810d..f0aab5f4bf7 100644 --- a/src/shared/proparser/qmakeevaluator.h +++ b/src/shared/proparser/qmakeevaluator.h @@ -172,7 +172,7 @@ public: void setTemplate(); - ProStringList split_value_list(const QString &vals, const ProFile *source = 0); + ProStringList split_value_list(const QStringRef &vals, const ProFile *source = 0); VisitReturn expandVariableReferences(const ushort *&tokPtr, int sizeHint, ProStringList *ret, bool joined); QString currentFileName() const; -- cgit v1.2.3 From 5237499742b105a884cd2e08129a896bea382766 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 12 May 2016 20:38:54 +0200 Subject: add $$take_first() and $$take_last() functions while implementing stacks and queues was possible before with the help of $$member(), these functions make it much more straight-forward. [ChangeLog][qmake] Added $$take_first() and $$take_last() functions. Change-Id: I4922a5331780e468a42c663c9ad3c6456a95a6bf Reviewed-by: Leena Miettinen Reviewed-by: Joerg Bornemann Reviewed-by: Lars Knoll (cherry picked from qtbase/3d21634fb693634b7d41a152287d29afb80ac5e2) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index b89f8793f9f..e09a5600159 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -81,7 +81,8 @@ QT_BEGIN_NAMESPACE #define fL1S(s) QString::fromLatin1(s) enum ExpandFunc { - E_INVALID = 0, E_MEMBER, E_FIRST, E_LAST, E_SIZE, E_CAT, E_FROMFILE, E_EVAL, E_LIST, + E_INVALID = 0, E_MEMBER, E_FIRST, E_TAKE_FIRST, E_LAST, E_TAKE_LAST, E_SIZE, + E_CAT, E_FROMFILE, E_EVAL, E_LIST, E_SPRINTF, E_FORMAT_NUMBER, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, E_FIND, E_SYSTEM, E_UNIQUE, E_REVERSE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_TITLE, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, @@ -106,7 +107,9 @@ void QMakeEvaluator::initFunctionStatics() } expandInits[] = { { "member", E_MEMBER }, { "first", E_FIRST }, + { "take_first", E_TAKE_FIRST }, { "last", E_LAST }, + { "take_last", E_TAKE_LAST }, { "size", E_SIZE }, { "cat", E_CAT }, { "fromfile", E_FROMFILE }, @@ -697,6 +700,20 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( } } break; + case E_TAKE_FIRST: + case E_TAKE_LAST: + if (args.count() != 1) { + evalError(fL1S("%1(var) requires one argument.").arg(func.toQString(m_tmp1))); + } else { + ProStringList &var = valuesRef(map(args.at(0))); + if (!var.isEmpty()) { + if (func_t == E_TAKE_FIRST) + ret.append(var.takeFirst()); + else + ret.append(var.takeLast()); + } + } + break; case E_SIZE: if (args.count() != 1) evalError(fL1S("size(var) requires one argument.")); -- cgit v1.2.3 From 455cc5a9f835067fe54ebc430835c1da5624a7cf Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 13 May 2016 13:31:14 +0200 Subject: add $$num_add() (numeric addition) function amazing how we managed to do without it for so long. ^^ the name is intentionally somewhat obscure to avoid clashes, and some namespacing is good anyway. [ChangeLog][qmake] Added $$num_add() function. Change-Id: Ib7648b1f425ef096a87b51f158d0f1409e5c4daa Reviewed-by: Leena Miettinen Reviewed-by: Lars Knoll Reviewed-by: Joerg Bornemann (cherry picked from qtbase/d3cc25ef52d0b2b7ba1cb06609f7c205ee19c2d6) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index e09a5600159..296caad9731 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -82,8 +82,8 @@ QT_BEGIN_NAMESPACE enum ExpandFunc { E_INVALID = 0, E_MEMBER, E_FIRST, E_TAKE_FIRST, E_LAST, E_TAKE_LAST, E_SIZE, - E_CAT, E_FROMFILE, E_EVAL, E_LIST, - E_SPRINTF, E_FORMAT_NUMBER, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, + E_CAT, E_FROMFILE, E_EVAL, E_LIST, E_SPRINTF, E_FORMAT_NUMBER, + E_NUM_ADD, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, E_FIND, E_SYSTEM, E_UNIQUE, E_REVERSE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_TITLE, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, E_REPLACE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS, @@ -117,6 +117,7 @@ void QMakeEvaluator::initFunctionStatics() { "list", E_LIST }, { "sprintf", E_SPRINTF }, { "format_number", E_FORMAT_NUMBER }, + { "num_add", E_NUM_ADD }, { "join", E_JOIN }, { "split", E_SPLIT }, { "basename", E_BASENAME }, @@ -601,6 +602,29 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( } formfail: break; + case E_NUM_ADD: + if (args.count() < 1 || args.at(0).isEmpty()) { + evalError(fL1S("num_add(num, ...) requires at least one argument.")); + } else { + qlonglong sum = 0; + foreach (const ProString &arg, args) { + if (arg.contains(QLatin1Char('.'))) { + evalError(fL1S("num_add(): floats are currently not supported.")); + goto nafail; + } + bool ok; + qlonglong num = arg.toLongLong(&ok); + if (!ok) { + evalError(fL1S("num_add(): malformed number %1.") + .arg(arg.toQString(m_tmp3))); + goto nafail; + } + sum += num; + } + ret += ProString(QString::number(sum)); + } + nafail: + break; case E_JOIN: { if (args.count() < 1 || args.count() > 4) { evalError(fL1S("join(var, glue, before, after) requires one to four arguments.")); -- cgit v1.2.3 From 8f7928e6163ad1f1d407a69079c723705cf48498 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 13 May 2016 15:58:20 +0200 Subject: add $$str_size() function this is strlen(), but the name is matched to $$size(), just namespaced to reflect that it operates on a string value rather than a list variable. [ChangeLog][qmake] Added $$str_size() function. Change-Id: I56c8b863da244e66bd283257a66b197aa73b0e57 Reviewed-by: Leena Miettinen Reviewed-by: Joerg Bornemann Reviewed-by: Lars Knoll (cherry picked from qtbase/22f3800cac47b1b3d10474e8489ddb83cffd4b1e) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index 296caad9731..ac4a20b316f 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -81,8 +81,8 @@ QT_BEGIN_NAMESPACE #define fL1S(s) QString::fromLatin1(s) enum ExpandFunc { - E_INVALID = 0, E_MEMBER, E_FIRST, E_TAKE_FIRST, E_LAST, E_TAKE_LAST, E_SIZE, - E_CAT, E_FROMFILE, E_EVAL, E_LIST, E_SPRINTF, E_FORMAT_NUMBER, + E_INVALID = 0, E_MEMBER, E_FIRST, E_TAKE_FIRST, E_LAST, E_TAKE_LAST, + E_SIZE, E_STR_SIZE, E_CAT, E_FROMFILE, E_EVAL, E_LIST, E_SPRINTF, E_FORMAT_NUMBER, E_NUM_ADD, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, E_FIND, E_SYSTEM, E_UNIQUE, E_REVERSE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_TITLE, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, @@ -111,6 +111,7 @@ void QMakeEvaluator::initFunctionStatics() { "last", E_LAST }, { "take_last", E_TAKE_LAST }, { "size", E_SIZE }, + { "str_size", E_STR_SIZE }, { "cat", E_CAT }, { "fromfile", E_FROMFILE }, { "eval", E_EVAL }, @@ -744,6 +745,12 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( else ret.append(ProString(QString::number(values(map(args.at(0))).size()))); break; + case E_STR_SIZE: + if (args.count() != 1) + evalError(fL1S("str_size(str) requires one argument.")); + else + ret.append(ProString(QString::number(args.at(0).size()))); + break; case E_CAT: if (args.count() < 1 || args.count() > 2) { evalError(fL1S("cat(file, singleline=true) requires one or two arguments.")); -- cgit v1.2.3 From f174dfee6ad18ef72e349c75619b5ea85ceb1b9c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 18 May 2016 16:35:01 +0200 Subject: add $$str_member() function just like $$member(), but operates on a string value rather than a list variable. it is the swiss army knife of cutting, providing equivalents of left(), right(), mid() and reverse() all in one. [ChangeLog][qmake] Added $$str_member() function. Change-Id: I7c7c6c971db402fff41b428d32a4451f45400728 Reviewed-by: Leena Miettinen Reviewed-by: Joerg Bornemann Reviewed-by: Lars Knoll (cherry picked from qtbase/e70330f99e53bd34a518879a0a4c68bc7cb03949) Reviewed-by: Jake Petroules --- src/shared/proparser/qmakebuiltins.cpp | 108 ++++++++++++++++++++++----------- src/shared/proparser/qmakeevaluator.h | 3 + 2 files changed, 74 insertions(+), 37 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index ac4a20b316f..f8953b44adc 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -81,7 +81,7 @@ QT_BEGIN_NAMESPACE #define fL1S(s) QString::fromLatin1(s) enum ExpandFunc { - E_INVALID = 0, E_MEMBER, E_FIRST, E_TAKE_FIRST, E_LAST, E_TAKE_LAST, + E_INVALID = 0, E_MEMBER, E_STR_MEMBER, E_FIRST, E_TAKE_FIRST, E_LAST, E_TAKE_LAST, E_SIZE, E_STR_SIZE, E_CAT, E_FROMFILE, E_EVAL, E_LIST, E_SPRINTF, E_FORMAT_NUMBER, E_NUM_ADD, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, E_FIND, E_SYSTEM, E_UNIQUE, E_REVERSE, E_QUOTE, E_ESCAPE_EXPAND, @@ -106,6 +106,7 @@ void QMakeEvaluator::initFunctionStatics() const ExpandFunc func; } expandInits[] = { { "member", E_MEMBER }, + { "str_member", E_STR_MEMBER }, { "first", E_FIRST }, { "take_first", E_TAKE_FIRST }, { "last", E_LAST }, @@ -203,6 +204,49 @@ static bool isTrue(const ProString &str) return !str.compare(statics.strtrue, Qt::CaseInsensitive) || str.toInt(); } +bool +QMakeEvaluator::getMemberArgs(const ProKey &func, int srclen, const ProStringList &args, + int *start, int *end) +{ + *start = 0, *end = 0; + if (args.count() >= 2) { + bool ok = true; + const ProString &start_str = args.at(1); + *start = start_str.toInt(&ok); + if (!ok) { + if (args.count() == 2) { + int dotdot = start_str.indexOf(statics.strDotDot); + if (dotdot != -1) { + *start = start_str.left(dotdot).toInt(&ok); + if (ok) + *end = start_str.mid(dotdot+2).toInt(&ok); + } + } + if (!ok) { + evalError(fL1S("%1() argument 2 (start) '%2' invalid.") + .arg(func.toQString(m_tmp1), start_str.toQString(m_tmp2))); + return false; + } + } else { + *end = *start; + if (args.count() == 3) + *end = args.at(2).toInt(&ok); + if (!ok) { + evalError(fL1S("%1() argument 3 (end) '%2' invalid.") + .arg(func.toQString(m_tmp1), args.at(2).toQString(m_tmp2))); + return false; + } + } + } + if (*start < 0) + *start += srclen; + if (*end < 0) + *end += srclen; + if (*start < 0 || *start >= srclen || *end < 0 || *end >= srclen) + return false; + return true; +} + #if defined(Q_OS_WIN) && defined(PROEVALUATOR_FULL) static QString windowsErrorCode() { @@ -667,47 +711,37 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( if (args.count() < 1 || args.count() > 3) { evalError(fL1S("member(var, start, end) requires one to three arguments.")); } else { - bool ok = true; - const ProStringList &var = values(map(args.at(0))); - int start = 0, end = 0; - if (args.count() >= 2) { - const ProString &start_str = args.at(1); - start = start_str.toInt(&ok); - if (!ok) { - if (args.count() == 2) { - int dotdot = start_str.indexOf(statics.strDotDot); - if (dotdot != -1) { - start = start_str.left(dotdot).toInt(&ok); - if (ok) - end = start_str.mid(dotdot+2).toInt(&ok); - } - } - if (!ok) - evalError(fL1S("member() argument 2 (start) '%2' invalid.") - .arg(start_str.toQString(m_tmp1))); + const ProStringList &src = values(map(args.at(0))); + int start, end; + if (getMemberArgs(func, src.size(), args, &start, &end)) { + ret.reserve(qAbs(end - start) + 1); + if (start < end) { + for (int i = start; i <= end && src.size() >= i; i++) + ret += src.at(i); } else { - end = start; - if (args.count() == 3) - end = args.at(2).toInt(&ok); - if (!ok) - evalError(fL1S("member() argument 3 (end) '%2' invalid.") - .arg(args.at(2).toQString(m_tmp1))); + for (int i = start; i >= end && src.size() >= i && i >= 0; i--) + ret += src.at(i); } } - if (ok) { - if (start < 0) - start += var.count(); - if (end < 0) - end += var.count(); - if (start < 0 || start >= var.count() || end < 0 || end >= var.count()) { - //nothing - } else if (start < end) { - for (int i = start; i <= end && var.count() >= i; i++) - ret.append(var[i]); + } + break; + case E_STR_MEMBER: + if (args.count() < 1 || args.count() > 3) { + evalError(fL1S("str_member(str, start, end) requires one to three arguments.")); + } else { + const ProString &src = args.at(0); + int start, end; + if (getMemberArgs(func, src.size(), args, &start, &end)) { + QString res; + res.reserve(qAbs(end - start) + 1); + if (start < end) { + for (int i = start; i <= end && src.size() >= i; i++) + res += src.at(i); } else { - for (int i = start; i >= end && var.count() >= i && i >= 0; i--) - ret += var[i]; + for (int i = start; i >= end && src.size() >= i && i >= 0; i--) + res += src.at(i); } + ret += ProString(res); } } break; diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h index f0aab5f4bf7..3f24414f2c3 100644 --- a/src/shared/proparser/qmakeevaluator.h +++ b/src/shared/proparser/qmakeevaluator.h @@ -227,6 +227,9 @@ public: QHash > &dependencies, ProValueMap &dependees, QMultiMap &rootSet) const; + bool getMemberArgs(const ProKey &name, int srclen, const ProStringList &args, + int *start, int *end); + VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, bool exe, const QString &contents); #ifndef QT_BOOTSTRAPPED -- cgit v1.2.3 From 962d1122bbb580cbc0e1a498db535a776c884b11 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 13 May 2016 16:53:01 +0200 Subject: add $$sorted() function [ChangeLog][qmake] Added $$sorted() function. Change-Id: Ic069d3ef7c0b7a260c714c76eecc71c41417d01f Reviewed-by: Leena Miettinen Reviewed-by: Joerg Bornemann Reviewed-by: Lars Knoll Reviewed-by: Martin Smith (cherry picked from qtbase/50e22c765343102c4e0acf1eee8a6ce6f6f39ccf) Reviewed-by: Jake Petroules --- src/shared/proparser/proitems.h | 1 + src/shared/proparser/qmakebuiltins.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h index 0f59ee16f22..31e662bcf06 100644 --- a/src/shared/proparser/proitems.h +++ b/src/shared/proparser/proitems.h @@ -96,6 +96,7 @@ public: bool operator!=(const QString &other) const { return !(*this == other); } bool operator!=(QLatin1String other) const { return !(*this == other); } bool operator!=(const char *other) const { return !(*this == other); } + bool operator<(const ProString &other) const { return toQStringRef() < other.toQStringRef(); } bool isNull() const { return m_string.isNull(); } bool isEmpty() const { return !m_length; } int length() const { return m_length; } diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index f8953b44adc..8a8bc70acdf 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -84,7 +84,7 @@ enum ExpandFunc { E_INVALID = 0, E_MEMBER, E_STR_MEMBER, E_FIRST, E_TAKE_FIRST, E_LAST, E_TAKE_LAST, E_SIZE, E_STR_SIZE, E_CAT, E_FROMFILE, E_EVAL, E_LIST, E_SPRINTF, E_FORMAT_NUMBER, E_NUM_ADD, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, - E_FIND, E_SYSTEM, E_UNIQUE, E_REVERSE, E_QUOTE, E_ESCAPE_EXPAND, + E_FIND, E_SYSTEM, E_UNIQUE, E_SORTED, E_REVERSE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_TITLE, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, E_REPLACE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS, E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH, @@ -128,6 +128,7 @@ void QMakeEvaluator::initFunctionStatics() { "find", E_FIND }, { "system", E_SYSTEM }, { "unique", E_UNIQUE }, + { "sorted", E_SORTED }, { "reverse", E_REVERSE }, { "quote", E_QUOTE }, { "escape_expand", E_ESCAPE_EXPAND }, @@ -908,6 +909,14 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( ret.removeDuplicates(); } break; + case E_SORTED: + if (args.count() != 1) { + evalError(fL1S("sorted(var) requires one argument.")); + } else { + ret = values(map(args.at(0))); + std::sort(ret.begin(), ret.end()); + } + break; case E_REVERSE: if (args.count() != 1) { evalError(fL1S("reverse(var) requires one argument.")); -- cgit v1.2.3 From 61e7ac7ceee19b08dcb44a18bfa9b39a386df799 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 19 May 2016 15:40:55 +0200 Subject: Improve error reporting when parsing JSON files At least report the error string and the file offset where the error happened. Change-Id: Iaa1733593b8af2a7a52b67c0f495731f045d2c11 Reviewed-by: Oswald Buddenhagen (cherry picked from qtbase/34c24ceb1ffce964c9f139d84b6b271bd2e45c33) Reviewed-by: Jake Petroules Reviewed-by: Robert Loehning --- src/shared/proparser/qmakebuiltins.cpp | 11 ++++++++--- src/shared/proparser/qmakeevaluator.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src/shared/proparser') diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index 8a8bc70acdf..734ef0165a0 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -390,11 +390,16 @@ static void addJsonValue(const QJsonValue &value, const QString &keyPrefix, ProV } } -static QMakeEvaluator::VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value) +QMakeEvaluator::VisitReturn QMakeEvaluator::parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value) { - QJsonDocument document = QJsonDocument::fromJson(json); - if (document.isNull()) + QJsonParseError error; + QJsonDocument document = QJsonDocument::fromJson(json, &error); + if (document.isNull()) { + if (error.error != QJsonParseError::NoError) + evalError(fL1S("Error parsing json at offset %1: %2") + .arg(error.offset).arg(error.errorString())); return QMakeEvaluator::ReturnFalse; + } QString currentKey = into + QLatin1Char('.'); diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h index 3f24414f2c3..e9cff77c67e 100644 --- a/src/shared/proparser/qmakeevaluator.h +++ b/src/shared/proparser/qmakeevaluator.h @@ -229,6 +229,7 @@ public: bool getMemberArgs(const ProKey &name, int srclen, const ProStringList &args, int *start, int *end); + VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value); VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, bool exe, const QString &contents); -- cgit v1.2.3