Alien-SmokeQt
view release on metacpan or search on metacpan
generator/parser/rpp/pp-macro-expander.cpp view on Meta::CPAN
for(; lastValid >= 0; --lastValid)
if(array[lastValid] != indexFromCharacter(' '))
break;
array.resize(lastValid+1);
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 {
Problem *problem = new Problem;
problem->file = m_engine->currentFileNameString();
problem->position = input.originalInputPosition();
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
}
//A header-section ends when the first non-directive and non-comment occurs
#define check_header_section \
if( m_search_significant_content ) \
{ \
\
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)
{
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
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;
{
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;
++input;
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 '('
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 == ',')
{
++input; // skip ','
RETURN_IF_INPUT_BROKEN
{
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());
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
while(stepsBack) {
--stepsBack;
output.popLastOutput();
}
//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
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()
&& input == '.'
&& (__actuals.size() + 1) == (int)__macro->formals.size());
}
( run in 0.471 second using v1.01-cache-2.11-cpan-13bb782fe5a )