refactor ProFileEvaluator, part 1: introduce handler interface

externalize the error message and evaluation notification callbacks into
an own handler interface.
This commit is contained in:
Oswald Buddenhagen
2010-06-18 13:30:03 +02:00
parent 752c823de2
commit 0c09acbb25
5 changed files with 235 additions and 214 deletions

View File

@@ -35,8 +35,38 @@
using namespace Qt4ProjectManager; using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal; using namespace Qt4ProjectManager::Internal;
static QString format(const QString &fileName, int lineNo, const QString &msg)
{
if (lineNo)
return QString::fromLatin1("%1(%2): %3").arg(fileName, QString::number(lineNo), msg);
else
return msg;
}
void ProMessageHandler::parseError(const QString &fileName, int lineNo, const QString &msg)
{
emit errorFound(format(fileName, lineNo, msg));
}
void ProMessageHandler::configError(const QString &msg)
{
emit errorFound(msg);
}
void ProMessageHandler::evalError(const QString &fileName, int lineNo, const QString &msg)
{
if (m_verbose)
emit errorFound(format(fileName, lineNo, msg));
}
void ProMessageHandler::fileMessage(const QString &)
{
// we ignore these...
}
ProFileReader::ProFileReader(ProFileOption *option) ProFileReader::ProFileReader(ProFileOption *option)
: ProFileEvaluator(option) : ProFileEvaluator(option, this)
, m_ignoreLevel(0) , m_ignoreLevel(0)
{ {
} }
@@ -79,23 +109,6 @@ QList<ProFile*> ProFileReader::includeFiles() const
return m_includeFiles.values(); return m_includeFiles.values();
} }
void ProFileReader::fileMessage(const QString &message)
{
Q_UNUSED(message)
// we ignore these...
}
void ProFileReader::logMessage(const QString &message)
{
Q_UNUSED(message)
// we ignore these...
}
void ProFileReader::errorMessage(const QString &message)
{
emit errorFound(message);
}
ProFile *ProFileReader::proFileFor(const QString &name) ProFile *ProFileReader::proFileFor(const QString &name)
{ {
return m_includeFiles.value(name); return m_includeFiles.value(name);

View File

@@ -39,7 +39,30 @@
namespace Qt4ProjectManager { namespace Qt4ProjectManager {
namespace Internal { namespace Internal {
class ProFileReader : public QObject, public ProFileEvaluator class ProMessageHandler : public QObject,
public ProFileEvaluatorHandler
{
Q_OBJECT
public:
ProMessageHandler(bool verbose = false) : m_verbose(verbose) {}
virtual ~ProMessageHandler() {}
virtual void aboutToEval(ProFile *, ProFile *, EvalFileType) {}
virtual void doneWithEval(ProFile *) {}
virtual void parseError(const QString &filename, int lineNo, const QString &msg);
virtual void configError(const QString &msg);
virtual void evalError(const QString &filename, int lineNo, const QString &msg);
virtual void fileMessage(const QString &msg);
signals:
void errorFound(const QString &error);
private:
bool m_verbose;
};
class ProFileReader : public ProMessageHandler, public ProFileEvaluator
{ {
Q_OBJECT Q_OBJECT
@@ -52,15 +75,9 @@ public:
QList<ProFile*> includeFiles() const; QList<ProFile*> includeFiles() const;
ProFile *proFileFor(const QString &name); ProFile *proFileFor(const QString &name);
signals:
void errorFound(const QString &error);
private:
virtual void aboutToEval(ProFile *parent, ProFile *proFile, EvalFileType type); virtual void aboutToEval(ProFile *parent, ProFile *proFile, EvalFileType type);
virtual void doneWithEval(ProFile *parent); virtual void doneWithEval(ProFile *parent);
virtual void logMessage(const QString &msg);
virtual void fileMessage(const QString &msg);
virtual void errorMessage(const QString &msg);
private: private:
QMap<QString, ProFile *> m_includeFiles; QMap<QString, ProFile *> m_includeFiles;

View File

@@ -169,16 +169,18 @@ ProFileOption::~ProFileOption()
// //
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
#define fL1S(s) QString::fromLatin1(s)
class ProFileEvaluator::Private class ProFileEvaluator::Private
{ {
public: public:
static void initStatics(); static void initStatics();
Private(ProFileEvaluator *q_, ProFileOption *option); Private(ProFileEvaluator *q_, ProFileOption *option,
ProFileEvaluatorHandler *handler);
~Private(); ~Private();
ProFileEvaluator *q; ProFileEvaluator *q;
int m_lineNo; // Error reporting int m_lineNo; // Error reporting
bool m_verbose;
/////////////// Reading pro file /////////////// Reading pro file
@@ -254,7 +256,7 @@ public:
static ALWAYS_INLINE void skipHashStr(const ushort *&tokPtr); static ALWAYS_INLINE void skipHashStr(const ushort *&tokPtr);
void skipExpression(const ushort *&tokPtr); void skipExpression(const ushort *&tokPtr);
VisitReturn visitProFile(ProFile *pro, ProFileEvaluator::EvalFileType type); VisitReturn visitProFile(ProFile *pro, ProFileEvaluatorHandler::EvalFileType type);
VisitReturn visitProBlock(const ushort *tokPtr); VisitReturn visitProBlock(const ushort *tokPtr);
VisitReturn visitProLoop(const ProString &variable, const ushort *exprPtr, VisitReturn visitProLoop(const ProString &variable, const ushort *exprPtr,
const ushort *tokPtr); const ushort *tokPtr);
@@ -276,10 +278,8 @@ public:
ProStringList evaluateExpandFunction(const ProString &function, const ProString &arguments); 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); ProStringList evaluateExpandFunction(const ProString &function, const ProStringList &args);
QString format(const char *format) const; void parseError(const QString &msg) const;
void logMessage(const QString &msg) const; void evalError(const QString &msg) const;
void errorMessage(const QString &msg) const;
void fileMessage(const QString &msg) const;
QString currentFileName() const; QString currentFileName() const;
QString currentDirectory() const; QString currentDirectory() const;
@@ -292,11 +292,11 @@ public:
VisitReturn evaluateConditionalFunction(const ProString &function, const ProStringList &args); VisitReturn evaluateConditionalFunction(const ProString &function, const ProStringList &args);
ProFile *parsedProFile(const QString &fileName, bool cache, ProFile *parsedProFile(const QString &fileName, bool cache,
const QString &contents = QString()); const QString &contents = QString());
bool evaluateFileDirect(const QString &fileName, ProFileEvaluator::EvalFileType type); bool evaluateFileDirect(const QString &fileName, ProFileEvaluatorHandler::EvalFileType type);
bool evaluateFile(const QString &fileName, ProFileEvaluator::EvalFileType type); bool evaluateFile(const QString &fileName, ProFileEvaluatorHandler::EvalFileType type);
bool evaluateFeatureFile(const QString &fileName, bool evaluateFeatureFile(const QString &fileName,
QHash<ProString, ProStringList> *values = 0, FunctionDefs *defs = 0); QHash<ProString, ProStringList> *values = 0, FunctionDefs *defs = 0);
bool evaluateFileInto(const QString &fileName, ProFileEvaluator::EvalFileType type, bool evaluateFileInto(const QString &fileName, ProFileEvaluatorHandler::EvalFileType type,
QHash<ProString, ProStringList> *values, FunctionDefs *defs); QHash<ProString, ProStringList> *values, FunctionDefs *defs);
static ALWAYS_INLINE VisitReturn returnBool(bool b) static ALWAYS_INLINE VisitReturn returnBool(bool b)
@@ -331,6 +331,7 @@ public:
bool m_parsePreAndPostFiles; bool m_parsePreAndPostFiles;
ProFileOption *m_option; ProFileOption *m_option;
ProFileEvaluatorHandler *m_handler;
enum ExpandFunc { enum ExpandFunc {
E_MEMBER=1, E_FIRST, E_LAST, E_SIZE, E_CAT, E_FROMFILE, E_EVAL, E_LIST, E_MEMBER=1, E_FIRST, E_LAST, E_SIZE, E_CAT, E_FROMFILE, E_EVAL, E_LIST,
@@ -540,14 +541,14 @@ ProString ProFileEvaluator::Private::map(const ProString &var)
} }
ProFileEvaluator::Private::Private(ProFileEvaluator *q_, ProFileOption *option) ProFileEvaluator::Private::Private(ProFileEvaluator *q_, ProFileOption *option,
: q(q_), m_option(option) ProFileEvaluatorHandler *handler)
: q(q_), m_option(option), m_handler(handler)
{ {
// So that single-threaded apps don't have to call initialize() for now. // So that single-threaded apps don't have to call initialize() for now.
initStatics(); initStatics();
// Configuration, more or less // Configuration, more or less
m_verbose = true;
m_cumulative = true; m_cumulative = true;
m_parsePreAndPostFiles = true; m_parsePreAndPostFiles = true;
@@ -569,7 +570,7 @@ bool ProFileEvaluator::Private::read(ProFile *pro)
QFile file(pro->fileName()); QFile file(pro->fileName());
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
if (IoUtils::exists(pro->fileName())) if (IoUtils::exists(pro->fileName()))
errorMessage(format("%1 not readable.").arg(pro->fileName())); parseError(fL1S("%1 not readable.").arg(pro->fileName()));
return false; return false;
} }
@@ -921,7 +922,7 @@ bool ProFileEvaluator::Private::readInternal(QString *out, const QString &in)
cur++; cur++;
checkTerm: checkTerm:
if (c != term) { if (c != term) {
logMessage(format("Missing %1 terminator [found %2]") parseError(fL1S("Missing %1 terminator [found %2]")
.arg(QChar(term)) .arg(QChar(term))
.arg(c ? QString(c) : QString::fromLatin1("end-of-line"))); .arg(c ? QString(c) : QString::fromLatin1("end-of-line")));
return false; return false;
@@ -1006,7 +1007,7 @@ bool ProFileEvaluator::Private::readInternal(QString *out, const QString &in)
if (c == '(') { if (c == '(') {
FLUSH_LHS_LITERAL(false); FLUSH_LHS_LITERAL(false);
if (ptr == buf) { if (ptr == buf) {
logMessage(format("Opening parenthesis without prior test name.")); parseError(fL1S("Opening parenthesis without prior test name."));
inError = true; inError = true;
goto skip; goto skip;
} }
@@ -1021,7 +1022,7 @@ bool ProFileEvaluator::Private::readInternal(QString *out, const QString &in)
FLUSH_LHS_LITERAL(false); FLUSH_LHS_LITERAL(false);
finalizeCond(tokPtr, buf, ptr); finalizeCond(tokPtr, buf, ptr);
if (m_state == StNew) if (m_state == StNew)
logMessage(format("And operator without prior condition.")); parseError(fL1S("And operator without prior condition."));
else else
m_operator = AndOperator; m_operator = AndOperator;
nextItem: nextItem:
@@ -1032,7 +1033,7 @@ bool ProFileEvaluator::Private::readInternal(QString *out, const QString &in)
FLUSH_LHS_LITERAL(false); FLUSH_LHS_LITERAL(false);
finalizeCond(tokPtr, buf, ptr); finalizeCond(tokPtr, buf, ptr);
if (m_state != StCond) if (m_state != StCond)
logMessage(format("Or operator without prior condition.")); parseError(fL1S("Or operator without prior condition."));
else else
m_operator = OrOperator; m_operator = OrOperator;
goto nextItem; goto nextItem;
@@ -1047,7 +1048,7 @@ bool ProFileEvaluator::Private::readInternal(QString *out, const QString &in)
finalizeCond(tokPtr, buf, ptr); finalizeCond(tokPtr, buf, ptr);
flushScopes(tokPtr); flushScopes(tokPtr);
if (!m_blockstack.top().braceLevel) { if (!m_blockstack.top().braceLevel) {
logMessage(format("Excess closing brace.")); parseError(fL1S("Excess closing brace."));
} else if (!--m_blockstack.top().braceLevel } else if (!--m_blockstack.top().braceLevel
&& m_blockstack.count() != 1) { && m_blockstack.count() != 1) {
leaveScope(tokPtr); leaveScope(tokPtr);
@@ -1079,7 +1080,7 @@ bool ProFileEvaluator::Private::readInternal(QString *out, const QString &in)
flushCond(tokPtr); flushCond(tokPtr);
putLineMarker(tokPtr); putLineMarker(tokPtr);
if (!(tlen = ptr - buf)) { if (!(tlen = ptr - buf)) {
logMessage(format("Assignment operator without prior variable name.")); parseError(fL1S("Assignment operator without prior variable name."));
inError = true; inError = true;
goto skip; goto skip;
} }
@@ -1118,11 +1119,11 @@ bool ProFileEvaluator::Private::readInternal(QString *out, const QString &in)
flushLine: flushLine:
FLUSH_LITERAL(false); FLUSH_LITERAL(false);
if (quote) { if (quote) {
logMessage(format("Missing closing %1 quote").arg(QChar(quote))); parseError(fL1S("Missing closing %1 quote").arg(QChar(quote)));
return false; return false;
} }
if (!xprStack.isEmpty()) { if (!xprStack.isEmpty()) {
logMessage(format("Missing closing parenthesis in function call")); parseError(fL1S("Missing closing parenthesis in function call"));
return false; return false;
} }
if (context == CtxValue) { if (context == CtxValue) {
@@ -1135,7 +1136,7 @@ bool ProFileEvaluator::Private::readInternal(QString *out, const QString &in)
if (!c) { if (!c) {
flushScopes(tokPtr); flushScopes(tokPtr);
if (m_blockstack.size() > 1) if (m_blockstack.size() > 1)
logMessage(format("Missing closing brace(s).")); parseError(fL1S("Missing closing brace(s)."));
while (m_blockstack.size()) while (m_blockstack.size())
leaveScope(tokPtr); leaveScope(tokPtr);
xprBuff.clear(); xprBuff.clear();
@@ -1163,7 +1164,7 @@ bool ProFileEvaluator::Private::readInternal(QString *out, const QString &in)
#undef FLUSH_RHS_LITERAL #undef FLUSH_RHS_LITERAL
extraChars: extraChars:
logMessage(format("Extra characters after test expression.")); parseError(fL1S("Extra characters after test expression."));
return false; return false;
} }
@@ -1257,7 +1258,7 @@ void ProFileEvaluator::Private::finalizeCond(ushort *&tokPtr, ushort *uc, ushort
m_tmp1.setRawData((QChar *)uc + 4, nlen); m_tmp1.setRawData((QChar *)uc + 4, nlen);
if (!m_tmp1.compare(statics.strelse, Qt::CaseInsensitive)) { if (!m_tmp1.compare(statics.strelse, Qt::CaseInsensitive)) {
if (m_invert || m_operator != NoOperator) { if (m_invert || m_operator != NoOperator) {
logMessage(format("Unexpected operator in front of else.")); parseError(fL1S("Unexpected operator in front of else."));
return; return;
} }
BlockScope &top = m_blockstack.top(); BlockScope &top = m_blockstack.top();
@@ -1279,7 +1280,7 @@ void ProFileEvaluator::Private::finalizeCond(ushort *&tokPtr, ushort *uc, ushort
break; break;
leaveScope(tokPtr); leaveScope(tokPtr);
} }
errorMessage(format("Unexpected 'else'.")); parseError(fL1S("Unexpected 'else'."));
return; return;
} }
} }
@@ -1306,7 +1307,7 @@ void ProFileEvaluator::Private::finalizeCall(ushort *&tokPtr, ushort *uc, ushort
putLineMarker(tokPtr); putLineMarker(tokPtr);
if (m_invert || m_operator == OrOperator) { if (m_invert || m_operator == OrOperator) {
// '|' could actually work reasonably, but qmake does nonsense here. // '|' could actually work reasonably, but qmake does nonsense here.
logMessage(format("Unexpected operator in front of for().")); parseError(fL1S("Unexpected operator in front of for()."));
return; return;
} }
if (*uce == TokLiteral) { if (*uce == TokLiteral) {
@@ -1341,7 +1342,7 @@ void ProFileEvaluator::Private::finalizeCall(ushort *&tokPtr, ushort *uc, ushort
uc = uce; uc = uce;
goto doFor; goto doFor;
} }
logMessage(format("Syntax is for(var, list), for(var, forever) or for(ever).")); parseError(fL1S("Syntax is for(var, list), for(var, forever) or for(ever)."));
return; return;
} else if (m_tmp1 == statics.strdefineReplace) { } else if (m_tmp1 == statics.strdefineReplace) {
defName = &statics.strdefineReplace; defName = &statics.strdefineReplace;
@@ -1354,7 +1355,7 @@ void ProFileEvaluator::Private::finalizeCall(ushort *&tokPtr, ushort *uc, ushort
flushScopes(tokPtr); flushScopes(tokPtr);
putLineMarker(tokPtr); putLineMarker(tokPtr);
if (m_invert) { if (m_invert) {
logMessage(format("Unexpected operator in front of function definition.")); parseError(fL1S("Unexpected operator in front of function definition."));
return; return;
} }
if (*uce == TokLiteral) { if (*uce == TokLiteral) {
@@ -1371,7 +1372,7 @@ void ProFileEvaluator::Private::finalizeCall(ushort *&tokPtr, ushort *uc, ushort
return; return;
} }
} }
logMessage(format("%1(function) requires one literal argument.").arg(*defName)); parseError(fL1S("%1(function) requires one literal argument.").arg(*defName));
return; return;
} }
} }
@@ -1780,7 +1781,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProBlock(
case TokCondition: case TokCondition:
if (!m_skipLevel && okey != or_op) { if (!m_skipLevel && okey != or_op) {
if (curr.size() != 1) { if (curr.size() != 1) {
logMessage(format("Conditional must expand to exactly one word.")); evalError(fL1S("Conditional must expand to exactly one word."));
okey = false; okey = false;
} else { } else {
okey = isActiveConfig(curr.at(0).toQString(m_tmp2), true) ^ invert; okey = isActiveConfig(curr.at(0).toQString(m_tmp2), true) ^ invert;
@@ -1793,7 +1794,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProBlock(
case TokTestCall: case TokTestCall:
if (!m_skipLevel && okey != or_op) { if (!m_skipLevel && okey != or_op) {
if (curr.size() != 1) { if (curr.size() != 1) {
logMessage(format("Test name must expand to exactly one word.")); evalError(fL1S("Test name must expand to exactly one word."));
skipExpression(tokPtr); skipExpression(tokPtr);
okey = false; okey = false;
} else { } else {
@@ -1858,7 +1859,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProLoop(
ProString it_list = expandVariableReferences(exprPtr, 0, true).at(0); ProString it_list = expandVariableReferences(exprPtr, 0, true).at(0);
if (_variable.isEmpty()) { if (_variable.isEmpty()) {
if (it_list != statics.strever) { if (it_list != statics.strever) {
logMessage(format("Invalid loop expression.")); evalError(fL1S("Invalid loop expression."));
return ReturnFalse; return ReturnFalse;
} }
it_list = ProString(statics.strforever); it_list = ProString(statics.strforever);
@@ -1898,7 +1899,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProLoop(
if (!variable.isEmpty()) if (!variable.isEmpty())
m_valuemapStack.top()[variable] = ProStringList(ProString(QString::number(index++), NoHash)); m_valuemapStack.top()[variable] = ProStringList(ProString(QString::number(index++), NoHash));
if (index > 1000) { if (index > 1000) {
errorMessage(format("ran into infinite loop (> 1000 iterations).")); evalError(fL1S("ran into infinite loop (> 1000 iterations)."));
break; break;
} }
} else { } else {
@@ -1941,7 +1942,7 @@ void ProFileEvaluator::Private::visitProVariable(
if (curr.size() != 1) { if (curr.size() != 1) {
skipExpression(tokPtr); skipExpression(tokPtr);
logMessage(format("Left hand side of assignment must expand to exactly one word.")); evalError(fL1S("Left hand side of assignment must expand to exactly one word."));
return; return;
} }
const ProString &varName = map(curr.first()); const ProString &varName = map(curr.first());
@@ -1952,13 +1953,13 @@ void ProFileEvaluator::Private::visitProVariable(
const ProStringList &varVal = expandVariableReferences(tokPtr, sizeHint, true); const ProStringList &varVal = expandVariableReferences(tokPtr, sizeHint, true);
const QString &val = varVal.at(0).toQString(m_tmp1); const QString &val = varVal.at(0).toQString(m_tmp1);
if (val.length() < 4 || val.at(0) != QLatin1Char('s')) { if (val.length() < 4 || val.at(0) != QLatin1Char('s')) {
logMessage(format("the ~= operator can handle only the s/// function.")); evalError(fL1S("the ~= operator can handle only the s/// function."));
return; return;
} }
QChar sep = val.at(1); QChar sep = val.at(1);
QStringList func = val.split(sep); QStringList func = val.split(sep);
if (func.count() < 3 || func.count() > 4) { if (func.count() < 3 || func.count() > 4) {
logMessage(format("the s/// function expects 3 or 4 arguments.")); evalError(fL1S("the s/// function expects 3 or 4 arguments."));
return; return;
} }
@@ -2027,9 +2028,9 @@ void ProFileEvaluator::Private::visitProVariable(
} }
ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProFile( ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProFile(
ProFile *pro, ProFileEvaluator::EvalFileType type) ProFile *pro, ProFileEvaluatorHandler::EvalFileType type)
{ {
q->aboutToEval(currentProFile(), pro, type); m_handler->aboutToEval(currentProFile(), pro, type);
m_lineNo = 0; m_lineNo = 0;
m_profileStack.push(pro); m_profileStack.push(pro);
if (m_profileStack.count() == 1) { if (m_profileStack.count() == 1) {
@@ -2074,7 +2075,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProFile(
if (!qmake_cache.isEmpty()) { if (!qmake_cache.isEmpty()) {
qmake_cache = resolvePath(qmake_cache); qmake_cache = resolvePath(qmake_cache);
QHash<ProString, ProStringList> cache_valuemap; QHash<ProString, ProStringList> cache_valuemap;
if (evaluateFileInto(qmake_cache, ProFileEvaluator::EvalConfigFile, if (evaluateFileInto(qmake_cache, ProFileEvaluatorHandler::EvalConfigFile,
&cache_valuemap, 0)) { &cache_valuemap, 0)) {
if (m_option->qmakespec.isEmpty()) { if (m_option->qmakespec.isEmpty()) {
const ProStringList &vals = cache_valuemap.value(ProString("QMAKESPEC")); const ProStringList &vals = cache_valuemap.value(ProString("QMAKESPEC"));
@@ -2099,7 +2100,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProFile(
} }
} }
if (qmakespec.isEmpty()) { if (qmakespec.isEmpty()) {
errorMessage(format("Could not find qmake configuration directory")); m_handler->configError(fL1S("Could not find qmake configuration directory"));
// Unlike in qmake, not finding the spec is not critical ... // Unlike in qmake, not finding the spec is not critical ...
} }
} }
@@ -2120,7 +2121,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProFile(
goto cool; goto cool;
} }
} }
errorMessage(format("Could not find qmake configuration file")); m_handler->configError(fL1S("Could not find qmake configuration file"));
// Unlike in qmake, a missing config is not critical ... // Unlike in qmake, a missing config is not critical ...
qmakespec.clear(); qmakespec.clear();
cool: ; cool: ;
@@ -2131,11 +2132,12 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProFile(
m_option->qmakespec = QDir::cleanPath(qmakespec); m_option->qmakespec = QDir::cleanPath(qmakespec);
QString spec = m_option->qmakespec + QLatin1String("/qmake.conf"); QString spec = m_option->qmakespec + QLatin1String("/qmake.conf");
if (!evaluateFileInto(spec, ProFileEvaluator::EvalConfigFile, if (!evaluateFileInto(spec, ProFileEvaluatorHandler::EvalConfigFile,
&m_option->base_valuemap, &m_option->base_functions)) { &m_option->base_valuemap, &m_option->base_functions)) {
errorMessage(format("Could not read qmake configuration file %1").arg(spec)); m_handler->configError(
fL1S("Could not read qmake configuration file %1").arg(spec));
} else if (!m_option->cachefile.isEmpty()) { } else if (!m_option->cachefile.isEmpty()) {
evaluateFileInto(m_option->cachefile, ProFileEvaluator::EvalConfigFile, evaluateFileInto(m_option->cachefile, ProFileEvaluatorHandler::EvalConfigFile,
&m_option->base_valuemap, &m_option->base_functions); &m_option->base_valuemap, &m_option->base_functions);
} }
m_option->qmakespec_name = IoUtils::fileName(m_option->qmakespec).toString(); m_option->qmakespec_name = IoUtils::fileName(m_option->qmakespec).toString();
@@ -2216,7 +2218,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProFile(
} }
} }
m_profileStack.pop(); m_profileStack.pop();
q->doneWithEval(currentProFile()); m_handler->doneWithEval(currentProFile());
return ReturnTrue; return ReturnTrue;
} }
@@ -2334,7 +2336,7 @@ QString ProFileEvaluator::Private::propertyValue(const QString &name, bool compl
if (name == QLatin1String("QMAKE_VERSION")) if (name == QLatin1String("QMAKE_VERSION"))
return QLatin1String("1.0"); //### FIXME return QLatin1String("1.0"); //### FIXME
if (complain) if (complain)
logMessage(format("Querying unknown property %1").arg(name)); evalError(fL1S("Querying unknown property %1").arg(name));
return QString(); return QString();
} }
@@ -2530,9 +2532,9 @@ ProStringList ProFileEvaluator::Private::expandVariableReferences(
} }
if (term) { if (term) {
if (unicode != term) { if (unicode != term) {
logMessage(format("Missing %1 terminator [found %2]") evalError(fL1S("Missing %1 terminator [found %2]")
.arg(QChar(term)) .arg(QChar(term))
.arg(unicode ? QString(unicode) : QString::fromLatin1(("end-of-line")))); .arg(unicode ? QString(unicode) : fL1S("end-of-line")));
// if (ok) // if (ok)
// *ok = false; // *ok = false;
if (pos) if (pos)
@@ -2745,7 +2747,7 @@ ProStringList ProFileEvaluator::Private::evaluateFunction(
const ushort *tokPtr = (const ushort *)func.string.constData() + func.offset; const ushort *tokPtr = (const ushort *)func.string.constData() + func.offset;
if (m_valuemapStack.count() >= 100) { if (m_valuemapStack.count() >= 100) {
errorMessage(format("ran into infinite recursion (depth > 100).")); evalError(fL1S("ran into infinite recursion (depth > 100)."));
oki = false; oki = false;
} else { } else {
m_valuemapStack.push(QHash<ProString, ProStringList>()); m_valuemapStack.push(QHash<ProString, ProStringList>());
@@ -2791,9 +2793,9 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateBoolFu
if (val) if (val)
return ReturnTrue; return ReturnTrue;
} else { } else {
logMessage(format("Unexpected return value from test '%1': %2") evalError(fL1S("Unexpected return value from test '%1': %2")
.arg(function.toQString(m_tmp1)) .arg(function.toQString(m_tmp1))
.arg(ret.join(QLatin1String(" :: ")))); .arg(ret.join(QLatin1String(" :: "))));
} }
} }
} }
@@ -2843,8 +2845,8 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
int end = -1; int end = -1;
if (func_t == E_SECTION) { if (func_t == E_SECTION) {
if (args.count() != 3 && args.count() != 4) { if (args.count() != 3 && args.count() != 4) {
logMessage(format("%1(var) section(var, sep, begin, end) " evalError(fL1S("%1(var) section(var, sep, begin, end) requires"
"requires three or four arguments.").arg(func.toQString(m_tmp1))); " three or four arguments.").arg(func.toQString(m_tmp1)));
} else { } else {
var = args[0]; var = args[0];
sep = args.at(1).toQString(); sep = args.at(1).toQString();
@@ -2854,8 +2856,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
} }
} else { } else {
if (args.count() != 1) { if (args.count() != 1) {
logMessage(format("%1(var) requires one argument.") evalError(fL1S("%1(var) requires one argument.").arg(func.toQString(m_tmp1)));
.arg(func.toQString(m_tmp1)));
} else { } else {
var = args[0]; var = args[0];
regexp = true; regexp = true;
@@ -2884,7 +2885,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
} }
case E_SPRINTF: case E_SPRINTF:
if(args.count() < 1) { if(args.count() < 1) {
logMessage(format("sprintf(format, ...) requires at least one argument")); evalError(fL1S("sprintf(format, ...) requires at least one argument"));
} else { } else {
QString tmp = args.at(0).toQString(m_tmp1); QString tmp = args.at(0).toQString(m_tmp1);
for (int i = 1; i < args.count(); ++i) for (int i = 1; i < args.count(); ++i)
@@ -2895,7 +2896,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
break; break;
case E_JOIN: { case E_JOIN: {
if (args.count() < 1 || args.count() > 4) { if (args.count() < 1 || args.count() > 4) {
logMessage(format("join(var, glue, before, after) requires one to four arguments.")); evalError(fL1S("join(var, glue, before, after) requires one to four arguments."));
} else { } else {
QString glue; QString glue;
ProString before, after; ProString before, after;
@@ -2913,7 +2914,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
} }
case E_SPLIT: case E_SPLIT:
if (args.count() != 2) { if (args.count() != 2) {
logMessage(format("split(var, sep) requires one or two arguments")); evalError(fL1S("split(var, sep) requires one or two arguments"));
} else { } else {
const QString &sep = (args.count() == 2) ? args.at(1).toQString(m_tmp1) : statics.field_sep; 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 ProString &var, values(map(args.at(0))))
@@ -2923,7 +2924,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
break; break;
case E_MEMBER: case E_MEMBER:
if (args.count() < 1 || args.count() > 3) { if (args.count() < 1 || args.count() > 3) {
logMessage(format("member(var, start, end) requires one to three arguments.")); evalError(fL1S("member(var, start, end) requires one to three arguments."));
} else { } else {
bool ok = true; bool ok = true;
const ProStringList &var = values(map(args.at(0))); const ProStringList &var = values(map(args.at(0)));
@@ -2941,15 +2942,15 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
} }
} }
if (!ok) if (!ok)
logMessage(format("member() argument 2 (start) '%2' invalid.") evalError(fL1S("member() argument 2 (start) '%2' invalid.")
.arg(start_str)); .arg(start_str));
} else { } else {
end = start; end = start;
if (args.count() == 3) if (args.count() == 3)
end = args.at(2).toQString(m_tmp1).toInt(&ok); end = args.at(2).toQString(m_tmp1).toInt(&ok);
if (!ok) if (!ok)
logMessage(format("member() argument 3 (end) '%2' invalid.\n") evalError(fL1S("member() argument 3 (end) '%2' invalid.\n")
.arg(args.at(2).toQString(m_tmp1))); .arg(args.at(2).toQString(m_tmp1)));
} }
} }
if (ok) { if (ok) {
@@ -2972,7 +2973,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
case E_FIRST: case E_FIRST:
case E_LAST: case E_LAST:
if (args.count() != 1) { if (args.count() != 1) {
logMessage(format("%1(var) requires one argument.").arg(func.toQString(m_tmp1))); evalError(fL1S("%1(var) requires one argument.").arg(func.toQString(m_tmp1)));
} else { } else {
const ProStringList &var = values(map(args.at(0))); const ProStringList &var = values(map(args.at(0)));
if (!var.isEmpty()) { if (!var.isEmpty()) {
@@ -2985,13 +2986,13 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
break; break;
case E_SIZE: case E_SIZE:
if(args.count() != 1) if(args.count() != 1)
logMessage(format("size(var) requires one argument.")); evalError(fL1S("size(var) requires one argument."));
else else
ret.append(ProString(QString::number(values(map(args.at(0))).size()), NoHash)); ret.append(ProString(QString::number(values(map(args.at(0))).size()), NoHash));
break; break;
case E_CAT: case E_CAT:
if (args.count() < 1 || args.count() > 2) { if (args.count() < 1 || args.count() > 2) {
logMessage(format("cat(file, singleline=true) requires one or two arguments.")); evalError(fL1S("cat(file, singleline=true) requires one or two arguments."));
} else { } else {
const QString &file = args.at(0).toQString(m_tmp1); const QString &file = args.at(0).toQString(m_tmp1);
@@ -3013,18 +3014,18 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
break; break;
case E_FROMFILE: case E_FROMFILE:
if (args.count() != 2) { if (args.count() != 2) {
logMessage(format("fromfile(file, variable) requires two arguments.")); evalError(fL1S("fromfile(file, variable) requires two arguments."));
} else { } else {
QHash<ProString, ProStringList> vars; QHash<ProString, ProStringList> vars;
QString fn = resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1))); QString fn = resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1)));
fn.detach(); fn.detach();
if (evaluateFileInto(fn, ProFileEvaluator::EvalAuxFile, &vars, 0)) if (evaluateFileInto(fn, ProFileEvaluatorHandler::EvalAuxFile, &vars, 0))
ret = vars.value(map(args.at(1))); ret = vars.value(map(args.at(1)));
} }
break; break;
case E_EVAL: case E_EVAL:
if (args.count() != 1) { if (args.count() != 1) {
logMessage(format("eval(variable) requires one argument")); evalError(fL1S("eval(variable) requires one argument"));
} else { } else {
ret += values(map(args.at(0))); ret += values(map(args.at(0)));
} }
@@ -3040,7 +3041,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
break; } break; }
case E_FIND: case E_FIND:
if (args.count() != 2) { if (args.count() != 2) {
logMessage(format("find(var, str) requires two arguments.")); evalError(fL1S("find(var, str) requires two arguments."));
} else { } else {
QRegExp regx(args.at(1).toQString()); QRegExp regx(args.at(1).toQString());
int t = 0; int t = 0;
@@ -3054,7 +3055,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
case E_SYSTEM: case E_SYSTEM:
if (!m_skipLevel) { if (!m_skipLevel) {
if (args.count() < 1 || args.count() > 2) { if (args.count() < 1 || args.count() > 2) {
logMessage(format("system(execute) requires one or two arguments.")); evalError(fL1S("system(execute) requires one or two arguments."));
} else { } else {
char buff[256]; char buff[256];
FILE *proc = QT_POPEN(QString(QLatin1String("cd ") FILE *proc = QT_POPEN(QString(QLatin1String("cd ")
@@ -3083,7 +3084,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
break; break;
case E_UNIQUE: case E_UNIQUE:
if(args.count() != 1) { if(args.count() != 1) {
logMessage(format("unique(var) requires one argument.")); evalError(fL1S("unique(var) requires one argument."));
} else { } else {
ret = values(map(args.at(0))); ret = values(map(args.at(0)));
ret.removeDuplicates(); ret.removeDuplicates();
@@ -3141,7 +3142,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
break; break;
case E_FILES: case E_FILES:
if (args.count() != 1 && args.count() != 2) { if (args.count() != 1 && args.count() != 2) {
logMessage(format("files(pattern, recursive=false) requires one or two arguments")); evalError(fL1S("files(pattern, recursive=false) requires one or two arguments"));
} else { } else {
bool recursive = false; bool recursive = false;
if (args.count() == 2) if (args.count() == 2)
@@ -3183,7 +3184,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
break; break;
case E_REPLACE: case E_REPLACE:
if(args.count() != 3 ) { if(args.count() != 3 ) {
logMessage(format("replace(var, before, after) requires three arguments")); evalError(fL1S("replace(var, before, after) requires three arguments"));
} else { } else {
const QRegExp before(args.at(1).toQString()); const QRegExp before(args.at(1).toQString());
const QString &after(args.at(2).toQString(m_tmp2)); const QString &after(args.at(2).toQString(m_tmp2));
@@ -3196,11 +3197,11 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
} }
break; break;
case 0: case 0:
logMessage(format("'%1' is not a recognized replace function") evalError(fL1S("'%1' is not a recognized replace function")
.arg(func.toQString(m_tmp1))); .arg(func.toQString(m_tmp1)));
break; break;
default: default:
logMessage(format("Function '%1' is not implemented").arg(func.toQString(m_tmp1))); evalError(fL1S("Function '%1' is not implemented").arg(func.toQString(m_tmp1)));
break; break;
} }
@@ -3240,8 +3241,8 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
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) {
logMessage(format("defined(function, [\"test\"|\"replace\"])" evalError(fL1S("defined(function, [\"test\"|\"replace\"])"
" requires one or two arguments.")); " requires one or two arguments."));
return ReturnFalse; return ReturnFalse;
} }
if (args.count() > 1) { if (args.count() > 1) {
@@ -3249,8 +3250,8 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
return returnBool(m_functionDefs.testFunctions.contains(args[0])); return returnBool(m_functionDefs.testFunctions.contains(args[0]));
else if (args[1] == QLatin1String("replace")) else if (args[1] == QLatin1String("replace"))
return returnBool(m_functionDefs.replaceFunctions.contains(args[0])); return returnBool(m_functionDefs.replaceFunctions.contains(args[0]));
logMessage(format("defined(function, type):" evalError(fL1S("defined(function, type): unexpected type [%1].\n")
" unexpected type [%1].\n").arg(args.at(1).toQString(m_tmp1))); .arg(args.at(1).toQString(m_tmp1)));
return ReturnFalse; return ReturnFalse;
} }
return returnBool(m_functionDefs.replaceFunctions.contains(args[0]) return returnBool(m_functionDefs.replaceFunctions.contains(args[0])
@@ -3262,7 +3263,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
if (m_skipLevel || m_cumulative) if (m_skipLevel || m_cumulative)
return ReturnTrue; return ReturnTrue;
if (m_valuemapStack.isEmpty()) { if (m_valuemapStack.isEmpty()) {
logMessage(format("unexpected return().")); evalError(fL1S("unexpected return()."));
return ReturnFalse; return ReturnFalse;
} }
return ReturnReturn; return ReturnReturn;
@@ -3270,7 +3271,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
if (m_skipLevel && !m_cumulative) if (m_skipLevel && !m_cumulative)
return ReturnTrue; return ReturnTrue;
if (args.count() != 1) { if (args.count() != 1) {
logMessage(format("export(variable) requires one argument.")); evalError(fL1S("export(variable) requires one argument."));
return ReturnFalse; return ReturnFalse;
} }
const ProString &var = map(args.at(0)); const ProString &var = map(args.at(0));
@@ -3293,12 +3294,12 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
} }
case T_INFILE: case T_INFILE:
if (args.count() < 2 || args.count() > 3) { if (args.count() < 2 || args.count() > 3) {
logMessage(format("infile(file, var, [values]) requires two or three arguments.")); evalError(fL1S("infile(file, var, [values]) requires two or three arguments."));
} else { } else {
QHash<ProString, ProStringList> vars; QHash<ProString, ProStringList> vars;
QString fn = resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1))); QString fn = resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1)));
fn.detach(); fn.detach();
if (!evaluateFileInto(fn, ProFileEvaluator::EvalAuxFile, &vars, 0)) if (!evaluateFileInto(fn, ProFileEvaluatorHandler::EvalAuxFile, &vars, 0))
return ReturnFalse; return ReturnFalse;
if (args.count() == 2) if (args.count() == 2)
return returnBool(vars.contains(args.at(1))); return returnBool(vars.contains(args.at(1)));
@@ -3334,20 +3335,20 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
return ReturnFalse; return ReturnFalse;
if (m_loopLevel) if (m_loopLevel)
return ReturnBreak; return ReturnBreak;
logMessage(format("unexpected break().")); evalError(fL1S("unexpected break()."));
return ReturnFalse; return ReturnFalse;
case T_NEXT: case T_NEXT:
if (m_skipLevel) if (m_skipLevel)
return ReturnFalse; return ReturnFalse;
if (m_loopLevel) if (m_loopLevel)
return ReturnNext; return ReturnNext;
logMessage(format("unexpected next().")); evalError(fL1S("unexpected next()."));
return ReturnFalse; return ReturnFalse;
case T_IF: { case T_IF: {
if (m_skipLevel && !m_cumulative) if (m_skipLevel && !m_cumulative)
return ReturnFalse; return ReturnFalse;
if (args.count() != 1) { if (args.count() != 1) {
logMessage(format("if(condition) requires one argument.")); evalError(fL1S("if(condition) requires one argument."));
return ReturnFalse; return ReturnFalse;
} }
const ProString &cond = args.at(0); const ProString &cond = args.at(0);
@@ -3413,7 +3414,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
} }
case T_CONFIG: { case T_CONFIG: {
if (args.count() < 1 || args.count() > 2) { if (args.count() < 1 || args.count() > 2) {
logMessage(format("CONFIG(config) requires one or two arguments.")); evalError(fL1S("CONFIG(config) requires one or two arguments."));
return ReturnFalse; return ReturnFalse;
} }
if (args.count() == 1) if (args.count() == 1)
@@ -3432,7 +3433,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
} }
case T_CONTAINS: { case T_CONTAINS: {
if (args.count() < 2 || args.count() > 3) { if (args.count() < 2 || args.count() > 3) {
logMessage(format("contains(var, val) requires two or three arguments.")); evalError(fL1S("contains(var, val) requires two or three arguments."));
return ReturnFalse; return ReturnFalse;
} }
@@ -3469,7 +3470,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
} }
case T_COUNT: { case T_COUNT: {
if (args.count() != 2 && args.count() != 3) { if (args.count() != 2 && args.count() != 3) {
logMessage(format("count(var, count, op=\"equals\") requires two or three arguments.")); evalError(fL1S("count(var, count, op=\"equals\") requires two or three arguments."));
return ReturnFalse; return ReturnFalse;
} }
int cnt = values(map(args.at(0))).count(); int cnt = values(map(args.at(0))).count();
@@ -3488,8 +3489,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
|| comp == QLatin1String("=") || comp == QLatin1String("==")) { || comp == QLatin1String("=") || comp == QLatin1String("==")) {
return returnBool(cnt == val); return returnBool(cnt == val);
} else { } else {
logMessage(format("unexpected modifier to count(%2)") evalError(fL1S("unexpected modifier to count(%2)").arg(comp.toQString(m_tmp1)));
.arg(comp.toQString(m_tmp1)));
return ReturnFalse; return ReturnFalse;
} }
} }
@@ -3498,8 +3498,8 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
case T_GREATERTHAN: case T_GREATERTHAN:
case T_LESSTHAN: { case T_LESSTHAN: {
if (args.count() != 2) { if (args.count() != 2) {
logMessage(format("%1(variable, value) requires two arguments.") evalError(fL1S("%1(variable, value) requires two arguments.")
.arg(function.toQString(m_tmp1))); .arg(function.toQString(m_tmp1)));
return ReturnFalse; return ReturnFalse;
} }
const QString &rhs(args.at(1).toQString(m_tmp1)), const QString &rhs(args.at(1).toQString(m_tmp1)),
@@ -3520,8 +3520,8 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
} }
case T_EQUALS: case T_EQUALS:
if (args.count() != 2) { if (args.count() != 2) {
logMessage(format("%1(variable, value) requires two arguments.") evalError(fL1S("%1(variable, value) requires two arguments.")
.arg(function.toQString(m_tmp1))); .arg(function.toQString(m_tmp1)));
return ReturnFalse; return ReturnFalse;
} }
return returnBool(values(map(args.at(0))).join(statics.field_sep) return returnBool(values(map(args.at(0))).join(statics.field_sep)
@@ -3530,8 +3530,8 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
if (m_skipLevel && !m_cumulative) if (m_skipLevel && !m_cumulative)
return ReturnFalse; return ReturnFalse;
if (args.count() != 1) { if (args.count() != 1) {
logMessage(format("%1(variable) requires one argument.") evalError(fL1S("%1(variable) requires one argument.")
.arg(function.toQString(m_tmp1))); .arg(function.toQString(m_tmp1)));
return ReturnFalse; return ReturnFalse;
} }
QHash<ProString, ProStringList> *hsh; QHash<ProString, ProStringList> *hsh;
@@ -3549,8 +3549,8 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
if (m_skipLevel && !m_cumulative) if (m_skipLevel && !m_cumulative)
return ReturnFalse; return ReturnFalse;
if (args.count() != 1) { if (args.count() != 1) {
logMessage(format("%1(variable) requires one argument.") evalError(fL1S("%1(variable) requires one argument.")
.arg(function.toQString(m_tmp1))); .arg(function.toQString(m_tmp1)));
return ReturnFalse; return ReturnFalse;
} }
QHash<ProString, ProStringList> *hsh; QHash<ProString, ProStringList> *hsh;
@@ -3575,17 +3575,17 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
if ((args.count() == 2) || (args.count() == 3) ) { if ((args.count() == 2) || (args.count() == 3) ) {
parseInto = args.at(1).toQString(m_tmp2); parseInto = args.at(1).toQString(m_tmp2);
} else if (args.count() != 1) { } else if (args.count() != 1) {
logMessage(format("include(file, into, silent) requires one, two or three arguments.")); evalError(fL1S("include(file, into, silent) requires one, two or three arguments."));
return ReturnFalse; return ReturnFalse;
} }
QString fn = resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1))); QString fn = resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1)));
fn.detach(); fn.detach();
bool ok; bool ok;
if (parseInto.isEmpty()) { if (parseInto.isEmpty()) {
ok = evaluateFile(fn, ProFileEvaluator::EvalIncludeFile); ok = evaluateFile(fn, ProFileEvaluatorHandler::EvalIncludeFile);
} else { } else {
QHash<ProString, ProStringList> symbols; QHash<ProString, ProStringList> symbols;
if ((ok = evaluateFileInto(fn, ProFileEvaluator::EvalIncludeFile, &symbols, 0))) { if ((ok = evaluateFileInto(fn, ProFileEvaluatorHandler::EvalIncludeFile, &symbols, 0))) {
QHash<ProString, ProStringList> newMap; QHash<ProString, ProStringList> newMap;
for (QHash<ProString, ProStringList>::ConstIterator for (QHash<ProString, ProStringList>::ConstIterator
it = m_valuemapStack.top().constBegin(), it = m_valuemapStack.top().constBegin(),
@@ -3615,7 +3615,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
if (args.count() == 2) { if (args.count() == 2) {
ignore_error = isTrue(args.at(1), m_tmp2); ignore_error = isTrue(args.at(1), m_tmp2);
} else if (args.count() != 1) { } else if (args.count() != 1) {
logMessage(format("load(feature) requires one or two arguments.")); evalError(fL1S("load(feature) requires one or two arguments."));
return ReturnFalse; return ReturnFalse;
} }
// XXX ignore_error unused // XXX ignore_error unused
@@ -3626,20 +3626,21 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
return ReturnFalse; return ReturnFalse;
case T_MESSAGE: { case T_MESSAGE: {
if (args.count() != 1) { if (args.count() != 1) {
logMessage(format("%1(message) requires one argument.") evalError(fL1S("%1(message) requires one argument.")
.arg(function.toQString(m_tmp1))); .arg(function.toQString(m_tmp1)));
return ReturnFalse; return ReturnFalse;
} }
const QString &msg = expandEnvVars(args.at(0).toQString(m_tmp2)); const QString &msg = expandEnvVars(args.at(0).toQString(m_tmp2));
fileMessage(QString::fromLatin1("Project %1: %2") if (!m_skipLevel)
.arg(function.toQString(m_tmp1).toUpper(), msg)); m_handler->fileMessage(fL1S("Project %1: %2")
.arg(function.toQString(m_tmp1).toUpper(), msg));
// ### Consider real termination in non-cumulative mode // ### Consider real termination in non-cumulative mode
return returnBool(function != QLatin1String("error")); return returnBool(function != QLatin1String("error"));
} }
#if 0 // Way too dangerous to enable. #if 0 // Way too dangerous to enable.
case T_SYSTEM: { case T_SYSTEM: {
if (args.count() != 1) { if (args.count() != 1) {
logMessage(format("system(exec) requires one argument.")); evalError(fL1S("system(exec) requires one argument."));
ReturnFalse; ReturnFalse;
} }
return returnBool(system((QLatin1String("cd ") return returnBool(system((QLatin1String("cd ")
@@ -3649,7 +3650,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
#endif #endif
case T_ISEMPTY: { case T_ISEMPTY: {
if (args.count() != 1) { if (args.count() != 1) {
logMessage(format("isEmpty(var) requires one argument.")); evalError(fL1S("isEmpty(var) requires one argument."));
return ReturnFalse; return ReturnFalse;
} }
const ProStringList &sl = values(map(args.at(0))); const ProStringList &sl = values(map(args.at(0)));
@@ -3664,7 +3665,7 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
} }
case T_EXISTS: { case T_EXISTS: {
if (args.count() != 1) { if (args.count() != 1) {
logMessage(format("exists(file) requires one argument.")); evalError(fL1S("exists(file) requires one argument."));
return ReturnFalse; return ReturnFalse;
} }
const QString &file = resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1))); const QString &file = resolvePath(expandEnvVars(args.at(0).toQString(m_tmp1)));
@@ -3683,11 +3684,11 @@ ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::evaluateCondit
return ReturnFalse; return ReturnFalse;
} }
case 0: case 0:
logMessage(format("'%1' is not a recognized test function") evalError(fL1S("'%1' is not a recognized test function")
.arg(function.toQString(m_tmp1))); .arg(function.toQString(m_tmp1)));
return ReturnFalse; return ReturnFalse;
default: default:
logMessage(format("Function '%1' is not implemented").arg(function.toQString(m_tmp1))); evalError(fL1S("Function '%1' is not implemented").arg(function.toQString(m_tmp1)));
return ReturnFalse; return ReturnFalse;
} }
} }
@@ -3924,7 +3925,7 @@ ProFile *ProFileEvaluator::Private::parsedProFile(const QString &fileName, bool
} }
bool ProFileEvaluator::Private::evaluateFileDirect( bool ProFileEvaluator::Private::evaluateFileDirect(
const QString &fileName, ProFileEvaluator::EvalFileType type) const QString &fileName, ProFileEvaluatorHandler::EvalFileType type)
{ {
int lineNo = m_lineNo; int lineNo = m_lineNo;
if (ProFile *pro = parsedProFile(fileName, true)) { if (ProFile *pro = parsedProFile(fileName, true)) {
@@ -3939,13 +3940,13 @@ bool ProFileEvaluator::Private::evaluateFileDirect(
} }
bool ProFileEvaluator::Private::evaluateFile( bool ProFileEvaluator::Private::evaluateFile(
const QString &fileName, ProFileEvaluator::EvalFileType type) const QString &fileName, ProFileEvaluatorHandler::EvalFileType type)
{ {
if (fileName.isEmpty()) if (fileName.isEmpty())
return false; return false;
foreach (const ProFile *pf, m_profileStack) foreach (const ProFile *pf, m_profileStack)
if (pf->fileName() == fileName) { if (pf->fileName() == fileName) {
errorMessage(format("circular inclusion of %1").arg(fileName)); evalError(fL1S("circular inclusion of %1").arg(fileName));
return false; return false;
} }
return evaluateFileDirect(fileName, type); return evaluateFileDirect(fileName, type);
@@ -3991,13 +3992,13 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(
} }
if (values) { if (values) {
return evaluateFileInto(fn, ProFileEvaluator::EvalFeatureFile, values, funcs); return evaluateFileInto(fn, ProFileEvaluatorHandler::EvalFeatureFile, values, funcs);
} else { } else {
bool cumulative = m_cumulative; bool cumulative = m_cumulative;
m_cumulative = false; m_cumulative = false;
// The path is fully normalized already. // The path is fully normalized already.
bool ok = evaluateFileDirect(fn, ProFileEvaluator::EvalFeatureFile); bool ok = evaluateFileDirect(fn, ProFileEvaluatorHandler::EvalFeatureFile);
m_cumulative = cumulative; m_cumulative = cumulative;
return ok; return ok;
@@ -4005,13 +4006,12 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(
} }
bool ProFileEvaluator::Private::evaluateFileInto( bool ProFileEvaluator::Private::evaluateFileInto(
const QString &fileName, ProFileEvaluator::EvalFileType type, const QString &fileName, ProFileEvaluatorHandler::EvalFileType type,
QHash<ProString, ProStringList> *values, FunctionDefs *funcs) QHash<ProString, ProStringList> *values, FunctionDefs *funcs)
{ {
ProFileEvaluator visitor(m_option); ProFileEvaluator visitor(m_option, m_handler);
visitor.d->m_cumulative = false; visitor.d->m_cumulative = false;
visitor.d->m_parsePreAndPostFiles = false; visitor.d->m_parsePreAndPostFiles = false;
visitor.d->m_verbose = m_verbose;
visitor.d->m_valuemapStack.top() = *values; visitor.d->m_valuemapStack.top() = *values;
if (funcs) if (funcs)
visitor.d->m_functionDefs = *funcs; visitor.d->m_functionDefs = *funcs;
@@ -4023,30 +4023,15 @@ bool ProFileEvaluator::Private::evaluateFileInto(
return true; return true;
} }
QString ProFileEvaluator::Private::format(const char *fmt) const void ProFileEvaluator::Private::parseError(const QString &message) const
{ {
ProFile *pro = currentProFile(); m_handler->parseError(currentFileName(), m_lineNo, message);
QString fileName = pro ? pro->fileName() : QLatin1String("Not a file");
int lineNumber = pro ? m_lineNo : 0;
return QString::fromLatin1("%1(%2):").arg(fileName).arg(lineNumber) + QString::fromAscii(fmt);
} }
void ProFileEvaluator::Private::logMessage(const QString &message) const void ProFileEvaluator::Private::evalError(const QString &message) const
{
if (m_verbose && !m_skipLevel)
q->logMessage(message);
}
void ProFileEvaluator::Private::fileMessage(const QString &message) const
{ {
if (!m_skipLevel) if (!m_skipLevel)
q->fileMessage(message); m_handler->evalError(currentFileName(), m_lineNo, message);
}
void ProFileEvaluator::Private::errorMessage(const QString &message) const
{
if (!m_skipLevel)
q->errorMessage(message);
} }
@@ -4061,8 +4046,9 @@ void ProFileEvaluator::initialize()
Private::initStatics(); Private::initStatics();
} }
ProFileEvaluator::ProFileEvaluator(ProFileOption *option) ProFileEvaluator::ProFileEvaluator(ProFileOption *option,
: d(new Private(this, option)) ProFileEvaluatorHandler *handler)
: d(new Private(this, option, handler))
{ {
} }
@@ -4185,7 +4171,7 @@ ProFile *ProFileEvaluator::parsedProFile(const QString &fileName, const QString
bool ProFileEvaluator::accept(ProFile *pro) bool ProFileEvaluator::accept(ProFile *pro)
{ {
return d->visitProFile(pro, ProFileEvaluator::EvalProjectFile); return d->visitProFile(pro, ProFileEvaluatorHandler::EvalProjectFile);
} }
QString ProFileEvaluator::propertyValue(const QString &name) const QString ProFileEvaluator::propertyValue(const QString &name) const
@@ -4193,34 +4179,6 @@ QString ProFileEvaluator::propertyValue(const QString &name) const
return d->propertyValue(name); return d->propertyValue(name);
} }
void ProFileEvaluator::aboutToEval(ProFile *, ProFile *, EvalFileType)
{
}
void ProFileEvaluator::doneWithEval(ProFile *)
{
}
void ProFileEvaluator::logMessage(const QString &message)
{
qWarning("%s", qPrintable(message));
}
void ProFileEvaluator::fileMessage(const QString &message)
{
qWarning("%s", qPrintable(message));
}
void ProFileEvaluator::errorMessage(const QString &message)
{
qWarning("%s", qPrintable(message));
}
void ProFileEvaluator::setVerbose(bool on)
{
d->m_verbose = on;
}
void ProFileEvaluator::setCumulative(bool on) void ProFileEvaluator::setCumulative(bool on)
{ {
d->m_cumulative = on; d->m_cumulative = on;

View File

@@ -45,6 +45,24 @@ QT_BEGIN_NAMESPACE
struct ProFileOption; struct ProFileOption;
class ProFileEvaluatorHandler
{
public:
// Some error during parsing
virtual void parseError(const QString &filename, int lineNo, const QString &msg) = 0;
// qmake/project configuration error
virtual void configError(const QString &msg) = 0;
// Some error during evaluation
virtual void evalError(const QString &filename, int lineNo, const QString &msg) = 0;
// error() and message() from .pro file
virtual void fileMessage(const QString &msg) = 0;
enum EvalFileType { EvalProjectFile, EvalIncludeFile, EvalConfigFile, EvalFeatureFile, EvalAuxFile };
virtual void aboutToEval(ProFile *parent, ProFile *proFile, EvalFileType type) = 0;
virtual void doneWithEval(ProFile *parent) = 0;
};
class ProFileEvaluator class ProFileEvaluator
{ {
class Private; class Private;
@@ -71,11 +89,10 @@ public:
// Call this from a concurrency-free context // Call this from a concurrency-free context
static void initialize(); static void initialize();
ProFileEvaluator(ProFileOption *option); ProFileEvaluator(ProFileOption *option, ProFileEvaluatorHandler *handler);
virtual ~ProFileEvaluator(); ~ProFileEvaluator();
ProFileEvaluator::TemplateType templateType() const; ProFileEvaluator::TemplateType templateType() const;
void setVerbose(bool on); // Default is false
void setCumulative(bool on); // Default is true! void setCumulative(bool on); // Default is true!
void setOutputDir(const QString &dir); // Default is empty void setOutputDir(const QString &dir); // Default is empty
@@ -99,14 +116,6 @@ public:
const ProFile *pro) const; const ProFile *pro) const;
QString propertyValue(const QString &val) const; QString propertyValue(const QString &val) const;
// for our descendents
enum EvalFileType { EvalProjectFile, EvalIncludeFile, EvalConfigFile, EvalFeatureFile, EvalAuxFile };
virtual void aboutToEval(ProFile *parent, ProFile *proFile, EvalFileType type);
virtual void doneWithEval(ProFile *parent);
virtual void logMessage(const QString &msg);
virtual void errorMessage(const QString &msg); // .pro parse errors
virtual void fileMessage(const QString &msg); // error() and message() from .pro file
private: private:
Private *d; Private *d;

View File

@@ -39,6 +39,31 @@
#include <QtCore/QStringList> #include <QtCore/QStringList>
#include <QtCore/QTextCodec> #include <QtCore/QTextCodec>
static void print(const QString &fileName, int lineNo, const QString &msg)
{
if (lineNo)
qWarning("%s(%d): %s", qPrintable(fileName), lineNo, qPrintable(msg));
else
qWarning("%s", qPrintable(msg));
}
class EvalHandler : public ProFileEvaluatorHandler {
public:
virtual void parseError(const QString &fileName, int lineNo, const QString &msg)
{ print(fileName, lineNo, msg); }
virtual void configError(const QString &msg)
{ qWarning("%s", qPrintable(msg)); }
virtual void evalError(const QString &fileName, int lineNo, const QString &msg)
{ print(fileName, lineNo, msg); }
virtual void fileMessage(const QString &msg)
{ qWarning("%s", qPrintable(msg)); }
virtual void aboutToEval(ProFile *, ProFile *, EvalFileType) {}
virtual void doneWithEval(ProFile *) {}
};
static EvalHandler evalHandler;
static QString value(ProFileEvaluator &reader, const QString &variable) static QString value(ProFileEvaluator &reader, const QString &variable)
{ {
QStringList vals = reader.values(variable); QStringList vals = reader.values(variable);
@@ -56,8 +81,7 @@ static int evaluate(const QString &fileName, const QString &in_pwd, const QStrin
return 0; return 0;
visited.insert(fileName); visited.insert(fileName);
ProFileEvaluator visitor(option); ProFileEvaluator visitor(option, &evalHandler);
visitor.setVerbose(true);
visitor.setCumulative(cumulative); visitor.setCumulative(cumulative);
visitor.setOutputDir(out_pwd); visitor.setOutputDir(out_pwd);