| 1 | // Copyright (C) 2016 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
| 3 | |
| 4 | #include "project.h" |
| 5 | |
| 6 | #include "cachekeys.h" |
| 7 | #include "option.h" |
| 8 | #include <qmakeevaluator_p.h> |
| 9 | |
| 10 | #include <qdir.h> |
| 11 | |
| 12 | #include <stdio.h> |
| 13 | |
| 14 | using namespace QMakeInternal; |
| 15 | |
| 16 | QT_BEGIN_NAMESPACE |
| 17 | |
| 18 | QMakeProject::QMakeProject() |
| 19 | : QMakeEvaluator(Option::globals, Option::parser, Option::vfs, &Option::evalHandler) |
| 20 | { |
| 21 | } |
| 22 | |
| 23 | QMakeProject::QMakeProject(QMakeProject *p) |
| 24 | : QMakeEvaluator(Option::globals, Option::parser, Option::vfs, &Option::evalHandler) |
| 25 | { |
| 26 | initFrom(other: p); |
| 27 | } |
| 28 | |
| 29 | bool QMakeProject::boolRet(VisitReturn vr) |
| 30 | { |
| 31 | if (vr == ReturnError) { |
| 32 | qmakeClearCaches(); |
| 33 | exit(status: 3); |
| 34 | } |
| 35 | Q_ASSERT(vr == ReturnTrue || vr == ReturnFalse); |
| 36 | return vr != ReturnFalse; |
| 37 | } |
| 38 | |
| 39 | bool QMakeProject::read(const QString &project, LoadFlags what) |
| 40 | { |
| 41 | m_projectFile = project; |
| 42 | setOutputDir(Option::output_dir); |
| 43 | QString absproj = (project == QLatin1String("-" )) |
| 44 | ? QLatin1String("(stdin)" ) |
| 45 | : QDir::cleanPath(path: QDir(qmake_getpwd()).absoluteFilePath(fileName: project)); |
| 46 | m_projectDir = QFileInfo(absproj).path(); |
| 47 | return boolRet(vr: evaluateFile(fileName: absproj, type: QMakeHandler::EvalProjectFile, flags: what)); |
| 48 | } |
| 49 | |
| 50 | static ProStringList prepareBuiltinArgs(const QList<ProStringList> &args) |
| 51 | { |
| 52 | ProStringList ret; |
| 53 | ret.reserve(asize: args.size()); |
| 54 | for (const ProStringList &arg : args) |
| 55 | ret << arg.join(sep: ' '); |
| 56 | return ret; |
| 57 | } |
| 58 | |
| 59 | bool QMakeProject::test(const ProKey &func, const QList<ProStringList> &args) |
| 60 | { |
| 61 | m_current.clear(); |
| 62 | |
| 63 | auto adef = statics.functions.constFind(key: func); |
| 64 | if (adef != statics.functions.constEnd()) |
| 65 | return boolRet(vr: evaluateBuiltinConditional(adef: *adef, function: func, args: prepareBuiltinArgs(args))); |
| 66 | |
| 67 | QHash<ProKey, ProFunctionDef>::ConstIterator it = |
| 68 | m_functionDefs.testFunctions.constFind(key: func); |
| 69 | if (it != m_functionDefs.testFunctions.constEnd()) |
| 70 | return boolRet(vr: evaluateBoolFunction(func: *it, argumentsList: args, function: func)); |
| 71 | |
| 72 | evalError(QStringLiteral("'%1' is not a recognized test function." ) |
| 73 | .arg(a: func.toQStringView())); |
| 74 | return false; |
| 75 | } |
| 76 | |
| 77 | QStringList QMakeProject::expand(const ProKey &func, const QList<ProStringList> &args) |
| 78 | { |
| 79 | m_current.clear(); |
| 80 | |
| 81 | auto adef = statics.expands.constFind(key: func); |
| 82 | if (adef != statics.expands.constEnd()) { |
| 83 | ProStringList ret; |
| 84 | if (evaluateBuiltinExpand(adef: *adef, function: func, args: prepareBuiltinArgs(args), ret) == ReturnError) |
| 85 | exit(status: 3); |
| 86 | return ret.toQStringList(); |
| 87 | } |
| 88 | |
| 89 | QHash<ProKey, ProFunctionDef>::ConstIterator it = |
| 90 | m_functionDefs.replaceFunctions.constFind(key: func); |
| 91 | if (it != m_functionDefs.replaceFunctions.constEnd()) { |
| 92 | ProStringList ret; |
| 93 | if (evaluateFunction(func: *it, argumentsList: args, ret: &ret) == QMakeProject::ReturnError) |
| 94 | exit(status: 3); |
| 95 | return ret.toQStringList(); |
| 96 | } |
| 97 | |
| 98 | evalError(QStringLiteral("'%1' is not a recognized replace function." ) |
| 99 | .arg(a: func.toQStringView())); |
| 100 | return QStringList(); |
| 101 | } |
| 102 | |
| 103 | ProString QMakeProject::expand(const QString &expr, const QString &where, int line) |
| 104 | { |
| 105 | ProString ret; |
| 106 | ProFile *pro = m_parser->parsedProBlock(contents: QStringView(expr), id: 0, name: where, line, |
| 107 | grammar: QMakeParser::ValueGrammar); |
| 108 | if (pro->isOk()) { |
| 109 | m_current.pro = pro; |
| 110 | m_current.line = 0; |
| 111 | const ushort *tokPtr = pro->tokPtr(); |
| 112 | ProStringList result; |
| 113 | if (expandVariableReferences(tokPtr, sizeHint: 1, ret: &result, joined: true) == ReturnError) |
| 114 | exit(status: 3); |
| 115 | if (!result.isEmpty()) |
| 116 | ret = result.at(i: 0); |
| 117 | } |
| 118 | pro->deref(); |
| 119 | return ret; |
| 120 | } |
| 121 | |
| 122 | bool QMakeProject::isEmpty(const ProKey &v) const |
| 123 | { |
| 124 | ProValueMap::ConstIterator it = m_valuemapStack.front().constFind(key: v); |
| 125 | return it == m_valuemapStack.front().constEnd() || it->isEmpty(); |
| 126 | } |
| 127 | |
| 128 | void QMakeProject::dump() const |
| 129 | { |
| 130 | QStringList out; |
| 131 | for (ProValueMap::ConstIterator it = m_valuemapStack.front().begin(); |
| 132 | it != m_valuemapStack.front().end(); ++it) { |
| 133 | if (!it.key().startsWith(c: '.')) { |
| 134 | QString str = it.key() + " =" ; |
| 135 | for (const ProString &v : it.value()) |
| 136 | str += ' ' + formatValue(val: v); |
| 137 | out << str; |
| 138 | } |
| 139 | } |
| 140 | out.sort(); |
| 141 | for (const QString &v : std::as_const(t&: out)) |
| 142 | puts(qPrintable(v)); |
| 143 | } |
| 144 | |
| 145 | QT_END_NAMESPACE |
| 146 | |