view release on metacpan or search on metacpan
CMakeLists.txt view on Meta::CPAN
cmake_minimum_required(VERSION 2.6)
add_subdirectory(generator)
add_subdirectory(cmake/modules)
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/modules )
# search packages used by Qt
find_package(Qt4 REQUIRED)
include(MacroOptionalFindPackage)
include(MacroOptionalAddBindings)
include(MacroOptionalAddSubdirectory)
include(MacroLogFeature)
add_definitions (${QT_DEFINITIONS})
include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
if(WITH_QT3_SUPPORT)
add_definitions(-DQT3_SUPPORT)
endif(WITH_QT3_SUPPORT)
macro_optional_find_package(QImageBlitz)
macro_log_feature(QIMAGEBLITZ_FOUND "QImageBlitz" "QImageBlitz library" "http://www.kde.org" FALSE "" "Needed to compile QImageBlitz bindings")
ChangeLog
CMakeLists.txt
cmake/modules/BasicFindPackageVersion.cmake.in
cmake/modules/CMakeLists.txt
cmake/modules/FindLibraryWithDebug.cmake
cmake/modules/FindPhonon.cmake
cmake/modules/FindQImageBlitz.cmake
cmake/modules/FindQScintilla.cmake
cmake/modules/FindQwt5.cmake
cmake/modules/HandleImportedTargetsInCMakeRequiredLibraries.cmake
cmake/modules/MacroLogFeature.cmake
cmake/modules/MacroOptionalAddBindings.cmake
cmake/modules/MacroOptionalAddSubdirectory.cmake
cmake/modules/MacroOptionalFindPackage.cmake
cmake/modules/MacroWriteBasicCMakeVersionFile.cmake
cmake/modules/SmokeConfig.cmake.in
COPYING
generator/CMakeLists.txt
generator/deptool/CMakeLists.txt
generator/deptool/main.cpp
generator/generatorenvironment.cpp
generator/generatorenvironment.h
generator/generator_export.h
generator/generatorpreprocessor.cpp
generator/generatorpreprocessor.h
cmake/modules/BasicFindPackageVersion.cmake.in view on Meta::CPAN
# This is a very basic file for the new style find_package() search mode,
# i.e. Config-mode. It is used by MACRO_WRITE_BASIC_CMAKE_VERSION_FILE() from
# MacroWriteBasicCMakeVersionFile.cmake.
# In this mode find_package() searches for a <package>Config.cmake
# file and an associated <package>Version.cmake file, which it loads to check
# the version number.
# This file can be used with configure_file() to generate such a file for a project
# with very basic logic.
# It sets PACKAGE_VERSION_EXACT if the current version string and the requested
# version string are exactly the same and it sets PACKAGE_VERSION_COMPATIBLE
# if the current version is >= requested version.
# If this is not good enough for your project, you need to write your own
# improved <package>Version.cmake file.
cmake/modules/CMakeLists.txt view on Meta::CPAN
configure_file(SmokeConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/SmokeConfig.cmake @ONLY)
set(smoke_cmake_files
FindLibraryWithDebug.cmake
FindPhonon.cmake
FindQImageBlitz.cmake
FindQScintilla.cmake
FindQwt5.cmake
HandleImportedTargetsInCMakeRequiredLibraries.cmake
MacroLogFeature.cmake
MacroOptionalAddBindings.cmake
MacroOptionalFindPackage.cmake
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/SmokeConfig.cmake ${smoke_cmake_files} DESTINATION ${SMOKE_CMAKE_MODULE_DIR})
cmake/modules/MacroLogFeature.cmake view on Meta::CPAN
# REQUIRED: TRUE or FALSE, indicating whether the featue is required
# MIN_VERSION: minimum version number. empty string if unneeded
# COMMENTS: More info you may want to provide. empty string if unnecessary
#
# MACRO_DISPLAY_FEATURE_LOG()
# Call this to display the collected results.
# Exits CMake with a FATAL error message if a required feature is missing
#
# Example:
#
# INCLUDE(MacroLogFeature)
#
# FIND_PACKAGE(JPEG)
# MACRO_LOG_FEATURE(JPEG_FOUND "libjpeg" "Support JPEG images" "http://www.ijg.org" TRUE "3.2a" "")
# ...
# MACRO_DISPLAY_FEATURE_LOG()
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
# Copyright (c) 2006, Allen Winter, <winter@kde.org>
# Copyright (c) 2009, Sebastian Trueg, <trueg@kde.org>
#
cmake/modules/MacroOptionalAddBindings.cmake view on Meta::CPAN
# Copyright (c) 2010 Maciej Mrozowski <reavertm@gmail.com>
#
# Redistribution and use is allowed according to the terms of the GPL license.
# Conditionally enable bindings.
# Pass -DDISABLE_<component_name>=ON to disable certain binding even if its dependencies are found.
# CMake project needs to be set before using this macro.
# Macro sets following variables:
# ${CMAKE_PROJECT_NAME}_ENABLED - list of enabled bindings
# ${CMAKE_PROJECT_NAME}_DISABLED - list of disabled bindings
# Usage:
# macro_optional_add_bindings(<component_found> <component_name> <subdir1> [<subdir2> ...])
#
# Example:
# project(SMOKE)
# [...]
# macro_optional_add_bindings(NEPOMUK_FOUND "Nepomuk" nepomuk nepomukquery)
# [...]
generator/generatorenvironment.cpp view on Meta::CPAN
}
GeneratorEnvironment::~GeneratorEnvironment()
{
if (!ParserOptions::qtMode) {
// if not in qt-mode, this won't be deleted by rpp::Environment
delete q_property;
}
}
void GeneratorEnvironment::setMacro(rpp::pp_macro* macro)
{
QString macroName = macro->name.str();
if ( macroName == "signals" || macroName == "slots" || macroName == "Q_SIGNALS" || macroName == "Q_SLOTS"
|| ParserOptions::dropMacros.contains(macroName)) {
delete macro;
return;
} else if (ParserOptions::qtMode && macroName == "Q_PROPERTY") {
delete macro;
rpp::Environment::setMacro(q_property);
return;
}
rpp::Environment::setMacro(macro);
}
generator/generatorenvironment.h view on Meta::CPAN
#ifndef PARSERENVIRONMENT_H
#define PARSERENVIRONMENT_H
#include <rpp/pp-environment.h>
class GeneratorEnvironment : public rpp::Environment
{
public:
GeneratorEnvironment(rpp::pp* preprocessor);
~GeneratorEnvironment();
virtual void setMacro(rpp::pp_macro* macro);
private:
rpp::pp_macro* q_property;
};
#endif // PARSERENVIRONMENT_H
generator/generatorpreprocessor.cpp view on Meta::CPAN
QList<QString> parsedHeaders;
Preprocessor::Preprocessor(const QList<QDir>& includeDirs, const QStringList& defines, const QFileInfo& file)
: m_includeDirs(includeDirs), m_defines(defines), m_file(file)
{
pp = new rpp::pp(this);
pp->setEnvironment(new GeneratorEnvironment(pp));
if (file.exists())
m_fileStack.push(file);
m_topBlock = new rpp::MacroBlock(0);
// some basic definitions
rpp::pp_macro* exportMacro = new rpp::pp_macro;
exportMacro->name = IndexedString("__cplusplus");
exportMacro->definition.append(IndexedString('1'));
exportMacro->function_like = false;
exportMacro->variadics = false;
m_topBlock->setMacro(exportMacro);
exportMacro = new rpp::pp_macro;
exportMacro->name = IndexedString("__GNUC__");
exportMacro->definition.append(IndexedString('4'));
exportMacro->function_like = false;
exportMacro->variadics = false;
m_topBlock->setMacro(exportMacro);
exportMacro = new rpp::pp_macro;
exportMacro->name = IndexedString("__GNUC_MINOR__");
exportMacro->definition.append(IndexedString('1'));
exportMacro->function_like = false;
exportMacro->variadics = false;
m_topBlock->setMacro(exportMacro);
exportMacro = new rpp::pp_macro;
#if defined(Q_OS_LINUX)
exportMacro->name = IndexedString("__linux__");
#elif defined(Q_OS_WIN32)
exportMacro->name = IndexedString("WIN32");
#elif defined(Q_OS_WIN64)
exportMacro->name = IndexedString("WIN64");
#elif defined(Q_OS_DARWIN)
exportMacro->name = IndexedString("__APPLE__");
#elif defined(Q_OS_SOLARIS)
exportMacro->name = IndexedString("__sun");
#else
// fall back to linux if nothing matches
exportMacro->name = IndexedString("__linux__");
#endif
exportMacro->function_like = false;
exportMacro->variadics = false;
m_topBlock->setMacro(exportMacro);
#if defined(Q_OS_DARWIN64)
exportMacro = new rpp::pp_macro;
exportMacro->name = IndexedString("__LP64__");
exportMacro->function_like = false;
exportMacro->variadics = false;
m_topBlock->setMacro(exportMacro);
#endif
#if (defined(QT_ARCH_ARM) || defined (QT_ARCH_ARMV6)) && !defined(QT_NO_ARM_EABI)
exportMacro = new rpp::pp_macro;
exportMacro->name = IndexedString("__ARM_EABI__");
exportMacro->function_like = false;
exportMacro->variadics = false;
m_topBlock->setMacro(exportMacro);
#endif
// ansidecl.h will define macros for keywords if we don't define __STDC__
exportMacro = new rpp::pp_macro;
exportMacro->name = IndexedString("__STDC__");
exportMacro->function_like = false;
exportMacro->variadics = false;
m_topBlock->setMacro(exportMacro);
exportMacro = new rpp::pp_macro;
exportMacro->name = IndexedString("__SMOKEGEN_RUN__");
exportMacro->definition.append(IndexedString('1'));
exportMacro->function_like = false;
exportMacro->variadics = false;
m_topBlock->setMacro(exportMacro);
foreach (QString define, defines) {
exportMacro = new rpp::pp_macro;
exportMacro->name = IndexedString(define);
exportMacro->function_like = false;
exportMacro->variadics = false;
m_topBlock->setMacro(exportMacro);
}
pp->environment()->visitBlock(m_topBlock);
}
Preprocessor::~Preprocessor()
{
delete pp;
}
generator/generatorpreprocessor.h view on Meta::CPAN
#include <QList>
#include <QPair>
#include <QStack>
#include <QString>
#include <rpp/pp-engine.h>
#include <rpp/pp-stream.h>
#include <rpp/preprocessor.h>
namespace rpp {
class MacroBlock;
}
extern QList<QString> parsedHeaders;
class Preprocessor : public rpp::Preprocessor
{
public:
Preprocessor(const QList<QDir>& includeDirs = QList<QDir>(), const QStringList& defines = QStringList(),
const QFileInfo& file = QFileInfo());
virtual ~Preprocessor();
generator/generatorpreprocessor.h view on Meta::CPAN
QList<QDir> includeDirs();
void setDefines(QStringList defines);
QStringList defines();
PreprocessedContents preprocess();
PreprocessedContents lastContents();
private:
rpp::pp *pp;
rpp::MacroBlock *m_topBlock;
QList<QDir> m_includeDirs;
QStringList m_defines;
QFileInfo m_file;
PreprocessedContents m_contents;
QHash<QString, QPair<QFileInfo, PreprocessedContents> > m_cache;
QList<PreprocessedContents> m_localContent;
QStack<QFileInfo> m_fileStack;
};
class HeaderStream : public rpp::Stream
generator/main.cpp view on Meta::CPAN
qCritical() << "not enough parameters for option" << args[i];
return EXIT_FAILURE;
}
if (args[i] == "-I") {
ParserOptions::includeDirs << QDir(args[++i]);
} else if (args[i] == "-config") {
configFile = QFileInfo(args[++i]);
} else if (args[i] == "-d") {
ParserOptions::definesList = QFileInfo(args[++i]);
} else if (args[i] == "-dm") {
ParserOptions::dropMacros += args[++i].split(',');
} else if (args[i] == "-g") {
generator = args[++i];
hasCommandLineGenerator = true;
} else if ((args[i] == "-h" || args[i] == "--help") && argc == 2) {
showUsage();
return EXIT_SUCCESS;
} else if (args[i] == "-t") {
ParserOptions::resolveTypedefs = true;
} else if (args[i] == "-qt") {
ParserOptions::qtMode = true;
generator/main.cpp view on Meta::CPAN
continue;
}
if (elem.tagName() == "dir") {
ParserOptions::includeDirs << QDir(elem.text());
}
dir = dir.nextSibling();
}
} else if (elem.tagName() == "definesList") {
// reference to an external file, so it can be auto-generated
ParserOptions::definesList = QFileInfo(elem.text());
} else if (elem.tagName() == "dropMacros") {
QDomNode macro = elem.firstChild();
while (!macro.isNull()) {
QDomElement elem = macro.toElement();
if (elem.isNull()) {
macro = macro.nextSibling();
continue;
}
if (elem.tagName() == "name") {
ParserOptions::dropMacros << elem.text();
}
macro = macro.nextSibling();
}
}
node = node.nextSibling();
}
} else {
qWarning() << "Couldn't find config file" << configFile.filePath();
}
generator/options.cpp view on Meta::CPAN
#include <QRegExp>
#include <QSet>
#include "options.h"
QFileInfo ParserOptions::definesList;
QList<QFileInfo>ParserOptions:: headerList;
QList<QDir> ParserOptions::includeDirs;
bool ParserOptions::resolveTypedefs = false;
bool ParserOptions::qtMode = false;
QStringList ParserOptions::dropMacros;
generator/options.h view on Meta::CPAN
class Typedef;
struct GENERATOR_EXPORT ParserOptions
{
static QFileInfo definesList;
static QList<QFileInfo> headerList;
static QList<QDir> includeDirs;
static bool resolveTypedefs;
static bool qtMode;
static QStringList dropMacros;
};
#endif
generator/parser/parsesession.cpp view on Meta::CPAN
}
ParseSession::~ParseSession()
{
delete mempool;
delete token_stream;
delete m_locationTable;
delete macros;
}
rpp::Anchor ParseSession::positionAt(std::size_t offset, bool collapseIfMacroExpansion) const
{
Q_ASSERT(m_locationTable);
return m_locationTable->positionAt(offset, m_contents, collapseIfMacroExpansion).first;
}
QPair<rpp::Anchor, uint> ParseSession::positionAndSpaceAt(std::size_t offset, bool collapseIfMacroExpansion) const
{
Q_ASSERT(m_locationTable);
return m_locationTable->positionAt(offset, m_contents, collapseIfMacroExpansion);
}
std::size_t ParseSession::size() const
{
return m_contents.size() + 1;
}
uint* ParseSession::contents()
{
return m_contents.data();
generator/parser/parsesession.h view on Meta::CPAN
namespace Cpp {
class EnvironmentFile;
}
class pool;
class TokenStream;
class Token;
typedef QVector<unsigned int> PreprocessedContents;
namespace rpp { class MacroBlock; class LocationTable; }
/// Contains everything needed to keep an AST useful once the rest of the parser
/// has gone away.
class CPPPARSER_EXPORT ParseSession
{
public:
ParseSession();
~ParseSession();
/**
* Return the position of the preprocessed source \a offset in the original source
* If the "collapsed" member of the returned anchor is true, the position is within a collapsed range.
@param collapseIfMacroExpansion @see LocationTable::positionForOffset
* \note the return line starts from 0, not 1.
*/
rpp::Anchor positionAt(std::size_t offset, bool collapseIfMacroExpansion = false) const;
QPair<rpp::Anchor, uint> positionAndSpaceAt(std::size_t offset, bool collapseIfMacroExpansion = false) const;
///The contents must already be tokenized. Either by the preprocessor, or by tokenizeFromByteArray(..)
void setContents(const PreprocessedContents& contents, rpp::LocationTable* locationTable);
/// Unweildy name, but we want to be clear here, if there is already a location table, this would be the wrong setup function to call
void setContentsAndGenerateLocationTable(const PreprocessedContents& contents);
void setUrl(const IndexedString& url);
const IndexedString& url() const;
uint *contents();
const uint *contents() const;
const PreprocessedContents& contentsVector() const;
std::size_t size() const;
pool* mempool;
TokenStream* token_stream;
rpp::MacroBlock* macros;
IndexedString m_url; //Should contain the url from which the content was extracted, can also be empty.
private:
PreprocessedContents m_contents;
rpp::LocationTable* m_locationTable;
};
#endif
generator/parser/rpp/macrorepository.cpp view on Meta::CPAN
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "macrorepository.h"
//The text is supposed to be utf8 encoded
using namespace rpp;
size_t MacroRepositoryItemRequest::itemSize() const {
return macro.dynamicSize();
}
MacroRepositoryItemRequest::MacroRepositoryItemRequest(const rpp::pp_macro& _macro) : macro(_macro) {
_macro.completeHash(); //Make sure the hash is valid
}
void MacroRepositoryItemRequest::destroy(rpp::pp_macro* item, KDevelop::AbstractItemRepository&) {
item->~pp_macro();
}
void MacroRepositoryItemRequest::createItem(rpp::pp_macro* item) const {
new (item) pp_macro(macro, false);
Q_ASSERT(*item == macro);
}
//Should return whether the here requested item equals the given item
bool MacroRepositoryItemRequest::equals(const rpp::pp_macro* item) const {
return macro == *item;
}
generator/parser/rpp/macrorepository.h view on Meta::CPAN
Boston, MA 02110-1301, USA.
*/
#ifndef MACROREPOSITORY_H
#define MACROREPOSITORY_H
#include <language/duchain/repositories/itemrepository.h>
#include <cppparserexport.h>
#include "pp-macro.h"
struct Q_DECL_EXPORT MacroRepositoryItemRequest {
//The text is supposed to be utf8 encoded
MacroRepositoryItemRequest(const rpp::pp_macro& _macro);
enum {
AverageSize = 20 //This should be the approximate average size of an Item
};
typedef unsigned int HashType;
HashType hash() const {
return macro.completeHash();
}
size_t itemSize() const;
void createItem(rpp::pp_macro* item) const;
static void destroy(rpp::pp_macro* item, KDevelop::AbstractItemRepository&);
static bool persistent(const rpp::pp_macro* /*item*/) {
return true; //Macros are reference-counted through the macro sets
}
//Should return whether the here requested item equals the given item
bool equals(const rpp::pp_macro* item) const;
const rpp::pp_macro& macro;
};
typedef KDevelop::ItemRepository<rpp::pp_macro, MacroRepositoryItemRequest> MacroDataRepository;
#endif
generator/parser/rpp/pp-engine.cpp view on Meta::CPAN
} else {
// Whoops, rewind :)
input.seek(pos);
}
}
macro->definition.append(IndexedString::fromIndex(input.current()));
++input;
}
m_environment->setMacro(macro);
}
void pp::skip (Stream& input, Stream& output, bool outputText)
{
pp_skip_string_literal skip_string_literal;
pp_skip_char_literal skip_char_literal;
while (!input.atEnd() && input != '\n')
{
generator/parser/rpp/pp-engine.cpp view on Meta::CPAN
problem->position = input.originalInputPosition();
QChar tk(token);
problem->description = QString("Expected \"identifier\", found: %1").arg((tk < TOKENS_END && tk > TOKENS_START) ? QString(tk) : QString("character %1").arg(token));
problem->explanation = QString("<h5>Token text</h5><pre>%1</pre><h5>Input</h5><pre>%2</pre>").arg(token_text.str())
.arg(QString::fromUtf8(input.stringFrom(start)));
problemEncountered(problem);
break;
}
{
pp_macro* m = m_environment->retrieveMacro(token_text, true);
result.set_long( (m && !m->isUndef()) ? 1 : 0);
}
token = next_token(input); // skip '('
if (expect_paren) {
if (token != ')') {
Problem* problem = new Problem;
problem->file = currentFileNameString();
problem->position = input.originalInputPosition();
generator/parser/rpp/pp-engine.cpp view on Meta::CPAN
//It's the first #ifndef and the header-section hasn't ended yet, assume it to be the header-guard
guardCandidate = macro_name;
}
hadGuardCandidate = true;
environment()->enterBlock(input.inputPosition().line);//, QString("%1defined(%2)").arg(check_undefined ? "!" : "").arg(macro_name).toUtf8());
if (test_if_level())
{
pp_macro* macro = m_environment->retrieveMacro(macro_name, true);
bool value = false;
if( macro && macro->defined )
value = true;
if (check_undefined)
value = !value;
_M_true_test[iflevel] = value;
_M_skipping[iflevel] = !value;
}
generator/parser/rpp/pp-engine.cpp view on Meta::CPAN
IndexedString macro_name = IndexedString::fromIndex(skip_identifier(input));
RETURN_ON_FAIL(!macro_name.isEmpty());
pp_macro* macro = new pp_macro;
macro->file = currentFileName();
macro->name = macro_name;
macro->sourceLine = input.originalInputPosition().line;
macro->defined = false;
m_environment->setMacro(macro);
}
IndexedString definedText("defined");
int pp::next_token (Stream& input)
{
if (haveNextToken)
return nextToken;
skip_blanks(input, devnull());
generator/parser/rpp/pp-engine.cpp view on Meta::CPAN
accept_token();
return result;
}
void pp::accept_token()
{
haveNextToken = false;
nextToken = 0;
}
bool pp::hideNextMacro( ) const
{
return hideNext;
}
void pp::setHideNextMacro( bool h )
{
hideNext = h;
}
Environment* pp::environment( ) const
{
return m_environment;
}
void pp::setEnvironment(Environment* env)
generator/parser/rpp/pp-engine.h view on Meta::CPAN
PreprocessedContents processFile(const QString& fileName);
/** Preprocess @p fileName with content @p data. Do not actually open file @p fileName
* Currently the file is expected to be utf8-encoded. */
PreprocessedContents processFile(const QString& fileName, const QByteArray& data);
void operator () (Stream& input, Stream& output);
void checkMarkNeeded(Stream& input, Stream& output);
bool hideNextMacro() const;
void setHideNextMacro(bool hideNext);
Environment* environment() const;
// once set, belongs to the engine
void setEnvironment(Environment* env);
const QList<Problem*>& problems() const;
void problemEncountered(Problem *problem);
//Returns a hash-value computed from all until currently open branching-conditions and their decisions(like #ifdef's)
uint branchingHash() const;
generator/parser/rpp/pp-environment.cpp view on Meta::CPAN
return m_locationTable;
}
LocationTable* Environment::takeLocationTable()
{
LocationTable* ret = m_locationTable;
m_locationTable = new LocationTable;
return ret;
}
MacroBlock* Environment::firstBlock() const
{
if (!m_blocks.isEmpty())
return m_blocks[0];
return 0;
}
MacroBlock* Environment::currentBlock() const
{
if (!m_blocks.isEmpty())
return m_blocks.top();
return 0;
}
void Environment::enterBlock(MacroBlock* block)
{
if (!m_blocks.isEmpty())
m_blocks.top()->childBlocks.append(block);
m_blocks.push(block);
}
void Environment::visitBlock(MacroBlock* block, int depth)
{
if (depth++ > 100) {
// TODO detect recursion?
qWarning() << "Likely cyclic include, aborting macro replay at depth 100" ;
return;
}
if (!block->condition.isEmpty()) {
Stream cs(&block->condition, Anchor(0,0));
Value result = m_preprocessor->eval_expression(cs);
generator/parser/rpp/pp-environment.cpp view on Meta::CPAN
return;
}
}
bool wasReplaying = m_replaying;
m_replaying = true;
int macroIndex = 0;
int childIndex = 0;
while (macroIndex < block->macros.count() || childIndex < block->childBlocks.count()) {
MacroBlock* child = childIndex < block->childBlocks.count() ? block->childBlocks.at(childIndex) : 0;
pp_macro* macro = macroIndex < block->macros.count() ? block->macros.at(macroIndex) : 0;
Q_ASSERT(child || macro);
bool visitMacro = macro && (!child || (child->sourceLine < macro->sourceLine));
if (!visitMacro) {
Q_ASSERT(child);
visitBlock(child, depth);
++childIndex;
} else {
Q_ASSERT(macro);
if (macro->defined)
setMacro(macro);
else
clearMacro(macro->name);
++macroIndex;
}
}
// No need to visit else block, it will be skipped (already a matched block)
m_replaying = wasReplaying;
}
MacroBlock* Environment::enterBlock(int sourceLine, const QVector<uint>& condition)
{
MacroBlock* ret = new MacroBlock(sourceLine);
ret->condition = condition;
enterBlock(ret);
return ret;
}
MacroBlock* Environment::elseBlock(int sourceLine, const QVector<uint>& condition)
{
MacroBlock* ret = new MacroBlock(sourceLine);
ret->condition = condition;
Q_ASSERT(!m_blocks.isEmpty());
m_blocks.top()->elseBlock = ret;
m_blocks.pop();
m_blocks.push(ret);
return ret;
}
void Environment::swapMacros( Environment* parentEnvironment ) {
EnvironmentMap oldEnvironment = m_environment;
m_environment = parentEnvironment->m_environment;
parentEnvironment->m_environment = oldEnvironment;
if(!parentEnvironment->currentBlock()) {
if(currentBlock()) {
foreach(pp_macro* macro, m_environment)
currentBlock()->macros.append(macro);
}
generator/parser/rpp/pp-environment.cpp view on Meta::CPAN
{
m_blocks.pop();
}
void Environment::clear()
{
m_environment.clear();
m_blocks.clear();
}
void Environment::clearMacro(const IndexedString& name)
{
// pp_macro* undef = new pp_macro();
// undef->name = name;
// undef->defined = false;
// if(!m_replaying)
// m_blocks.top()->macros.append(undef);
//
// setMacro(undef); //Before, m_environment.remove(..) was called
if(!m_replaying) {
pp_macro* undef = new pp_macro;
undef->name = name;
undef->defined = false;
m_blocks.top()->macros.append(undef);
}
///@todo Think about how this plays together with environment-management
///We need undef-macros to be put into the definedMacros etc. lists
m_environment.remove(name);
}
void Environment::setMacro(pp_macro* macro)
{
if (!m_replaying && !m_blocks.isEmpty())
m_blocks.top()->macros.append(macro);
/* if( !macro->defined )
clearMacro(macro->name);
else*/
m_environment.insert(macro->name, macro);
}
const Environment::EnvironmentMap& Environment::environment() const {
return m_environment;
}
pp_macro* Environment::retrieveStoredMacro(const IndexedString& name) const
{
EnvironmentMap::const_iterator it = m_environment.find(name);
if (it != m_environment.end())
return *it;
return 0;
}
pp_macro* Environment::retrieveMacro(const IndexedString& name, bool /*isImportant*/) const
{
return retrieveStoredMacro(name);
}
MacroBlock::MacroBlock(int _sourceLine)
: elseBlock(0)
, sourceLine(_sourceLine)
{
}
MacroBlock::~MacroBlock()
{
foreach (pp_macro* macro, macros)
delete macro;
qDeleteAll(childBlocks);
delete elseBlock;
}
void MacroBlock::setMacro(pp_macro* macro)
{
macros.append(macro);
}
void rpp::Environment::cleanup()
{
delete firstBlock();
clear();
}
QList<pp_macro*> Environment::allMacros() const
{
return m_environment.values();
}
generator/parser/rpp/pp-environment.h view on Meta::CPAN
#include "../cppparser_export.h"
#include "../indexedstring.h"
namespace rpp {
class pp_macro;
class pp;
class LocationTable;
class CPPPARSER_EXPORT MacroBlock
{
public:
MacroBlock(int _sourceLine);
virtual ~MacroBlock();
void setMacro(pp_macro* macro);
QList<MacroBlock*> childBlocks;
// The condition that opened this block(list of string indices)
QVector<uint> condition;
// The block to use if this block's condition was not met
MacroBlock* elseBlock;
// The source line where the block occurred
int sourceLine;
// This block is the owner of these macros
QList<pp_macro*> macros;
};
class CPPPARSER_EXPORT Environment
{
public:
typedef QHash<IndexedString, pp_macro*> EnvironmentMap;
Environment(pp* preprocessor);
virtual ~Environment();
MacroBlock* firstBlock() const;
MacroBlock* currentBlock() const;
void enterBlock(MacroBlock* block);
MacroBlock* enterBlock(int sourceLine, const QVector<uint>& condition = QVector<uint>());
MacroBlock* elseBlock(int sourceLine, const QVector<uint>& condition = QVector<uint>());
void leaveBlock();
// Replay previously saved blocks on this environment
void visitBlock(MacroBlock* block, int depth = 0);
void clear();
// For those not interested in the result, just in getting memory released etc.
void cleanup();
void clearMacro(const IndexedString& name);
//Note: Undef-macros are allowed too
virtual void setMacro(pp_macro* macro);
virtual pp_macro* retrieveMacro(const IndexedString& name, bool isImportant) const;
//Returns macros that are really stored locally(retrieveMacro may be overridden to perform more complex actions)
pp_macro* retrieveStoredMacro(const IndexedString& name) const;
QList<pp_macro*> allMacros() const;
//Take the set of environment-macros from the given environment
virtual void swapMacros( Environment* parentEnvironment );
//Faster access then allMacros(..), because nothing is copied
const EnvironmentMap& environment() const; //krazy:exclude=constref
LocationTable* locationTable() const;
LocationTable* takeLocationTable();
private:
EnvironmentMap m_environment;
QStack<MacroBlock*> m_blocks;
bool m_replaying;
pp* m_preprocessor;
LocationTable* m_locationTable;
};
}
#endif // PP_ENVIRONMENT_H
generator/parser/rpp/pp-location.cpp view on Meta::CPAN
anchor(0, Anchor(0,0), 0);
const unsigned int newline = indexFromCharacter('\n');
int line = 0;
for (std::size_t i = 0; i < (std::size_t)contents.size(); ++i)
if (contents.at(i) == newline)
anchor(i + 1, Anchor(++line, 0), 0);
}
QPair<rpp::Anchor, uint> LocationTable::positionAt(std::size_t offset, const PreprocessedContents& contents, bool collapseIfMacroExpansion) const
{
AnchorInTable ret = anchorForOffset(offset, collapseIfMacroExpansion);
if(!ret.anchor.collapsed)
for(std::size_t a = ret.position; a < offset; ++a)
ret.anchor.column += IndexedString::fromIndex(contents[a]).length();
uint room = 0;
if(ret.nextPosition)
if(ret.nextAnchor.line == ret.anchor.line && ret.nextAnchor.column > ret.anchor.column)
room = ret.nextAnchor.column - ret.anchor.column;
generator/parser/rpp/pp-location.cpp view on Meta::CPAN
if (offset && anchor.column) {
// Check to see if it's different to what we already know
QPair<rpp::Anchor, uint> known = positionAt(offset, *contents);
if (known.first == anchor && !anchor.collapsed && known.first.macroExpansion == anchor.macroExpansion)
return;
}
m_currentOffset = m_offsetTable.insert(offset, anchor);
}
LocationTable::AnchorInTable LocationTable::anchorForOffset(std::size_t offset, bool collapseIfMacroExpansion) const
{
// Look nearby for a match first
QMap<std::size_t, Anchor>::ConstIterator constEnd = m_offsetTable.constEnd();
if (m_currentOffset != constEnd) {
std::size_t current = m_currentOffset.key();
bool checkForwards = (current < offset);
// TODO check for optimal number of iterations
for (int i = 0; i < 5; ++i) {
if (checkForwards) {
generator/parser/rpp/pp-location.cpp view on Meta::CPAN
//kDebug() << k_funcinfo << offset << "found" << m_currentOffset.key();
if (m_currentOffset == constEnd)
--m_currentOffset;
if (m_currentOffset.key() > offset)
--m_currentOffset;
done:
Q_ASSERT(m_currentOffset != constEnd);
Anchor ret = m_currentOffset.value();
if(ret.macroExpansion.isValid() && collapseIfMacroExpansion)
ret.collapsed = true;
AnchorInTable retItem;
retItem.position = m_currentOffset.key();
retItem.anchor = ret;
++m_currentOffset;
if(m_currentOffset == constEnd) {
retItem.nextPosition = 0;
generator/parser/rpp/pp-location.h view on Meta::CPAN
/// Generates the location table from the contents
LocationTable(const PreprocessedContents& contents);
///@param contents is allowed to be zero only if offset is zero, or if anchor.column is zero.
void anchor(std::size_t offset, Anchor anchor, const PreprocessedContents* contents);
/**
* Return the position of the preprocessed source \a offset in the original source
* If the "collapsed" member of the returned anchor is true, the position is within a collapsed range.
@param collapseIfMacroExpansion @see LocationTable::positionForOffset
* \note the return line starts from 0, not 1.
* Returns the found position stored in the anchor, and the possible maximum length until the next anchored position, or zero.
*/
QPair<rpp::Anchor, uint> positionAt(std::size_t offset, const PreprocessedContents& contents, bool collapseIfMacroExpansion = false) const;
struct AnchorInTable {
uint position; //Position of this anchor
Anchor anchor; //This anchor
uint nextPosition;//Position of the next following anchor, or zero
Anchor nextAnchor;//The next following anchor
};
/**
* Returns the nearest anchor before @param position, and the position of the anchor.
* If the character is in a collapsed range, the collapsed member is true.
@param collapseIfMacroExpansion When this is true, all ranges that come from macro-expansion will be
considered collapsed.(The returned anchor will also have the collapsed member set)
* */
AnchorInTable anchorForOffset(std::size_t position, bool collapseIfMacroExpansion = false) const;
void dump() const;
/**
* Splits the given @param text using this location-table into sub-strings each assigned to a cursor where it starts.
* @param textStartPosition must be given as the start-position, because the location-table might not contain an anchor
* for the first character.
* */
void splitByAnchors(const PreprocessedContents& text, const Anchor& textStartPosition, QList<PreprocessedContents>& strings, QList<Anchor>& anchors) const;
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
#include "../problem.h"
#include "../indexedstring.h"
#include "pp-internal.h"
#include "pp-engine.h"
#include "pp-environment.h"
#include "pp-location.h"
#include "preprocessor.h"
#include "chartools.h"
const int maxMacroExpansionDepth = 50;
QString joinIndexVector(const uint* arrays, uint size, QString between) {
QString ret;
FOREACH_CUSTOM(uint item, arrays, size) {
if(!ret.isEmpty())
ret += between;
ret += IndexedString::fromIndex(item).str();
}
return ret;
}
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
int firstValid = 0;
for(; firstValid < array.size(); ++firstValid)
if(array[firstValid] != indexFromCharacter(' '))
break;
array = array.mid(firstValid);
}
using namespace rpp;
pp_frame::pp_frame(pp_macro* __expandingMacro, const QList<pp_actual>& __actuals)
: depth(0)
, expandingMacro(__expandingMacro)
, actuals(__actuals)
{
}
pp_actual pp_macro_expander::resolve_formal(IndexedString name, Stream& input)
{
if (!m_frame)
return pp_actual();
Q_ASSERT(m_frame->expandingMacro != 0);
const QVector<IndexedString>& formals = m_frame->expandingMacro->formals;
uint formalsSize = formals.size();
if(name.isEmpty()) {
Problem *problem = new Problem;
problem->file = m_engine->currentFileNameString();
problem->position = input.originalInputPosition();
problem->description = "Macro error";
m_engine->problemEncountered(problem);
return pp_actual();
}
for (uint index = 0; index < formalsSize; ++index) {
if (name.index() == formals[index].index()) {
if (index < (uint)m_frame->actuals.size()) {
return m_frame->actuals[index];
}
else {
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
if(m_in_header_section) { \
m_in_header_section = false; \
m_engine->preprocessor()->headerSectionEnded(input); \
} \
m_found_significant_content = true; \
m_search_significant_content = false; \
if( input.atEnd() ) \
continue; \
} \
struct EnableMacroExpansion {
EnableMacroExpansion(Stream& _input, const SimpleCursor& expansionPosition) : input(_input), hadMacroExpansion(_input.macroExpansion().isValid()) {
if(!hadMacroExpansion)
_input.setMacroExpansion(expansionPosition);
}
~EnableMacroExpansion() {
if(!hadMacroExpansion)
input.setMacroExpansion(SimpleCursor::invalid());
}
Stream& input;
bool hadMacroExpansion;
};
IndexedString definedIndex = IndexedString("defined");
IndexedString lineIndex = IndexedString("__LINE__");
IndexedString fileIndex = IndexedString("__FILE__");
IndexedString dateIndex = IndexedString("__DATE__");
IndexedString timeIndex= IndexedString("__TIME__");
void pp_macro_expander::operator()(Stream& input, Stream& output)
{
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
}else{
input.seek(start);
}
}
continue;
}
// TODO handle inbuilt "defined" etc functions
pp_macro* macro = m_engine->environment()->retrieveMacro(name, false);
if (!macro || !macro->defined || macro->hidden || macro->function_like || m_engine->hideNextMacro())
{
m_engine->setHideNextMacro(name == definedIndex);
if (name == lineIndex)
output.appendString(inputPosition, convertFromByteArray(QString::number(input.inputPosition().line).toUtf8()));
else if (name == fileIndex)
output.appendString(inputPosition, convertFromByteArray(QString("\"%1\"").arg(m_engine->currentFileNameString()).toUtf8()));
else if (name == dateIndex)
output.appendString(inputPosition, convertFromByteArray(QDate::currentDate().toString("MMM dd yyyy").toUtf8()));
else if (name == timeIndex)
output.appendString(inputPosition, convertFromByteArray(QTime::currentTime().toString("hh:mm:ss").toUtf8()));
else
output.appendString(inputPosition, name);
continue;
}
EnableMacroExpansion enable(output, input.inputPosition()); //Configure the output-stream so it marks all stored input-positions as transformed through a macro
if (macro->definition.size()) {
macro->hidden = true;
pp_macro_expander expand_macro(m_engine);
///@todo UGLY conversion
Stream ms((uint*)macro->definition.constData(), macro->definition.size(), Anchor(input.inputPosition(), true));
ms.setOriginalInputPosition(input.originalInputPosition());
PreprocessedContents expanded;
{
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
//Eventually execute a function-macro
IndexedString previous = IndexedString::fromIndex(indexFromCharacter(' ')); //Previous already has been expanded
uint stepsBack = 0;
while(isCharacter(previous.index()) && characterFromIndex(previous.index()) == ' ' && output.peekLastOutput(stepsBack)) {
previous = IndexedString::fromIndex(output.peekLastOutput(stepsBack));
++stepsBack;
}
pp_macro* macro = m_engine->environment()->retrieveMacro(previous, false);
if(!macro || !macro->function_like || !macro->defined || macro->hidden) {
output << input;
++input;
continue;
}
//In case expansion fails, we can skip back to this position
int openingPosition = input.offset();
Anchor openingPositionCursor = input.inputPosition();
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
}
//Q_ASSERT(!input.atEnd() && input == ')');
++input; // skip ')'
#if 0 // ### enable me
assert ((macro->variadics && macro->formals.size () >= actuals.size ())
|| macro->formals.size() == actuals.size());
#endif
EnableMacroExpansion enable(output, input.inputPosition()); //Configure the output-stream so it marks all stored input-positions as transformed through a macro
pp_frame frame(macro, actuals);
if(m_frame)
frame.depth = m_frame->depth + 1;
if(frame.depth >= maxMacroExpansionDepth)
{
qDebug() << "reached maximum macro-expansion depth while expanding" << macro->name.str();
RETURN_IF_INPUT_BROKEN
output << input;
++input;
}else{
pp_macro_expander expand_macro(m_engine, &frame);
macro->hidden = true;
///@todo UGLY conversion
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
#include "../problem.h"
#include "../indexedstring.h"
#include "pp-internal.h"
#include "pp-engine.h"
#include "pp-environment.h"
#include "pp-location.h"
#include "preprocessor.h"
#include "chartools.h"
const int maxMacroExpansionDepth = 50;
QString joinIndexVector(const uint* arrays, uint size, QString between) {
QString ret;
FOREACH_CUSTOM(uint item, arrays, size) {
if(!ret.isEmpty())
ret += between;
ret += IndexedString::fromIndex(item).str();
}
return ret;
}
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
int firstValid = 0;
for(; firstValid < array.size(); ++firstValid)
if(array[firstValid] != indexFromCharacter(' '))
break;
array = array.mid(firstValid);
}
using namespace rpp;
pp_frame::pp_frame(pp_macro* __expandingMacro, const QList<pp_actual>& __actuals)
: depth(0)
, expandingMacro(__expandingMacro)
, actuals(__actuals)
{
}
pp_actual pp_macro_expander::resolve_formal(IndexedString name, Stream& input)
{
if (!m_frame)
return pp_actual();
Q_ASSERT(m_frame->expandingMacro != 0);
const QVector<IndexedString>& formals = m_frame->expandingMacro->formals;
uint formalsSize = formals.size();
if(name.isEmpty()) {
Problem *problem = new Problem;
problem->file = m_engine->currentFileNameString();
problem->position = input.originalInputPosition();
problem->description = "Macro error";
m_engine->problemEncountered(problem);
return pp_actual();
}
for (uint index = 0; index < formalsSize; ++index) {
if (name.index() == formals[index].index()) {
if (index < (uint)m_frame->actuals.size()) {
return m_frame->actuals[index];
}
else {
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
if(m_in_header_section) { \
m_in_header_section = false; \
m_engine->preprocessor()->headerSectionEnded(input); \
} \
m_found_significant_content = true; \
m_search_significant_content = false; \
if( input.atEnd() ) \
continue; \
} \
struct EnableMacroExpansion {
EnableMacroExpansion(Stream& _input, const SimpleCursor& expansionPosition) : input(_input), hadMacroExpansion(_input.macroExpansion().isValid()) {
if(!hadMacroExpansion)
_input.setMacroExpansion(expansionPosition);
}
~EnableMacroExpansion() {
if(!hadMacroExpansion)
input.setMacroExpansion(SimpleCursor::invalid());
}
Stream& input;
bool hadMacroExpansion;
};
IndexedString definedIndex = IndexedString("defined");
IndexedString lineIndex = IndexedString("__LINE__");
IndexedString fileIndex = IndexedString("__FILE__");
IndexedString dateIndex = IndexedString("__DATE__");
IndexedString timeIndex= IndexedString("__TIME__");
void pp_macro_expander::operator()(Stream& input, Stream& output)
{
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
}else{
input.seek(start);
}
}
continue;
}
// TODO handle inbuilt "defined" etc functions
pp_macro* macro = m_engine->environment()->retrieveMacro(name, false);
if (!macro || !macro->defined || macro->hidden || macro->function_like || m_engine->hideNextMacro())
{
m_engine->setHideNextMacro(name == definedIndex);
if (name == lineIndex)
output.appendString(inputPosition, convertFromByteArray(QString::number(input.inputPosition().line).toUtf8()));
else if (name == fileIndex)
output.appendString(inputPosition, convertFromByteArray(QString("\"%1\"").arg(m_engine->currentFileNameString()).toUtf8()));
else if (name == dateIndex)
output.appendString(inputPosition, convertFromByteArray(QDate::currentDate().toString("MMM dd yyyy").toUtf8()));
else if (name == timeIndex)
output.appendString(inputPosition, convertFromByteArray(QTime::currentTime().toString("hh:mm:ss").toUtf8()));
else
output.appendString(inputPosition, name);
continue;
}
EnableMacroExpansion enable(output, input.inputPosition()); //Configure the output-stream so it marks all stored input-positions as transformed through a macro
if (macro->definition.size()) {
macro->hidden = true;
pp_macro_expander expand_macro(m_engine);
///@todo UGLY conversion
Stream ms((uint*)macro->definition.constData(), macro->definition.size(), Anchor(input.inputPosition(), true));
ms.setOriginalInputPosition(input.originalInputPosition());
PreprocessedContents expanded;
{
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
//Eventually execute a function-macro
IndexedString previous = IndexedString::fromIndex(indexFromCharacter(' ')); //Previous already has been expanded
uint stepsBack = 0;
while(isCharacter(previous.index()) && characterFromIndex(previous.index()) == ' ' && output.peekLastOutput(stepsBack)) {
previous = IndexedString::fromIndex(output.peekLastOutput(stepsBack));
++stepsBack;
}
pp_macro* macro = m_engine->environment()->retrieveMacro(previous, false);
if(!macro || !macro->function_like || !macro->defined || macro->hidden) {
output << input;
++input;
continue;
}
//In case expansion fails, we can skip back to this position
int openingPosition = input.offset();
Anchor openingPositionCursor = input.inputPosition();
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
}
//Q_ASSERT(!input.atEnd() && input == ')');
++input; // skip ')'
#if 0 // ### enable me
assert ((macro->variadics && macro->formals.size () >= actuals.size ())
|| macro->formals.size() == actuals.size());
#endif
EnableMacroExpansion enable(output, input.inputPosition()); //Configure the output-stream so it marks all stored input-positions as transformed through a macro
pp_frame frame(macro, actuals);
if(m_frame)
frame.depth = m_frame->depth + 1;
if(frame.depth >= maxMacroExpansionDepth)
{
qDebug() << "reached maximum macro-expansion depth while expanding" << macro->name.str();
output << input;
++input;
}else{
pp_macro_expander expand_macro(m_engine, &frame);
macro->hidden = true;
///@todo UGLY conversion
Stream ms((uint*)macro->definition.constData(), macro->definition.size(), Anchor(input.inputPosition(), true));
ms.setOriginalInputPosition(input.originalInputPosition());
generator/parser/rpp/pp-macro-expander.h view on Meta::CPAN
foreach(const PreprocessedContents& t, text)
ret += t;
return ret;
}
};
class pp_frame
{
public:
pp_frame (pp_macro* __expandingMacro, const QList<pp_actual>& __actuals);
int depth;
pp_macro* expandingMacro;
QList<pp_actual> actuals;
};
class pp_macro_expander
{
public:
explicit pp_macro_expander(pp* engine, pp_frame* frame = 0, bool inHeaderSection = false);
pp_actual resolve_formal(IndexedString name, Stream& input);
generator/parser/rpp/pp-macro.h view on Meta::CPAN
return dynamicSize();
}*/
typedef uint HashType;
IndexedString name;
IndexedString file;
int sourceLine; //line
bool defined: 1; // !isUndefMacro
bool hidden: 1;
bool function_like: 1; // hasArguments
bool variadics: 1;
bool fixed : 1; //If this is set, the macro can not be overridden or undefined.
mutable bool m_valueHashValid : 1;
//The valueHash is not necessarily valid
mutable HashType m_valueHash; //Hash that represents the values of all macros
bool operator==(const pp_macro& rhs) const;
generator/parser/rpp/pp-stream.cpp view on Meta::CPAN
return Anchor(m_inputLine, m_pos - m_inputLineStartedAt, m_inputPositionLocked, m_macroExpansion);
}
void Stream::setInputPosition(const Anchor& position)
{
m_inputLine = position.line;
m_inputLineStartedAt = m_pos - position.column;
m_inputPositionLocked = position.collapsed;
}
void Stream::setMacroExpansion(const SimpleCursor& expansion)
{
m_macroExpansion = expansion;
}
SimpleCursor Stream::macroExpansion() const
{
return m_macroExpansion;
}
rpp::Anchor rpp::Stream::currentOutputAnchor() const {
generator/parser/rpp/pp-stream.h view on Meta::CPAN
void seek(int offset);
/// Start from the beginning again
void reset();
/// Lock/unlock the input position. If the input position is locked, it will not be moved forwards.
void lockInputPosition(bool lock);
/// If a macro-expansion is set, all anchors given to mark() will get that macro-expansion set.
/// It marks the position from where the macro-expansion was started that leads to the current output @see rpp::Anchor
void setMacroExpansion(const SimpleCursor&);
SimpleCursor macroExpansion() const;
//Checks whether the current index represents a character, and eventually compares it
bool operator==(const char otherc) const {
return isCharacter(*c) && *c == indexFromCharacter(otherc);
}
//Checks whether the current index represents a character, and eventually compares it
bool operator!=(const char otherc) const {
return !isCharacter(*c) || *c != indexFromCharacter(otherc);
generator/parser/rpp/tests/main.cpp view on Meta::CPAN
QString result = QString::fromUtf8(stringFromContents(preprocess.processFile(QString(filename))));
preprocess.environment()->cleanup();
QStringList resultLines = result.split('\n');
for (int i = 0; i < resultLines.count(); ++i)
qDebug() << i << ":" << resultLines[i];
preprocess.environment()->locationTable()->dump();
/*foreach (const Preprocessor::MacroItem& macro, p.macros())
kDebug(9007) << "Macro '" << macro.name << "' param (" << macro.parameters << ") def (" << macro.definition << ") isFnLike (" << macro.isFunctionLike << ") filename (" << macro.fileName << ")";*/
return EXIT_SUCCESS;
}