Revision control
++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
++
++ #ifndef QMAKEEVALUATOR_H
++ #define QMAKEEVALUATOR_H
++
++ #if defined(PROEVALUATOR_FULL) && defined(PROEVALUATOR_THREAD_SAFE)
++ # error PROEVALUATOR_FULL is incompatible with PROEVALUATOR_THREAD_SAFE due to cache() implementation
++ #endif
++
++ #include "qmakeparser.h"
++ #include "qmakevfs.h"
++ #include "ioutils.h"
++
++ #include <qlist.h>
++ #include <qmap.h>
++ #include <qset.h>
++ #include <qstack.h>
++ #include <qstring.h>
++ #include <qstringlist.h>
++ #include <qshareddata.h>
++ #if QT_CONFIG(process)
++ # include <qprocess.h>
++ #else
++ # include <qiodevice.h>
++ #endif
++ #ifdef PROEVALUATOR_THREAD_SAFE
++ # include <qmutex.h>
++ #endif
++
++ #include <list>
++
++ QT_BEGIN_NAMESPACE
++
++ class QMakeGlobals;
++
++ class QMAKE_EXPORT QMakeHandler : public QMakeParserHandler
++ {
++ public:
++ enum {
++ SourceEvaluator = 0x10,
++
++ CumulativeEvalMessage = 0x1000,
++
++ EvalWarnLanguage = SourceEvaluator | WarningMessage | WarnLanguage,
++ EvalWarnDeprecated = SourceEvaluator | WarningMessage | WarnDeprecated,
++
++ EvalError = ErrorMessage | SourceEvaluator
++ };
++
++ // error(), warning() and message() from .pro file
++ virtual void fileMessage(int type, const QString &msg) = 0;
++
++ enum EvalFileType { EvalProjectFile, EvalIncludeFile, EvalConfigFile, EvalFeatureFile, EvalAuxFile };
++ virtual void aboutToEval(ProFile *parent, ProFile *proFile, EvalFileType type) = 0;
++ virtual void doneWithEval(ProFile *parent) = 0;
++ };
++
++ typedef QPair<QString, QString> QMakeFeatureKey; // key, parent
++ typedef QHash<QMakeFeatureKey, QString> QMakeFeatureHash;
++
++ class QMAKE_EXPORT QMakeFeatureRoots : public QSharedData
++ {
++ public:
++ QMakeFeatureRoots(const QStringList &_paths) : paths(_paths) {}
++ const QStringList paths;
++ mutable QMakeFeatureHash cache;
++ #ifdef PROEVALUATOR_THREAD_SAFE
++ mutable QMutex mutex;
++ #endif
++ };
++
++ // We use a list-based stack instead of a vector-based one, so that
++ // the addresses of value maps stay constant. The qmake generators rely on that.
++ class QMAKE_EXPORT ProValueMapStack : public std::list<ProValueMap>
++ {
++ public:
++ inline void push(const ProValueMap &t) { push_back(t); }
++ inline ProValueMap pop() { auto r = std::move(back()); pop_back(); return r; }
++ ProValueMap &top() { return back(); }
++ const ProValueMap &top() const { return back(); }
++ };
++
++ namespace QMakeInternal { struct QMakeBuiltin; }
++
++ class QMAKE_EXPORT QMakeEvaluator
++ {
++ public:
++ enum LoadFlag {
++ LoadProOnly = 0,
++ LoadPreFiles = 1,
++ LoadPostFiles = 2,
++ LoadAll = LoadPreFiles|LoadPostFiles,
++ LoadSilent = 0x10,
++ LoadHidden = 0x20
++ };
++ Q_DECLARE_FLAGS(LoadFlags, LoadFlag)
++
++ static void initStatics();
++ static void initFunctionStatics();
++ QMakeEvaluator(QMakeGlobals *option, QMakeParser *parser, QMakeVfs *vfs,
++ QMakeHandler *handler);
++ ~QMakeEvaluator();
++
++ void setExtraVars(const ProValueMap &extraVars) { m_extraVars = extraVars; }
++ void setExtraConfigs(const ProStringList &extraConfigs) { m_extraConfigs = extraConfigs; }
++ void setOutputDir(const QString &outputDir) { m_outputDir = outputDir; }
++
++ ProStringList values(const ProKey &variableName) const;
++ ProStringList &valuesRef(const ProKey &variableName);
++ ProString first(const ProKey &variableName) const;
++ ProString propertyValue(const ProKey &val) const;
++
++ ProString dirSep() const { return m_dirSep; }
++ bool isHostBuild() const { return m_hostBuild; }
++
++ enum VisitReturn {
++ ReturnFalse,
++ ReturnTrue,
++ ReturnError,
++ ReturnBreak,
++ ReturnNext,
++ ReturnReturn
++ };
++
++ static ALWAYS_INLINE VisitReturn returnBool(bool b)
++ { return b ? ReturnTrue : ReturnFalse; }
++
++ static ALWAYS_INLINE uint getBlockLen(const ushort *&tokPtr);
++ VisitReturn evaluateExpression(const ushort *&tokPtr, ProStringList *ret, bool joined);
++ static ALWAYS_INLINE void skipStr(const ushort *&tokPtr);
++ static ALWAYS_INLINE void skipHashStr(const ushort *&tokPtr);
++ void skipExpression(const ushort *&tokPtr);
++
++ void loadDefaults();
++ bool prepareProject(const QString &inDir);
++ bool loadSpecInternal();
++ bool loadSpec();
++ void initFrom(const QMakeEvaluator *other);
++ void setupProject();
++ void evaluateCommand(const QString &cmds, const QString &where);
++ void applyExtraConfigs();
++ VisitReturn visitProFile(ProFile *pro, QMakeHandler::EvalFileType type,
++ LoadFlags flags);
++ VisitReturn visitProBlock(ProFile *pro, const ushort *tokPtr);
++ VisitReturn visitProBlock(const ushort *tokPtr);
++ VisitReturn visitProLoop(const ProKey &variable, const ushort *exprPtr,
++ const ushort *tokPtr);
++ void visitProFunctionDef(ushort tok, const ProKey &name, const ushort *tokPtr);
++ VisitReturn visitProVariable(ushort tok, const ProStringList &curr, const ushort *&tokPtr);
++
++ ALWAYS_INLINE const ProKey &map(const ProString &var) { return map(var.toKey()); }
++ const ProKey &map(const ProKey &var);
++ ProValueMap *findValues(const ProKey &variableName, ProValueMap::Iterator *it);
++
++ void setTemplate();
++
++ ProStringList split_value_list(QStringView vals, int source = 0);
++ VisitReturn expandVariableReferences(const ushort *&tokPtr, int sizeHint, ProStringList *ret, bool joined);
++
++ QString currentFileName() const;
++ QString currentDirectory() const;
++ ProFile *currentProFile() const;
++ int currentFileId() const;
++ QString resolvePath(const QString &fileName) const
++ { return QMakeInternal::IoUtils::resolvePath(currentDirectory(), fileName); }
++ QString filePathArg0(const ProStringList &args);
++ QString filePathEnvArg0(const ProStringList &args);
++
++ VisitReturn evaluateFile(const QString &fileName, QMakeHandler::EvalFileType type,
++ LoadFlags flags);
++ VisitReturn evaluateFileChecked(const QString &fileName, QMakeHandler::EvalFileType type,
++ LoadFlags flags);
++ VisitReturn evaluateFeatureFile(const QString &fileName, bool silent = false);
++ VisitReturn evaluateFileInto(const QString &fileName,
++ ProValueMap *values, // output-only
++ LoadFlags flags);
++ VisitReturn evaluateConfigFeatures();
++ void message(int type, const QString &msg) const;
++ void evalError(const QString &msg) const
++ { message(QMakeHandler::EvalError, msg); }
++ void languageWarning(const QString &msg) const
++ { message(QMakeHandler::EvalWarnLanguage, msg); }
++ void deprecationWarning(const QString &msg) const
++ { message(QMakeHandler::EvalWarnDeprecated, msg); }
++
++ VisitReturn prepareFunctionArgs(const ushort *&tokPtr, QList<ProStringList> *ret);
++ VisitReturn evaluateFunction(const ProFunctionDef &func,
++ const QList<ProStringList> &argumentsList, ProStringList *ret);
++ VisitReturn evaluateBoolFunction(const ProFunctionDef &func,
++ const QList<ProStringList> &argumentsList,
++ const ProString &function);
++
++ VisitReturn evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr, ProStringList *ret);
++ VisitReturn evaluateConditionalFunction(const ProKey &function, const ushort *&tokPtr);
++
++ VisitReturn evaluateBuiltinExpand(const QMakeInternal::QMakeBuiltin &adef,
++ const ProKey &function, const ProStringList &args, ProStringList &ret);
++ VisitReturn evaluateBuiltinConditional(const QMakeInternal::QMakeBuiltin &adef,
++ const ProKey &function, const ProStringList &args);
++
++ VisitReturn evaluateConditional(QStringView cond, const QString &where, int line = -1);
++ #ifdef PROEVALUATOR_FULL
++ VisitReturn checkRequirements(const ProStringList &deps);
++ #endif
++
++ void updateMkspecPaths();
++ void updateFeaturePaths();
++
++ bool isActiveConfig(QStringView config, bool regex = false);
++
++ void populateDeps(
++ const ProStringList &deps, const ProString &prefix, const ProStringList &suffixes,
++ const ProString &priosfx,
++ QHash<ProKey, QSet<ProKey> > &dependencies, ProValueMap &dependees,
++ QMultiMap<int, ProString> &rootSet) const;
++
++ bool getMemberArgs(const ProKey &name, int srclen, const ProStringList &args,
++ int *start, int *end);
++ VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value);
++
++ VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
++ QMakeVfs::VfsFlags flags, const QString &contents);
++ #if QT_CONFIG(process)
++ void runProcess(QProcess *proc, const QString &command) const;
++ #endif
++ QByteArray getCommandOutput(const QString &args, int *exitCode) const;
++
++ private:
++ // Implementation detail of evaluateBuiltinConditional():
++ VisitReturn testFunc_cache(const ProStringList &args);
++
++ public:
++ QMakeEvaluator *m_caller;
++ #ifdef PROEVALUATOR_CUMULATIVE
++ bool m_cumulative;
++ int m_skipLevel;
++ #else
++ enum { m_cumulative = 0 };
++ enum { m_skipLevel = 0 };
++ #endif
++
++ static QString quoteValue(const ProString &val);
++
++ #ifdef PROEVALUATOR_DEBUG
++ void debugMsgInternal(int level, const char *fmt, ...) const;
++ void traceMsgInternal(const char *fmt, ...) const;
++ static QString formatValue(const ProString &val, bool forceQuote = false);
++ static QString formatValueList(const ProStringList &vals, bool commas = false);
++ static QString formatValueListList(const QList<ProStringList> &vals);
++
++ const int m_debugLevel;
++ #else
++ ALWAYS_INLINE void debugMsgInternal(int, const char *, ...) const {}
++ ALWAYS_INLINE void traceMsgInternal(const char *, ...) const {}
++
++ enum { m_debugLevel = 0 };
++ #endif
++
++ struct Location {
++ Location() : pro(nullptr), line(0) {}
++ Location(ProFile *_pro, ushort _line) : pro(_pro), line(_line) {}
++ void clear() { pro = nullptr; line = 0; }
++ ProFile *pro;
++ ushort line;
++ };
++
++ Location m_current; // Currently evaluated location
++ QStack<Location> m_locationStack; // All execution location changes
++ QStack<ProFile *> m_profileStack; // Includes only
++
++ ProValueMap m_extraVars;
++ ProStringList m_extraConfigs;
++ QString m_outputDir;
++
++ int m_listCount;
++ int m_toggle;
++ bool m_valuemapInited;
++ bool m_hostBuild;
++ QString m_qmakespec;
++ QString m_qmakespecName;
++ QString m_superfile;
++ QString m_conffile;
++ QString m_cachefile;
++ QString m_stashfile;
++ QString m_sourceRoot;
++ QString m_buildRoot;
++ QStringList m_qmakepath;
++ QStringList m_qmakefeatures;
++ QStringList m_mkspecPaths;
++ QExplicitlySharedDataPointer<QMakeFeatureRoots> m_featureRoots;
++ ProString m_dirSep;
++ ProFunctionDefs m_functionDefs;
++ ProStringList m_returnValue;
++ ProValueMapStack m_valuemapStack; // VariableName must be us-ascii, the content however can be non-us-ascii.
++ QString m_tmp1, m_tmp2, m_tmp3, m_tmp[2]; // Temporaries for efficient toQString
++
++ QMakeGlobals *m_option;
++ QMakeParser *m_parser;
++ QMakeHandler *m_handler;
++ QMakeVfs *m_vfs;
++ };
++ Q_DECLARE_TYPEINFO(QMakeEvaluator::Location, Q_PRIMITIVE_TYPE);
++
++ Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeEvaluator::LoadFlags)
++
++ QT_END_NAMESPACE
++
++ #endif // QMAKEEVALUATOR_H