Commit 058354ce authored by Oswald Buddenhagen's avatar Oswald Buddenhagen
Browse files

refactor ProFileEvaluator, part 2: split off ProFileParser

parent 0c09acbb
......@@ -66,7 +66,8 @@ void ProMessageHandler::fileMessage(const QString &)
ProFileReader::ProFileReader(ProFileOption *option)
: ProFileEvaluator(option, this)
: ProFileParser(ProFileCacheManager::instance()->cache(), this)
, ProFileEvaluator(option, this, this)
, m_ignoreLevel(0)
{
}
......
......@@ -30,6 +30,7 @@
#ifndef PROFILEREADER_H
#define PROFILEREADER_H
#include "profileparser.h"
#include "profileevaluator.h"
#include <QtCore/QObject>
......@@ -40,7 +41,7 @@ namespace Qt4ProjectManager {
namespace Internal {
class ProMessageHandler : public QObject,
public ProFileEvaluatorHandler
public ProFileParserHandler, public ProFileEvaluatorHandler
{
Q_OBJECT
......@@ -62,7 +63,7 @@ private:
bool m_verbose;
};
class ProFileReader : public ProMessageHandler, public ProFileEvaluator
class ProFileReader : public ProMessageHandler, public ProFileParser, public ProFileEvaluator
{
Q_OBJECT
......
......@@ -418,7 +418,7 @@ bool MaemoPackageContents::removeValueFromProFile(const QString &var,
void MaemoPackageContents::parseProFile(ParseType type) const
{
if (type == ParseFromLines) {
m_proFile = m_proFileReader->parsedProFile(m_proFileName,
m_proFile = m_proFileReader->parsedProFile(m_proFileName, false,
m_proFileLines.join("\n"));
} else {
m_proFile = m_proFileReader->readProFile(m_proFileName)
......
......@@ -803,7 +803,7 @@ void Qt4PriFileNode::changeFiles(const FileType fileType,
}
ProFileReader *reader = m_project->createProFileReader(m_qt4ProFileNode);
includeFile = reader->parsedProFile(m_projectFilePath, contents);
includeFile = reader->parsedProFile(m_projectFilePath, false, contents);
m_project->destroyProFileReader(reader);
}
......
......@@ -933,7 +933,6 @@ ProFileReader *Qt4Project::createProFileReader(Qt4ProFileNode *qt4ProFileNode)
}
ProFileCacheManager::instance()->incRefCount();
m_proFileOption->cache = ProFileCacheManager::instance()->cache();
}
++m_proFileOptionRefCnt;
......@@ -954,11 +953,11 @@ void Qt4Project::destroyProFileReader(ProFileReader *reader)
QString dir = QFileInfo(m_fileInfo->fileName()).absolutePath();
if (!dir.endsWith(QLatin1Char('/')))
dir += QLatin1Char('/');
m_proFileOption->cache->discardFiles(dir);
ProFileCacheManager::instance()->discardFiles(dir);
ProFileCacheManager::instance()->decRefCount();
delete m_proFileOption;
m_proFileOption = 0;
ProFileCacheManager::instance()->decRefCount();
}
}
......
......@@ -1329,7 +1329,6 @@ void QtVersion::updateToolChainAndMkspec() const
ProFileOption option;
option.properties = versionInfo();
option.cache = ProFileCacheManager::instance()->cache();
ProFileCacheManager::instance()->incRefCount();
ProFileReader *reader = new ProFileReader(&option);
reader->setCumulative(false);
......
This diff is collapsed.
......@@ -32,11 +32,9 @@
#include "proitems.h"
#include <QtCore/QIODevice>
#include <QtCore/QHash>
#include <QtCore/QStringList>
#include <QtCore/QStack>
#ifdef PROPARSER_THREAD_SAFE
#ifdef PROEVALUATOR_THREAD_SAFE
# include <QtCore/QMutex>
# include <QtCore/QWaitCondition>
#endif
......@@ -44,12 +42,11 @@
QT_BEGIN_NAMESPACE
struct ProFileOption;
class ProFileParser;
class ProFileEvaluatorHandler
{
public:
// Some error during parsing
virtual void parseError(const QString &filename, int lineNo, const QString &msg) = 0;
// qmake/project configuration error
virtual void configError(const QString &msg) = 0;
// Some error during evaluation
......@@ -89,7 +86,7 @@ public:
// Call this from a concurrency-free context
static void initialize();
ProFileEvaluator(ProFileOption *option, ProFileEvaluatorHandler *handler);
ProFileEvaluator(ProFileOption *option, ProFileParser *parser, ProFileEvaluatorHandler *handler);
~ProFileEvaluator();
ProFileEvaluator::TemplateType templateType() const;
......@@ -101,9 +98,6 @@ public:
void setConfigCommandLineArguments(const QStringList &addUserConfigCmdArgs, const QStringList &removeUserConfigCmdArgs);
void setParsePreAndPostFiles(bool on); // Default is true
// 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, const QString &contents = QString());
bool accept(ProFile *pro);
bool contains(const QString &variableName) const;
......@@ -119,46 +113,11 @@ public:
private:
Private *d;
// This doesn't help gcc 3.3 ...
template<typename T> friend class QTypeInfo;
friend struct ProFileOption;
friend class ProFileCache;
};
Q_DECLARE_TYPEINFO(ProFileEvaluator::FunctionDef, Q_MOVABLE_TYPE);
class 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 ProFileEvaluator::Private;
};
// This struct is from qmake, but we are not using everything.
struct ProFileOption
{
......@@ -187,7 +146,6 @@ struct ProFileOption
QString qmakespec;
QString cachefile;
QHash<QString, QString> properties;
ProFileCache *cache;
enum TARG_MODE { TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, TARG_MAC9_MODE, TARG_QNX6_MODE };
TARG_MODE target_mode;
......
This diff is collapsed.
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef PROFILEPARSER_H
#define PROFILEPARSER_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 ProFileParserHandler
{
public:
// Some error during parsing
virtual void parseError(const QString &filename, int lineNo, const QString &msg) = 0;
};
class ProFileCache;
class 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 = QString());
private:
struct BlockScope {
BlockScope() : start(0), braceLevel(0), special(false), inBranch(false) {}
BlockScope(BlockScope &other) :
start(other.start), braceLevel(other.braceLevel),
special(other.special), inBranch(other.inBranch) {}
ushort *start; // Where this block started; store length here
int braceLevel; // Nesting of braces in scope
bool special; // Single-line conditionals 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 litCount; // Number of literals in current expression
int expCount; // Number of expansions 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);
void finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int argc);
void finalizeTest(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
QString m_fileName;
int m_lineNo;
QStack<BlockScope> m_blockstack;
ScopeState m_state;
int m_markLine; // Put marker for this line
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;
};
#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
class 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;
};
#endif // PROFILEPARSER_H
......@@ -334,9 +334,13 @@ ProFile::ProFile(const QString &fileName)
: m_refCount(1),
m_fileName(fileName)
{
int nameOff = fileName.lastIndexOf(QLatin1Char('/'));
m_displayFileName = fileName.mid(nameOff + 1);
m_directoryName = fileName.left(nameOff);
if (fileName.startsWith(QLatin1Char('('))) {
m_displayFileName = fileName;
} else {
int nameOff = fileName.lastIndexOf(QLatin1Char('/'));
m_displayFileName = fileName.mid(nameOff + 1);
m_directoryName = fileName.left(nameOff);
}
}
ProFile::~ProFile()
......
......@@ -6,6 +6,7 @@ DEPENDPATH *= $$PWD $$PWD/..
# Input
HEADERS += \
profileparser.h \
profileevaluator.h \
proitems.h \
prowriter.h \
......@@ -13,6 +14,7 @@ HEADERS += \
$$PWD/../namespace_global.h
SOURCES += \
profileparser.cpp \
profileevaluator.cpp \
proitems.cpp \
prowriter.cpp \
......
......@@ -27,6 +27,7 @@
**
**************************************************************************/
#include "profileparser.h"
#include "profileevaluator.h"
#include <QtCore/QCoreApplication>
......@@ -47,10 +48,14 @@ static void print(const QString &fileName, int lineNo, const QString &msg)
qWarning("%s", qPrintable(msg));
}
class EvalHandler : public ProFileEvaluatorHandler {
class ParseHandler : public ProFileParserHandler {
public:
virtual void parseError(const QString &fileName, int lineNo, const QString &msg)
{ print(fileName, lineNo, msg); }
};
class EvalHandler : public ProFileEvaluatorHandler {
public:
virtual void configError(const QString &msg)
{ qWarning("%s", qPrintable(msg)); }
virtual void evalError(const QString &fileName, int lineNo, const QString &msg)
......@@ -62,6 +67,7 @@ public:
virtual void doneWithEval(ProFile *) {}
};
static ParseHandler parseHandler;
static EvalHandler evalHandler;
static QString value(ProFileEvaluator &reader, const QString &variable)
......@@ -74,19 +80,19 @@ static QString value(ProFileEvaluator &reader, const QString &variable)
}
static int evaluate(const QString &fileName, const QString &in_pwd, const QString &out_pwd,
bool cumulative, ProFileOption *option, int level)
bool cumulative, ProFileOption *option, ProFileParser *parser, int level)
{
static QSet<QString> visited;
if (visited.contains(fileName))
return 0;
visited.insert(fileName);
ProFileEvaluator visitor(option, &evalHandler);
ProFileEvaluator visitor(option, parser, &evalHandler);
visitor.setCumulative(cumulative);
visitor.setOutputDir(out_pwd);
ProFile *pro;
if (!(pro = visitor.parsedProFile(fileName)))
if (!(pro = parser->parsedProFile(fileName)))
return 2;
if (!visitor.accept(pro)) {
pro->deref();
......@@ -128,7 +134,7 @@ static int evaluate(const QString &fileName, const QString &in_pwd, const QStrin
fflush(stdout);
nlevel++;
}
evaluate(inFile, inPwd, outPwd, cumulative, option, nlevel);
evaluate(inFile, inPwd, outPwd, cumulative, option, parser, nlevel);
}
}
......@@ -149,6 +155,7 @@ int main(int argc, char **argv)
qFatal("need at least two arguments: [-v] <cumulative?> <filenme> [<out_pwd>]");
ProFileOption option;
ProFileParser parser(0, &parseHandler);
static const struct {
const char * const name;
......@@ -178,5 +185,5 @@ int main(int argc, char **argv)
QString in_pwd = infi.absolutePath();
QString out_pwd = (args.count() > 2) ? QFileInfo(args[2]).absoluteFilePath() : in_pwd;
return evaluate(file, in_pwd, out_pwd, cumulative, &option, level);
return evaluate(file, in_pwd, out_pwd, cumulative, &option, &parser, level);
}
......@@ -15,8 +15,8 @@ build_all:!build_pass {
CONFIG += release
}
SOURCES = main.cpp profileevaluator.cpp proitems.cpp ioutils.cpp
HEADERS = profileevaluator.h proitems.h ioutils.h
SOURCES = main.cpp profileparser.cpp profileevaluator.cpp proitems.cpp ioutils.cpp
HEADERS = profileparser.h profileevaluator.h proitems.h ioutils.h
DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
DEFINES += QT_USE_FAST_OPERATOR_PLUS QT_USE_FAST_CONCATENATION
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment