Alien-SmokeQt

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

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;
    



( run in 0.696 second using v1.01-cache-2.11-cpan-5b529ec07f3 )