resolve some variables already at parse time

they are "compiler defines", with no dependency on the evaluation context.

Change-Id: I25bf006347ecd2edb501a344820e2ac11ff389e9
Reviewed-by: Daniel Teske <daniel.teske@nokia.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
This commit is contained in:
Oswald Buddenhagen
2012-05-07 16:20:30 +02:00
parent a0bc0cb990
commit 55cad4a424
4 changed files with 77 additions and 19 deletions

View File

@@ -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;

View File

@@ -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_

View File

@@ -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)

View File

@@ -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);