summaryrefslogtreecommitdiffstats
path: root/tools/linguist
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@nokia.com>2009-05-18 15:46:30 (GMT)
committerOswald Buddenhagen <oswald.buddenhagen@nokia.com>2009-07-20 12:30:35 (GMT)
commit7074ea4c4160f50aa40aade5cd983df6ea9ebacd (patch)
treea160c7b4830897424f2cb197cfad4600249bcc7b /tools/linguist
parentabf8b1c273776fa16afacd04e7bb3c5c07a35ab7 (diff)
downloadQt-7074ea4c4160f50aa40aade5cd983df6ea9ebacd.zip
Qt-7074ea4c4160f50aa40aade5cd983df6ea9ebacd.tar.gz
Qt-7074ea4c4160f50aa40aade5cd983df6ea9ebacd.tar.bz2
support custom functions: implement defineTest(), defineReplace(), defined(), return() & export()
cherry-picked d077ba29c34782d1699693b6e3f07c2037eecdba and 93571f7d42a81a8236ceac1f745ef277f194f1ca from creator
Diffstat (limited to 'tools/linguist')
-rw-r--r--tools/linguist/shared/abstractproitemvisitor.h9
-rw-r--r--tools/linguist/shared/profileevaluator.cpp293
-rw-r--r--tools/linguist/shared/proitems.cpp61
-rw-r--r--tools/linguist/shared/proitems.h30
4 files changed, 283 insertions, 110 deletions
diff --git a/tools/linguist/shared/abstractproitemvisitor.h b/tools/linguist/shared/abstractproitemvisitor.h
index 0f312ae..dd72dfe 100644
--- a/tools/linguist/shared/abstractproitemvisitor.h
+++ b/tools/linguist/shared/abstractproitemvisitor.h
@@ -49,17 +49,18 @@ QT_BEGIN_NAMESPACE
struct AbstractProItemVisitor
{
virtual ~AbstractProItemVisitor() {}
- virtual void visitBeginProBlock(ProBlock *block) = 0;
+
+ virtual ProItem::ProItemReturn visitBeginProBlock(ProBlock *block) = 0;
virtual void visitEndProBlock(ProBlock *block) = 0;
virtual void visitBeginProVariable(ProVariable *variable) = 0;
virtual void visitEndProVariable(ProVariable *variable) = 0;
- virtual bool visitBeginProFile(ProFile *value) = 0;
- virtual bool visitEndProFile(ProFile *value) = 0;
+ virtual ProItem::ProItemReturn visitBeginProFile(ProFile *value) = 0;
+ virtual ProItem::ProItemReturn visitEndProFile(ProFile *value) = 0;
virtual void visitProValue(ProValue *value) = 0;
- virtual void visitProFunction(ProFunction *function) = 0;
+ virtual ProItem::ProItemReturn visitProFunction(ProFunction *function) = 0;
virtual void visitProOperator(ProOperator *function) = 0;
virtual void visitProCondition(ProCondition *function) = 0;
};
diff --git a/tools/linguist/shared/profileevaluator.cpp b/tools/linguist/shared/profileevaluator.cpp
index 71d1d61..c17f9f6 100644
--- a/tools/linguist/shared/profileevaluator.cpp
+++ b/tools/linguist/shared/profileevaluator.cpp
@@ -171,14 +171,14 @@ public:
/////////////// Evaluating pro file contents
// implementation of AbstractProItemVisitor
- void visitBeginProBlock(ProBlock *block);
+ ProItem::ProItemReturn visitBeginProBlock(ProBlock *block);
void visitEndProBlock(ProBlock *block);
void visitBeginProVariable(ProVariable *variable);
void visitEndProVariable(ProVariable *variable);
- bool visitBeginProFile(ProFile *value);
- bool visitEndProFile(ProFile *value);
+ ProItem::ProItemReturn visitBeginProFile(ProFile *value);
+ ProItem::ProItemReturn visitEndProFile(ProFile *value);
void visitProValue(ProValue *value);
- void visitProFunction(ProFunction *function);
+ ProItem::ProItemReturn visitProFunction(ProFunction *function);
void visitProOperator(ProOperator *oper);
void visitProCondition(ProCondition *condition);
@@ -198,10 +198,15 @@ public:
QString currentDirectory() const;
ProFile *currentProFile() const;
- bool evaluateConditionalFunction(const QString &function, const QString &arguments);
+ ProItem::ProItemReturn evaluateConditionalFunction(const QString &function, const QString &arguments);
bool evaluateFile(const QString &fileName);
bool evaluateFeatureFile(const QString &fileName);
+ static inline ProItem::ProItemReturn returnBool(bool b)
+ { return b ? ProItem::ReturnTrue : ProItem::ReturnFalse; }
+
+ QStringList evaluateFunction(ProBlock *funcPtr, const QStringList &argumentsList, bool *ok);
+
QStringList qmakeFeaturePaths();
struct State {
@@ -228,6 +233,14 @@ public:
QHash<QString, QString> m_properties;
QString m_outputDir;
+ bool m_definingTest;
+ QString m_definingFunc;
+ QHash<QString, ProBlock *> m_testFunctions;
+ QHash<QString, ProBlock *> m_replaceFunctions;
+ QStringList m_returnValue;
+ QStack<QHash<QString, QStringList> > m_valuemapStack;
+ QStack<QHash<const ProFile*, QHash<QString, QStringList> > > m_filevaluemapStack;
+
int m_prevLineNo; // Checking whether we're assigning the same TARGET
ProFile *m_prevProFile; // See m_prevLineNo
};
@@ -253,6 +266,7 @@ ProFileEvaluator::Private::Private(ProFileEvaluator *q_)
m_invertNext = false;
m_skipLevel = 0;
m_isFirstVariableValue = true;
+ m_definingFunc.clear();
}
bool ProFileEvaluator::Private::read(ProFile *pro)
@@ -564,13 +578,27 @@ void ProFileEvaluator::Private::updateItem()
}
-void ProFileEvaluator::Private::visitBeginProBlock(ProBlock *block)
+ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProBlock(ProBlock *block)
{
if (block->blockKind() & ProBlock::ScopeContentsKind) {
- if (!m_sts.condition)
- ++m_skipLevel;
- else
- Q_ASSERT(!m_skipLevel);
+ if (!m_definingFunc.isEmpty()) {
+ if (!m_skipLevel || m_cumulative) {
+ QHash<QString, ProBlock *> *hash =
+ (m_definingTest ? &m_testFunctions : &m_replaceFunctions);
+ if (ProBlock *def = hash->value(m_definingFunc))
+ def->deref();
+ hash->insert(m_definingFunc, block);
+ block->ref();
+ block->setBlockKind(block->blockKind() | ProBlock::FunctionBodyKind);
+ }
+ m_definingFunc.clear();
+ return ProItem::ReturnSkip;
+ } else if (!(block->blockKind() & ProBlock::FunctionBodyKind)) {
+ if (!m_sts.condition)
+ ++m_skipLevel;
+ else
+ Q_ASSERT(!m_skipLevel);
+ }
} else {
if (!m_skipLevel) {
if (m_sts.condition) {
@@ -581,11 +609,13 @@ void ProFileEvaluator::Private::visitBeginProBlock(ProBlock *block)
Q_ASSERT(!m_sts.condition);
}
}
+ return ProItem::ReturnTrue;
}
void ProFileEvaluator::Private::visitEndProBlock(ProBlock *block)
{
- if (block->blockKind() & ProBlock::ScopeContentsKind) {
+ if ((block->blockKind() & ProBlock::ScopeContentsKind)
+ && !(block->blockKind() & ProBlock::FunctionBodyKind)) {
if (m_skipLevel) {
Q_ASSERT(!m_sts.condition);
--m_skipLevel;
@@ -633,10 +663,9 @@ void ProFileEvaluator::Private::visitProCondition(ProCondition *cond)
m_invertNext = false;
}
-bool ProFileEvaluator::Private::visitBeginProFile(ProFile * pro)
+ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProFile(ProFile * pro)
{
PRE(pro);
- bool ok = true;
m_lineNo = pro->lineNumber();
if (m_origfile.isEmpty())
m_origfile = pro->fileName();
@@ -660,16 +689,15 @@ bool ProFileEvaluator::Private::visitBeginProFile(ProFile * pro)
m_cumulative = cumulative;
}
- ok = QDir::setCurrent(pro->directoryName());
+ return returnBool(QDir::setCurrent(pro->directoryName()));
}
- return ok;
+ return ProItem::ReturnTrue;
}
-bool ProFileEvaluator::Private::visitEndProFile(ProFile * pro)
+ProItem::ProItemReturn ProFileEvaluator::Private::visitEndProFile(ProFile * pro)
{
PRE(pro);
- bool ok = true;
m_lineNo = pro->lineNumber();
if (m_profileStack.count() == 1 && !m_oldPath.isEmpty()) {
const QString &mkspecDirectory = propertyValue(QLatin1String("QMAKE_MKSPECS"));
@@ -698,13 +726,21 @@ bool ProFileEvaluator::Private::visitEndProFile(ProFile * pro)
break;
}
+ foreach (ProBlock *itm, m_replaceFunctions)
+ itm->deref();
+ m_replaceFunctions.clear();
+ foreach (ProBlock *itm, m_testFunctions)
+ itm->deref();
+ m_testFunctions.clear();
+
m_cumulative = cumulative;
}
m_profileStack.pop();
- ok = QDir::setCurrent(m_oldPath);
+ return returnBool(QDir::setCurrent(m_oldPath));
}
- return ok;
+
+ return ProItem::ReturnTrue;
}
static void replaceInList(QStringList *varlist,
@@ -834,7 +870,7 @@ void ProFileEvaluator::Private::visitProValue(ProValue *value)
m_isFirstVariableValue = false;
}
-void ProFileEvaluator::Private::visitProFunction(ProFunction *func)
+ProItem::ProItemReturn ProFileEvaluator::Private::visitProFunction(ProFunction *func)
{
// Make sure that called subblocks don't inherit & destroy the state
bool invertThis = m_invertNext;
@@ -849,10 +885,13 @@ void ProFileEvaluator::Private::visitProFunction(ProFunction *func)
QString arguments = text.mid(lparen + 1, rparen - lparen - 1);
QString funcName = text.left(lparen);
m_lineNo = func->lineNumber();
- bool result = evaluateConditionalFunction(funcName.trimmed(), arguments);
- if (!m_skipLevel && (result ^ invertThis))
+ ProItem::ProItemReturn result = evaluateConditionalFunction(funcName.trimmed(), arguments);
+ if (result != ProItem::ReturnFalse && result != ProItem::ReturnTrue)
+ return result;
+ if (!m_skipLevel && ((result == ProItem::ReturnTrue) ^ invertThis))
m_sts.condition = true;
}
+ return ProItem::ReturnTrue;
}
@@ -1192,10 +1231,49 @@ bool ProFileEvaluator::Private::isActiveConfig(const QString &config, bool regex
return false;
}
+QStringList ProFileEvaluator::Private::evaluateFunction(
+ ProBlock *funcPtr, const QStringList &argumentsList, bool *ok)
+{
+ bool oki;
+ QStringList ret;
+
+ if (m_valuemapStack.count() >= 100) {
+ q->errorMessage(format("ran into infinite recursion (depth > 100)."));
+ oki = false;
+ } else {
+ State sts = m_sts;
+ m_valuemapStack.push(m_valuemap);
+ m_filevaluemapStack.push(m_filevaluemap);
+
+ QStringList args;
+ for (int i = 0; i < argumentsList.count(); ++i) {
+ QStringList theArgs = expandVariableReferences(argumentsList[i]);
+ args += theArgs;
+ m_valuemap[QString::number(i+1)] = theArgs;
+ }
+ m_valuemap[QLatin1String("ARGS")] = args;
+ oki = (funcPtr->Accept(this) != ProItem::ReturnFalse); // True || Return
+ ret = m_returnValue;
+ m_returnValue.clear();
+
+ m_valuemap = m_valuemapStack.pop();
+ m_filevaluemap = m_filevaluemapStack.pop();
+ m_sts = sts;
+ }
+ if (ok)
+ *ok = oki;
+ if (oki)
+ return ret;
+ return QStringList();
+}
+
QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &func, const QString &arguments)
{
QStringList argumentsList = split_arg_list(arguments);
+ if (ProBlock *funcPtr = m_replaceFunctions.value(func, 0))
+ return evaluateFunction(funcPtr, argumentsList, 0);
+
QStringList args;
for (int i = 0; i < argumentsList.count(); ++i)
args += expandVariableReferences(argumentsList[i]).join(Option::field_sep);
@@ -1600,13 +1678,40 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
return ret;
}
-bool ProFileEvaluator::Private::evaluateConditionalFunction(
+ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
const QString &function, const QString &arguments)
{
QStringList argumentsList = split_arg_list(arguments);
+
+ if (ProBlock *funcPtr = m_testFunctions.value(function, 0)) {
+ bool ok;
+ QStringList ret = evaluateFunction(funcPtr, argumentsList, &ok);
+ if (ok) {
+ if (ret.isEmpty()) {
+ return ProItem::ReturnTrue;
+ } else {
+ if (ret.first() != QLatin1String("false")) {
+ if (ret.first() == QLatin1String("true")) {
+ return ProItem::ReturnTrue;
+ } else {
+ bool ok;
+ int val = ret.first().toInt(&ok);
+ if (ok) {
+ if (val)
+ return ProItem::ReturnTrue;
+ } else {
+ q->logMessage(format("Unexpected return value from test '%1': %2")
+ .arg(function).arg(ret.join(QLatin1String(" :: "))));
+ }
+ }
+ }
+ }
+ }
+ return ProItem::ReturnFalse;
+ }
+
QString sep;
sep.append(Option::field_sep);
-
QStringList args;
for (int i = 0; i < argumentsList.count(); ++i)
args += expandVariableReferences(argumentsList[i]).join(sep);
@@ -1614,7 +1719,8 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(
enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS,
T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE,
- T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_MESSAGE, T_IF };
+ T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_MESSAGE, T_IF,
+ T_DEFINE_TEST, T_DEFINE_REPLACE };
static QHash<QString, int> *functions = 0;
if (!functions) {
@@ -1647,51 +1753,103 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(
functions->insert(QLatin1String("message"), T_MESSAGE); //v
functions->insert(QLatin1String("warning"), T_MESSAGE); //v
functions->insert(QLatin1String("error"), T_MESSAGE); //v
+ functions->insert(QLatin1String("defineTest"), T_DEFINE_TEST); //v
+ functions->insert(QLatin1String("defineReplace"), T_DEFINE_REPLACE); //v
}
TestFunc func_t = (TestFunc)functions->value(function);
switch (func_t) {
+ case T_DEFINE_TEST:
+ m_definingTest = true;
+ goto defineFunc;
+ case T_DEFINE_REPLACE:
+ m_definingTest = false;
+ defineFunc:
+ if (args.count() != 1) {
+ q->logMessage(format("%s(function) requires one argument.").arg(function));
+ return ProItem::ReturnFalse;
+ }
+ m_definingFunc = args.first();
+ return ProItem::ReturnTrue;
+ case T_DEFINED:
+ if (args.count() < 1 || args.count() > 2) {
+ q->logMessage(format("defined(function, [\"test\"|\"replace\"])"
+ " requires one or two arguments."));
+ return ProItem::ReturnFalse;
+ }
+ if (args.count() > 1) {
+ if (args[1] == QLatin1String("test"))
+ return returnBool(m_testFunctions.contains(args[0]));
+ else if (args[1] == QLatin1String("replace"))
+ return returnBool(m_replaceFunctions.contains(args[0]));
+ q->logMessage(format("defined(function, type):"
+ " unexpected type [%1].\n").arg(args[1]));
+ return ProItem::ReturnFalse;
+ }
+ return returnBool(m_replaceFunctions.contains(args[0])
+ || m_testFunctions.contains(args[0]));
+ case T_RETURN:
+ m_returnValue = args;
+ // It is "safe" to ignore returns - due to qmake brokeness
+ // they cannot be used to terminate loops anyway.
+ if (m_skipLevel || m_cumulative)
+ return ProItem::ReturnTrue;
+ if (m_valuemapStack.isEmpty()) {
+ q->logMessage(format("unexpected return()."));
+ return ProItem::ReturnFalse;
+ }
+ return ProItem::ReturnReturn;
+ case T_EXPORT:
+ if (m_skipLevel && !m_cumulative)
+ return ProItem::ReturnTrue;
+ if (args.count() != 1) {
+ q->logMessage(format("export(variable) requires one argument."));
+ return ProItem::ReturnFalse;
+ }
+ for (int i = 0; i < m_valuemapStack.size(); ++i) {
+ m_valuemapStack[i][args[0]] = m_valuemap[args[0]];
+ m_filevaluemapStack[i][currentProFile()][args[0]] =
+ m_filevaluemap[currentProFile()][args[0]];
+ }
+ return ProItem::ReturnTrue;
#if 0
case T_INFILE:
case T_REQUIRES:
case T_GREATERTHAN:
case T_LESSTHAN:
case T_EQUALS:
- case T_EXPORT:
case T_CLEAR:
case T_UNSET:
case T_EVAL:
case T_IF:
- case T_RETURN:
case T_BREAK:
case T_NEXT:
- case T_DEFINED:
#endif
case T_CONFIG: {
if (args.count() < 1 || args.count() > 2) {
q->logMessage(format("CONFIG(config) requires one or two arguments."));
- return false;
+ return ProItem::ReturnFalse;
}
if (args.count() == 1) {
//cond = isActiveConfig(args.first()); XXX
- return false;
+ return ProItem::ReturnFalse;
}
const QStringList mutuals = args[1].split(QLatin1Char('|'));
const QStringList &configs = valuesDirect(QLatin1String("CONFIG"));
for (int i = configs.size() - 1; i >= 0; i--) {
for (int mut = 0; mut < mutuals.count(); mut++) {
if (configs[i] == mutuals[mut].trimmed()) {
- return (configs[i] == args[0]);
+ return returnBool(configs[i] == args[0]);
}
}
}
- return false;
+ return ProItem::ReturnFalse;
}
case T_CONTAINS: {
if (args.count() < 2 || args.count() > 3) {
q->logMessage(format("contains(var, val) requires two or three arguments."));
- return false;
+ return ProItem::ReturnFalse;
}
QRegExp regx(args[1]);
@@ -1700,7 +1858,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(
for (int i = 0; i < l.size(); ++i) {
const QString val = l[i];
if (regx.exactMatch(val) || val == args[1]) {
- return true;
+ return ProItem::ReturnTrue;
}
}
} else {
@@ -1709,47 +1867,47 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(
const QString val = l[i];
for (int mut = 0; mut < mutuals.count(); mut++) {
if (val == mutuals[mut].trimmed()) {
- return (regx.exactMatch(val) || val == args[1]);
+ return returnBool(regx.exactMatch(val) || val == args[1]);
}
}
}
}
- return false;
+ return ProItem::ReturnFalse;
}
case T_COUNT: {
if (args.count() != 2 && args.count() != 3) {
q->logMessage(format("count(var, count, op=\"equals\") requires two or three arguments."));
- return false;
+ return ProItem::ReturnFalse;
}
if (args.count() == 3) {
QString comp = args[2];
if (comp == QLatin1String(">") || comp == QLatin1String("greaterThan")) {
- return (values(args.first()).count() > args[1].toInt());
+ return returnBool(values(args.first()).count() > args[1].toInt());
} else if (comp == QLatin1String(">=")) {
- return (values(args.first()).count() >= args[1].toInt());
+ return returnBool(values(args.first()).count() >= args[1].toInt());
} else if (comp == QLatin1String("<") || comp == QLatin1String("lessThan")) {
- return (values(args.first()).count() < args[1].toInt());
+ return returnBool(values(args.first()).count() < args[1].toInt());
} else if (comp == QLatin1String("<=")) {
- return (values(args.first()).count() <= args[1].toInt());
+ return returnBool(values(args.first()).count() <= args[1].toInt());
} else if (comp == QLatin1String("equals") || comp == QLatin1String("isEqual")
|| comp == QLatin1String("=") || comp == QLatin1String("==")) {
- return (values(args.first()).count() == args[1].toInt());
+ return returnBool(values(args.first()).count() == args[1].toInt());
} else {
q->logMessage(format("unexpected modifier to count(%2)").arg(comp));
- return false;
+ return ProItem::ReturnFalse;
}
}
- return (values(args.first()).count() == args[1].toInt());
+ return returnBool(values(args.first()).count() == args[1].toInt());
}
case T_INCLUDE: {
if (m_skipLevel && !m_cumulative)
- return false;
+ return ProItem::ReturnFalse;
QString parseInto;
if (args.count() == 2) {
parseInto = args[1];
} else if (args.count() != 1) {
q->logMessage(format("include(file) requires one or two arguments."));
- return false;
+ return ProItem::ReturnFalse;
}
QString fileName = args.first();
// ### this breaks if we have include(c:/reallystupid.pri) but IMHO that's really bad style.
@@ -1758,11 +1916,11 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(
State sts = m_sts;
bool ok = evaluateFile(fileName);
m_sts = sts;
- return ok;
+ return returnBool(ok);
}
case T_LOAD: {
if (m_skipLevel && !m_cumulative)
- return false;
+ return ProItem::ReturnFalse;
QString parseInto;
bool ignore_error = false;
if (args.count() == 2) {
@@ -1770,18 +1928,18 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(
ignore_error = (sarg.toLower() == QLatin1String("true") || sarg.toInt());
} else if (args.count() != 1) {
q->logMessage(format("load(feature) requires one or two arguments."));
- return false;
+ return ProItem::ReturnFalse;
}
// XXX ignore_error unused
- return evaluateFeatureFile(args.first());
+ return returnBool(evaluateFeatureFile(args.first()));
}
case T_DEBUG:
// Yup - do nothing. Nothing is going to enable debug output anyway.
- return false;
+ return ProItem::ReturnFalse;
case T_MESSAGE: {
if (args.count() != 1) {
q->logMessage(format("%1(message) requires one argument.").arg(function));
- return false;
+ return ProItem::ReturnFalse;
}
QString msg = fixEnvVariables(args.first());
if (function == QLatin1String("error")) {
@@ -1798,42 +1956,42 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(
} else {
q->fileMessage(format("Project MESSAGE: %1").arg(msg));
}
- return false;
+ return ProItem::ReturnFalse;
}
#if 0 // Way too dangerous to enable.
case T_SYSTEM: {
if (args.count() != 1) {
q->logMessage(format("system(exec) requires one argument."));
- false;
+ ProItem::ReturnFalse;
}
- return (system(args.first().toLatin1().constData()) == 0);
+ return returnBool(system(args.first().toLatin1().constData()) == 0);
}
#endif
case T_ISEMPTY: {
if (args.count() != 1) {
q->logMessage(format("isEmpty(var) requires one argument."));
- return false;
+ return ProItem::ReturnFalse;
}
QStringList sl = values(args.first());
if (sl.count() == 0) {
- return true;
+ return ProItem::ReturnTrue;
} else if (sl.count() > 0) {
QString var = sl.first();
if (var.isEmpty())
- return true;
+ return ProItem::ReturnTrue;
}
- return false;
+ return ProItem::ReturnFalse;
}
case T_EXISTS: {
if (args.count() != 1) {
q->logMessage(format("exists(file) requires one argument."));
- return false;
+ return ProItem::ReturnFalse;
}
QString file = args.first();
file = Option::fixPathToLocalOS(file);
if (QFile::exists(file)) {
- return true;
+ return ProItem::ReturnTrue;
}
//regular expression I guess
QString dirstr = currentDirectory();
@@ -1844,17 +2002,16 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(
}
if (file.contains(QLatin1Char('*')) || file.contains(QLatin1Char('?')))
if (!QDir(dirstr).entryList(QStringList(file)).isEmpty())
- return true;
+ return ProItem::ReturnTrue;
- return false;
+ return ProItem::ReturnFalse;
}
case 0:
- // This is too chatty currently (missing defineTest and defineReplace)
- //q->logMessage(format("'%1' is not a recognized test function").arg(function));
- return false;
+ q->logMessage(format("'%1' is not a recognized test function").arg(function));
+ return ProItem::ReturnFalse;
default:
q->logMessage(format("Function '%1' is not implemented").arg(function));
- return false;
+ return ProItem::ReturnFalse;
}
}
@@ -2013,7 +2170,7 @@ bool ProFileEvaluator::Private::evaluateFile(const QString &fileName)
ProFile *pro = q->parsedProFile(fileName);
if (pro) {
m_profileStack.push(pro);
- bool ok = pro->Accept(this);
+ bool ok = (pro->Accept(this) == ProItem::ReturnTrue);
m_profileStack.pop();
q->releaseParsedProFile(pro);
return ok;
diff --git a/tools/linguist/shared/proitems.cpp b/tools/linguist/shared/proitems.cpp
index 83d4a0f..0d9f5c4 100644
--- a/tools/linguist/shared/proitems.cpp
+++ b/tools/linguist/shared/proitems.cpp
@@ -58,15 +58,21 @@ QString ProItem::comment() const
}
// --------------- ProBlock ----------------
+
ProBlock::ProBlock(ProBlock *parent)
{
m_blockKind = 0;
m_parent = parent;
+ m_refCount = 1;
}
ProBlock::~ProBlock()
{
- qDeleteAll(m_proitems);
+ foreach (ProItem *itm, m_proitems)
+ if (itm->kind() == BlockKind)
+ static_cast<ProBlock *>(itm)->deref();
+ else
+ delete itm;
}
void ProBlock::appendItem(ProItem *proitem)
@@ -109,15 +115,16 @@ ProItem::ProItemKind ProBlock::kind() const
return ProItem::BlockKind;
}
-bool ProBlock::Accept(AbstractProItemVisitor *visitor)
+ProItem::ProItemReturn ProBlock::Accept(AbstractProItemVisitor *visitor)
{
- visitor->visitBeginProBlock(this);
- foreach (ProItem *item, m_proitems) {
- if (!item->Accept(visitor))
- return false;
- }
+ if (visitor->visitBeginProBlock(this) == ReturnSkip)
+ return ReturnTrue;
+ ProItemReturn rt = ReturnTrue;
+ foreach (ProItem *item, m_proitems)
+ if ((rt = item->Accept(visitor)) != ReturnTrue && rt != ReturnFalse)
+ break;
visitor->visitEndProBlock(this);
- return true;
+ return rt;
}
// --------------- ProVariable ----------------
@@ -149,15 +156,13 @@ QString ProVariable::variable() const
return m_variable;
}
-bool ProVariable::Accept(AbstractProItemVisitor *visitor)
+ProItem::ProItemReturn ProVariable::Accept(AbstractProItemVisitor *visitor)
{
visitor->visitBeginProVariable(this);
- foreach (ProItem *item, m_proitems) {
- if (!item->Accept(visitor))
- return false;
- }
+ foreach (ProItem *item, m_proitems)
+ item->Accept(visitor); // cannot fail
visitor->visitEndProVariable(this);
- return true;
+ return ReturnTrue;
}
// --------------- ProValue ----------------
@@ -192,10 +197,10 @@ ProItem::ProItemKind ProValue::kind() const
return ProItem::ValueKind;
}
-bool ProValue::Accept(AbstractProItemVisitor *visitor)
+ProItem::ProItemReturn ProValue::Accept(AbstractProItemVisitor *visitor)
{
visitor->visitProValue(this);
- return true;
+ return ReturnTrue;
}
// --------------- ProFunction ----------------
@@ -219,10 +224,9 @@ ProItem::ProItemKind ProFunction::kind() const
return ProItem::FunctionKind;
}
-bool ProFunction::Accept(AbstractProItemVisitor *visitor)
+ProItem::ProItemReturn ProFunction::Accept(AbstractProItemVisitor *visitor)
{
- visitor->visitProFunction(this);
- return true;
+ return visitor->visitProFunction(this);
}
// --------------- ProCondition ----------------
@@ -246,10 +250,10 @@ ProItem::ProItemKind ProCondition::kind() const
return ProItem::ConditionKind;
}
-bool ProCondition::Accept(AbstractProItemVisitor *visitor)
+ProItem::ProItemReturn ProCondition::Accept(AbstractProItemVisitor *visitor)
{
visitor->visitProCondition(this);
- return true;
+ return ReturnTrue;
}
// --------------- ProOperator ----------------
@@ -273,10 +277,10 @@ ProItem::ProItemKind ProOperator::kind() const
return ProItem::OperatorKind;
}
-bool ProOperator::Accept(AbstractProItemVisitor *visitor)
+ProItem::ProItemReturn ProOperator::Accept(AbstractProItemVisitor *visitor)
{
visitor->visitProOperator(this);
- return true;
+ return ReturnTrue;
}
// --------------- ProFile ----------------
@@ -321,13 +325,12 @@ bool ProFile::isModified() const
return m_modified;
}
-bool ProFile::Accept(AbstractProItemVisitor *visitor)
+ProItem::ProItemReturn ProFile::Accept(AbstractProItemVisitor *visitor)
{
- visitor->visitBeginProFile(this);
- foreach (ProItem *item, m_proitems) {
- if (!item->Accept(visitor))
- return false;
- }
+ ProItemReturn rt;
+ if ((rt = visitor->visitBeginProFile(this)) != ReturnTrue)
+ return rt;
+ ProBlock::Accept(visitor); // cannot fail
return visitor->visitEndProFile(this);
}
diff --git a/tools/linguist/shared/proitems.h b/tools/linguist/shared/proitems.h
index aad0ba2..be086ac 100644
--- a/tools/linguist/shared/proitems.h
+++ b/tools/linguist/shared/proitems.h
@@ -60,6 +60,13 @@ public:
BlockKind
};
+ enum ProItemReturn {
+ ReturnFalse,
+ ReturnTrue,
+ ReturnSkip,
+ ReturnReturn
+ };
+
ProItem() : m_lineNumber(0) {}
virtual ~ProItem() {}
@@ -68,7 +75,7 @@ public:
void setComment(const QString &comment);
QString comment() const;
- virtual bool Accept(AbstractProItemVisitor *visitor) = 0;
+ virtual ProItemReturn Accept(AbstractProItemVisitor *visitor) = 0;
int lineNumber() const { return m_lineNumber; }
void setLineNumber(int lineNumber) { m_lineNumber = lineNumber; }
@@ -86,7 +93,8 @@ public:
ScopeContentsKind = 0x02,
VariableKind = 0x04,
ProFileKind = 0x08,
- SingleLine = 0x10
+ FunctionBodyKind = 0x10,
+ SingleLine = 0x80
};
ProBlock(ProBlock *parent);
@@ -102,14 +110,18 @@ public:
void setParent(ProBlock *parent);
ProBlock *parent() const;
+ void ref() { ++m_refCount; }
+ void deref() { if (!--m_refCount) delete this; }
+
ProItem::ProItemKind kind() const;
- virtual bool Accept(AbstractProItemVisitor *visitor);
+ virtual ProItemReturn Accept(AbstractProItemVisitor *visitor);
protected:
QList<ProItem *> m_proitems;
private:
ProBlock *m_parent;
int m_blockKind;
+ int m_refCount;
};
class ProVariable : public ProBlock
@@ -131,7 +143,7 @@ public:
void setVariable(const QString &name);
QString variable() const;
- virtual bool Accept(AbstractProItemVisitor *visitor);
+ virtual ProItemReturn Accept(AbstractProItemVisitor *visitor);
private:
VariableOperator m_variableKind;
QString m_variable;
@@ -150,7 +162,7 @@ public:
ProItem::ProItemKind kind() const;
- virtual bool Accept(AbstractProItemVisitor *visitor);
+ virtual ProItemReturn Accept(AbstractProItemVisitor *visitor);
private:
QString m_value;
ProVariable *m_variable;
@@ -166,7 +178,7 @@ public:
ProItem::ProItemKind kind() const;
- virtual bool Accept(AbstractProItemVisitor *visitor);
+ virtual ProItemReturn Accept(AbstractProItemVisitor *visitor);
private:
QString m_text;
};
@@ -181,7 +193,7 @@ public:
ProItem::ProItemKind kind() const;
- virtual bool Accept(AbstractProItemVisitor *visitor);
+ virtual ProItemReturn Accept(AbstractProItemVisitor *visitor);
private:
QString m_text;
};
@@ -201,7 +213,7 @@ public:
ProItem::ProItemKind kind() const;
- virtual bool Accept(AbstractProItemVisitor *visitor);
+ virtual ProItemReturn Accept(AbstractProItemVisitor *visitor);
private:
OperatorKind m_operatorKind;
};
@@ -219,7 +231,7 @@ public:
void setModified(bool modified);
bool isModified() const;
- virtual bool Accept(AbstractProItemVisitor *visitor);
+ virtual ProItemReturn Accept(AbstractProItemVisitor *visitor);
private:
QString m_fileName;