diff options
Diffstat (limited to 'tools/linguist/shared/profileparser.h')
-rw-r--r-- | tools/linguist/shared/profileparser.h | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/tools/linguist/shared/profileparser.h b/tools/linguist/shared/profileparser.h new file mode 100644 index 0000000..643e339 --- /dev/null +++ b/tools/linguist/shared/profileparser.h @@ -0,0 +1,195 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Linguist 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 PROFILEPARSER_H +#define PROFILEPARSER_H + +#include "proparser_global.h" +#include "proitems.h" +#include <QtCore/QHash> +#include <QtCore/QStack> +#ifdef PROPARSER_THREAD_SAFE +# include <QtCore/QMutex> +# include <QtCore/QWaitCondition> +#endif + +// Be fast even for debug builds +#ifdef __GNUC__ +# define ALWAYS_INLINE inline __attribute__((always_inline)) +#elif defined(_MSC_VER) +# define ALWAYS_INLINE __forceinline +#else +# define ALWAYS_INLINE inline +#endif + +QT_BEGIN_NAMESPACE +class PROPARSER_EXPORT ProFileParserHandler +{ +public: + // Some error during parsing + virtual void parseError(const QString &filename, int lineNo, const QString &msg) = 0; +}; + +class ProFileCache; + +class PROPARSER_EXPORT ProFileParser +{ +public: + // Call this from a concurrency-free context + static void initialize(); + + ProFileParser(ProFileCache *cache, ProFileParserHandler *handler); + + // fileName is expected to be absolute and cleanPath()ed. + // If contents is non-null, it will be used instead of the file's actual content + ProFile *parsedProFile(const QString &fileName, bool cache = false, + const QString *contents = 0); + ProFile *parsedProBlock(const QString &name, const QString &contents) + { return parsedProFile(name, false, &contents); } + +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, 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); + + 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); + 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 parseError(const QString &msg) const; + + // 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; + ProFileParserHandler *m_handler; + + // This doesn't help gcc 3.3 ... + template<typename T> friend class QTypeInfo; + + friend class ProFileCache; +}; + +class PROPARSER_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 ProFileParser; +}; + +#if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3) +Q_DECLARE_TYPEINFO(ProFileParser::BlockScope, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(ProFileParser::Context, Q_PRIMITIVE_TYPE); +#endif + +QT_END_NAMESPACE + +#endif // PROFILEPARSER_H |