diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index 9aeb7df1cc4..01899b1a511 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -102,10 +102,9 @@ void QMakeEvaluator::initStatics() initFunctionStatics(); static const char * const names[] = { - "LITERAL_DOLLAR", "LITERAL_HASH", "LITERAL_WHITESPACE", "DIRLIST_SEPARATOR", "DIR_SEPARATOR", "OUT_PWD", "PWD", - "_FILE_", "_LINE_", "_PRO_FILE_", "_PRO_FILE_PWD_", + "_PRO_FILE_", "_PRO_FILE_PWD_", "QMAKE_HOST.arch", "QMAKE_HOST.name", "QMAKE_HOST.os", "QMAKE_HOST.version", "QMAKE_HOST.version_string", "_DATE_", "_QMAKE_CACHE_" @@ -1755,9 +1754,6 @@ ProStringList QMakeEvaluator::values(const ProString &variableName) const int vlidx = *vli; QString ret; switch ((VarName)vlidx) { - case V_LITERAL_WHITESPACE: ret = QLatin1String("\t"); break; - case V_LITERAL_DOLLAR: ret = QLatin1String("$"); break; - case V_LITERAL_HASH: ret = QLatin1String("#"); break; case V_OUT_PWD: // the outgoing dir (shadow of _PRO_FILE_PWD_) ret = m_outputDir; break; @@ -1771,12 +1767,6 @@ ProStringList QMakeEvaluator::values(const ProString &variableName) const case V_DIRLIST_SEPARATOR: ret = m_option->dirlist_sep; break; - case V__LINE_: // currently executed line number - ret = QString::number(m_current.line); - break; - case V__FILE_: // currently executed file - ret = m_current.pro->fileName(); - break; case V__DATE_: //current date/time ret = QDateTime::currentDateTime().toString(); break; diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h index 0757f42543f..1724d7d0028 100644 --- a/src/shared/proparser/qmakeevaluator.h +++ b/src/shared/proparser/qmakeevaluator.h @@ -203,10 +203,9 @@ public: QMakeHandler *m_handler; enum VarName { - V_LITERAL_DOLLAR, V_LITERAL_HASH, V_LITERAL_WHITESPACE, V_DIRLIST_SEPARATOR, V_DIR_SEPARATOR, V_OUT_PWD, V_PWD, - V__FILE_, V__LINE_, V__PRO_FILE_, V__PRO_FILE_PWD_, + V__PRO_FILE_, V__PRO_FILE_PWD_, V_QMAKE_HOST_arch, V_QMAKE_HOST_name, V_QMAKE_HOST_os, V_QMAKE_HOST_version, V_QMAKE_HOST_version_string, V__DATE_, V__QMAKE_CACHE_ diff --git a/src/shared/proparser/qmakeparser.cpp b/src/shared/proparser/qmakeparser.cpp index 0f30492d147..9f45eca9fab 100644 --- a/src/shared/proparser/qmakeparser.cpp +++ b/src/shared/proparser/qmakeparser.cpp @@ -98,6 +98,11 @@ static struct { QString strfor; QString strdefineTest; QString strdefineReplace; + QString strLINE; + QString strFILE; + QString strLITERAL_HASH; + QString strLITERAL_DOLLAR; + QString strLITERAL_WHITESPACE; } statics; } @@ -111,6 +116,11 @@ void QMakeParser::initialize() statics.strfor = QLatin1String("for"); statics.strdefineTest = QLatin1String("defineTest"); statics.strdefineReplace = QLatin1String("defineReplace"); + statics.strLINE = QLatin1String("_LINE_"); + statics.strFILE = QLatin1String("_FILE_"); + statics.strLITERAL_HASH = QLatin1String("LITERAL_HASH"); + statics.strLITERAL_DOLLAR = QLatin1String("LITERAL_DOLLAR"); + statics.strLITERAL_WHITESPACE = QLatin1String("LITERAL_WHITESPACE"); } QMakeParser::QMakeParser(ProFileCache *cache, QMakeParserHandler *handler) @@ -268,7 +278,7 @@ bool QMakeParser::read(ProFile *pro, const QString &in) // Expression precompiler buffer. QString xprBuff; xprBuff.reserve(tokBuff.capacity()); // Excessive, but simple - ushort * const buf = (ushort *)xprBuff.constData(); + ushort *buf = (ushort *)xprBuff.constData(); // Parser state m_blockstack.clear(); @@ -480,14 +490,18 @@ bool QMakeParser::read(ProFile *pro, const QString &in) } tlen = ptr - xprPtr; if (rtok == TokVariable) { - xprPtr[-4] = tok; - uint hash = ProString::hash((const QChar *)xprPtr, tlen); - xprPtr[-3] = (ushort)hash; - xprPtr[-2] = (ushort)(hash >> 16); + if (!resolveVariable(xprPtr, tlen, needSep, &ptr, + &buf, &xprBuff, &tokPtr, &tokBuff, cur, in)) { + xprPtr[-4] = tok; + uint hash = ProString::hash((const QChar *)xprPtr, tlen); + xprPtr[-3] = (ushort)hash; + xprPtr[-2] = (ushort)(hash >> 16); + xprPtr[-1] = tlen; + } } else { xprPtr[-2] = tok; + xprPtr[-1] = tlen; } - xprPtr[-1] = tlen; if ((tok & TokMask) == TokFuncName) { cur++; funcCall: @@ -1017,6 +1031,57 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg putBlock(tokPtr, uc, ptr - uc); } +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) +{ + QString out; + m_tmp.setRawData((const QChar *)xprPtr, tlen); + if (m_tmp == statics.strLINE) { + out.setNum(m_lineNo); + } else if (m_tmp == statics.strFILE) { + out = m_proFile->fileName(); + // The string is typically longer than the variable reference, so we need + // to ensure that there is enough space in the output buffer - as unlikely + // as an overflow is to actually happen in practice. + int need = (in.length() - (cur - (const ushort *)in.constData()) + 2) * 5 + out.length(); + int tused = *tokPtr - (ushort *)tokBuff->constData(); + int xused; + int total; + bool ptrFinal = xprPtr >= (ushort *)tokBuff->constData() + && xprPtr < (ushort *)tokBuff->constData() + tokBuff->capacity(); + if (ptrFinal) { + xused = xprPtr - (ushort *)tokBuff->constData(); + total = xused + need; + } else { + xused = xprPtr - *buf; + total = tused + xused + need; + } + if (tokBuff->capacity() < total) { + tokBuff->reserve(total); + *tokPtr = (ushort *)tokBuff->constData() + tused; + xprBuff->reserve(total); + *buf = (ushort *)xprBuff->constData(); + xprPtr = (ptrFinal ? (ushort *)tokBuff->constData() : *buf) + xused; + } + } else if (m_tmp == statics.strLITERAL_HASH) { + out = QLatin1String("#"); + } else if (m_tmp == statics.strLITERAL_DOLLAR) { + out = QLatin1String("$"); + } else if (m_tmp == statics.strLITERAL_WHITESPACE) { + out = QLatin1String("\t"); + } else { + return false; + } + xprPtr -= 2; // Was set up for variable reference + xprPtr[-2] = TokLiteral | needSep; + xprPtr[-1] = out.length(); + memcpy(xprPtr, out.constData(), out.length() * 2); + *ptr = xprPtr + out.length(); + return true; +} + void QMakeParser::parseError(const QString &msg) const { if (!m_inError && m_handler) diff --git a/src/shared/proparser/qmakeparser.h b/src/shared/proparser/qmakeparser.h index b0e54627e90..b5d36d1da40 100644 --- a/src/shared/proparser/qmakeparser.h +++ b/src/shared/proparser/qmakeparser.h @@ -102,6 +102,10 @@ private: void putHashStr(ushort *&pTokPtr, const ushort *buf, uint len); void finalizeHashStr(ushort *buf, uint len); void putLineMarker(ushort *&tokPtr); + 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); void finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr, int wordCount); void finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int argc); void finalizeTest(ushort *&tokPtr);