view release on metacpan or search on metacpan
generator/parser/rpp/pp-configuration
generator/parser/rpp/pp-engine.cpp
generator/parser/rpp/pp-engine.h
generator/parser/rpp/pp-environment.cpp
generator/parser/rpp/pp-environment.h
generator/parser/rpp/pp-internal.cpp
generator/parser/rpp/pp-internal.h
generator/parser/rpp/pp-location.cpp
generator/parser/rpp/pp-location.h
generator/parser/rpp/pp-macro.cpp
generator/parser/rpp/pp-macro-expander.cpp
generator/parser/rpp/pp-macro-expander.cpp.orig
generator/parser/rpp/pp-macro-expander.h
generator/parser/rpp/pp-macro.h
generator/parser/rpp/pp-scanner.cpp
generator/parser/rpp/pp-scanner.h
generator/parser/rpp/pp-stream.cpp
generator/parser/rpp/pp-stream.h
generator/parser/rpp/preprocessor.cpp
generator/parser/rpp/preprocessor.h
generator/parser/rpp/rpp.pri
generator/parser/rpp/tests/CMakeLists.txt
generator/parser/rpp/tests/main.cpp
generator/parser/CMakeLists.txt view on Meta::CPAN
tokens.cpp
dumptree.cpp
parsesession.cpp
commentparser.cpp
commentformatter.cpp
codegenerator.cpp
indexedstring.cpp
stringhelpers.cpp
rpp/pp-stream.cpp
rpp/pp-macro-expander.cpp
rpp/pp-scanner.cpp
rpp/pp-macro.cpp
rpp/pp-engine.cpp
rpp/pp-internal.cpp
rpp/pp-environment.cpp
rpp/pp-location.cpp
rpp/preprocessor.cpp
rpp/chartools.cpp
)
generator/parser/rpp/CMakeLists.txt view on Meta::CPAN
add_subdirectory( tests )
########### next target ###############
set(kdevcpprpp_LIB_SRCS
pp-stream.cpp
pp-macro-expander.cpp
pp-scanner.cpp
pp-macro.cpp
pp-engine.cpp
pp-internal.cpp
pp-environment.cpp
pp-location.cpp
preprocessor.cpp
chartools.cpp
macrorepository.cpp
)
generator/parser/rpp/CMakeLists.txt view on Meta::CPAN
# to the plugin target
kde4_add_library(kdev4cpprpp SHARED ${kdevcpprpp_LIB_SRCS})
target_link_libraries(kdev4cpprpp ${KDE4_KDECORE_LIBS} ${KDEVPLATFORM_LANGUAGE_LIBRARY} ${KDE4_KTEXTEDITOR_LIBS} )
install(TARGETS kdev4cpprpp ${INSTALL_TARGETS_DEFAULT_ARGS} )
########### install files ###############
# install(FILES
# pp-engine.h
# pp-internal.h
# pp-macro-expander.h
# pp-macro.h
# pp-scanner.h
# pp-stream.h
# pp-environment.h
# preprocessor.h
# DESTINATION ${INCLUDE_INSTALL_DIR}/kdevelop/rpp
# )
generator/parser/rpp/pp-engine.cpp view on Meta::CPAN
#include "pp-location.h"
#include "chartools.h"
// #include "macrorepository.h"
using namespace rpp;
#define RETURN_ON_FAIL(x) if(!(x)) { ++input; qDebug() << "Preprocessor: Condition not satisfied"; return; }
pp::pp(Preprocessor* preprocessor)
: m_environment(new Environment(this))
, expand(this, 0, true)
, m_preprocessor(preprocessor)
, nextToken(0)
, haveNextToken(false)
, hideNext(false)
, hadGuardCandidate(false)
, checkGuardEnd(false)
{
iflevel = 0;
_M_skipping[iflevel] = 0;
_M_true_test[iflevel] = 0;
generator/parser/rpp/pp-engine.cpp view on Meta::CPAN
if(directive == ifdefDirective)
return handle_ifdef(false, input);
if(directive == ifndefDirective)
return handle_ifdef(true, input);
}
void pp::handle_include(bool skip_current_path, Stream& input, Stream& output)
{
if (isLetter(input.current()) || input == '_') {
pp_macro_expander expand_include(this);
Anchor inputPosition = input.inputPosition();
SimpleCursor originalInputPosition = input.originalInputPosition();
PreprocessedContents includeString;
{
Stream cs(&includeString);
expand_include(input, cs);
}
skip_blanks(input, devnull());
RETURN_ON_FAIL(!includeString.isEmpty() && (includeString.first() == indexFromCharacter('<') || includeString.first() == indexFromCharacter('"')));
Stream newInput(&includeString, inputPosition);
newInput.setOriginalInputPosition(originalInputPosition);
handle_include(skip_current_path, newInput, output);
return;
}
generator/parser/rpp/pp-engine.cpp view on Meta::CPAN
} else if (input == '\n') {
output << input;
++input;
} else if (skipping ()) {
skip (input, devnull());
} else {
output.mark(input.inputPosition());
if(checkGuardEnd) {
expand.startSignificantContentSearch();
}
expand (input, output);
if(checkGuardEnd) {
if(expand.foundSignificantContent() || !input.atEnd()) {
guardCandidate = IndexedString();
}
checkGuardEnd = false;
}
}
}
if(!guardCandidate.isEmpty())
preprocessor()->foundHeaderGuard(input, guardCandidate);
generator/parser/rpp/pp-engine.cpp view on Meta::CPAN
{
skip_blanks(input, devnull());
return eval_constant_expression(input);
}
void pp::handle_if (Stream& input)
{
if (test_if_level())
{
pp_macro_expander expand_condition(this);
skip_blanks(input, devnull());
Anchor inputPosition = input.inputPosition();
SimpleCursor originalInputPosition = input.originalInputPosition();
PreprocessedContents condition;
{
Stream cs(&condition);
expand_condition(input, cs);
}
environment()->enterBlock(input.inputPosition().line, condition);
Stream cs(&condition, inputPosition);
cs.setOriginalInputPosition(originalInputPosition);
Value result = eval_expression(cs);
_M_true_test[iflevel] = !result.is_zero();
_M_skipping[iflevel] = result.is_zero();
} else {
// Capture info for precompiled macros
pp_macro_expander expand_condition(this);
skip_blanks(input, devnull());
PreprocessedContents condition;
{
Stream cs(&condition);
expand_condition(input, cs);
}
environment()->enterBlock(input.inputPosition().line, condition);
_M_true_test[iflevel] = true;
_M_skipping[iflevel] = true;
}
}
generator/parser/rpp/pp-engine.cpp view on Meta::CPAN
if (iflevel == 0 && !skipping())
{
Problem* problem = new Problem;
problem->file = currentFileNameString();
problem->position = input.originalInputPosition();
problem->description = "#else without #if";
problemEncountered(problem);
}
else
{
pp_macro_expander expand_condition(this);
skip_blanks(input, devnull());
Anchor inputPosition = input.inputPosition();
SimpleCursor originalInputPosition = input.originalInputPosition();
PreprocessedContents condition;
{
Stream cs(&condition);
cs.setOriginalInputPosition(originalInputPosition);
expand_condition(input, cs);
}
environment()->elseBlock(input.inputPosition().line, condition);
if (!_M_true_test[iflevel] && !_M_skipping[iflevel - 1])
{
Stream cs(&condition, inputPosition);
Value result = eval_expression(cs);
_M_true_test[iflevel] = !result.is_zero();
_M_skipping[iflevel] = result.is_zero();
generator/parser/rpp/pp-engine.cpp view on Meta::CPAN
if( _M_true_test[a] )
hash += 7;
}
return hash;
}
void pp::handle_ifdef (bool check_undefined, Stream& input)
{
IndexedString macro_name = IndexedString::fromIndex(skip_identifier(input));
///@todo eventually fix the block description
if(check_undefined && expand.in_header_section() && guardCandidate.isEmpty() && !hadGuardCandidate && iflevel == 0) {
//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())
{
generator/parser/rpp/pp-engine.h view on Meta::CPAN
//krazy:excludeall=inline
#include <QtCore/QHash>
#include <QtCore/QStack>
#include "../cppparser_export.h"
#include "../problem.h"
#include "pp-macro.h"
#include "pp-macro-expander.h"
#include "pp-scanner.h"
typedef QVector<unsigned int> PreprocessedContents;
namespace rpp {
class Preprocessor;
class Environment;
struct Value
generator/parser/rpp/pp-engine.h view on Meta::CPAN
PP_DEFINE_BIN_OP2(&&)
PP_DEFINE_BIN_OP2(||)
#undef PP_DEFINE_BIN_OP
};
class CPPPARSER_EXPORT pp
{
Environment* m_environment;
pp_macro_expander expand;
pp_skip_identifier skip_identifier;
pp_skip_comment_or_divop skip_comment_or_divop;
pp_skip_blanks skip_blanks;
pp_skip_number skip_number;
QStack<IndexedString> m_files;
Preprocessor* m_preprocessor;
QList<Problem*> m_problems;
enum { MAX_LEVEL = 512 };
int _M_skipping[MAX_LEVEL];
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "pp-macro-expander.h"
#include <QDate>
#include <QTime>
#include <QtDebug>
#include "../problem.h"
#include "../indexedstring.h"
#include "pp-internal.h"
#include "pp-engine.h"
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();
}
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
problem->description = QString("Call to macro %1 missing argument number %2").arg(name.str()).arg(index);
problem->explanation = QString("Formals: %1").arg(joinIndexVector(formals, ", "));
m_engine->problemEncountered(problem);
}
}
}
return pp_actual();
}
#define RETURN_IF_INPUT_BROKEN if(input.atEnd()) { qDebug() << "too early end while expanding" << macro->name.str(); return; }
pp_macro_expander::pp_macro_expander(pp* engine, pp_frame* frame, bool inHeaderSection)
: m_engine(engine)
, m_frame(frame)
, m_in_header_section(inHeaderSection)
, m_search_significant_content(false)
, m_found_significant_content(false)
{
if(m_in_header_section)
m_search_significant_content = true; //Find the end of the header section
}
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
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)
{
skip_blanks(input, output);
while (!input.atEnd())
{
if (isComment(input))
{
skip_comment_or_divop(input, output, true);
}else{
if (input == '\n')
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
Q_ASSERT(isCharacter(input.current()));
Q_ASSERT(IndexedString::fromIndex(input.current()).str() == "#");
++input;
// search for the paste token
if(input == '#') {
++input;
skip_blanks (input, devnull());
IndexedString previous = IndexedString::fromIndex(output.popLastOutput()); //Previous already has been expanded
while(output.offset() > 0 && isCharacter(previous.index()) && characterFromIndex(previous.index()) == ' ')
previous = IndexedString::fromIndex(output.popLastOutput());
IndexedString add = IndexedString::fromIndex(skip_identifier (input));
PreprocessedContents newExpanded;
{
//Expand "add", so it is eventually replaced by an actual
PreprocessedContents actualText;
actualText.append(add.index());
{
Stream as(&actualText);
pp_macro_expander expand_actual(m_engine, m_frame);
Stream nas(&newExpanded);
expand_actual(as, nas);
}
}
if(!newExpanded.isEmpty()) {
IndexedString first = IndexedString::fromIndex(newExpanded.first());
if(!isCharacter(first.index()) || QChar(characterFromIndex(first.index())).isLetterOrNumber() || characterFromIndex(first.index()) == '_') {
//Merge the tokens
newExpanded.first() = IndexedString(previous.byteArray() + first.byteArray()).index();
}else{
//Cannot merge, prepend the previous text
newExpanded.prepend(previous.index());
}
}else{
newExpanded.append(previous.index());
}
//Now expand the merged text completely into the output.
pp_macro_expander final_expansion(m_engine, m_frame);
Stream nas(&newExpanded, output.currentOutputAnchor());
final_expansion(nas, output);
continue;
}
skip_blanks(input, output);
IndexedString identifier = IndexedString::fromIndex( skip_identifier(input) );
Anchor inputPosition = input.inputPosition();
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
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;
{
Stream es(&expanded);
expand_macro(ms, es);
}
if (!expanded.isEmpty())
{
Stream es(&expanded, Anchor(input.inputPosition(), true));
es.setOriginalInputPosition(input.originalInputPosition());
skip_whitespaces(es, devnull());
IndexedString identifier = IndexedString::fromIndex( skip_identifier(es) );
output.appendString(Anchor(input.inputPosition(), true), expanded);
output << ' '; //Prevent implicit token merging
}
macro->hidden = false;
}
}else if(input == '(') {
//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;
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
//In case expansion fails, we can skip back to this position
int openingPosition = input.offset();
Anchor openingPositionCursor = input.inputPosition();
QList<pp_actual> actuals;
++input; // skip '('
RETURN_IF_INPUT_BROKEN
pp_macro_expander expand_actual(m_engine, m_frame);
{
PreprocessedContents actualText;
skip_whitespaces(input, devnull());
Anchor actualStart = input.inputPosition();
{
Stream as(&actualText);
skip_argument_variadics(actuals, macro, input, as);
}
trim(actualText);
pp_actual newActual;
{
PreprocessedContents newActualText;
Stream as(&actualText, actualStart);
as.setOriginalInputPosition(input.originalInputPosition());
rpp::LocationTable table;
table.anchor(0, actualStart, 0);
Stream nas(&newActualText, actualStart, &table);
expand_actual(as, nas);
table.splitByAnchors(newActualText, actualStart, newActual.text, newActual.inputPosition);
}
newActual.forceValid = true;
actuals.append(newActual);
}
// TODO: why separate from the above?
while (!input.atEnd() && input == ',')
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
pp_actual newActual;
{
PreprocessedContents newActualText;
Stream as(&actualText, actualStart);
as.setOriginalInputPosition(input.originalInputPosition());
PreprocessedContents actualText;
rpp::LocationTable table;
table.anchor(0, actualStart, 0);
Stream nas(&newActualText, actualStart, &table);
expand_actual(as, nas);
table.splitByAnchors(newActualText, actualStart, newActual.text, newActual.inputPosition);
}
newActual.forceValid = true;
actuals.append(newActual);
}
}
if( input != ')' ) {
//Failed to expand the macro. Output the macro name and continue normal
//processing behind it.(Code completion depends on this behavior when expanding
//incomplete input-lines)
input.seek(openingPosition);
input.setInputPosition(openingPositionCursor);
//Move one character into the output, so we don't get an endless loop
output << input;
++input;
continue;
}
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
|| 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
Stream ms((uint*)macro->definition.constData(), macro->definition.size(), Anchor(input.inputPosition(), true));
ms.setOriginalInputPosition(input.originalInputPosition());
expand_macro(ms, output);
output << ' '; //Prevent implicit token merging
macro->hidden = false;
}
} else {
output << input;
++input;
}
}
}
}
void pp_macro_expander::skip_argument_variadics (const QList<pp_actual>& __actuals, pp_macro *__macro, Stream& input, Stream& output)
{
int first;
do {
first = input.offset();
skip_argument(input, output);
} while ( __macro->variadics
&& first != input.offset()
&& !input.atEnd()
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "pp-macro-expander.h"
#include <QDate>
#include <QTime>
#include <QtDebug>
#include "../problem.h"
#include "../indexedstring.h"
#include "pp-internal.h"
#include "pp-engine.h"
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();
}
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
problem->description = QString("Call to macro %1 missing argument number %2").arg(name.str()).arg(index);
problem->explanation = QString("Formals: %1").arg(joinIndexVector(formals, ", "));
m_engine->problemEncountered(problem);
}
}
}
return pp_actual();
}
pp_macro_expander::pp_macro_expander(pp* engine, pp_frame* frame, bool inHeaderSection)
: m_engine(engine)
, m_frame(frame)
, m_in_header_section(inHeaderSection)
, m_search_significant_content(false)
, m_found_significant_content(false)
{
if(m_in_header_section)
m_search_significant_content = true; //Find the end of the header section
}
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
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)
{
skip_blanks(input, output);
while (!input.atEnd())
{
if (isComment(input))
{
skip_comment_or_divop(input, output, true);
}else{
if (input == '\n')
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
Q_ASSERT(isCharacter(input.current()));
Q_ASSERT(IndexedString::fromIndex(input.current()).str() == "#");
++input;
// search for the paste token
if(input == '#') {
++input;
skip_blanks (input, devnull());
IndexedString previous = IndexedString::fromIndex(output.popLastOutput()); //Previous already has been expanded
while(output.offset() > 0 && isCharacter(previous.index()) && characterFromIndex(previous.index()) == ' ')
previous = IndexedString::fromIndex(output.popLastOutput());
IndexedString add = IndexedString::fromIndex(skip_identifier (input));
PreprocessedContents newExpanded;
{
//Expand "add", so it is eventually replaced by an actual
PreprocessedContents actualText;
actualText.append(add.index());
{
Stream as(&actualText);
pp_macro_expander expand_actual(m_engine, m_frame);
Stream nas(&newExpanded);
expand_actual(as, nas);
}
}
if(!newExpanded.isEmpty()) {
IndexedString first = IndexedString::fromIndex(newExpanded.first());
if(!isCharacter(first.index()) || QChar(characterFromIndex(first.index())).isLetterOrNumber() || characterFromIndex(first.index()) == '_') {
//Merge the tokens
newExpanded.first() = IndexedString(previous.byteArray() + first.byteArray()).index();
}else{
//Cannot merge, prepend the previous text
newExpanded.prepend(previous.index());
}
}else{
newExpanded.append(previous.index());
}
//Now expand the merged text completely into the output.
pp_macro_expander final_expansion(m_engine, m_frame);
Stream nas(&newExpanded, output.currentOutputAnchor());
final_expansion(nas, output);
continue;
}
skip_blanks(input, output);
IndexedString identifier = IndexedString::fromIndex( skip_identifier(input) );
Anchor inputPosition = input.inputPosition();
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
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;
{
Stream es(&expanded);
expand_macro(ms, es);
}
if (!expanded.isEmpty())
{
Stream es(&expanded, Anchor(input.inputPosition(), true));
es.setOriginalInputPosition(input.originalInputPosition());
skip_whitespaces(es, devnull());
IndexedString identifier = IndexedString::fromIndex( skip_identifier(es) );
output.appendString(Anchor(input.inputPosition(), true), expanded);
output << ' '; //Prevent implicit token merging
}
macro->hidden = false;
}
}else if(input == '(') {
//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;
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
continue;
}
//In case expansion fails, we can skip back to this position
int openingPosition = input.offset();
Anchor openingPositionCursor = input.inputPosition();
QList<pp_actual> actuals;
++input; // skip '('
pp_macro_expander expand_actual(m_engine, m_frame);
{
PreprocessedContents actualText;
skip_whitespaces(input, devnull());
Anchor actualStart = input.inputPosition();
{
Stream as(&actualText);
skip_argument_variadics(actuals, macro, input, as);
}
trim(actualText);
pp_actual newActual;
{
PreprocessedContents newActualText;
Stream as(&actualText, actualStart);
as.setOriginalInputPosition(input.originalInputPosition());
rpp::LocationTable table;
table.anchor(0, actualStart, 0);
Stream nas(&newActualText, actualStart, &table);
expand_actual(as, nas);
table.splitByAnchors(newActualText, actualStart, newActual.text, newActual.inputPosition);
}
newActual.forceValid = true;
actuals.append(newActual);
}
// TODO: why separate from the above?
while (!input.atEnd() && input == ',')
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
pp_actual newActual;
{
PreprocessedContents newActualText;
Stream as(&actualText, actualStart);
as.setOriginalInputPosition(input.originalInputPosition());
PreprocessedContents actualText;
rpp::LocationTable table;
table.anchor(0, actualStart, 0);
Stream nas(&newActualText, actualStart, &table);
expand_actual(as, nas);
table.splitByAnchors(newActualText, actualStart, newActual.text, newActual.inputPosition);
}
newActual.forceValid = true;
actuals.append(newActual);
}
}
if( input != ')' ) {
//Failed to expand the macro. Output the macro name and continue normal
//processing behind it.(Code completion depends on this behavior when expanding
//incomplete input-lines)
input.seek(openingPosition);
input.setInputPosition(openingPositionCursor);
//Move one character into the output, so we don't get an endless loop
output << input;
++input;
continue;
}
//Remove the name of the called macro
generator/parser/rpp/pp-macro-expander.cpp.orig view on Meta::CPAN
|| 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());
expand_macro(ms, output);
output << ' '; //Prevent implicit token merging
macro->hidden = false;
}
} else {
output << input;
++input;
}
}
}
}
void pp_macro_expander::skip_argument_variadics (const QList<pp_actual>& __actuals, pp_macro *__macro, Stream& input, Stream& output)
{
int first;
do {
first = input.offset();
skip_argument(input, output);
} while ( __macro->variadics
&& first != input.offset()
&& !input.atEnd()
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);
/// Expands text with the known macros. Continues until it finds a new text line
/// beginning with #, at which point control is returned.
void operator()(Stream& input, Stream& output);
void skip_argument_variadics (const QList<pp_actual>& __actuals, pp_macro *__macro,
Stream& input, Stream& output);
generator/parser/rpp/pp-stream.h view on Meta::CPAN
uint popLastOutput();
///Allows peeking at the items that were added to the output recently
uint peekLastOutput(uint backOffset = 0) const;
///Returns the cursor that points to the current input position.
Anchor inputPosition() const;
///If the input position is collapsed, the input position will be locked from now on. It will stay the same until a new one is set.
void setInputPosition(const Anchor& position);
///Input-position that marks the start of the topmost currently expanding macro in the original document
SimpleCursor originalInputPosition() const;
void setOriginalInputPosition(const SimpleCursor& position);
///Used for output streams to mark stream positions with input position
///The macroExpansion member may have no effect if macroExpansion is set for this stream.
void mark(const Anchor& position);
///Returns the anchor for the current output position.
Anchor currentOutputAnchor() const;