From a1947aeffe158a0ea7de3ced1bf8d6a4719a27ef Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 3 Apr 2020 17:11:36 +0200 Subject: Port qmake over to user QRegularExpression Use the DotMatchesEverythingOption for all places where we interpret .pro files, to increase compatibility with QRegExp. Change-Id: I347d6b17858069f3c9cedcedd04df58358d83f27 Reviewed-by: Joerg Bornemann --- qmake/generators/mac/pbuilder_pbx.cpp | 15 +++--- qmake/generators/makefile.cpp | 42 ++++++++------- qmake/generators/projectgenerator.cpp | 4 +- qmake/generators/unix/unixmake2.cpp | 14 ++--- qmake/generators/win32/mingw_make.cpp | 4 +- qmake/generators/win32/msbuild_objectmodel.cpp | 9 ++-- qmake/generators/win32/msvc_nmake.cpp | 8 +-- qmake/generators/win32/msvc_objectmodel.cpp | 4 +- qmake/generators/win32/winmakefile.cpp | 8 +-- qmake/library/ioutils.cpp | 6 +-- qmake/library/qmakebuiltins.cpp | 72 +++++++++++++++++--------- qmake/library/qmakeevaluator.cpp | 15 +++--- qmake/main.cpp | 10 ++-- qmake/option.cpp | 16 +++--- 14 files changed, 129 insertions(+), 98 deletions(-) (limited to 'qmake') diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index ec0a044361..c6aab40d85 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -30,7 +30,7 @@ #include "option.h" #include "meta.h" #include -#include +#include #include #include #include @@ -1865,11 +1865,12 @@ QString ProjectBuilderMakefileGenerator::fixForOutput(const QString &values) { //get the environment variables references - QRegExp reg_var("\\$\\((.*)\\)"); - for(int rep = 0; (rep = reg_var.indexIn(values, rep)) != -1;) { - if(project->values("QMAKE_PBX_VARS").indexOf(reg_var.cap(1)) == -1) - project->values("QMAKE_PBX_VARS").append(reg_var.cap(1)); - rep += reg_var.matchedLength(); + QRegularExpression reg_var("\\$\\((.*)\\)"); + QRegularExpressionMatch match; + for (int rep = 0; (match = reg_var.match(values, rep)).hasMatch();) { + if (project->values("QMAKE_PBX_VARS").indexOf(match.captured(1)) == -1) + project->values("QMAKE_PBX_VARS").append(match.captured(1)); + rep = match.capturedEnd(); } return values; @@ -2019,7 +2020,7 @@ ProjectBuilderMakefileGenerator::writeSettings(const QString &var, const ProStri for(int i = 0; i < indent_level; ++i) newline += "\t"; - static QRegExp allowedVariableCharacters("^[a-zA-Z0-9_]*$"); + static QRegularExpression allowedVariableCharacters("^[a-zA-Z0-9_]*$"); ret += var.contains(allowedVariableCharacters) ? var : quotedStringLiteral(var); ret += " = "; diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 9d2d240bc2..3ccd53f0a2 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include #include @@ -1575,11 +1575,12 @@ MakefileGenerator::replaceExtraCompilerVariables( //do the work QString ret = orig_var; - QRegExp reg_var("\\$\\{.*\\}"); - reg_var.setMinimal(true); - for(int rep = 0; (rep = reg_var.indexIn(ret, rep)) != -1; ) { + QRegularExpression reg_var("\\$\\{.*\\}", QRegularExpression::InvertedGreedinessOption); + QRegularExpressionMatch match; + for (int rep = 0; (match = reg_var.match(ret, rep)).hasMatch(); ) { + rep = match.capturedStart(); QStringList val; - const ProString var(ret.mid(rep + 2, reg_var.matchedLength() - 3)); + const ProString var(ret.mid(rep + 2, match.capturedLength() - 3)); bool filePath = false; if(val.isEmpty() && var.startsWith(QLatin1String("QMAKE_VAR_"))) { const ProKey varname = var.mid(10).toKey(); @@ -1675,10 +1676,10 @@ MakefileGenerator::replaceExtraCompilerVariables( } else { fullVal = val.join(' '); } - ret.replace(rep, reg_var.matchedLength(), fullVal); - rep += fullVal.length(); + ret.replace(match.capturedStart(), match.capturedLength(), fullVal); + rep = match.capturedStart(), fullVal.length(); } else { - rep += reg_var.matchedLength(); + rep = match.capturedEnd(); } } @@ -2018,7 +2019,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) const bool existingDepsOnly = config.contains("dep_existing_only"); QStringList tmp_dep = project->values(ProKey(*it + ".depends")).toQStringList(); if (config.indexOf("combine") != -1) { - if (tmp_out.contains(QRegExp("(^|[^$])\\$\\{QMAKE_(?!VAR_)"))) { + if (tmp_out.contains(QRegularExpression("(^|[^$])\\$\\{QMAKE_(?!VAR_)"))) { warn_msg(WarnLogic, "QMAKE_EXTRA_COMPILERS(%s) with combine has variable output.", (*it).toLatin1().constData()); continue; @@ -2167,9 +2168,10 @@ MakefileGenerator::writeExtraVariables(QTextStream &t) const ProValueMap &vars = project->variables(); const ProStringList &exports = project->values("QMAKE_EXTRA_VARIABLES"); for (ProStringList::ConstIterator exp_it = exports.begin(); exp_it != exports.end(); ++exp_it) { - QRegExp rx((*exp_it).toQString(), Qt::CaseInsensitive, QRegExp::Wildcard); + auto pattern = QRegularExpression::wildcardToRegularExpression((*exp_it).toQString()); + QRegularExpression rx(pattern, QRegularExpression::CaseInsensitiveOption); for (ProValueMap::ConstIterator it = vars.begin(); it != vars.end(); ++it) { - if (rx.exactMatch(it.key().toQString())) + if (rx.match(it.key().toQString()).hasMatch()) outlist << ("EXPORT_" + it.key() + " = " + it.value().join(' ')); } } @@ -2314,7 +2316,7 @@ MakefileGenerator::findSubDirsSubTargets() const ProString ofile = subdirs[subdir]; QString oname = ofile.toQString(); QString fixedSubdir = oname; - fixedSubdir.replace(QRegExp("[^a-zA-Z0-9_]"),"-"); + fixedSubdir.replace(QRegularExpression("[^a-zA-Z0-9_]"),"-"); SubTarget *st = new SubTarget; st->name = oname; @@ -2386,7 +2388,7 @@ MakefileGenerator::findSubDirsSubTargets() const if(subdirs[subDep] == depends.at(depend)) { QString subName = subdirs[subDep].toQString(); QString fixedSubDep = subName; - fixedSubDep.replace(QRegExp("[^a-zA-Z0-9_]"),"-"); + fixedSubDep.replace(QRegularExpression("[^a-zA-Z0-9_]"),"-"); const ProKey dtkey(fixedSubDep + ".target"); if (!project->isEmpty(dtkey)) { st->depends += project->first(dtkey); @@ -2400,7 +2402,7 @@ MakefileGenerator::findSubDirsSubTargets() const if (!project->isEmpty(dskey)) d = project->first(dskey).toQString(); } - st->depends += "sub-" + d.replace(QRegExp("[^a-zA-Z0-9_]"),"-"); + st->depends += "sub-" + d.replace(QRegularExpression("[^a-zA-Z0-9_]"),"-"); } found = true; break; @@ -2408,7 +2410,7 @@ MakefileGenerator::findSubDirsSubTargets() const } if(!found) { QString depend_str = depends.at(depend).toQString(); - st->depends += depend_str.replace(QRegExp("[^a-zA-Z0-9_]"),"-"); + st->depends += depend_str.replace(QRegularExpression("[^a-zA-Z0-9_]"),"-"); } } } @@ -2417,7 +2419,7 @@ MakefileGenerator::findSubDirsSubTargets() const st->target = project->first(tkey).toQString(); } else { st->target = "sub-" + file; - st->target.replace(QRegExp("[^a-zA-Z0-9_]"), "-"); + st->target.replace(QRegularExpression("[^a-zA-Z0-9_]"), "-"); } } } @@ -2882,12 +2884,12 @@ MakefileGenerator::escapeDependencyPath(const QString &path) const #ifdef Q_OS_UNIX // When running on Unix, we need to escape colons (which may appear // anywhere in a path, and would be mis-parsed as dependency separators). - static const QRegExp criticalChars(QStringLiteral("([\t :#])")); + static const QRegularExpression criticalChars(QStringLiteral("([\t :#])")); #else // MinGW make has a hack for colons which denote drive letters, and no // other colons may appear in paths. And escaping colons actually breaks // the make from the Android SDK. - static const QRegExp criticalChars(QStringLiteral("([\t #])")); + static const QRegularExpression criticalChars(QStringLiteral("([\t #])")); #endif ret.replace(criticalChars, QStringLiteral("\\\\1")); ret.replace(QLatin1Char('='), QStringLiteral("$(EQ)")); @@ -3070,8 +3072,8 @@ MakefileGenerator::findFileForDep(const QMakeLocalFileName &dep, const QMakeLoca const ProStringList &nodeplist = project->values("SKIP_DEPENDS"); for (ProStringList::ConstIterator it = nodeplist.begin(); it != nodeplist.end(); ++it) { - QRegExp regx((*it).toQString()); - if(regx.indexIn(dep.local()) != -1) { + QRegularExpression regx((*it).toQString()); + if (regx.match(dep.local()).hasMatch()) { found = true; break; } diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp index 613c97fb85..ac6793cbf3 100644 --- a/qmake/generators/projectgenerator.cpp +++ b/qmake/generators/projectgenerator.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include QT_BEGIN_NAMESPACE @@ -245,7 +245,7 @@ ProjectGenerator::init() v["INCLUDEPATH"] += inc.real(); } } - if(no_qt_files && file_no_path.indexOf(QRegExp("^q[a-z_0-9].h$")) != -1) + if (no_qt_files && file_no_path.contains(QRegularExpression("^q[a-z_0-9].h$"))) no_qt_files = false; QString h_ext; for(int hit = 0; hit < Option::h_ext.size(); ++hit) { diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 19975bc8bb..09af15130f 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -30,7 +30,7 @@ #include "unixmake.h" #include "option.h" #include "meta.h" -#include +#include #include #include #include @@ -290,7 +290,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if (project->isActiveConfig("gcc_MD_depends")) { ProStringList objects = project->values("OBJECTS"); for (ProStringList::Iterator it = objects.begin(); it != objects.end(); ++it) { - QString d_file = (*it).toQString().replace(QRegExp(Option::obj_ext + "$"), ".d"); + QString d_file = (*it).toQString().replace(QRegularExpression(Option::obj_ext + "$"), ".d"); t << "-include " << escapeDependencyPath(d_file) << Qt::endl; project->values("QMAKE_DISTCLEAN") << d_file; } @@ -346,7 +346,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if(!d_file.isEmpty()) { d_file = odir + ".deps/" + fileFixify(d_file, FileFixifyBackwards) + ".d"; QString d_file_d = escapeDependencyPath(d_file); - QStringList deps = findDependencies((*it).toQString()).filter(QRegExp( + QStringList deps = findDependencies((*it).toQString()).filter(QRegularExpression( "((^|/)" + Option::h_moc_mod + "|" + Option::cpp_moc_ext + "$)")); if(!deps.isEmpty()) t << d_file_d << ": " << finalizeDependencyPaths(deps).join(' ') << Qt::endl; @@ -507,7 +507,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if(do_incremental) { ProString s_ext = project->first("QMAKE_EXTENSION_SHLIB"); QString incr_target = var("QMAKE_ORIG_TARGET").replace( - QRegExp("\\." + s_ext), "").replace(QRegExp("^lib"), "") + "_incremental"; + QRegularExpression("\\." + s_ext), "").replace(QRegularExpression("^lib"), "") + "_incremental"; if(incr_target.indexOf(Option::dir_sep) != -1) incr_target = incr_target.right(incr_target.length() - (incr_target.lastIndexOf(Option::dir_sep) + 1)); @@ -1533,8 +1533,10 @@ std::pair UnixMakefileGenerator::writeObjectsPart(QTextStream &t, for (ProStringList::ConstIterator objit = objs.begin(); objit != objs.end(); ++objit) { bool increment = false; for (ProStringList::ConstIterator incrit = incrs.begin(); incrit != incrs.end(); ++incrit) { - if ((*objit).toQString().indexOf(QRegExp((*incrit).toQString(), Qt::CaseSensitive, - QRegExp::Wildcard)) != -1) { + auto pattern = + QRegularExpression::wildcardToRegularExpression((*incrit).toQString(), + QRegularExpression::UnanchoredWildcardConversion); + if ((*objit).toQString().contains(QRegularExpression(pattern))) { increment = true; incrs_out.append((*objit)); break; diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index 096b041056..7a717a80a9 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -31,7 +31,7 @@ #include -#include +#include #include #include #include @@ -209,7 +209,7 @@ void MingwMakefileGenerator::writeIncPart(QTextStream &t) const ProStringList &incs = project->values("INCLUDEPATH"); for (ProStringList::ConstIterator incit = incs.begin(); incit != incs.end(); ++incit) { QString inc = (*incit).toQString(); - inc.replace(QRegExp("\\\\$"), ""); + inc.replace(QRegularExpression("\\\\$"), ""); if (!isystem.isEmpty() && isSystemInclude(inc)) t << isystem << ' '; diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index 355260c974..82c0983272 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include QT_BEGIN_NAMESPACE @@ -834,12 +834,13 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool) QFile manifestFile(Option::output_dir + QLatin1Char('/') + manifest); if (manifestFile.open(QFile::ReadOnly)) { const QString contents = manifestFile.readAll(); - QRegExp regexp("[\\\\/a-zA-Z0-9_\\-\\!]*\\.(png|jpg|jpeg)"); + QRegularExpression regexp("[\\\\/a-zA-Z0-9_\\-\\!]*\\.(png|jpg|jpeg)"); int pos = 0; while (pos > -1) { - pos = regexp.indexIn(contents, pos); + QRegularExpressionMatch m; + pos = contents.indexOf(regexp, pos, &m); if (pos >= 0) { - const QString match = regexp.cap(0); + const QString match = m.captured(0); icons.insert(match); pos += match.length(); } diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 73e84a3269..cf58ead2e9 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -29,7 +29,7 @@ #include "msvc_nmake.h" #include "option.h" -#include +#include #include #include #include @@ -370,12 +370,12 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t) for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) t << '{' << escapeDependencyPath(sourceDir) << '}' << (*cppit) << '{' << escapeDependencyPath(objDir) << '}' << Option::obj_ext << "::\n\t" - << var("QMAKE_RUN_CXX_IMP_BATCH").replace(QRegExp("\\$@"), fileVar("OBJECTS_DIR")) + << var("QMAKE_RUN_CXX_IMP_BATCH").replace(QRegularExpression("\\$@"), fileVar("OBJECTS_DIR")) << "\n\t$<\n<<\n\n"; for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit) t << '{' << escapeDependencyPath(sourceDir) << '}' << (*cit) << '{' << escapeDependencyPath(objDir) << '}' << Option::obj_ext << "::\n\t" - << var("QMAKE_RUN_CC_IMP_BATCH").replace(QRegExp("\\$@"), fileVar("OBJECTS_DIR")) + << var("QMAKE_RUN_CC_IMP_BATCH").replace(QRegularExpression("\\$@"), fileVar("OBJECTS_DIR")) << "\n\t$<\n<<\n\n"; } } else { @@ -434,7 +434,7 @@ void NmakeMakefileGenerator::writeBuildRulesPart(QTextStream &t) } const QString resourceId = (templateName == "app") ? "1" : "2"; - const bool incrementalLinking = project->values("QMAKE_LFLAGS").toQStringList().filter(QRegExp("(/|-)INCREMENTAL:NO")).isEmpty(); + const bool incrementalLinking = project->values("QMAKE_LFLAGS").toQStringList().filter(QRegularExpression("(/|-)INCREMENTAL:NO")).isEmpty(); if (incrementalLinking && !linkerSupportsEmbedding) { // Link a resource that contains the manifest without modifying the exe/dll after linking. diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index 3002ce889c..9e93fe51f3 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -34,7 +34,7 @@ #include #include -#include +#include using namespace QMakeInternal; @@ -321,7 +321,7 @@ triState operator!(const triState &rhs) QStringList VCToolBase::fixCommandLine(const QString &input) { // The splitting regexp is a bit bizarre for backwards compat reasons (why else ...). - return input.split(QRegExp(QLatin1String("(\n\t|\r\\\\h|\r\n)\\s*"))); + return input.split(QRegularExpression(QLatin1String("(\n\t|\r\\\\h|\r\n)\\s*"))); } static QString vcCommandSeparator() diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 112ad1f739..57f02c13d0 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include @@ -561,7 +561,7 @@ void Win32MakefileGenerator::writeIncPart(QTextStream &t) const ProStringList &incs = project->values("INCLUDEPATH"); for(int i = 0; i < incs.size(); ++i) { QString inc = incs.at(i).toQString(); - inc.replace(QRegExp("\\\\$"), ""); + inc.replace(QRegularExpression("\\\\$"), ""); if(!inc.isEmpty()) t << "-I" << escapeFilePath(inc) << ' '; } @@ -588,7 +588,7 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t) t << "####### Output directory\n\n"; if(!project->values("OBJECTS_DIR").isEmpty()) - t << "OBJECTS_DIR = " << escapeFilePath(var("OBJECTS_DIR").remove(QRegExp("\\\\$"))) << Qt::endl; + t << "OBJECTS_DIR = " << escapeFilePath(var("OBJECTS_DIR").remove(QRegularExpression("\\\\$"))) << Qt::endl; else t << "OBJECTS_DIR = . \n"; t << Qt::endl; @@ -860,7 +860,7 @@ QString Win32MakefileGenerator::escapeDependencyPath(const QString &path) const { QString ret = path; if (!ret.isEmpty()) { - static const QRegExp criticalChars(QStringLiteral("([\t #])")); + static const QRegularExpression criticalChars(QStringLiteral("([\t #])")); if (ret.contains(criticalChars)) ret = "\"" + ret + "\""; debug_msg(2, "EscapeDependencyPath: %s -> %s", path.toLatin1().constData(), ret.toLatin1().constData()); diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index d2171274d8..fac0541779 100644 --- a/qmake/library/ioutils.cpp +++ b/qmake/library/ioutils.cpp @@ -30,7 +30,7 @@ #include #include -#include +#include #ifdef Q_OS_WIN # include @@ -178,9 +178,9 @@ QString IoUtils::shellQuoteWin(const QString &arg) // The process-level standard quoting allows escaping quotes with backslashes (note // that backslashes don't escape themselves, unless they are followed by a quote). // Consequently, quotes are escaped and their preceding backslashes are doubled. - ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\"")); + ret.replace(QRegularExpression(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\"")); // Trailing backslashes must be doubled as well, as they are followed by a quote. - ret.replace(QRegExp(QLatin1String("(\\\\+)$")), QLatin1String("\\1\\1")); + ret.replace(QRegularExpression(QLatin1String("(\\\\+)$")), QLatin1String("\\1\\1")); // However, the shell also interprets the command, and no backslash-escaping exists // there - a quote always toggles the quoting state, but is nonetheless passed down // to the called process verbatim. In the unquoted state, the circumflex escapes diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 460720168f..96583e5e76 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include @@ -639,7 +639,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( if (!var.isEmpty()) { const auto strings = values(map(var)); if (regexp) { - QRegExp sepRx(sep); + QRegularExpression sepRx(sep, QRegularExpression::DotMatchesEverythingOption); + if (!sepRx.isValid()) { + evalError(fL1S("section(): Encountered invalid regular expression '%1'.").arg(sep)); + goto allfail; + } for (const ProString &str : strings) { ProStringRwUser u1(str, m_tmp[m_toggle ^= 1]); ret << u1.extract(u1.str().section(sepRx, beg, end)); @@ -890,11 +894,15 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( m_valuemapStack.top()[ret.at(0).toKey()] = lst; break; } case E_FIND: { - QRegExp regx(args.at(1).toQString()); + QRegularExpression regx(args.at(1).toQString(), QRegularExpression::DotMatchesEverythingOption); + if (!regx.isValid()) { + evalError(fL1S("find(): Encountered invalid regular expression '%1'.").arg(regx.pattern())); + goto allfail; + } const auto vals = values(map(args.at(0))); for (const ProString &val : vals) { ProStringRoUser u1(val, m_tmp[m_toggle ^= 1]); - if (regx.indexIn(u1.str()) != -1) + if (u1.str().contains(regx)) ret += val; } break; @@ -990,7 +998,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( case E_RE_ESCAPE: for (int i = 0; i < args.size(); ++i) { ProStringRwUser u1(args.at(i), m_tmp1); - ret << u1.extract(QRegExp::escape(u1.str())); + ret << u1.extract(QRegularExpression::escape(u1.str())); } break; case E_VAL_ESCAPE: { @@ -1038,8 +1046,12 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( dirs.append(QString()); } - r.detach(); // Keep m_tmp out of QRegExp's cache - QRegExp regex(r, Qt::CaseSensitive, QRegExp::Wildcard); + QString pattern = QRegularExpression::wildcardToRegularExpression(r); + QRegularExpression regex(pattern, QRegularExpression::DotMatchesEverythingOption); + if (!regex.isValid()) { + evalError(fL1S("section(): Encountered invalid wildcard expression '%1'.").arg(pattern)); + goto allfail; + } for (int d = 0; d < dirs.count(); d++) { QString dir = dirs[d]; QDir qdir(pfx + dir); @@ -1051,7 +1063,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( if (recursive) dirs.append(fname + QLatin1Char('/')); } - if (regex.exactMatch(qdir[i])) + if (regex.match(qdir[i]).hasMatch()) ret += ProString(fname).setSource(currentFileId()); } } @@ -1086,7 +1098,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( } #endif case E_REPLACE: { - const QRegExp before(args.at(1).toQString()); + const QRegularExpression before(args.at(1).toQString(), QRegularExpression::DotMatchesEverythingOption); + if (!before.isValid()) { + evalError(fL1S("replace(): Encountered invalid regular expression '%1'.").arg(before.pattern())); + goto allfail; + } ProStringRwUser u2(args.at(2), m_tmp2); const QString &after = u2.str(); const auto vals = values(map(args.at(0))); @@ -1528,21 +1544,24 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( return ok; if (args.count() == 2) return returnBool(vars.contains(map(args.at(1)))); - QRegExp regx; + QRegularExpression regx; + regx.setPatternOptions(QRegularExpression::DotMatchesEverythingOption); ProStringRoUser u1(args.at(2), m_tmp1); const QString &qry = u1.str(); - if (qry != QRegExp::escape(qry)) { - QString copy = qry; - copy.detach(); - regx.setPattern(copy); + if (qry != QRegularExpression::escape(qry)) { + regx.setPattern(QRegularExpression::anchoredPattern(qry)); + if (!regx.isValid()) { + evalError(fL1S("infile(): Encountered invalid regular expression '%1'.").arg(qry)); + return ReturnFalse; + } } const auto strings = vars.value(map(args.at(1))); for (const ProString &s : strings) { if (s == qry) return ReturnTrue; - if (!regx.isEmpty()) { + if (!regx.pattern().isEmpty()) { ProStringRoUser u2(s, m_tmp[m_toggle ^= 1]); - if (regx.exactMatch(u2.str())) + if (regx.match(u2.str()).hasMatch()) return ReturnTrue; } } @@ -1590,11 +1609,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( case T_CONTAINS: { ProStringRoUser u1(args.at(1), m_tmp1); const QString &qry = u1.str(); - QRegExp regx; - if (qry != QRegExp::escape(qry)) { - QString copy = qry; - copy.detach(); - regx.setPattern(copy); + QRegularExpression regx; + regx.setPatternOptions(QRegularExpression::DotMatchesEverythingOption); + if (qry != QRegularExpression::escape(qry)) { + regx.setPattern(QRegularExpression::anchoredPattern(qry)); + if (!regx.isValid()) { + evalError(fL1S("contains(): Encountered invalid regular expression '%1'.").arg(qry)); + return ReturnFalse; + } } const ProStringList &l = values(map(args.at(0))); if (args.count() == 2) { @@ -1602,9 +1624,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( const ProString &val = l[i]; if (val == qry) return ReturnTrue; - if (!regx.isEmpty()) { + if (!regx.pattern().isEmpty()) { ProStringRoUser u2(val, m_tmp[m_toggle ^= 1]); - if (regx.exactMatch(u2.str())) + if (regx.match(u2.str()).hasMatch()) return ReturnTrue; } } @@ -1617,9 +1639,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( if (val.toQStringRef() == mutuals[mut].trimmed()) { if (val == qry) return ReturnTrue; - if (!regx.isEmpty()) { + if (!regx.pattern().isEmpty()) { ProStringRoUser u2(val, m_tmp[m_toggle ^= 1]); - if (regx.exactMatch(u2.str())) + if (regx.match(u2.str()).hasMatch()) return ReturnTrue; } return ReturnFalse; diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index 7041a2402e..f78537c340 100644 --- a/qmake/library/qmakeevaluator.cpp +++ b/qmake/library/qmakeevaluator.cpp @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include @@ -334,7 +334,7 @@ ProStringList QMakeEvaluator::split_value_list(const QStringRef &vals, int sourc } static void replaceInList(ProStringList *varlist, - const QRegExp ®exp, const QString &replace, bool global, QString &tmp) + const QRegularExpression ®exp, const QString &replace, bool global, QString &tmp) { for (ProStringList::Iterator varit = varlist->begin(); varit != varlist->end(); ) { ProStringRoUser u1(*varit, tmp); @@ -898,9 +898,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProVariable( QString pattern = func[1].toString(); QString replace = func[2].toString(); if (quote) - pattern = QRegExp::escape(pattern); + pattern = QRegularExpression::escape(pattern); - QRegExp regexp(pattern, case_sense ? Qt::CaseSensitive : Qt::CaseInsensitive); + QRegularExpression regexp(pattern, case_sense ? QRegularExpression::NoPatternOption : + QRegularExpression::CaseInsensitiveOption); // We could make a union of modified and unmodified values, // but this will break just as much as it fixes, so leave it as is. @@ -1635,17 +1636,17 @@ bool QMakeEvaluator::isActiveConfig(const QStringRef &config, bool regex) return m_hostBuild; if (regex && (config.contains(QLatin1Char('*')) || config.contains(QLatin1Char('?')))) { - QRegExp re(config.toString(), Qt::CaseSensitive, QRegExp::Wildcard); + QRegularExpression re(QRegularExpression::wildcardToRegularExpression(config.toString())); // mkspecs - if (re.exactMatch(m_qmakespecName)) + if (re.match(m_qmakespecName).hasMatch()) return true; // CONFIG variable const auto configValues = values(statics.strCONFIG); for (const ProString &configValue : configValues) { ProStringRoUser u1(configValue, m_tmp[m_toggle ^= 1]); - if (re.exactMatch(u1.str())) + if (re.match(u1.str()).hasMatch()) return true; } } else { diff --git a/qmake/main.cpp b/qmake/main.cpp index c0e6088d80..3cd79145e5 100644 --- a/qmake/main.cpp +++ b/qmake/main.cpp @@ -34,7 +34,7 @@ #include "metamakefile.h" #include #include -#include +#include #include #include #include @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE #ifdef Q_OS_WIN struct SedSubst { - QRegExp from; + QRegularExpression from; QString to; }; Q_DECLARE_TYPEINFO(SedSubst, Q_MOVABLE_TYPE); @@ -85,7 +85,7 @@ static int doSed(int argc, char **argv) return 3; } QChar sep = ++j < cmd.length() ? cmd.at(j) : QChar(); - Qt::CaseSensitivity matchcase = Qt::CaseSensitive; + QRegularExpression::PatternOptions matchcase = QRegularExpression::NoPatternOption; bool escaped = false; int phase = 1; QStringList phases; @@ -129,14 +129,14 @@ static int doSed(int argc, char **argv) } if (curr.contains(QLatin1Char('i'))) { curr.remove(QLatin1Char('i')); - matchcase = Qt::CaseInsensitive; + matchcase = QRegularExpression::CaseInsensitiveOption; } if (curr != QLatin1String("g")) { fprintf(stderr, "Error: sed s command supports only g & i options; g is required\n"); return 3; } SedSubst subst; - subst.from = QRegExp(phases.at(0), matchcase); + subst.from = QRegularExpression(phases.at(0), matchcase); subst.to = phases.at(1); subst.to.replace(QLatin1String("\\\\"), QLatin1String("\\")); // QString::replace(rx, sub) groks \1, but not \\. substs << subst; diff --git a/qmake/option.cpp b/qmake/option.cpp index 9ec2fe6411..2d5ef9dfd6 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -30,7 +30,7 @@ #include "cachekeys.h" #include #include -#include +#include #include #include #include @@ -519,12 +519,14 @@ Option::fixString(QString string, uchar flags) //fix the environment variables if(flags & Option::FixEnvVars) { - int rep; - static QRegExp reg_var("\\$\\(.*\\)"); - reg_var.setMinimal(true); - while((rep = reg_var.indexIn(string)) != -1) - string.replace(rep, reg_var.matchedLength(), - QString::fromLocal8Bit(qgetenv(string.mid(rep + 2, reg_var.matchedLength() - 3).toLatin1().constData()).constData())); + static QRegularExpression reg_var("\\$\\(.*\\)", QRegularExpression::InvertedGreedinessOption); + QRegularExpressionMatch match; + while ((match = reg_var.match(string)).hasMatch()) { + int start = match.capturedStart(); + int len = match.capturedLength(); + string.replace(start, len, + QString::fromLocal8Bit(qgetenv(string.mid(start + 2, len - 3).toLatin1().constData()).constData())); + } } //canonicalize it (and treat as a path) -- cgit v1.2.3