Alien-SmokeQt

 view release on metacpan or  search on metacpan

generator/parser/rpp/pp-engine.cpp  view on Meta::CPAN

        ++input;

      } while (input == '.');
    }

    while (!input.atEnd() && input == ',')
    {
      skip_blanks(++input, devnull());

      uint formal = skip_identifier(input);
      if (formal)
        macro->formals.append( IndexedString::fromIndex(formal) );

      skip_blanks (input, devnull());

      if (input == '.') {
        macro->variadics = true;

        do {
          ++input;

        } while (input == '.');
      }
    }

    RETURN_ON_FAIL(input == ')');
    ++input;
  }

  skip_blanks (input, devnull());

  while (!input.atEnd() && input != '\n')
  {
    if(input == '/' && (input.peekNextCharacter() == '/' || input.peekNextCharacter() == '*')) {
      skip_comment_or_divop(input, devnull());
      if(!input.atEnd() && input != '\n')
        skip_blanks (input, devnull());
      continue;
    }
    if (input == '\\')
    {
      int pos = input.offset();
      skip_blanks (++input, devnull());

      if (!input.atEnd() && input == '\n')
      {
        skip_blanks(++input, devnull());
        macro->definition.append(IndexedString::fromIndex(indexFromCharacter(' ')));
        continue;

      } 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')
  {
    if (input == '/')
    {
      skip_comment_or_divop (input, output, outputText);
    }
    else if (input == '"')
    {
      skip_string_literal (input, output);
    }
    else if (input == '\'')
    {
      skip_char_literal (input, output);
    }
    else if (input == '\\')
    {
      output << input;
      skip_blanks (++input, output);

      if (!input.atEnd() && input == '\n')
      {
        output << input;
        ++input;
      }
    }
    else
    {
      output << input;
      ++input;
    }
  }
}

inline bool pp::test_if_level()
{
  bool result = !_M_skipping[iflevel++];
  _M_skipping[iflevel] = _M_skipping[iflevel - 1];
  _M_true_test[iflevel] = false;
  return result;
}

inline int pp::skipping() const
{ return _M_skipping[iflevel]; }

Value pp::eval_primary(Stream& input)
{
  int start = input.offset();
  bool expect_paren = false;
  int token = next_token_accept(input);
  Value result;

  switch (token) {
    case TOKEN_NUMBER:
      result.set_long(token_value);
      break;

    case TOKEN_UNUMBER:
      result.set_ulong(token_uvalue);
      break;

    case TOKEN_DEFINED:
      token = next_token_accept(input);

      if (token == '(')
      {
        expect_paren = true;
        token = next_token_accept(input);
      }

      if (token != TOKEN_IDENTIFIER)
      {
        Problem* problem = new Problem;
        problem->file = currentFileNameString();
        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();
          QChar tk(token);
          problem->description = QString("Expected \")\", found %1").arg(tk.isLetterOrNumber() ? 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);
        } else {
          accept_token();
        }
      }
      break;

    case TOKEN_IDENTIFIER:
      break;

    case '-':
      result.set_long(- eval_primary(input).l);
      break;

    case '+':
      result.set_long(+ eval_primary(input).l);
      break;

    case '!':
      result.set_long(eval_primary(input).is_zero());
      break;

    case '(':
      result = eval_constant_expression(input);
      token = next_token(input);

      if (token != ')') {
        Problem* problem = new Problem;
        problem->file = currentFileNameString();
        problem->position = input.originalInputPosition();
        QChar tk(token);
        problem->description = QString("Expected \")\", found %1").arg(tk.isLetterOrNumber() ? 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);
      } else {
        accept_token();
      }

      break;

    default:
      break;
  }

  return result;

generator/parser/rpp/pp-engine.cpp  view on Meta::CPAN

    }
  }
}


void pp::handle_endif(Stream& input, Stream& output)
{
  if (iflevel == 0 && !skipping())
  {
    Problem* problem = new Problem;
    problem->file = currentFileNameString();
    problem->position = input.originalInputPosition();
    problem->description = QString("#endif without #if at output line %1")
                                   .arg(m_environment->locationTable()->anchorForOffset(output.offset()).anchor.line);
    problemEncountered(problem);
  }
  else
  {
    environment()->leaveBlock();

    _M_skipping[iflevel] = 0;
    _M_true_test[iflevel] = 0;

    --iflevel;
    if(iflevel == 0) {
      if(!guardCandidate.isEmpty()) {
        checkGuardEnd = true;
      }
    }
  }
}

uint pp::branchingHash() const
{
  uint hash = 0;
  for( int a = 0; a <= iflevel; a++ ) {
    hash *= 19;
    if( _M_skipping[a] )
      hash += 3;
    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())
  {
    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;
  }
}


void pp::handle_undef(Stream& input)
{
  skip_blanks (input, devnull());

  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());

  if (input.atEnd())
  {
    return 0;
  }

  char ch = 0;
  if(isCharacter(input.current()))
    ch = characterFromIndex(input.current());
  char ch2 = input.peekNextCharacter();

  nextToken = 0;

  switch (ch) {
    case '/':
      if (ch2 == '/' || ch2 == '*')
      {
        skip_comment_or_divop(input, devnull());
        return next_token(input);
      }
      ++input;
      nextToken = '/';
      break;

    case '<':
      ++input;
      if (ch2 == '<')
      {
        ++input;
        nextToken = TOKEN_LT_LT;
      }
      else if (ch2 == '=')
      {
        ++input;
        nextToken = TOKEN_LT_EQ;
      }
      else
        nextToken = '<';

      break;

    case '>':
      ++input;
      if (ch2 == '>')
      {
        ++input;
        nextToken = TOKEN_GT_GT;
      }
      else if (ch2 == '=')
      {

generator/parser/rpp/pp-engine.cpp  view on Meta::CPAN

        token_text = IndexedString::fromIndex( skip_identifier (input) );
        if (token_text == definedText)
          nextToken = TOKEN_DEFINED;
        else
          nextToken = TOKEN_IDENTIFIER;
      }
      else if (isNumber(ch))
      {
        PreprocessedContents byteNumber;
        {
          Stream ns(&byteNumber);
          skip_number(input, ns);
        }

        QString number(QString::fromUtf8(stringFromContents(byteNumber)));
        int base = 10;
        if (number.startsWith("0x")) {
          base = 16;
        } else if (number.startsWith('0')) {
          base = 8;
        }

        if (number.endsWith('u', Qt::CaseInsensitive)) {
          token_uvalue = number.toULong(0, base);
          nextToken = TOKEN_UNUMBER;

        } else {
          token_value = number.toLong(0, base);
          nextToken = TOKEN_NUMBER;
        }
      }
      else
      {
        if(isCharacter(input.current()))
          nextToken = characterFromIndex(input.current());
        else
          nextToken = TOKEN_IDENTIFIER;
        ++input;
      }
  }

  //kDebug(9007) << "Next token '" << ch << ch2 << "'" << nextToken << "txt" << token_text << "val" << token_value;

  haveNextToken = true;
  return nextToken;
}

int pp::next_token_accept (Stream& input)
{
  int result = next_token(input);
  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)
{
  delete m_environment;
  m_environment = env;
}

const QList< Problem* > & rpp::pp::problems() const
{
  return m_problems;
}

void rpp::pp::problemEncountered(Problem *problem)
{
  m_problems.append(problem);
}



( run in 0.462 second using v1.01-cache-2.11-cpan-71847e10f99 )