make error() abort the qmake run, not just the current file
[qt:qttools.git] / src / linguist / shared / qmakeevaluator.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the Qt Linguist of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QMAKEEVALUATOR_H
43 #define QMAKEEVALUATOR_H
44
45 #if defined(PROEVALUATOR_FULL) && defined(PROEVALUATOR_THREAD_SAFE)
46 #  error PROEVALUATOR_FULL is incompatible with PROEVALUATOR_THREAD_SAFE due to cache() implementation
47 #endif
48
49 #include "qmakeparser.h"
50 #include "ioutils.h"
51
52 #include <qlist.h>
53 #include <qlinkedlist.h>
54 #include <qset.h>
55 #include <qstack.h>
56 #include <qstring.h>
57 #include <qstringlist.h>
58 #ifndef QT_BOOTSTRAPPED
59 # include <qprocess.h>
60 #endif
61
62 QT_BEGIN_NAMESPACE
63
64 class QMakeGlobals;
65
66 class QMAKE_EXPORT QMakeHandler : public QMakeParserHandler
67 {
68 public:
69     enum {
70         SourceEvaluator = 0x10,
71
72         EvalWarnLanguage = SourceEvaluator |  WarningMessage | WarnLanguage,
73         EvalWarnDeprecated = SourceEvaluator | WarningMessage | WarnDeprecated,
74
75         EvalError = ErrorMessage | SourceEvaluator
76     };
77
78     // error(), warning() and message() from .pro file
79     virtual void fileMessage(const QString &msg) = 0;
80
81     enum EvalFileType { EvalProjectFile, EvalIncludeFile, EvalConfigFile, EvalFeatureFile, EvalAuxFile };
82     virtual void aboutToEval(ProFile *parent, ProFile *proFile, EvalFileType type) = 0;
83     virtual void doneWithEval(ProFile *parent) = 0;
84 };
85
86 // We use a QLinkedList based stack instead of a QVector based one (QStack), so that
87 // the addresses of value maps stay constant. The qmake generators rely on that.
88 class QMAKE_EXPORT ProValueMapStack : public QLinkedList<ProValueMap>
89 {
90 public:
91     inline void push(const ProValueMap &t) { append(t); }
92     inline ProValueMap pop() { return takeLast(); }
93     ProValueMap &top() { return last(); }
94     const ProValueMap &top() const { return last(); }
95 };
96
97 class QMAKE_EXPORT QMakeEvaluator
98 {
99 public:
100     enum LoadFlag {
101         LoadProOnly = 0,
102         LoadPreFiles = 1,
103         LoadPostFiles = 2,
104         LoadAll = LoadPreFiles|LoadPostFiles,
105         LoadSilent = 0x10
106     };
107     Q_DECLARE_FLAGS(LoadFlags, LoadFlag)
108
109     static void initStatics();
110     static void initFunctionStatics();
111     QMakeEvaluator(QMakeGlobals *option, QMakeParser *parser,
112                    QMakeHandler *handler);
113     ~QMakeEvaluator();
114
115     void setExtraVars(const ProValueMap &extraVars) { m_extraVars = extraVars; }
116     void setExtraConfigs(const ProStringList &extraConfigs) { m_extraConfigs = extraConfigs; }
117     void setOutputDir(const QString &outputDir) { m_outputDir = outputDir; }
118
119     ProStringList values(const ProKey &variableName) const;
120     ProStringList &valuesRef(const ProKey &variableName);
121     ProString first(const ProKey &variableName) const;
122     ProString propertyValue(const ProKey &val) const;
123
124     ProString dirSep() const { return m_dirSep; }
125     bool isHostBuild() const { return m_hostBuild; }
126
127     enum VisitReturn {
128         ReturnFalse,
129         ReturnTrue,
130         ReturnError,
131         ReturnBreak,
132         ReturnNext,
133         ReturnReturn
134     };
135
136     static ALWAYS_INLINE VisitReturn returnBool(bool b)
137         { return b ? ReturnTrue : ReturnFalse; }
138
139     static ALWAYS_INLINE uint getBlockLen(const ushort *&tokPtr);
140     ProString getStr(const ushort *&tokPtr);
141     ProKey getHashStr(const ushort *&tokPtr);
142     void evaluateExpression(const ushort *&tokPtr, ProStringList *ret, bool joined);
143     static ALWAYS_INLINE void skipStr(const ushort *&tokPtr);
144     static ALWAYS_INLINE void skipHashStr(const ushort *&tokPtr);
145     void skipExpression(const ushort *&tokPtr);
146
147     void loadDefaults();
148     bool prepareProject(const QString &inDir);
149     bool loadSpecInternal();
150     bool loadSpec();
151     void initFrom(const QMakeEvaluator &other);
152     void setupProject();
153     void evaluateCommand(const QString &cmds, const QString &where);
154     VisitReturn visitProFile(ProFile *pro, QMakeHandler::EvalFileType type,
155                              LoadFlags flags);
156     VisitReturn visitProBlock(ProFile *pro, const ushort *tokPtr);
157     VisitReturn visitProBlock(const ushort *tokPtr);
158     VisitReturn visitProLoop(const ProKey &variable, const ushort *exprPtr,
159                              const ushort *tokPtr);
160     void visitProFunctionDef(ushort tok, const ProKey &name, const ushort *tokPtr);
161     void visitProVariable(ushort tok, const ProStringList &curr, const ushort *&tokPtr);
162
163     ALWAYS_INLINE const ProKey &map(const ProString &var) { return map(var.toKey()); }
164     const ProKey &map(const ProKey &var);
165     ProValueMap *findValues(const ProKey &variableName, ProValueMap::Iterator *it);
166
167     void setTemplate();
168
169     ProStringList split_value_list(const QString &vals, const ProFile *source = 0);
170     ProStringList expandVariableReferences(const ProString &value, int *pos = 0, bool joined = false);
171     ProStringList expandVariableReferences(const ushort *&tokPtr, int sizeHint = 0, bool joined = false);
172
173     QString currentFileName() const;
174     QString currentDirectory() const;
175     ProFile *currentProFile() const;
176     QString resolvePath(const QString &fileName) const
177         { return QMakeInternal::IoUtils::resolvePath(currentDirectory(), fileName); }
178
179     VisitReturn evaluateFile(const QString &fileName, QMakeHandler::EvalFileType type,
180                              LoadFlags flags);
181     VisitReturn evaluateFileChecked(const QString &fileName, QMakeHandler::EvalFileType type,
182                                     LoadFlags flags);
183     VisitReturn evaluateFeatureFile(const QString &fileName, bool silent = false);
184     VisitReturn evaluateFileInto(const QString &fileName,
185                                  ProValueMap *values, // output-only
186                                  LoadFlags flags);
187     VisitReturn evaluateConfigFeatures();
188     void message(int type, const QString &msg) const;
189     void evalError(const QString &msg) const
190             { message(QMakeHandler::EvalError, msg); }
191     void languageWarning(const QString &msg) const
192             { message(QMakeHandler::EvalWarnLanguage, msg); }
193     void deprecationWarning(const QString &msg) const
194             { message(QMakeHandler::EvalWarnDeprecated, msg); }
195
196     QList<ProStringList> prepareFunctionArgs(const ushort *&tokPtr);
197     ProStringList evaluateFunction(const ProFunctionDef &func,
198                                    const QList<ProStringList> &argumentsList, VisitReturn *ok);
199     VisitReturn evaluateBoolFunction(const ProFunctionDef &func,
200                                      const QList<ProStringList> &argumentsList,
201                                      const ProString &function);
202
203     ProStringList evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr);
204     VisitReturn evaluateConditionalFunction(const ProKey &function, const ushort *&tokPtr);
205
206     ProStringList evaluateBuiltinExpand(int func_t, const ProKey &function, const ProStringList &args);
207     VisitReturn evaluateBuiltinConditional(int func_t, const ProKey &function, const ProStringList &args);
208
209     bool evaluateConditional(const QString &cond, const QString &where, int line = -1);
210 #ifdef PROEVALUATOR_FULL
211     void checkRequirements(const ProStringList &deps);
212 #endif
213
214     void updateMkspecPaths();
215     void updateFeaturePaths();
216
217     bool isActiveConfig(const QString &config, bool regex = false);
218
219     void populateDeps(
220             const ProStringList &deps, const ProString &prefix, const ProStringList &suffixes,
221             QHash<ProKey, QSet<ProKey> > &dependencies,
222             ProValueMap &dependees, ProStringList &rootSet) const;
223
224     VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
225                           const QString &contents);
226 #ifndef QT_BOOTSTRAPPED
227     void runProcess(QProcess *proc, const QString &command) const;
228 #endif
229     QByteArray getCommandOutput(const QString &args) const;
230
231     static void removeEach(ProStringList *varlist, const ProStringList &value);
232
233     QMakeEvaluator *m_caller;
234 #ifdef PROEVALUATOR_CUMULATIVE
235     bool m_cumulative;
236     int m_skipLevel;
237 #else
238     enum { m_cumulative = 0 };
239     enum { m_skipLevel = 0 };
240 #endif
241
242 #ifdef PROEVALUATOR_DEBUG
243     void debugMsgInternal(int level, const char *fmt, ...) const;
244     void traceMsgInternal(const char *fmt, ...) const;
245     static QString formatValue(const ProString &val, bool forceQuote = false);
246     static QString formatValueList(const ProStringList &vals, bool commas = false);
247     static QString formatValueListList(const QList<ProStringList> &vals);
248
249     const int m_debugLevel;
250 #else
251     ALWAYS_INLINE void debugMsgInternal(int, const char *, ...) const {}
252     ALWAYS_INLINE void traceMsgInternal(const char *, ...) const {}
253
254     enum { m_debugLevel = 0 };
255 #endif
256
257     struct Location {
258         Location() : pro(0), line(0) {}
259         Location(ProFile *_pro, ushort _line) : pro(_pro), line(_line) {}
260         void clear() { pro = 0; line = 0; }
261         ProFile *pro;
262         ushort line;
263     };
264
265     Location m_current; // Currently evaluated location
266     QStack<Location> m_locationStack; // All execution location changes
267     QStack<ProFile *> m_profileStack; // Includes only
268
269     ProValueMap m_extraVars;
270     ProStringList m_extraConfigs;
271     QString m_outputDir;
272
273     int m_listCount;
274     bool m_valuemapInited;
275     bool m_hostBuild;
276     QString m_qmakespec;
277     QString m_qmakespecName;
278     QString m_superfile;
279     QString m_conffile;
280     QString m_cachefile;
281     QString m_sourceRoot;
282     QString m_buildRoot;
283     QStringList m_qmakepath;
284     QStringList m_qmakefeatures;
285     QStringList m_mkspecPaths;
286     QStringList m_featureRoots;
287     ProString m_dirSep;
288     ProFunctionDefs m_functionDefs;
289     ProStringList m_returnValue;
290     ProValueMapStack m_valuemapStack; // VariableName must be us-ascii, the content however can be non-us-ascii.
291     QString m_tmp1, m_tmp2, m_tmp3, m_tmp[2]; // Temporaries for efficient toQString
292     mutable QString m_mtmp;
293
294     QMakeGlobals *m_option;
295     QMakeParser *m_parser;
296     QMakeHandler *m_handler;
297 };
298
299 Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeEvaluator::LoadFlags)
300
301 QT_END_NAMESPACE
302
303 #endif // QMAKEEVALUATOR_H