diff options
Diffstat (limited to 'qmake/library/qmakebuiltins.cpp')
-rw-r--r-- | qmake/library/qmakebuiltins.cpp | 401 |
1 files changed, 298 insertions, 103 deletions
diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 93a292ccf5..02c910fe46 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> @@ -84,9 +86,10 @@ QT_BEGIN_NAMESPACE #define fL1S(s) QString::fromLatin1(s) enum ExpandFunc { - E_INVALID = 0, E_MEMBER, E_FIRST, E_LAST, E_SIZE, E_CAT, E_FROMFILE, E_EVAL, E_LIST, - E_SPRINTF, E_FORMAT_NUMBER, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, - E_FIND, E_SYSTEM, E_UNIQUE, E_REVERSE, E_QUOTE, E_ESCAPE_EXPAND, + E_INVALID = 0, E_MEMBER, E_STR_MEMBER, E_FIRST, E_TAKE_FIRST, E_LAST, E_TAKE_LAST, + E_SIZE, E_STR_SIZE, E_CAT, E_FROMFILE, E_EVAL, E_LIST, E_SPRINTF, E_FORMAT_NUMBER, + E_NUM_ADD, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, + E_FIND, E_SYSTEM, E_UNIQUE, E_SORTED, E_REVERSE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_TITLE, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, E_REPLACE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS, E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH, @@ -96,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 }; @@ -108,15 +111,20 @@ void QMakeEvaluator::initFunctionStatics() const ExpandFunc func; } expandInits[] = { { "member", E_MEMBER }, + { "str_member", E_STR_MEMBER }, { "first", E_FIRST }, + { "take_first", E_TAKE_FIRST }, { "last", E_LAST }, + { "take_last", E_TAKE_LAST }, { "size", E_SIZE }, + { "str_size", E_STR_SIZE }, { "cat", E_CAT }, { "fromfile", E_FROMFILE }, { "eval", E_EVAL }, { "list", E_LIST }, { "sprintf", E_SPRINTF }, { "format_number", E_FORMAT_NUMBER }, + { "num_add", E_NUM_ADD }, { "join", E_JOIN }, { "split", E_SPLIT }, { "basename", E_BASENAME }, @@ -125,6 +133,7 @@ void QMakeEvaluator::initFunctionStatics() { "find", E_FIND }, { "system", E_SYSTEM }, { "unique", E_UNIQUE }, + { "sorted", E_SORTED }, { "reverse", E_REVERSE }, { "quote", E_QUOTE }, { "escape_expand", E_ESCAPE_EXPAND }, @@ -171,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 }, @@ -201,6 +211,49 @@ static bool isTrue(const ProString &str) return !str.compare(statics.strtrue, Qt::CaseInsensitive) || str.toInt(); } +bool +QMakeEvaluator::getMemberArgs(const ProKey &func, int srclen, const ProStringList &args, + int *start, int *end) +{ + *start = 0, *end = 0; + if (args.count() >= 2) { + bool ok = true; + const ProString &start_str = args.at(1); + *start = start_str.toInt(&ok); + if (!ok) { + if (args.count() == 2) { + int dotdot = start_str.indexOf(statics.strDotDot); + if (dotdot != -1) { + *start = start_str.left(dotdot).toInt(&ok); + if (ok) + *end = start_str.mid(dotdot+2).toInt(&ok); + } + } + if (!ok) { + evalError(fL1S("%1() argument 2 (start) '%2' invalid.") + .arg(func.toQString(m_tmp1), start_str.toQString(m_tmp2))); + return false; + } + } else { + *end = *start; + if (args.count() == 3) + *end = args.at(2).toInt(&ok); + if (!ok) { + evalError(fL1S("%1() argument 3 (end) '%2' invalid.") + .arg(func.toQString(m_tmp1), args.at(2).toQString(m_tmp2))); + return false; + } + } + } + if (*start < 0) + *start += srclen; + if (*end < 0) + *end += srclen; + if (*start < 0 || *start >= srclen || *end < 0 || *end >= srclen) + return false; + return true; +} + #if defined(Q_OS_WIN) && defined(PROEVALUATOR_FULL) static QString windowsErrorCode() { @@ -271,7 +324,7 @@ QMakeEvaluator::quoteValue(const ProString &val) break; case 32: quote = true; - // fallthrough + Q_FALLTHROUGH(); default: ret += c; break; @@ -343,11 +396,49 @@ static void addJsonValue(const QJsonValue &value, const QString &keyPrefix, ProV } } -static QMakeEvaluator::VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value) +struct ErrorPosition { + int line; + int column; +}; + +static ErrorPosition calculateErrorPosition(const QByteArray &json, int offset) +{ + ErrorPosition pos = { 0, 0 }; + offset--; // offset is 1-based, switching to 0-based + for (int i = 0; i < offset; ++i) { + switch (json.at(i)) { + case '\n': + pos.line++; + pos.column = 0; + break; + case '\r': + break; + case '\t': + pos.column = (pos.column + 8) & ~7; + break; + default: + pos.column++; + break; + } + } + // Lines and columns in text editors are 1-based: + pos.line++; + pos.column++; + return pos; +} + +QMakeEvaluator::VisitReturn QMakeEvaluator::parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value) { - QJsonDocument document = QJsonDocument::fromJson(json); - if (document.isNull()) + QJsonParseError error; + QJsonDocument document = QJsonDocument::fromJson(json, &error); + if (document.isNull()) { + if (error.error != QJsonParseError::NoError) { + ErrorPosition errorPos = calculateErrorPosition(json, error.offset); + evalError(fL1S("Error parsing JSON at %1:%2: %3") + .arg(errorPos.line).arg(errorPos.column).arg(error.errorString())); + } return QMakeEvaluator::ReturnFalse; + } QString currentKey = into + QLatin1Char('.'); @@ -395,12 +486,13 @@ void QMakeEvaluator::runProcess(QProcess *proc, const QString &command) const } #endif -QByteArray QMakeEvaluator::getCommandOutput(const QString &args) const +QByteArray QMakeEvaluator::getCommandOutput(const QString &args, int *exitCode) const { QByteArray out; #ifndef QT_BOOTSTRAPPED QProcess proc; runProcess(&proc, args); + *exitCode = (proc.exitStatus() == QProcess::NormalExit) ? proc.exitCode() : -1; QByteArray errout = proc.readAllStandardError(); # ifdef PROEVALUATOR_FULL // FIXME: Qt really should have the option to set forwarding per channel @@ -430,7 +522,12 @@ QByteArray QMakeEvaluator::getCommandOutput(const QString &args) const break; out += QByteArray(buff, read_in); } - QT_PCLOSE(proc); + int ec = QT_PCLOSE(proc); +# ifdef Q_OS_WIN + *exitCode = ec >= 0 ? ec : -1; +# else + *exitCode = WIFEXITED(ec) ? WEXITSTATUS(ec) : -1; +# endif } # ifdef Q_OS_WIN out.replace("\r\n", "\n"); @@ -540,31 +637,30 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( bool leftalign = false; enum { DefaultSign, PadSign, AlwaysSign } sign = DefaultSign; if (args.count() >= 2) { - const auto opts = split_value_list(args.at(1).toQString(m_tmp2)); + const auto opts = split_value_list(args.at(1).toQStringRef()); for (const ProString &opt : opts) { - opt.toQString(m_tmp3); - if (m_tmp3.startsWith(QLatin1String("ibase="))) { - ibase = m_tmp3.mid(6).toInt(); - } else if (m_tmp3.startsWith(QLatin1String("obase="))) { - obase = m_tmp3.mid(6).toInt(); - } else if (m_tmp3.startsWith(QLatin1String("width="))) { - width = m_tmp3.mid(6).toInt(); - } else if (m_tmp3 == QLatin1String("zeropad")) { + if (opt.startsWith(QLatin1String("ibase="))) { + ibase = opt.mid(6).toInt(); + } else if (opt.startsWith(QLatin1String("obase="))) { + obase = opt.mid(6).toInt(); + } else if (opt.startsWith(QLatin1String("width="))) { + width = opt.mid(6).toInt(); + } else if (opt == QLatin1String("zeropad")) { zeropad = true; - } else if (m_tmp3 == QLatin1String("padsign")) { + } else if (opt == QLatin1String("padsign")) { sign = PadSign; - } else if (m_tmp3 == QLatin1String("alwayssign")) { + } else if (opt == QLatin1String("alwayssign")) { sign = AlwaysSign; - } else if (m_tmp3 == QLatin1String("leftalign")) { + } else if (opt == QLatin1String("leftalign")) { leftalign = true; } else { - evalError(fL1S("format_number(): invalid format option %1.").arg(m_tmp3)); + evalError(fL1S("format_number(): invalid format option %1.") + .arg(opt.toQString(m_tmp3))); goto formfail; } } } - args.at(0).toQString(m_tmp3); - if (m_tmp3.contains(QLatin1Char('.'))) { + if (args.at(0).contains(QLatin1Char('.'))) { evalError(fL1S("format_number(): floats are currently not supported.")); break; } @@ -572,7 +668,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( qlonglong num = args.at(0).toLongLong(&ok, ibase); if (!ok) { evalError(fL1S("format_number(): malformed number %2 for base %1.") - .arg(ibase).arg(m_tmp3)); + .arg(ibase).arg(args.at(0).toQString(m_tmp3))); break; } QString outstr; @@ -600,14 +696,36 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( } formfail: break; + case E_NUM_ADD: + if (args.count() < 1 || args.at(0).isEmpty()) { + evalError(fL1S("num_add(num, ...) requires at least one argument.")); + } else { + qlonglong sum = 0; + for (const ProString &arg : qAsConst(args)) { + if (arg.contains(QLatin1Char('.'))) { + evalError(fL1S("num_add(): floats are currently not supported.")); + goto nafail; + } + bool ok; + qlonglong num = arg.toLongLong(&ok); + if (!ok) { + evalError(fL1S("num_add(): malformed number %1.") + .arg(arg.toQString(m_tmp3))); + goto nafail; + } + sum += num; + } + ret += ProString(QString::number(sum)); + } + nafail: + break; case E_JOIN: { if (args.count() < 1 || args.count() > 4) { evalError(fL1S("join(var, glue, before, after) requires one to four arguments.")); } else { - QString glue; - ProString before, after; + ProString glue, before, after; if (args.count() >= 2) - glue = args.at(1).toQString(m_tmp1); + glue = args.at(1); if (args.count() >= 3) before = args[2]; if (args.count() == 4) @@ -642,47 +760,37 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( if (args.count() < 1 || args.count() > 3) { evalError(fL1S("member(var, start, end) requires one to three arguments.")); } else { - bool ok = true; - const ProStringList &var = values(map(args.at(0))); - int start = 0, end = 0; - if (args.count() >= 2) { - const ProString &start_str = args.at(1); - start = start_str.toInt(&ok); - if (!ok) { - if (args.count() == 2) { - int dotdot = start_str.indexOf(statics.strDotDot); - if (dotdot != -1) { - start = start_str.left(dotdot).toInt(&ok); - if (ok) - end = start_str.mid(dotdot+2).toInt(&ok); - } - } - if (!ok) - evalError(fL1S("member() argument 2 (start) '%2' invalid.") - .arg(start_str.toQString(m_tmp1))); + const ProStringList &src = values(map(args.at(0))); + int start, end; + if (getMemberArgs(func, src.size(), args, &start, &end)) { + ret.reserve(qAbs(end - start) + 1); + if (start < end) { + for (int i = start; i <= end && src.size() >= i; i++) + ret += src.at(i); } else { - end = start; - if (args.count() == 3) - end = args.at(2).toInt(&ok); - if (!ok) - evalError(fL1S("member() argument 3 (end) '%2' invalid.") - .arg(args.at(2).toQString(m_tmp1))); + for (int i = start; i >= end && src.size() >= i && i >= 0; i--) + ret += src.at(i); } } - if (ok) { - if (start < 0) - start += var.count(); - if (end < 0) - end += var.count(); - if (start < 0 || start >= var.count() || end < 0 || end >= var.count()) { - //nothing - } else if (start < end) { - for (int i = start; i <= end && var.count() >= i; i++) - ret.append(var[i]); + } + break; + case E_STR_MEMBER: + if (args.count() < 1 || args.count() > 3) { + evalError(fL1S("str_member(str, start, end) requires one to three arguments.")); + } else { + const ProString &src = args.at(0); + int start, end; + if (getMemberArgs(func, src.size(), args, &start, &end)) { + QString res; + res.reserve(qAbs(end - start) + 1); + if (start < end) { + for (int i = start; i <= end && src.size() >= i; i++) + res += src.at(i); } else { - for (int i = start; i >= end && var.count() >= i && i >= 0; i--) - ret += var[i]; + for (int i = start; i >= end && src.size() >= i && i >= 0; i--) + res += src.at(i); } + ret += ProString(res); } } break; @@ -700,12 +808,32 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( } } break; + case E_TAKE_FIRST: + case E_TAKE_LAST: + if (args.count() != 1) { + evalError(fL1S("%1(var) requires one argument.").arg(func.toQString(m_tmp1))); + } else { + ProStringList &var = valuesRef(map(args.at(0))); + if (!var.isEmpty()) { + if (func_t == E_TAKE_FIRST) + ret.append(var.takeFirst()); + else + ret.append(var.takeLast()); + } + } + break; case E_SIZE: if (args.count() != 1) evalError(fL1S("size(var) requires one argument.")); else ret.append(ProString(QString::number(values(map(args.at(0))).size()))); break; + case E_STR_SIZE: + if (args.count() != 1) + evalError(fL1S("str_size(str) requires one argument.")); + else + ret.append(ProString(QString::number(args.at(0).size()))); + break; case E_CAT: if (args.count() < 1 || args.count() > 2) { evalError(fL1S("cat(file, singleline=true) requires one or two arguments.")); @@ -716,12 +844,11 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( bool lines = false; bool singleLine = true; if (args.count() > 1) { - args.at(1).toQString(m_tmp2); - if (!m_tmp2.compare(QLatin1String("false"), Qt::CaseInsensitive)) + if (!args.at(1).compare(QLatin1String("false"), Qt::CaseInsensitive)) singleLine = false; - else if (!m_tmp2.compare(QLatin1String("blob"), Qt::CaseInsensitive)) + else if (!args.at(1).compare(QLatin1String("blob"), Qt::CaseInsensitive)) blob = true; - else if (!m_tmp2.compare(QLatin1String("lines"), Qt::CaseInsensitive)) + else if (!args.at(1).compare(QLatin1String("lines"), Qt::CaseInsensitive)) lines = true; } @@ -735,7 +862,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( if (lines) { ret += ProString(stream.readLine()); } else { - ret += split_value_list(stream.readLine().trimmed()); + const QString &line = stream.readLine(); + ret += split_value_list(QStringRef(&line).trimmed()); if (!singleLine) ret += ProString("\n"); } @@ -767,7 +895,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( ret = ProStringList(ProString(tmp)); ProStringList lst; for (const ProString &arg : args) - lst += split_value_list(arg.toQString(m_tmp1), arg.sourceFile()); // Relies on deep copy + lst += split_value_list(arg.toQStringRef(), arg.sourceFile()); // Relies on deep copy m_valuemapStack.top()[ret.at(0).toKey()] = lst; break; } case E_FIND: @@ -786,22 +914,26 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( break; case E_SYSTEM: if (!m_skipLevel) { - if (args.count() < 1 || args.count() > 2) { - evalError(fL1S("system(execute) requires one or two arguments.")); + if (args.count() < 1 || args.count() > 3) { + evalError(fL1S("system(command, [mode], [stsvar]) requires one to three arguments.")); } else { bool blob = false; bool lines = false; bool singleLine = true; if (args.count() > 1) { - args.at(1).toQString(m_tmp2); - if (!m_tmp2.compare(QLatin1String("false"), Qt::CaseInsensitive)) + if (!args.at(1).compare(QLatin1String("false"), Qt::CaseInsensitive)) singleLine = false; - else if (!m_tmp2.compare(QLatin1String("blob"), Qt::CaseInsensitive)) + else if (!args.at(1).compare(QLatin1String("blob"), Qt::CaseInsensitive)) blob = true; - else if (!m_tmp2.compare(QLatin1String("lines"), Qt::CaseInsensitive)) + else if (!args.at(1).compare(QLatin1String("lines"), Qt::CaseInsensitive)) lines = true; } - QByteArray bytes = getCommandOutput(args.at(0).toQString(m_tmp2)); + int exitCode; + QByteArray bytes = getCommandOutput(args.at(0).toQString(m_tmp2), &exitCode); + if (args.count() > 2 && !args.at(2).isEmpty()) { + m_valuemapStack.top()[args.at(2).toKey()] = + ProStringList(ProString(QString::number(exitCode))); + } if (lines) { QTextStream stream(bytes); while (!stream.atEnd()) @@ -814,7 +946,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( output.replace(QLatin1Char('\t'), QLatin1Char(' ')); if (singleLine) output.replace(QLatin1Char('\n'), QLatin1Char(' ')); - ret += split_value_list(output); + ret += split_value_list(QStringRef(&output)); } } } @@ -828,6 +960,14 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( ret.removeDuplicates(); } break; + case E_SORTED: + if (args.count() != 1) { + evalError(fL1S("sorted(var) requires one argument.")); + } else { + ret = values(map(args.at(0))); + std::sort(ret.begin(), ret.end()); + } + break; case E_REVERSE: if (args.count() != 1) { evalError(fL1S("reverse(var) requires one argument.")); @@ -950,20 +1090,27 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( break; #ifdef PROEVALUATOR_FULL case E_PROMPT: { - if (args.count() != 1) { - evalError(fL1S("prompt(question) requires one argument.")); + if (args.count() != 1 && args.count() != 2) { + evalError(fL1S("prompt(question, [decorate=true]) requires one or two arguments.")); // } else if (currentFileName() == QLatin1String("-")) { // evalError(fL1S("prompt(question) cannot be used when '-o -' is used")); } else { QString msg = m_option->expandEnvVars(args.at(0).toQString(m_tmp1)); - if (!msg.endsWith(QLatin1Char('?'))) - msg += QLatin1Char('?'); - fprintf(stderr, "Project PROMPT: %s ", qPrintable(msg)); - + bool decorate = true; + if (args.count() == 2) + decorate = isTrue(args.at(1)); + if (decorate) { + if (!msg.endsWith(QLatin1Char('?'))) + msg += QLatin1Char('?'); + fprintf(stderr, "Project PROMPT: %s ", qPrintable(msg)); + } else { + fputs(qPrintable(msg), stderr); + } QFile qfile; if (qfile.open(stdin, QIODevice::ReadOnly)) { QTextStream t(&qfile); - ret = split_value_list(t.readLine()); + const QString &line = t.readLine(); + ret = split_value_list(QStringRef(&line)); } } break; } @@ -997,7 +1144,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand( ProString priosfx = args.count() < 4 ? ProString(".priority") : args.at(3); populateDeps(orgList, prefix, args.count() < 3 ? ProStringList(ProString(".depends")) - : split_value_list(args.at(2).toQString(m_tmp2)), + : split_value_list(args.at(2).toQStringRef()), priosfx, dependencies, dependees, rootSet); while (!rootSet.isEmpty()) { QMultiMap<int, ProString>::iterator it = rootSet.begin(); @@ -1188,6 +1335,54 @@ 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; + } + for (auto fit = m_functionDefs.testFunctions.begin(); fit != m_functionDefs.testFunctions.end(); ) { + if (fit->pro() == pro) + fit = m_functionDefs.testFunctions.erase(fit); + else + ++fit; + } + for (auto fit = m_functionDefs.replaceFunctions.begin(); fit != m_functionDefs.replaceFunctions.end(); ) { + if (fit->pro() == pro) + fit = m_functionDefs.replaceFunctions.erase(fit); + else + ++fit; + } + pro->deref(); + ProStringList &iif = m_valuemapStack.first()[ProKey("QMAKE_INTERNAL_INCLUDED_FILES")]; + int idx = iif.indexOf(ProString(fn)); + if (idx >= 0) + iif.removeAt(idx); + return ReturnTrue; + } case T_INFILE: if (args.count() < 2 || args.count() > 3) { evalError(fL1S("infile(file, var, [values]) requires two or three arguments.")); @@ -1224,7 +1419,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( return ReturnFalse; // Another qmake breakage case T_EVAL: { VisitReturn ret = ReturnFalse; - ProFile *pro = m_parser->parsedProBlock(args.join(statics.field_sep), + QString contents = args.join(statics.field_sep); + ProFile *pro = m_parser->parsedProBlock(QStringRef(&contents), m_current.pro->fileName(), m_current.line); if (m_cumulative || pro->isOk()) { m_locationStack.push(m_current); @@ -1240,7 +1436,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( evalError(fL1S("if(condition) requires one argument.")); return ReturnFalse; } - return evaluateConditional(args.at(0).toQString(), + return evaluateConditional(args.at(0).toQStringRef(), m_current.pro->fileName(), m_current.line); } case T_CONFIG: { @@ -1249,7 +1445,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( return ReturnFalse; } if (args.count() == 1) - return returnBool(isActiveConfig(args.at(0).toQString(m_tmp2))); + return returnBool(isActiveConfig(args.at(0).toQStringRef())); const QStringList &mutuals = args.at(1).toQString(m_tmp2).split(QLatin1Char('|')); const ProStringList &configs = values(statics.strCONFIG); @@ -1332,8 +1528,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( .arg(function.toQString(m_tmp1))); return ReturnFalse; } - const QString &rhs(args.at(1).toQString(m_tmp1)), - &lhs(values(map(args.at(0))).join(statics.field_sep)); + const ProString &rhs = args.at(1); + const QString &lhs = values(map(args.at(0))).join(statics.field_sep); bool ok; int rhs_int = rhs.toInt(&ok); if (ok) { // do integer compare @@ -1345,8 +1541,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } } if (func_t == T_GREATERTHAN) - return returnBool(lhs > rhs); - return returnBool(lhs < rhs); + return returnBool(lhs > rhs.toQStringRef()); + return returnBool(lhs < rhs.toQStringRef()); } case T_EQUALS: if (args.count() != 2) { @@ -1414,7 +1610,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; } @@ -1431,17 +1628,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; } @@ -1493,7 +1688,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( #ifdef PROEVALUATOR_FULL fputs(msg.toLatin1().constData(), stderr); #endif - } else { + } else if (!msg.isEmpty() || func_t != T_ERROR) { m_handler->fileMessage( (func_t == T_ERROR ? QMakeHandler::ErrorMessage : func_t == T_WARNING ? QMakeHandler::WarningMessage : @@ -1587,7 +1782,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( if (!vals.isEmpty()) contents = vals.join(QLatin1Char('\n')) + QLatin1Char('\n'); if (args.count() >= 3) { - const auto opts = split_value_list(args.at(2).toQString(m_tmp2)); + const auto opts = split_value_list(args.at(2).toQStringRef()); for (const ProString &opt : opts) { opt.toQString(m_tmp3); if (m_tmp3 == QLatin1String("append")) { @@ -1660,7 +1855,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( enum { CacheSet, CacheAdd, CacheSub } mode = CacheSet; ProKey srcvar; if (args.count() >= 2) { - const auto opts = split_value_list(args.at(1).toQString(m_tmp2)); + const auto opts = split_value_list(args.at(1).toQStringRef()); for (const ProString &opt : opts) { opt.toQString(m_tmp3); if (m_tmp3 == QLatin1String("transient")) { |