diff options
author | Oswald Buddenhagen <oswald.buddenhagen@nokia.com> | 2012-09-05 18:29:19 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-09-11 00:13:01 +0200 |
commit | 0e78e5080262b8fa7a86f7cd0c8716839db048f6 (patch) | |
tree | 83ca3f608a6c9a359ba783d496ffdbc9ef7a6073 /qmake/library/qmakeparser.h | |
parent | ed7594db5db7b28ce4c4646624de97b52fbf16d5 (diff) |
port qmake to qt creator's qmake language evaluator
this is a monster commit which does the following things:
- import the evaluator as-is from qt creator into qmake/library/
- integrate it into qmake's makefiles
- overwrite proitems.h with actual special types
- remove the parts of Option which are redundant with QMakeGlobals
- make QMakeProperty a singleton owned by Option::globals. the dynamic
handling so far made no sense.
- make QMakeProject a subclass of QMakeEvaluator, with relatively few
extensions
the changes to existing qmake code outside project.* and option.* are
minor. implementing the changes gradually would mean changing a lot of
code which will be just replaced in the next commit, so i'm not wasting
my time on it.
Change-Id: I9746650423b8c5b3fbd8c3979a73228982a46195
Reviewed-by: Qt Doc Bot <qt_docbot@qt-project.org>
Reviewed-by: Joerg Bornemann <joerg.bornemann@nokia.com>
Diffstat (limited to 'qmake/library/qmakeparser.h')
-rw-r--r-- | qmake/library/qmakeparser.h | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/qmake/library/qmakeparser.h b/qmake/library/qmakeparser.h new file mode 100644 index 0000000000..cbda916dc2 --- /dev/null +++ b/qmake/library/qmakeparser.h @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the qmake application of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMAKEPARSER_H +#define QMAKEPARSER_H + +#include "qmake_global.h" +#include "proitems.h" + +#include <qhash.h> +#include <qstack.h> +#ifdef PROPARSER_THREAD_SAFE +# include <qmutex.h> +# include <qwaitcondition.h> +#endif + +QT_BEGIN_NAMESPACE +class QMAKE_EXPORT QMakeParserHandler +{ +public: + enum { + CategoryMask = 0xf00, + WarningMessage = 0x000, + ErrorMessage = 0x100, + + SourceMask = 0xf0, + SourceParser = 0, + + CodeMask = 0xf, + WarnLanguage = 0, + WarnDeprecated, + + ParserWarnLanguage = SourceParser | WarningMessage | WarnLanguage, + ParserWarnDeprecated = SourceParser | WarningMessage | WarnDeprecated, + + ParserIoError = ErrorMessage | SourceParser, + ParserError + }; + virtual void message(int type, const QString &msg, + const QString &fileName = QString(), int lineNo = 0) = 0; +}; + +class ProFileCache; + +class QMAKE_EXPORT QMakeParser +{ +public: + // Call this from a concurrency-free context + static void initialize(); + + QMakeParser(ProFileCache *cache, QMakeParserHandler *handler); + + enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar }; + // fileName is expected to be absolute and cleanPath()ed. + ProFile *parsedProFile(const QString &fileName, bool cache = false); + ProFile *parsedProBlock(const QString &contents, const QString &name, int line = 0, + SubGrammar grammar = FullGrammar); + +private: + struct BlockScope { + BlockScope() : start(0), braceLevel(0), special(false), inBranch(false) {} + BlockScope(const BlockScope &other) { *this = other; } + ushort *start; // Where this block started; store length here + int braceLevel; // Nesting of braces in scope + bool special; // Single-line conditionals inside loops, etc. cannot have else branches + bool inBranch; // The 'else' branch of the previous TokBranch is still open + }; + + enum ScopeState { + StNew, // Fresh scope + StCtrl, // Control statement (for or else) met on current line + StCond // Conditionals met on current line + }; + + enum Context { CtxTest, CtxValue, CtxPureValue, CtxArgs }; + struct ParseCtx { + int parens; // Nesting of non-functional parentheses + int argc; // Number of arguments in current function call + int wordCount; // Number of words in current expression + Context context; + ushort quote; // Enclosing quote type + ushort terminator; // '}' if replace function call is braced, ':' if test function + }; + + bool read(ProFile *pro); + bool read(ProFile *pro, const QString &content, int line, SubGrammar grammar); + + ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok); + ALWAYS_INLINE void putBlockLen(ushort *&tokPtr, uint len); + ALWAYS_INLINE void putBlock(ushort *&tokPtr, const ushort *buf, uint len); + void putHashStr(ushort *&pTokPtr, const ushort *buf, uint len); + void finalizeHashStr(ushort *buf, uint len); + void putLineMarker(ushort *&tokPtr); + ALWAYS_INLINE bool resolveVariable(ushort *xprPtr, int tlen, int needSep, ushort **ptr, + ushort **buf, QString *xprBuff, + ushort **tokPtr, QString *tokBuff, + const ushort *cur, const QString &in); + void finalizeCond(ushort *&tokPtr, ushort *uc, ushort *ptr, int wordCount); + void finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int argc); + void finalizeTest(ushort *&tokPtr); + void bogusTest(ushort *&tokPtr); + void enterScope(ushort *&tokPtr, bool special, ScopeState state); + void leaveScope(ushort *&tokPtr); + void flushCond(ushort *&tokPtr); + void flushScopes(ushort *&tokPtr); + + void message(int type, const QString &msg) const; + void parseError(const QString &msg) const + { message(QMakeParserHandler::ParserError, msg); } + void languageWarning(const QString &msg) const + { message(QMakeParserHandler::ParserWarnLanguage, msg); } + void deprecationWarning(const QString &msg) const + { message(QMakeParserHandler::ParserWarnDeprecated, msg); } + + // Current location + ProFile *m_proFile; + int m_lineNo; + + QStack<BlockScope> m_blockstack; + ScopeState m_state; + int m_markLine; // Put marker for this line + bool m_inError; // Current line had a parsing error; suppress followup error messages + bool m_canElse; // Conditionals met on previous line, but no scope was opened + bool m_invert; // Pending conditional is negated + enum { NoOperator, AndOperator, OrOperator } m_operator; // Pending conditional is ORed/ANDed + + QString m_tmp; // Temporary for efficient toQString + + ProFileCache *m_cache; + QMakeParserHandler *m_handler; + + // This doesn't help gcc 3.3 ... + template<typename T> friend class QTypeInfo; + + friend class ProFileCache; +}; + +class QMAKE_EXPORT ProFileCache +{ +public: + ProFileCache() {} + ~ProFileCache(); + + void discardFile(const QString &fileName); + void discardFiles(const QString &prefix); + +private: + struct Entry { + ProFile *pro; +#ifdef PROPARSER_THREAD_SAFE + struct Locker { + Locker() : waiters(0), done(false) {} + QWaitCondition cond; + int waiters; + bool done; + }; + Locker *locker; +#endif + }; + + QHash<QString, Entry> parsed_files; +#ifdef PROPARSER_THREAD_SAFE + QMutex mutex; +#endif + + friend class QMakeParser; +}; + +#if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3) +Q_DECLARE_TYPEINFO(QMakeParser::BlockScope, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QMakeParser::Context, Q_PRIMITIVE_TYPE); +#endif + +QT_END_NAMESPACE + +#endif // PROFILEPARSER_H |