⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 preprocessorcontrol.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the qt3to4 porting application of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "preprocessorcontrol.h"#include <QDir>#include <QFile>#include <QFileInfo>#include <QTemporaryFile>using namespace TokenEngine;using namespace Rpp;IncludeFiles::IncludeFiles(const QString &basePath, const QStringList &searchPaths):m_basePath(basePath){    //prepend basePath to all relative paths in searchPaths    foreach (QString path, searchPaths) {        QString finalPath;        if (QDir::isAbsolutePath(path))            finalPath = QDir::cleanPath(path);        else            finalPath = QDir::cleanPath(m_basePath + "/" + path);        if(QFile::exists(finalPath))            m_searchPaths.append(finalPath);    }}/*    Performs an #include "..." style file lookup.    Aboslute filenames are checked directly. Relative filenames are first    looked for relative to the current file path, then the includepaths    are searched if not found.*/QString IncludeFiles::quoteLookup(const QString &currentFile,                                  const QString &includeFile) const{    //if includeFile is absolute, check if it exists    if(QDir::isAbsolutePath(includeFile))        if(QFile::exists(includeFile))            return includeFile;        else            return QString();    //If currentFile is not an absolute file path, make it one by    //prepending m_baspath    QString currentFilePath;    if(QDir::isAbsolutePath(currentFile))        currentFilePath = currentFile;    else        currentFilePath = QDir::cleanPath(m_basePath + "/" + currentFile);    //Check if it includeFile exists in the same dir as currentFilePath    const QString currentPath = QFileInfo(currentFilePath).path();    QString localFile = QDir::cleanPath(currentPath + "/" + includeFile);    if(QFile::exists(localFile))        return localFile;    return searchIncludePaths(includeFile);}/*    Performs an #include <...> style file lookup.    Aboslute filenames are checked directly.    Relative paths are searched for in the includepaths.*/QString IncludeFiles::angleBracketLookup(const QString &includeFile) const{    //if includeFile is absolute, check if it exists    if(QDir::isAbsolutePath(includeFile))        if(QFile::exists(includeFile))            return includeFile;        else            return QString();    return searchIncludePaths(includeFile);}QString IncludeFiles::resolve(const QString &filename) const{    if(QDir::isAbsolutePath(filename))        return filename;    QString prepended = QDir::cleanPath(m_basePath + "/" + filename);    if(QFile::exists(prepended))        return prepended;    else        return QString();}/*    Searches for includeFile paths by appending it to all includePaths    and checking if the file exists. Returns QString() if the file is not    found.*/QString IncludeFiles::searchIncludePaths(const QString &includeFile) const{    QString foundFile;    foreach(QString includePath, m_searchPaths) {        QString testFile = includePath + "/" + includeFile;        if(QFile::exists(testFile)){            foundFile = testFile;            break;        }    }    return foundFile;}QByteArray PreprocessorCache::readFile(const QString &filename) const{    // If anybody is connected to the readFile signal we tell them to    // read the file for us.    if (receivers(SIGNAL(readFile(QByteArray&,QString))) > 0) {        QByteArray array;        // Workaround for "not beeing able to emit from const function"        PreprocessorCache *cache = const_cast<PreprocessorCache *>(this);        emit cache->readFile(array, filename);        return array;    }    QFile f(filename);    if (!f.exists())        return QByteArray();    f.open(QIODevice::ReadOnly);    if (!f.isOpen())        return QByteArray();    return f.readAll();}PreprocessorCache::PreprocessorCache(){    connect(&m_preprocessor, SIGNAL(error(QString,QString)),            this, SIGNAL(error(QString,QString)));}/*    Return a TokenSequence with the contents of filname.    Assumens filename exists and is readable, returns a empty    TokenSequence if not.    The result is cached.*/TokenContainer PreprocessorCache::sourceTokens(const QString &filename){    // Check if the source tokens are already in the cache.    if(m_sourceTokens.contains(filename))        return m_sourceTokens.value(filename);    // Read and tokenize file.    QByteArray fileContents = readFile(filename);    if(fileContents == QByteArray())        return TokenContainer();    QVector<TokenEngine::Token> tokenList = m_tokenizer.tokenize(fileContents);    // Create a FileInfo object that holds the filename for this container.    FileInfo *containterFileInfo = new FileInfo;    containterFileInfo->filename = filename;    // Create container.    TokenContainer tokenContainer(fileContents, tokenList, containterFileInfo);    // Insert into cache.    m_sourceTokens.insert(filename, tokenContainer);    return tokenContainer;}/*    Return a Source* tree representing the contents of filename.    Assumens filename exists and is readable, returns a empty    Source object if not.    The result is cached.*/Source *PreprocessorCache::sourceTree(const QString &filename){    // Check if the Rpp tree for this file is already in the cache.    if(m_sourceTrees.contains(filename))        return m_sourceTrees.value(filename);    // Get the tokens for the contents of this file.    TokenContainer tokenContainer = sourceTokens(filename);    // Run lexer and the preprocessor-parser.    QVector<Type> tokenTypes = m_lexer.lex(tokenContainer);    Source *source = m_preprocessor.parse(tokenContainer, tokenTypes, &m_memoryPool);    source->setFileName(filename);    // Insert into cache.    if(tokenContainer.count() > 0) //don't cache empty files.        m_sourceTrees.insert(filename, source);    return source;}/*    Returns whether the cache contains a TokenContainer for the given filename.*/bool PreprocessorCache::containsSourceTokens(const QString &filename){    return m_sourceTokens.contains(filename);}/*    Returns whether the cache contains a Preprocessor tree for the given filename.*/bool PreprocessorCache::containsSourceTree(const QString &filename){    return m_sourceTrees.contains(filename);}PreprocessorController::PreprocessorController(IncludeFiles includeFiles,        PreprocessorCache &preprocessorCache,        QStringList preLoadFilesFilenames):m_includeFiles(includeFiles), m_preprocessorCache(preprocessorCache) {    // Load qt3 headers from resources. The headers are stored as    // QHash<QString, QByteArray>, serialized using QDataStream. The hash    // maps filename -> contents.    if (preLoadFilesFilenames != QStringList()) {        foreach (QString filename,  preLoadFilesFilenames) {            QFile f(filename);            if (f.open(QIODevice::ReadOnly)) {                QByteArray buffer = f.readAll();                f.close();                QDataStream stream(buffer);                QHash<QString, QByteArray> files;                stream >> files;                m_preLoadFiles.unite(files);            }        }    }        //connect include callback    connect(&m_rppTreeEvaluator,        SIGNAL(includeCallback(::Rpp::Source *&, const ::Rpp::Source *,        const QString &, ::Rpp::RppTreeEvaluator::IncludeType)),        SLOT(includeSlot(::Rpp::Source *&, const ::Rpp::Source *,        const QString &, ::Rpp::RppTreeEvaluator::IncludeType)));    // connect readFile callback    connect(&m_preprocessorCache, SIGNAL(readFile(QByteArray&,QString)),        SLOT(readFile(QByteArray&,QString)));    //connect error handlers    connect(&m_preprocessorCache , SIGNAL(error(QString,QString)),            this, SIGNAL(error(QString,QString)));}/*    Callback from RppTreeEvaluator, called when we evaluate an #include    directive. We do a filename lookup based on the type of include, and then ask    the cache to give us the source tree for that file.*/void PreprocessorController::includeSlot(Source *&includee,                                         const Source *includer,                                         const QString &filename,                                         RppTreeEvaluator::IncludeType includeType){    QString newFilename;    if(includeType == RppTreeEvaluator::QuoteInclude)        newFilename = m_includeFiles.quoteLookup(includer->fileName(), filename);    else //AngleBracketInclude        newFilename = m_includeFiles.angleBracketLookup(filename);    if (QFile::exists(newFilename)) {        includee = m_preprocessorCache.sourceTree(newFilename);        return;    }    if (m_preLoadFiles.contains(filename)) {        includee = m_preprocessorCache.sourceTree(filename);        return;    }    includee = m_preprocessorCache.sourceTree(newFilename);    emit error("Error", "Could not find file " + filename);}/*    Callback connected to preprocessorCache. Tries to load a file from    m_preLoadFiles before going to disk.*/void PreprocessorController::readFile(QByteArray &contents, QString filename){    if (m_preLoadFiles.contains(filename)) {        contents = m_preLoadFiles.value(filename);        return;    }    QFile f(filename);    if (!f.exists())        return;    f.open(QIODevice::ReadOnly);    if (!f.isOpen())        return;    contents = f.readAll();}/*    Preprocess file give by filename. Filename is resloved agains the basepath    set in IncludeFiles.*/TokenSectionSequence PreprocessorController::evaluate(const QString &filename, Rpp::DefineMap *activedefinitions){    QString resolvedFilename = m_includeFiles.resolve(filename);    if(!QFile::exists(resolvedFilename))        emit error("Error", "Could not find file: " + filename);    Source *source  = m_preprocessorCache.sourceTree(resolvedFilename);    return m_rppTreeEvaluator.evaluate(source, activedefinitions);}QByteArray defaultDefines =    "#define __attribute__(a...)  \n \         #define __attribute__ \n \         #define __extension \n \         #define __extension__ \n \         #define __restrict \n \         #define __restrict__      \n \         #define __volatile         volatile\n \         #define __volatile__       volatile\n \         #define __inline             inline\n \         #define __inline__           inline\n \         #define __const               const\n \         #define __const__             const\n \         #define __asm               asm\n \         #define __asm__             asm\n \         #define __GNUC__                 2\n \         #define __GNUC_MINOR__          95\n  \         #define __cplusplus \n \         #define __linux__ \n";/*    Returns a DefineMap containing the above macro definitions. The DefineMap    will contain pointers to data stored in the provided cache object.*/Rpp::DefineMap *defaultMacros(PreprocessorCache &cache){    DefineMap *defineMap = new DefineMap();    //write out default macros to a temp file    QTemporaryFile tempfile;    tempfile.open();    tempfile.write(defaultDefines);    IncludeFiles *includeFiles = new IncludeFiles(QString(), QStringList());    PreprocessorController preprocessorController(*includeFiles, cache);    //evaluate default macro file.    preprocessorController.evaluate(tempfile.fileName(), defineMap);    delete includeFiles;    return defineMap;}void StandardOutErrorHandler::error(QString type, QString text){    Q_UNUSED(type);    puts(qPrintable(text));}/*    RppPreprocessor is a convenience class that contains all the components    needed to preprocess files. Error messages are printed to standard out.*/RppPreprocessor::RppPreprocessor(QString basePath, QStringList includePaths, QStringList preLoadFilesFilenames):m_includeFiles(basePath, includePaths),m_activeDefinitions(defaultMacros(m_cache)),m_controller(m_includeFiles, m_cache, preLoadFilesFilenames){    QObject::connect(&m_controller, SIGNAL(error(QString,QString)), &m_errorHandler, SLOT(error(QString,QString)));}RppPreprocessor::~RppPreprocessor(){    delete m_activeDefinitions;}TokenEngine::TokenSectionSequence RppPreprocessor::evaluate(const QString &filename){    DefineMap defMap = *m_activeDefinitions;    return m_controller.evaluate(filename, &defMap);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -