forked from qt-creator/qt-creator
implement if() by means of precompilation
the performance is about the same (depending on the expression type it's better or worse), but a lot of code just disappears. Change-Id: I60eb9b87f23cc811d3f9577841c38966ecfd8e43 Reviewed-by: Daniel Teske <daniel.teske@nokia.com> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
This commit is contained in:
@@ -293,8 +293,13 @@ void QMakeEvaluator::populateDeps(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ProStringList QMakeEvaluator::evaluateExpandFunction(
|
ProStringList QMakeEvaluator::evaluateExpandFunction(
|
||||||
const ProString &func, const ProStringList &args)
|
const ProString &func, const ushort *&tokPtr)
|
||||||
{
|
{
|
||||||
|
QHash<ProString, ProFunctionDef>::ConstIterator it =
|
||||||
|
m_functionDefs.replaceFunctions.constFind(func);
|
||||||
|
if (it != m_functionDefs.replaceFunctions.constEnd())
|
||||||
|
return evaluateFunction(*it, prepareFunctionArgs(tokPtr), 0);
|
||||||
|
|
||||||
ExpandFunc func_t = ExpandFunc(statics.expands.value(func));
|
ExpandFunc func_t = ExpandFunc(statics.expands.value(func));
|
||||||
if (func_t == 0) {
|
if (func_t == 0) {
|
||||||
const QString &fn = func.toQString(m_tmp1);
|
const QString &fn = func.toQString(m_tmp1);
|
||||||
@@ -306,6 +311,8 @@ ProStringList QMakeEvaluator::evaluateExpandFunction(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//why don't the builtin functions just use args_list? --Sam
|
||||||
|
const ProStringList &args = expandVariableReferences(tokPtr, 5, true);
|
||||||
ProStringList ret;
|
ProStringList ret;
|
||||||
|
|
||||||
switch (func_t) {
|
switch (func_t) {
|
||||||
@@ -924,10 +931,18 @@ ProStringList QMakeEvaluator::evaluateExpandFunction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
|
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
|
||||||
const ProString &function, const ProStringList &args)
|
const ProString &function, const ushort *&tokPtr)
|
||||||
{
|
{
|
||||||
|
QHash<ProString, ProFunctionDef>::ConstIterator it =
|
||||||
|
m_functionDefs.testFunctions.constFind(function);
|
||||||
|
if (it != m_functionDefs.testFunctions.constEnd())
|
||||||
|
return evaluateBoolFunction(*it, prepareFunctionArgs(tokPtr), function);
|
||||||
|
|
||||||
TestFunc func_t = (TestFunc)statics.functions.value(function);
|
TestFunc func_t = (TestFunc)statics.functions.value(function);
|
||||||
|
|
||||||
|
//why don't the builtin functions just use args_list? --Sam
|
||||||
|
const ProStringList &args = expandVariableReferences(tokPtr, 5, true);
|
||||||
|
|
||||||
switch (func_t) {
|
switch (func_t) {
|
||||||
case T_DEFINED:
|
case T_DEFINED:
|
||||||
if (args.count() < 1 || args.count() > 2) {
|
if (args.count() < 1 || args.count() > 2) {
|
||||||
@@ -1047,67 +1062,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
|
|||||||
evalError(fL1S("if(condition) requires one argument."));
|
evalError(fL1S("if(condition) requires one argument."));
|
||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
}
|
}
|
||||||
const ProString &cond = args.at(0);
|
return returnBool(evaluateConditional(args.at(0).toQString(), fL1S("(if)")));
|
||||||
bool quoted = false;
|
|
||||||
bool ret = true;
|
|
||||||
bool orOp = false;
|
|
||||||
bool invert = false;
|
|
||||||
bool isFunc = false;
|
|
||||||
int parens = 0;
|
|
||||||
QString test;
|
|
||||||
test.reserve(20);
|
|
||||||
QString argsString;
|
|
||||||
argsString.reserve(50);
|
|
||||||
const QChar *d = cond.constData();
|
|
||||||
const QChar *ed = d + cond.size();
|
|
||||||
while (d < ed) {
|
|
||||||
ushort c = (d++)->unicode();
|
|
||||||
bool isOp = false;
|
|
||||||
if (quoted) {
|
|
||||||
if (c == '"')
|
|
||||||
quoted = false;
|
|
||||||
else if (c == '!' && test.isEmpty())
|
|
||||||
invert = true;
|
|
||||||
else
|
|
||||||
test += c;
|
|
||||||
} else if (c == '(') {
|
|
||||||
isFunc = true;
|
|
||||||
if (parens)
|
|
||||||
argsString += c;
|
|
||||||
++parens;
|
|
||||||
} else if (c == ')') {
|
|
||||||
--parens;
|
|
||||||
if (parens)
|
|
||||||
argsString += c;
|
|
||||||
} else if (!parens) {
|
|
||||||
if (c == '"')
|
|
||||||
quoted = true;
|
|
||||||
else if (c == ':' || c == '|')
|
|
||||||
isOp = true;
|
|
||||||
else if (c == '!' && test.isEmpty())
|
|
||||||
invert = true;
|
|
||||||
else
|
|
||||||
test += c;
|
|
||||||
} else {
|
|
||||||
argsString += c;
|
|
||||||
}
|
|
||||||
if (!quoted && !parens && (isOp || d == ed)) {
|
|
||||||
if (m_cumulative || (orOp != ret)) {
|
|
||||||
test = test.trimmed();
|
|
||||||
if (isFunc)
|
|
||||||
ret = evaluateConditionalFunction(ProString(test), ProString(argsString, NoHash));
|
|
||||||
else
|
|
||||||
ret = isActiveConfig(test, true);
|
|
||||||
ret ^= invert;
|
|
||||||
}
|
|
||||||
orOp = (c == '|');
|
|
||||||
invert = false;
|
|
||||||
isFunc = false;
|
|
||||||
test.clear();
|
|
||||||
argsString.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnBool(ret);
|
|
||||||
}
|
}
|
||||||
case T_CONFIG: {
|
case T_CONFIG: {
|
||||||
if (args.count() < 1 || args.count() > 2) {
|
if (args.count() < 1 || args.count() > 2) {
|
||||||
|
|||||||
@@ -1368,278 +1368,6 @@ QString QMakeEvaluator::currentDirectory() const
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The (QChar*)current->constData() constructs below avoid pointless detach() calls
|
|
||||||
// FIXME: This is inefficient. Should not make new string if it is a straight subsegment
|
|
||||||
static ALWAYS_INLINE void appendChar(ushort unicode,
|
|
||||||
QString *current, QChar **ptr, ProString *pending)
|
|
||||||
{
|
|
||||||
if (!pending->isEmpty()) {
|
|
||||||
int len = pending->size();
|
|
||||||
current->resize(current->size() + len);
|
|
||||||
::memcpy((QChar*)current->constData(), pending->constData(), len * 2);
|
|
||||||
pending->clear();
|
|
||||||
*ptr = (QChar*)current->constData() + len;
|
|
||||||
}
|
|
||||||
*(*ptr)++ = QChar(unicode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void appendString(const ProString &string,
|
|
||||||
QString *current, QChar **ptr, ProString *pending)
|
|
||||||
{
|
|
||||||
if (string.isEmpty())
|
|
||||||
return;
|
|
||||||
QChar *uc = (QChar*)current->constData();
|
|
||||||
int len;
|
|
||||||
if (*ptr != uc) {
|
|
||||||
len = *ptr - uc;
|
|
||||||
current->resize(current->size() + string.size());
|
|
||||||
} else if (!pending->isEmpty()) {
|
|
||||||
len = pending->size();
|
|
||||||
current->resize(current->size() + len + string.size());
|
|
||||||
::memcpy((QChar*)current->constData(), pending->constData(), len * 2);
|
|
||||||
pending->clear();
|
|
||||||
} else {
|
|
||||||
*pending = string;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*ptr = (QChar*)current->constData() + len;
|
|
||||||
::memcpy(*ptr, string.constData(), string.size() * 2);
|
|
||||||
*ptr += string.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void flushCurrent(ProStringList *ret,
|
|
||||||
QString *current, QChar **ptr, ProString *pending, bool joined)
|
|
||||||
{
|
|
||||||
QChar *uc = (QChar*)current->constData();
|
|
||||||
int len = *ptr - uc;
|
|
||||||
if (len) {
|
|
||||||
ret->append(ProString(QString(uc, len), NoHash));
|
|
||||||
*ptr = uc;
|
|
||||||
} else if (!pending->isEmpty()) {
|
|
||||||
ret->append(*pending);
|
|
||||||
pending->clear();
|
|
||||||
} else if (joined) {
|
|
||||||
ret->append(ProString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void flushFinal(ProStringList *ret,
|
|
||||||
const QString ¤t, const QChar *ptr, const ProString &pending,
|
|
||||||
const ProString &str, bool replaced, bool joined)
|
|
||||||
{
|
|
||||||
int len = ptr - current.data();
|
|
||||||
if (len) {
|
|
||||||
if (!replaced && len == str.size())
|
|
||||||
ret->append(str);
|
|
||||||
else
|
|
||||||
ret->append(ProString(QString(current.data(), len), NoHash));
|
|
||||||
} else if (!pending.isEmpty()) {
|
|
||||||
ret->append(pending);
|
|
||||||
} else if (joined) {
|
|
||||||
ret->append(ProString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProStringList QMakeEvaluator::expandVariableReferences(
|
|
||||||
const ProString &str, int *pos, bool joined)
|
|
||||||
{
|
|
||||||
ProStringList ret;
|
|
||||||
// if (ok)
|
|
||||||
// *ok = true;
|
|
||||||
if (str.isEmpty() && !pos)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
const ushort LSQUARE = '[';
|
|
||||||
const ushort RSQUARE = ']';
|
|
||||||
const ushort LCURLY = '{';
|
|
||||||
const ushort RCURLY = '}';
|
|
||||||
const ushort LPAREN = '(';
|
|
||||||
const ushort RPAREN = ')';
|
|
||||||
const ushort DOLLAR = '$';
|
|
||||||
const ushort BACKSLASH = '\\';
|
|
||||||
const ushort UNDERSCORE = '_';
|
|
||||||
const ushort DOT = '.';
|
|
||||||
const ushort SPACE = ' ';
|
|
||||||
const ushort TAB = '\t';
|
|
||||||
const ushort COMMA = ',';
|
|
||||||
const ushort SINGLEQUOTE = '\'';
|
|
||||||
const ushort DOUBLEQUOTE = '"';
|
|
||||||
|
|
||||||
ushort unicode, quote = 0, parens = 0;
|
|
||||||
const ushort *str_data = (const ushort *)str.constData();
|
|
||||||
const int str_len = str.size();
|
|
||||||
|
|
||||||
ProString var, args;
|
|
||||||
|
|
||||||
bool replaced = false;
|
|
||||||
bool putSpace = false;
|
|
||||||
QString current; // Buffer for successively assembled string segments
|
|
||||||
current.resize(str.size());
|
|
||||||
QChar *ptr = current.data();
|
|
||||||
ProString pending; // Buffer for string segments from variables
|
|
||||||
// Only one of the above buffers can be filled at a given time.
|
|
||||||
for (int i = pos ? *pos : 0; i < str_len; ++i) {
|
|
||||||
unicode = str_data[i];
|
|
||||||
if (unicode == DOLLAR) {
|
|
||||||
if (str_len > i+2 && str_data[i+1] == DOLLAR) {
|
|
||||||
++i;
|
|
||||||
ushort term = 0;
|
|
||||||
enum { VAR, ENVIRON, FUNCTION, PROPERTY } var_type = VAR;
|
|
||||||
unicode = str_data[++i];
|
|
||||||
if (unicode == LSQUARE) {
|
|
||||||
unicode = str_data[++i];
|
|
||||||
term = RSQUARE;
|
|
||||||
var_type = PROPERTY;
|
|
||||||
} else if (unicode == LCURLY) {
|
|
||||||
unicode = str_data[++i];
|
|
||||||
var_type = VAR;
|
|
||||||
term = RCURLY;
|
|
||||||
} else if (unicode == LPAREN) {
|
|
||||||
unicode = str_data[++i];
|
|
||||||
var_type = ENVIRON;
|
|
||||||
term = RPAREN;
|
|
||||||
}
|
|
||||||
int name_start = i;
|
|
||||||
forever {
|
|
||||||
if (!(unicode & (0xFF<<8)) &&
|
|
||||||
unicode != DOT && unicode != UNDERSCORE &&
|
|
||||||
//unicode != SINGLEQUOTE && unicode != DOUBLEQUOTE &&
|
|
||||||
(unicode < 'a' || unicode > 'z') && (unicode < 'A' || unicode > 'Z') &&
|
|
||||||
(unicode < '0' || unicode > '9'))
|
|
||||||
break;
|
|
||||||
if (++i == str_len)
|
|
||||||
break;
|
|
||||||
unicode = str_data[i];
|
|
||||||
// at this point, i points to either the 'term' or 'next' character (which is in unicode)
|
|
||||||
}
|
|
||||||
var = str.mid(name_start, i - name_start);
|
|
||||||
if (var_type == VAR && unicode == LPAREN) {
|
|
||||||
var_type = FUNCTION;
|
|
||||||
name_start = i + 1;
|
|
||||||
int depth = 0;
|
|
||||||
forever {
|
|
||||||
if (++i == str_len)
|
|
||||||
break;
|
|
||||||
unicode = str_data[i];
|
|
||||||
if (unicode == LPAREN) {
|
|
||||||
depth++;
|
|
||||||
} else if (unicode == RPAREN) {
|
|
||||||
if (!depth)
|
|
||||||
break;
|
|
||||||
--depth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
args = str.mid(name_start, i - name_start);
|
|
||||||
if (++i < str_len)
|
|
||||||
unicode = str_data[i];
|
|
||||||
else
|
|
||||||
unicode = 0;
|
|
||||||
// at this point i is pointing to the 'next' character (which is in unicode)
|
|
||||||
// this might actually be a term character since you can do $${func()}
|
|
||||||
}
|
|
||||||
if (term) {
|
|
||||||
if (unicode != term) {
|
|
||||||
evalError(fL1S("Missing %1 terminator [found %2]")
|
|
||||||
.arg(QChar(term))
|
|
||||||
.arg(unicode ? QString(unicode) : fL1S("end-of-line")));
|
|
||||||
// if (ok)
|
|
||||||
// *ok = false;
|
|
||||||
if (pos)
|
|
||||||
*pos = str_len;
|
|
||||||
return ProStringList();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// move the 'cursor' back to the last char of the thing we were looking at
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProStringList replacement;
|
|
||||||
if (var_type == ENVIRON) {
|
|
||||||
replacement = split_value_list(m_option->getEnv(var.toQString(m_tmp1)));
|
|
||||||
} else if (var_type == PROPERTY) {
|
|
||||||
replacement << propertyValue(var);
|
|
||||||
} else if (var_type == FUNCTION) {
|
|
||||||
replacement += evaluateExpandFunction(var, args);
|
|
||||||
} else if (var_type == VAR) {
|
|
||||||
replacement = values(map(var));
|
|
||||||
}
|
|
||||||
if (!replacement.isEmpty()) {
|
|
||||||
if (quote || joined) {
|
|
||||||
if (putSpace) {
|
|
||||||
putSpace = false;
|
|
||||||
if (!replacement.at(0).isEmpty()) // Bizarre, indeed
|
|
||||||
appendChar(' ', ¤t, &ptr, &pending);
|
|
||||||
}
|
|
||||||
appendString(ProString(replacement.join(statics.field_sep), NoHash),
|
|
||||||
¤t, &ptr, &pending);
|
|
||||||
} else {
|
|
||||||
appendString(replacement.at(0), ¤t, &ptr, &pending);
|
|
||||||
if (replacement.size() > 1) {
|
|
||||||
flushCurrent(&ret, ¤t, &ptr, &pending, false);
|
|
||||||
int j = 1;
|
|
||||||
if (replacement.size() > 2) {
|
|
||||||
// FIXME: ret.reserve(ret.size() + replacement.size() - 2);
|
|
||||||
for (; j < replacement.size() - 1; ++j)
|
|
||||||
ret << replacement.at(j);
|
|
||||||
}
|
|
||||||
pending = replacement.at(j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
replaced = true;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if (unicode == BACKSLASH) {
|
|
||||||
static const char symbols[] = "[]{}()$\\'\"";
|
|
||||||
ushort unicode2 = str_data[i+1];
|
|
||||||
if (!(unicode2 & 0xff00) && strchr(symbols, unicode2)) {
|
|
||||||
unicode = unicode2;
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
} else if (quote) {
|
|
||||||
if (unicode == quote) {
|
|
||||||
quote = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE) {
|
|
||||||
quote = unicode;
|
|
||||||
continue;
|
|
||||||
} else if (unicode == SPACE || unicode == TAB) {
|
|
||||||
if (!joined)
|
|
||||||
flushCurrent(&ret, ¤t, &ptr, &pending, false);
|
|
||||||
else if ((ptr - (QChar*)current.constData()) || !pending.isEmpty())
|
|
||||||
putSpace = true;
|
|
||||||
continue;
|
|
||||||
} else if (pos) {
|
|
||||||
if (unicode == LPAREN) {
|
|
||||||
++parens;
|
|
||||||
} else if (unicode == RPAREN) {
|
|
||||||
--parens;
|
|
||||||
} else if (!parens && unicode == COMMA) {
|
|
||||||
if (!joined) {
|
|
||||||
*pos = i + 1;
|
|
||||||
flushFinal(&ret, current, ptr, pending, str, replaced, false);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
flushCurrent(&ret, ¤t, &ptr, &pending, true);
|
|
||||||
putSpace = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (putSpace) {
|
|
||||||
putSpace = false;
|
|
||||||
appendChar(' ', ¤t, &ptr, &pending);
|
|
||||||
}
|
|
||||||
appendChar(unicode, ¤t, &ptr, &pending);
|
|
||||||
}
|
|
||||||
if (pos)
|
|
||||||
*pos = str_len;
|
|
||||||
flushFinal(&ret, current, ptr, pending, str, replaced, joined);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QMakeEvaluator::isActiveConfig(const QString &config, bool regex)
|
bool QMakeEvaluator::isActiveConfig(const QString &config, bool regex)
|
||||||
{
|
{
|
||||||
// magic types for easy flipping
|
// magic types for easy flipping
|
||||||
@@ -1722,14 +1450,6 @@ QList<ProStringList> QMakeEvaluator::prepareFunctionArgs(const ushort *&tokPtr)
|
|||||||
return args_list;
|
return args_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<ProStringList> QMakeEvaluator::prepareFunctionArgs(const ProString &arguments)
|
|
||||||
{
|
|
||||||
QList<ProStringList> args_list;
|
|
||||||
for (int pos = 0; pos < arguments.size(); )
|
|
||||||
args_list << expandVariableReferences(arguments, &pos);
|
|
||||||
return args_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProStringList QMakeEvaluator::evaluateFunction(
|
ProStringList QMakeEvaluator::evaluateFunction(
|
||||||
const ProFunctionDef &func, const QList<ProStringList> &argumentsList, bool *ok)
|
const ProFunctionDef &func, const QList<ProStringList> &argumentsList, bool *ok)
|
||||||
{
|
{
|
||||||
@@ -1792,54 +1512,19 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBoolFunction(
|
|||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProStringList QMakeEvaluator::evaluateExpandFunction(
|
bool QMakeEvaluator::evaluateConditional(const QString &cond, const QString &context)
|
||||||
const ProString &func, const ushort *&tokPtr)
|
|
||||||
{
|
{
|
||||||
QHash<ProString, ProFunctionDef>::ConstIterator it =
|
bool ret = false;
|
||||||
m_functionDefs.replaceFunctions.constFind(func);
|
ProFile *pro = m_parser->parsedProBlock(context, cond, QMakeParser::TestGrammar);
|
||||||
if (it != m_functionDefs.replaceFunctions.constEnd())
|
if (pro) {
|
||||||
return evaluateFunction(*it, prepareFunctionArgs(tokPtr), 0);
|
if (pro->isOk()) {
|
||||||
|
m_locationStack.push(m_current);
|
||||||
//why don't the builtin functions just use args_list? --Sam
|
ret = visitProBlock(pro, pro->tokPtr()) == ReturnTrue;
|
||||||
return evaluateExpandFunction(func, expandVariableReferences(tokPtr, 5, true));
|
m_current = m_locationStack.pop();
|
||||||
}
|
}
|
||||||
|
pro->deref();
|
||||||
ProStringList QMakeEvaluator::evaluateExpandFunction(
|
|
||||||
const ProString &func, const ProString &arguments)
|
|
||||||
{
|
|
||||||
QHash<ProString, ProFunctionDef>::ConstIterator it =
|
|
||||||
m_functionDefs.replaceFunctions.constFind(func);
|
|
||||||
if (it != m_functionDefs.replaceFunctions.constEnd())
|
|
||||||
return evaluateFunction(*it, prepareFunctionArgs(arguments), 0);
|
|
||||||
|
|
||||||
//why don't the builtin functions just use args_list? --Sam
|
|
||||||
int pos = 0;
|
|
||||||
return evaluateExpandFunction(func, expandVariableReferences(arguments, &pos, true));
|
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
|
|
||||||
const ProString &function, const ProString &arguments)
|
|
||||||
{
|
|
||||||
QHash<ProString, ProFunctionDef>::ConstIterator it =
|
|
||||||
m_functionDefs.testFunctions.constFind(function);
|
|
||||||
if (it != m_functionDefs.testFunctions.constEnd())
|
|
||||||
return evaluateBoolFunction(*it, prepareFunctionArgs(arguments), function);
|
|
||||||
|
|
||||||
//why don't the builtin functions just use args_list? --Sam
|
|
||||||
int pos = 0;
|
|
||||||
return evaluateConditionalFunction(function, expandVariableReferences(arguments, &pos, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
|
|
||||||
const ProString &function, const ushort *&tokPtr)
|
|
||||||
{
|
|
||||||
QHash<ProString, ProFunctionDef>::ConstIterator it =
|
|
||||||
m_functionDefs.testFunctions.constFind(function);
|
|
||||||
if (it != m_functionDefs.testFunctions.constEnd())
|
|
||||||
return evaluateBoolFunction(*it, prepareFunctionArgs(tokPtr), function);
|
|
||||||
|
|
||||||
//why don't the builtin functions just use args_list? --Sam
|
|
||||||
return evaluateConditionalFunction(function, expandVariableReferences(tokPtr, 5, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProValueMap *QMakeEvaluator::findValues(const ProString &variableName, ProValueMap::Iterator *rit)
|
ProValueMap *QMakeEvaluator::findValues(const ProString &variableName, ProValueMap::Iterator *rit)
|
||||||
|
|||||||
@@ -156,19 +156,16 @@ public:
|
|||||||
{ message(QMakeHandler::EvalWarnDeprecated, msg); }
|
{ message(QMakeHandler::EvalWarnDeprecated, msg); }
|
||||||
|
|
||||||
QList<ProStringList> prepareFunctionArgs(const ushort *&tokPtr);
|
QList<ProStringList> prepareFunctionArgs(const ushort *&tokPtr);
|
||||||
QList<ProStringList> prepareFunctionArgs(const ProString &arguments);
|
|
||||||
ProStringList evaluateFunction(const ProFunctionDef &func,
|
ProStringList evaluateFunction(const ProFunctionDef &func,
|
||||||
const QList<ProStringList> &argumentsList, bool *ok);
|
const QList<ProStringList> &argumentsList, bool *ok);
|
||||||
VisitReturn evaluateBoolFunction(const ProFunctionDef &func,
|
VisitReturn evaluateBoolFunction(const ProFunctionDef &func,
|
||||||
const QList<ProStringList> &argumentsList,
|
const QList<ProStringList> &argumentsList,
|
||||||
const ProString &function);
|
const ProString &function);
|
||||||
|
|
||||||
ProStringList evaluateExpandFunction(const ProString &function, const ProString &arguments);
|
|
||||||
ProStringList evaluateExpandFunction(const ProString &function, const ushort *&tokPtr);
|
ProStringList evaluateExpandFunction(const ProString &function, const ushort *&tokPtr);
|
||||||
ProStringList evaluateExpandFunction(const ProString &function, const ProStringList &args);
|
|
||||||
VisitReturn evaluateConditionalFunction(const ProString &function, const ProString &arguments);
|
|
||||||
VisitReturn evaluateConditionalFunction(const ProString &function, const ushort *&tokPtr);
|
VisitReturn evaluateConditionalFunction(const ProString &function, const ushort *&tokPtr);
|
||||||
VisitReturn evaluateConditionalFunction(const ProString &function, const ProStringList &args);
|
|
||||||
|
bool evaluateConditional(const QString &cond, const QString &context);
|
||||||
|
|
||||||
QStringList qmakeMkspecPaths() const;
|
QStringList qmakeMkspecPaths() const;
|
||||||
QStringList qmakeFeaturePaths() const;
|
QStringList qmakeFeaturePaths() const;
|
||||||
|
|||||||
@@ -194,10 +194,10 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, bool cache)
|
|||||||
return pro;
|
return pro;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProFile *QMakeParser::parsedProBlock(const QString &name, const QString &contents)
|
ProFile *QMakeParser::parsedProBlock(const QString &name, const QString &contents, SubGrammar grammar)
|
||||||
{
|
{
|
||||||
ProFile *pro = new ProFile(name);
|
ProFile *pro = new ProFile(name);
|
||||||
if (!read(pro, contents)) {
|
if (!read(pro, contents, grammar)) {
|
||||||
delete pro;
|
delete pro;
|
||||||
pro = 0;
|
pro = 0;
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ bool QMakeParser::read(ProFile *pro)
|
|||||||
|
|
||||||
QString content(QString::fromLocal8Bit(file.readAll()));
|
QString content(QString::fromLocal8Bit(file.readAll()));
|
||||||
file.close();
|
file.close();
|
||||||
return read(pro, content);
|
return read(pro, content, FullGrammar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMakeParser::putTok(ushort *&tokPtr, ushort tok)
|
void QMakeParser::putTok(ushort *&tokPtr, ushort tok)
|
||||||
@@ -256,7 +256,7 @@ void QMakeParser::finalizeHashStr(ushort *buf, uint len)
|
|||||||
buf[-2] = (ushort)(hash >> 16);
|
buf[-2] = (ushort)(hash >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QMakeParser::read(ProFile *pro, const QString &in)
|
bool QMakeParser::read(ProFile *pro, const QString &in, SubGrammar grammar)
|
||||||
{
|
{
|
||||||
m_proFile = pro;
|
m_proFile = pro;
|
||||||
m_lineNo = 1;
|
m_lineNo = 1;
|
||||||
@@ -670,6 +670,10 @@ bool QMakeParser::read(ProFile *pro, const QString &in)
|
|||||||
finalizeCond(tokPtr, buf, ptr, wordCount);
|
finalizeCond(tokPtr, buf, ptr, wordCount);
|
||||||
flushCond(tokPtr);
|
flushCond(tokPtr);
|
||||||
++m_blockstack.top().braceLevel;
|
++m_blockstack.top().braceLevel;
|
||||||
|
if (grammar == TestGrammar) {
|
||||||
|
parseError(fL1S("Opening scope not permitted in this context."));
|
||||||
|
pro->setOk(false);
|
||||||
|
}
|
||||||
goto nextItem;
|
goto nextItem;
|
||||||
} else if (c == '}') {
|
} else if (c == '}') {
|
||||||
FLUSH_LHS_LITERAL();
|
FLUSH_LHS_LITERAL();
|
||||||
@@ -708,7 +712,10 @@ bool QMakeParser::read(ProFile *pro, const QString &in)
|
|||||||
FLUSH_LHS_LITERAL();
|
FLUSH_LHS_LITERAL();
|
||||||
flushCond(tokPtr);
|
flushCond(tokPtr);
|
||||||
putLineMarker(tokPtr);
|
putLineMarker(tokPtr);
|
||||||
if (wordCount != 1) {
|
if (grammar == TestGrammar) {
|
||||||
|
parseError(fL1S("Assignment not permitted in this context."));
|
||||||
|
pro->setOk(false);
|
||||||
|
} else if (wordCount != 1) {
|
||||||
parseError(fL1S("Assignment needs exactly one word on the left hand side."));
|
parseError(fL1S("Assignment needs exactly one word on the left hand side."));
|
||||||
pro->setOk(false);
|
pro->setOk(false);
|
||||||
// Put empty variable name.
|
// Put empty variable name.
|
||||||
|
|||||||
@@ -76,9 +76,11 @@ public:
|
|||||||
|
|
||||||
QMakeParser(ProFileCache *cache, QMakeParserHandler *handler);
|
QMakeParser(ProFileCache *cache, QMakeParserHandler *handler);
|
||||||
|
|
||||||
|
enum SubGrammar { FullGrammar, TestGrammar };
|
||||||
// fileName is expected to be absolute and cleanPath()ed.
|
// fileName is expected to be absolute and cleanPath()ed.
|
||||||
ProFile *parsedProFile(const QString &fileName, bool cache = false);
|
ProFile *parsedProFile(const QString &fileName, bool cache = false);
|
||||||
ProFile *parsedProBlock(const QString &name, const QString &contents);
|
ProFile *parsedProBlock(const QString &name, const QString &contents,
|
||||||
|
SubGrammar grammar = FullGrammar);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct BlockScope {
|
struct BlockScope {
|
||||||
@@ -107,7 +109,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool read(ProFile *pro);
|
bool read(ProFile *pro);
|
||||||
bool read(ProFile *pro, const QString &content);
|
bool read(ProFile *pro, const QString &content, SubGrammar grammar);
|
||||||
|
|
||||||
ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok);
|
ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok);
|
||||||
ALWAYS_INLINE void putBlockLen(ushort *&tokPtr, uint len);
|
ALWAYS_INLINE void putBlockLen(ushort *&tokPtr, uint len);
|
||||||
|
|||||||
Reference in New Issue
Block a user