summaryrefslogtreecommitdiffstats
path: root/qmake/library/qmakebuiltins.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qmake/library/qmakebuiltins.cpp')
-rw-r--r--qmake/library/qmakebuiltins.cpp48
1 files changed, 41 insertions, 7 deletions
diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp
index ba621c1c72..4418c95f4b 100644
--- a/qmake/library/qmakebuiltins.cpp
+++ b/qmake/library/qmakebuiltins.cpp
@@ -52,6 +52,8 @@
# include <qthreadpool.h>
#endif
+#include <algorithm>
+
#ifdef Q_OS_UNIX
#include <time.h>
#include <utime.h>
@@ -97,7 +99,7 @@ enum ExpandFunc {
enum TestFunc {
T_INVALID = 0, T_REQUIRES, T_GREATERTHAN, T_LESSTHAN, T_EQUALS,
T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
- T_DEFINED, T_CONTAINS, T_INFILE,
+ T_DEFINED, T_DISCARD_FROM, T_CONTAINS, T_INFILE,
T_COUNT, T_ISEMPTY, T_PARSE_JSON, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF,
T_MKPATH, T_WRITE_FILE, T_TOUCH, T_CACHE
};
@@ -178,6 +180,7 @@ void QMakeEvaluator::initFunctionStatics()
{ "if", T_IF },
{ "isActiveConfig", T_CONFIG },
{ "system", T_SYSTEM },
+ { "discard_from", T_DISCARD_FROM },
{ "defined", T_DEFINED },
{ "contains", T_CONTAINS },
{ "infile", T_INFILE },
@@ -1292,6 +1295,38 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
return ReturnTrue;
}
+ case T_DISCARD_FROM: {
+ if (args.count() != 1 || args.at(0).isEmpty()) {
+ evalError(fL1S("discard_from(file) requires one argument."));
+ return ReturnFalse;
+ }
+ if (m_valuemapStack.count() != 1) {
+ evalError(fL1S("discard_from() cannot be called from functions."));
+ return ReturnFalse;
+ }
+ QString fn = resolvePath(args.at(0).toQString(m_tmp1));
+ ProFile *pro = m_parser->parsedProFile(fn, QMakeParser::ParseOnlyCached);
+ if (!pro)
+ return ReturnFalse;
+ ProValueMap &vmap = m_valuemapStack.first();
+ for (auto vit = vmap.begin(); vit != vmap.end(); ) {
+ if (!vit->isEmpty()) {
+ auto isFrom = [pro](const ProString &s) {
+ return s.sourceFile() == pro;
+ };
+ vit->erase(std::remove_if(vit->begin(), vit->end(), isFrom), vit->end());
+ if (vit->isEmpty()) {
+ // When an initially non-empty variable becomes entirely empty,
+ // undefine it altogether.
+ vit = vmap.erase(vit);
+ continue;
+ }
+ }
+ ++vit;
+ }
+ pro->deref();
+ return ReturnTrue;
+ }
case T_INFILE:
if (args.count() < 2 || args.count() > 3) {
evalError(fL1S("infile(file, var, [values]) requires two or three arguments."));
@@ -1519,7 +1554,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
if (m_cumulative)
flags = LoadSilent;
if (args.count() >= 2) {
- parseInto = args.at(1).toQString(m_tmp2);
+ if (!args.at(1).isEmpty())
+ parseInto = args.at(1) + QLatin1Char('.');
if (args.count() >= 3 && isTrue(args.at(2)))
flags = LoadSilent;
}
@@ -1536,17 +1572,15 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
it = m_valuemapStack.top().constBegin(),
end = m_valuemapStack.top().constEnd();
it != end; ++it) {
- const QString &ky = it.key().toQString(m_tmp1);
- if (!(ky.startsWith(parseInto) &&
- (ky.length() == parseInto.length()
- || ky.at(parseInto.length()) == QLatin1Char('.'))))
+ const ProString &ky = it.key();
+ if (!ky.startsWith(parseInto))
newMap[it.key()] = it.value();
}
for (ProValueMap::ConstIterator it = symbols.constBegin();
it != symbols.constEnd(); ++it) {
const QString &ky = it.key().toQString(m_tmp1);
if (!ky.startsWith(QLatin1Char('.')))
- newMap.insert(ProKey(parseInto + QLatin1Char('.') + ky), it.value());
+ newMap.insert(ProKey(parseInto + ky), it.value());
}
m_valuemapStack.top() = newMap;
}