summaryrefslogtreecommitdiff
path: root/src/plugins/cpptools/rpp/pp-engine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/cpptools/rpp/pp-engine.cpp')
-rw-r--r--src/plugins/cpptools/rpp/pp-engine.cpp1124
1 files changed, 0 insertions, 1124 deletions
diff --git a/src/plugins/cpptools/rpp/pp-engine.cpp b/src/plugins/cpptools/rpp/pp-engine.cpp
deleted file mode 100644
index 66e8957f35..0000000000
--- a/src/plugins/cpptools/rpp/pp-engine.cpp
+++ /dev/null
@@ -1,1124 +0,0 @@
-/***************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-**
-** Non-Open Source Usage
-**
-** Licensees may use this file in accordance with the Qt Beta Version
-** License Agreement, Agreement version 2.2 provided with the Software or,
-** alternatively, in accordance with the terms contained in a written
-** agreement between you and Nokia.
-**
-** GNU General Public License Usage
-**
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License versions 2.0 or 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the packaging
-** of this file. Please review the following information to ensure GNU
-** General Public Licensing requirements will be met:
-**
-** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt GPL Exception
-** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
-**
-***************************************************************************/
-/*
- Copyright 2005 Roberto Raggi <roberto@kdevelop.org>
-
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation.
-
- The above copyright notice and this permission notice shall be included in
- 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.h"
-
-#include <Lexer.h>
-#include <Token.h>
-#include <QtDebug>
-#include <algorithm>
-
-using namespace rpp;
-using namespace CPlusPlus;
-
-namespace {
-
-class RangeLexer
-{
- const Token *first;
- const Token *last;
- Token trivial;
-
-public:
- inline RangeLexer(const Token *first, const Token *last)
- : first(first), last(last)
- {
- // WARN: `last' must be a valid iterator.
- trivial.offset = last->offset;
- }
-
- inline operator bool() const
- { return first != last; }
-
- inline bool isValid() const
- { return first != last; }
-
- inline int size() const
- { return std::distance(first, last); }
-
- inline const Token *dot() const
- { return first; }
-
- inline const Token &operator*() const
- {
- if (first != last)
- return *first;
-
- return trivial;
- }
-
- inline const Token *operator->() const
- {
- if (first != last)
- return first;
-
- return &trivial;
- }
-
- inline RangeLexer &operator++()
- {
- ++first;
- return *this;
- }
-};
-
-class ExpressionEvaluator
-{
- ExpressionEvaluator(const ExpressionEvaluator &other);
- void operator = (const ExpressionEvaluator &other);
-
-public:
- ExpressionEvaluator(Environment *env)
- : env(env), _lex(0)
- { }
-
- Value operator()(const Token *firstToken, const Token *lastToken,
- const QByteArray &source)
- {
- this->source = source;
- const Value previousValue = switchValue(Value());
- RangeLexer tmp(firstToken, lastToken);
- RangeLexer *previousLex = _lex;
- _lex = &tmp;
- process_expression();
- _lex = previousLex;
- return switchValue(previousValue);
- }
-
-protected:
- Value switchValue(const Value &value)
- {
- Value previousValue = _value;
- _value = value;
- return previousValue;
- }
-
- bool isTokenDefined() const
- {
- if ((*_lex)->isNot(T_IDENTIFIER))
- return false;
- const QByteArray spell = tokenSpell();
- if (spell.size() != 7)
- return false;
- return spell == "defined";
- }
-
- QByteArray tokenSpell() const
- {
- const QByteArray text = QByteArray::fromRawData(source.constData() + (*_lex)->offset,
- (*_lex)->length);
- return text;
- }
-
- bool process_expression()
- { return process_constant_expression(); }
-
- bool process_primary()
- {
- if ((*_lex)->is(T_INT_LITERAL)) {
- _value.set_long(tokenSpell().toLong());
- ++(*_lex);
- return true;
- } else if (isTokenDefined()) {
- ++(*_lex);
- if ((*_lex)->is(T_IDENTIFIER)) {
- _value.set_long(env->resolve(tokenSpell()) != 0);
- ++(*_lex);
- return true;
- } else if ((*_lex)->is(T_LPAREN)) {
- ++(*_lex);
- if ((*_lex)->is(T_IDENTIFIER)) {
- _value.set_long(env->resolve(tokenSpell()) != 0);
- ++(*_lex);
- if ((*_lex)->is(T_RPAREN)) {
- ++(*_lex);
- return true;
- }
- }
- return false;
- }
- return true;
- } else if ((*_lex)->is(T_IDENTIFIER)) {
- _value.set_long(0);
- ++(*_lex);
- return true;
- } else if ((*_lex)->is(T_MINUS)) {
- ++(*_lex);
- process_primary();
- _value.set_long(- _value.l);
- return true;
- } else if ((*_lex)->is(T_PLUS)) {
- ++(*_lex);
- process_primary();
- return true;
- } else if ((*_lex)->is(T_EXCLAIM)) {
- ++(*_lex);
- process_primary();
- _value.set_long(_value.is_zero());
- return true;
- } else if ((*_lex)->is(T_LPAREN)) {
- ++(*_lex);
- process_expression();
- if ((*_lex)->is(T_RPAREN))
- ++(*_lex);
- return true;
- }
-
- return false;
- }
-
- bool process_multiplicative()
- {
- process_primary();
-
- while ((*_lex)->is(T_STAR) || (*_lex)->is(T_SLASH) || (*_lex)->is(T_PERCENT)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_primary();
-
- if (op.is(T_STAR)) {
- _value = left * _value;
- } else if (op.is(T_SLASH)) {
- if (_value.is_zero())
- _value.set_long(0);
- else
- _value = left / _value;
- } else if (op.is(T_PERCENT)) {
- if (_value.is_zero())
- _value.set_long(0);
- else
- _value = left % _value;
- }
- }
-
- return true;
- }
-
- bool process_additive()
- {
- process_multiplicative();
-
- while ((*_lex)->is(T_PLUS) || (*_lex)->is(T_MINUS)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_multiplicative();
-
- if (op.is(T_PLUS))
- _value = left + _value;
- else if (op.is(T_MINUS))
- _value = left - _value;
- }
-
- return true;
- }
-
- bool process_shift()
- {
- process_additive();
-
- while ((*_lex)->is(T_MINUS_MINUS) || (*_lex)->is(T_GREATER_GREATER)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_additive();
-
- if (op.is(T_MINUS_MINUS))
- _value = left << _value;
- else if (op.is(T_GREATER_GREATER))
- _value = left >> _value;
- }
-
- return true;
- }
-
- bool process_relational()
- {
- process_shift();
-
- while ((*_lex)->is(T_LESS) || (*_lex)->is(T_LESS_EQUAL) ||
- (*_lex)->is(T_GREATER) || (*_lex)->is(T_GREATER_EQUAL)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_shift();
-
- if (op.is(T_LESS))
- _value = left < _value;
- else if (op.is(T_LESS_EQUAL))
- _value = left <= _value;
- else if (op.is(T_GREATER))
- _value = left > _value;
- else if (op.is(T_GREATER_EQUAL))
- _value = left >= _value;
- }
-
- return true;
- }
-
- bool process_equality()
- {
- process_relational();
-
- while ((*_lex)->is(T_EXCLAIM_EQUAL) || (*_lex)->is(T_EQUAL_EQUAL)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_relational();
-
- if (op.is(T_EXCLAIM_EQUAL))
- _value = left != _value;
- else if (op.is(T_EQUAL_EQUAL))
- _value = left == _value;
- }
-
- return true;
- }
-
- bool process_and()
- {
- process_equality();
-
- while ((*_lex)->is(T_AMPER)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_equality();
-
- _value = left & _value;
- }
-
- return true;
- }
-
- bool process_xor()
- {
- process_and();
-
- while ((*_lex)->is(T_CARET)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_and();
-
- _value = left ^ _value;
- }
-
- return true;
- }
-
- bool process_or()
- {
- process_xor();
-
- while ((*_lex)->is(T_CARET)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_xor();
-
- _value = left | _value;
- }
-
- return true;
- }
-
- bool process_logical_and()
- {
- process_or();
-
- while ((*_lex)->is(T_AMPER_AMPER)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_or();
-
- _value = left && _value;
- }
-
- return true;
- }
-
- bool process_logical_or()
- {
- process_logical_and();
-
- while ((*_lex)->is(T_PIPE_PIPE)) {
- const Token op = *(*_lex);
- ++(*_lex);
-
- const Value left = _value;
- process_logical_and();
-
- _value = left || _value;
- }
-
- return true;
- }
-
- bool process_constant_expression()
- {
- process_logical_or();
- const Value cond = _value;
- if ((*_lex)->is(T_QUESTION)) {
- ++(*_lex);
- process_constant_expression();
- Value left = _value, right;
- if ((*_lex)->is(T_COLON)) {
- ++(*_lex);
- process_constant_expression();
- right = _value;
- }
- _value = ! cond.is_zero() ? left : right;
- }
-
- return true;
- }
-
-private:
- Environment *env;
- QByteArray source;
- RangeLexer *_lex;
- Value _value;
-};
-
-} // end of anonymous namespace
-
-
-pp::pp (Client *client, Environment &env)
- : client(client),
- env(env),
- expand(env)
-{
- resetIfLevel ();
-}
-
-void pp::pushState(const State &s)
-{
- _savedStates.append(state());
- _source = s.source;
- _tokens = s.tokens;
- _dot = s.dot;
-}
-
-pp::State pp::state() const
-{
- State state;
- state.source = _source;
- state.tokens = _tokens;
- state.dot = _dot;
- return state;
-}
-
-void pp::popState()
-{
- const State &state = _savedStates.last();
- _source = state.source;
- _tokens = state.tokens;
- _dot = state.dot;
- _savedStates.removeLast();
-}
-
-void pp::operator () (const QByteArray &filename,
- const QByteArray &source,
- QByteArray *result)
-{
- const QByteArray previousFile = env.current_file;
- env.current_file = filename;
-
- operator () (source, result);
-
- env.current_file = previousFile;
-}
-
-pp::State pp::createStateFromSource(const QByteArray &source) const
-{
- State state;
- state.source = source;
- Lexer lex(state.source.constBegin(), state.source.constEnd());
- lex.setScanKeywords(false);
- Token tok;
- do {
- lex(&tok);
- state.tokens.append(tok);
- } while (tok.isNot(T_EOF_SYMBOL));
- state.dot = state.tokens.constBegin();
- return state;
-}
-
-void pp::operator()(const QByteArray &source, QByteArray *result)
-{
- pushState(createStateFromSource(source));
-
- const unsigned previousCurrentLine = env.currentLine;
- env.currentLine = 0;
-
- while (true) {
- if (env.currentLine != _dot->lineno) {
- if (env.currentLine > _dot->lineno) {
- result->append("\n# ");
- result->append(QByteArray::number(_dot->lineno));
- result->append(' ');
- result->append('"');
- result->append(env.current_file);
- result->append('"');
- result->append('\n');
- } else {
- for (unsigned i = env.currentLine; i < _dot->lineno; ++i)
- result->append('\n');
- }
- env.currentLine = _dot->lineno;
- }
-
- if (_dot->is(T_EOF_SYMBOL)) {
- break;
- } else if (_dot->is(T_POUND) && (! _dot->joined && _dot->newline)) {
- TokenIterator start = _dot;
- do {
- ++_dot;
- } while (_dot->isNot(T_EOF_SYMBOL) && (_dot->joined || ! _dot->newline));
-
- //qDebug() << QByteArray(first + beginPP.offset,
- //tokens.last().end() - beginPP.offset);
-
- const bool skippingBlocks = _skipping[iflevel];
-
- processDirective(start, _dot);
-
- if (client && skippingBlocks != _skipping[iflevel]) {
- unsigned offset = start->offset;
- if (_skipping[iflevel]) {
- if (_dot->newline)
- ++offset;
- client->startSkippingBlocks(offset);
- } else {
- if (offset)
- --offset;
- client->stopSkippingBlocks(offset);
- }
- }
- } else if (skipping()) {
- do {
- ++_dot;
- } while (_dot->isNot(T_EOF_SYMBOL) && (_dot->joined || ! _dot->newline));
- } else {
- if (_dot->joined)
- result->append("\\\n");
- else if (_dot->whitespace)
- result->append(' ');
-
- if (_dot->isNot(T_IDENTIFIER)) {
- result->append(tokenSpell(*_dot));
- ++_dot;
- } else {
- const TokenIterator identifierToken = _dot;
- ++_dot; // skip T_IDENTIFIER
-
- const QByteArray spell = tokenSpell(*identifierToken);
- if (env.isBuiltinMacro(spell)) {
- const Macro trivial;
-
- if (client)
- client->startExpandingMacro(identifierToken->offset,
- trivial, spell);
-
- expand(spell.constBegin(), spell.constEnd(), result);
-
- if (client)
- client->stopExpandingMacro(_dot->offset, trivial);
-
- continue;
- }
-
- Macro *m = env.resolve(spell);
- if (! m) {
- result->append(spell);
- } else {
- if (! m->function_like) {
- if (_dot->isNot(T_LPAREN)) {
- if (client)
- client->startExpandingMacro(identifierToken->offset,
- *m, spell);
-
- m->hidden = true;
-
- expand(m->definition.constBegin(),
- m->definition.constEnd(),
- result);
-
- if (client)
- client->stopExpandingMacro(_dot->offset, *m);
-
- m->hidden = false;
- continue;
- } else {
- QByteArray tmp;
- m->hidden = true;
-
- if (client)
- client->startExpandingMacro(identifierToken->offset,
- *m, spell);
-
- expand(m->definition.constBegin(),
- m->definition.constEnd(),
- &tmp);
-
- if (client)
- client->stopExpandingMacro(_dot->offset, *m);
-
- m->hidden = false;
-
- m = 0; // reset the active the macro
-
- pushState(createStateFromSource(tmp));
- if (_dot->is(T_IDENTIFIER)) {
- const QByteArray id = tokenSpell(*_dot);
- Macro *macro = env.resolve(id);
- if (macro && macro->function_like)
- m = macro;
- }
- popState();
-
- if (! m) {
- result->append(tmp);
- continue;
- }
- }
- }
-
- // collect the actual arguments
- if (_dot->isNot(T_LPAREN)) {
- // ### warnng expected T_LPAREN
- result->append(m->name);
- continue;
- }
-
- int count = 0;
- while (_dot->isNot(T_EOF_SYMBOL)) {
- if (_dot->is(T_LPAREN))
- ++count;
- else if (_dot->is(T_RPAREN)) {
- if (! --count)
- break;
- }
- ++_dot;
- }
- if (_dot->isNot(T_RPAREN)) {
- // ### warning expected T_RPAREN
- } else {
- const char *beginOfText = startOfToken(*identifierToken);
- const char *endOfText = endOfToken(*_dot);
- ++_dot; // skip T_RPAREN
-
- if (client) {
- const QByteArray text =
- QByteArray::fromRawData(beginOfText,
- endOfText - beginOfText);
-
- client->startExpandingMacro(identifierToken->offset,
- *m, text);
- }
-
- expand(beginOfText, endOfText, result);
-
- if (client)
- client->stopExpandingMacro(_dot->offset, *m);
- }
- }
- }
- }
- }
-
- popState();
- env.currentLine = previousCurrentLine;
-}
-
-const char *pp::startOfToken(const Token &token) const
-{ return _source.constBegin() + token.begin(); }
-
-const char *pp::endOfToken(const Token &token) const
-{ return _source.constBegin() + token.end(); }
-
-QByteArray pp::tokenSpell(const Token &token) const
-{
- const QByteArray text = QByteArray::fromRawData(_source.constBegin() + token.offset,
- token.length);
- return text;
-}
-
-QByteArray pp::tokenText(const Token &token) const
-{
- const QByteArray text(_source.constBegin() + token.offset,
- token.length);
- return text;
-}
-
-void pp::processDirective(TokenIterator firstToken, TokenIterator lastToken)
-{
- RangeLexer tk(firstToken, lastToken);
- ++tk; // skip T_POUND
-
- if (tk->is(T_IDENTIFIER)) {
- const QByteArray directive = tokenSpell(*tk);
- switch (PP_DIRECTIVE_TYPE d = classifyDirective(directive)) {
- case PP_DEFINE:
- if (! skipping())
- processDefine(firstToken, lastToken);
- break;
-
- case PP_INCLUDE:
- case PP_INCLUDE_NEXT:
- if (! skipping())
- processInclude(d == PP_INCLUDE_NEXT, firstToken, lastToken);
- break;
-
- case PP_UNDEF:
- if (! skipping())
- processUndef(firstToken, lastToken);
- break;
-
- case PP_ELIF:
- processElif(firstToken, lastToken);
- break;
-
- case PP_ELSE:
- processElse(firstToken, lastToken);
- break;
-
- case PP_ENDIF:
- processEndif(firstToken, lastToken);
- break;
-
- case PP_IF:
- processIf(firstToken, lastToken);
- break;
-
- case PP_IFDEF:
- case PP_IFNDEF:
- processIfdef(d == PP_IFNDEF, firstToken, lastToken);
- break;
-
- default:
- break;
- } // switch
- }
-}
-
-QVector<Token> pp::tokenize(const QByteArray &text) const
-{
- QVector<Token> tokens;
- Lexer lex(text.constBegin(), text.constEnd());
- lex.setScanKeywords(false);
- Token tk;
- do {
- lex(&tk);
- tokens.append(tk);
- } while (tk.isNot(T_EOF_SYMBOL));
- return tokens;
-}
-
-void pp::processInclude(bool skipCurentPath,
- TokenIterator firstToken, TokenIterator lastToken,
- bool acceptMacros)
-{
- RangeLexer tk(firstToken, lastToken);
- ++tk; // skip T_POUND
- ++tk; // skip `include|nclude_next'
-
- if (acceptMacros && tk->is(T_IDENTIFIER)) {
-#if 0
- QByteArray name;
- name.reserve(256);
- MacroExpander expandInclude(env);
- expandInclude(startOfToken(tokens.at(2)),
- startOfToken(tokens.last()),
- &name);
- const QByteArray previousSource = switchSource(name);
- //processInclude(skipCurentPath, tokenize(name), /*accept macros=*/ false);
- (void) switchSource(previousSource);
-#endif
- } else if (tk->is(T_LESS)) {
- TokenIterator start = tk.dot();
- for (; tk->isNot(T_EOF_SYMBOL); ++tk) {
- if (tk->is(T_GREATER))
- break;
- }
- const char *beginOfPath = endOfToken(*start);
- const char *endOfPath = startOfToken(*tk);
- const QByteArray path = QByteArray::fromRawData(beginOfPath,
- endOfPath - beginOfPath);
-
- QString fn = QString::fromUtf8(path.constData(), path.length());
-
- if (client)
- client->sourceNeeded(fn, Client::IncludeGlobal);
- } else if (tk->is(T_ANGLE_STRING_LITERAL) || tk->is(T_STRING_LITERAL)) {
- const QByteArray spell = tokenSpell(*tk);
- const char *beginOfPath = spell.constBegin();
- const char *endOfPath = spell.constEnd();
- const char quote = *beginOfPath;
- if (beginOfPath + 1 != endOfPath && ((quote == '"' && endOfPath[-1] == '"') ||
- (quote == '<' && endOfPath[-1] == '>'))) {
- const QByteArray path = QByteArray::fromRawData(beginOfPath + 1,
- spell.length() - 2);
- QString fn = QString::fromUtf8(path.constData(), path.length());
-
- if (client)
- client->sourceNeeded(fn, Client::IncludeLocal);
- }
- }
-}
-
-void pp::processDefine(TokenIterator firstToken, TokenIterator lastToken)
-{
- RangeLexer tk(firstToken, lastToken);
-
- if (tk.size() < 3)
- return; // nothing to do
-
- ++tk; // skip T_POUND
- ++tk; // skip T_DEFINE
-
- if (tk->isNot(T_IDENTIFIER)) {
- // ### warning expected an `identifier'
- return;
- }
-
- Macro macro;
- macro.name = tokenText(*tk);
- ++tk; // skip T_IDENTIFIER
-
- if (tk->is(T_LPAREN) && ! tk->whitespace) {
- // a function-like macro definition
- macro.function_like = true;
-
- ++tk; // skip T_LPAREN
- if (tk->is(T_IDENTIFIER)) {
- macro.formals.append(tokenText(*tk));
- ++tk; // skip T_IDENTIFIER
- while (tk->is(T_COMMA)) {
- ++tk;// skip T_COMMA
- if (tk->isNot(T_IDENTIFIER))
- break;
- macro.formals.append(tokenText(*tk));
- ++tk; // skip T_IDENTIFIER
- }
- }
-
- if (tk->is(T_DOT_DOT_DOT)) {
- macro.variadics = true;
- ++tk; // skip T_DOT_DOT_DOT
- }
-
- if (tk->isNot(T_RPAREN)) {
- // ### warning expected `)'
- return;
- }
-
- ++tk; // skip T_RPAREN
- }
-
- QByteArray macroId = macro.name;
- const bool isQtWord = isQtReservedWord(macroId);
-
- if (macro.function_like) {
- macroId += '(';
- for (int i = 0; i < macro.formals.size(); ++i) {
- if (i != 0)
- macroId += ", ";
-
- const QByteArray formal = macro.formals.at(i);
- macroId += formal;
- }
- macroId += ')';
- }
-
- if (isQtWord)
- macro.definition = macroId;
- else {
- // ### make me fast!
- const char *startOfDefinition = startOfToken(*tk);
- const char *endOfDefinition = startOfToken(*lastToken);
- macro.definition.append(startOfDefinition,
- endOfDefinition - startOfDefinition);
- macro.definition.replace("\\\n", " ");
- macro.definition.replace('\n', ' ');
- macro.definition = macro.definition.trimmed();
- }
-
- env.bind(macro);
-
- QByteArray macroText;
- macroText.reserve(64);
- macroText += "#define ";
-
- macroText += macroId;
- macroText += ' ';
- macroText += macro.definition;
- macroText += '\n';
-
- client->macroAdded(macroId, macroText);
-}
-
-void pp::processIf(TokenIterator firstToken, TokenIterator lastToken)
-{
- RangeLexer tk(firstToken, lastToken);
-
- ++tk; // skip T_POUND
- ++tk; // skipt `if'
-
- if (testIfLevel()) {
- const char *first = startOfToken(*tk);
- const char *last = startOfToken(*lastToken);
-
- MacroExpander expandCondition (env);
- QByteArray condition;
- condition.reserve(256);
- expandCondition(first, last, &condition);
-
- QVector<Token> tokens = tokenize(condition);
-
- const Value result = evalExpression(tokens.constBegin(),
- tokens.constEnd() - 1,
- condition);
-
- _true_test[iflevel] = ! result.is_zero ();
- _skipping[iflevel] = result.is_zero ();
- }
-}
-
-void pp::processElse(TokenIterator firstToken, TokenIterator lastToken)
-{
- RangeLexer tk(firstToken, lastToken);
-
- if (iflevel == 0 && !skipping ()) {
- // std::cerr << "*** WARNING #else without #if" << std::endl;
- } else if (iflevel > 0 && _skipping[iflevel - 1]) {
- _skipping[iflevel] = true;
- } else {
- _skipping[iflevel] = _true_test[iflevel];
- }
-}
-
-void pp::processElif(TokenIterator firstToken, TokenIterator lastToken)
-{
- RangeLexer tk(firstToken, lastToken);
- ++tk; // skip T_POUND
- ++tk; // skipt `elif'
-
- if (! (iflevel > 0)) {
- // std::cerr << "*** WARNING: " << __FILE__ << __LINE__ << std::endl;
- } else if (iflevel == 0 && !skipping()) {
- // std::cerr << "*** WARNING #else without #if" << std::endl;
- } else if (!_true_test[iflevel] && !_skipping[iflevel - 1]) {
- const Value result = evalExpression(tk.dot(), lastToken, _source);
- _true_test[iflevel] = ! result.is_zero ();
- _skipping[iflevel] = result.is_zero ();
- } else {
- _skipping[iflevel] = true;
- }
-}
-
-void pp::processEndif(TokenIterator, TokenIterator)
-{
- if (iflevel == 0 && !skipping()) {
- // std::cerr << "*** WARNING #endif without #if" << std::endl;
- } else {
- _skipping[iflevel] = false;
- _true_test[iflevel] = false;
-
- --iflevel;
- }
-}
-
-void pp::processIfdef(bool checkUndefined,
- TokenIterator firstToken, TokenIterator lastToken)
-{
- RangeLexer tk(firstToken, lastToken);
-
- ++tk; // skip T_POUND
- ++tk; // skip `ifdef'
- if (testIfLevel()) {
- if (tk->is(T_IDENTIFIER)) {
- const QByteArray macroName = tokenSpell(*tk);
- bool value = env.resolve(macroName) != 0 || env.isBuiltinMacro(macroName);
-
- if (checkUndefined)
- value = ! value;
-
- _true_test[iflevel] = value;
- _skipping [iflevel] = ! value;
- }
- }
-}
-
-void pp::processUndef(TokenIterator firstToken, TokenIterator lastToken)
-{
- RangeLexer tk(firstToken, lastToken);
-
- ++tk; // skip T_POUND
- ++tk; // skip `undef'
-
- if (tk->is(T_IDENTIFIER)) {
- const QByteArray macroName = tokenText(*tk);
- env.remove(macroName);
-
- QByteArray macroText;
- macroText += "#undef ";
- macroText += macroName;
- macroText += '\n';
- client->macroAdded(macroName, macroText);
- }
-}
-
-void pp::resetIfLevel ()
-{
- iflevel = 0;
- _skipping[iflevel] = false;
- _true_test[iflevel] = false;
-}
-
-pp::PP_DIRECTIVE_TYPE pp::classifyDirective (const QByteArray &__directive) const
-{
- switch (__directive.size())
- {
- case 2:
- if (__directive[0] == 'i' && __directive[1] == 'f')
- return PP_IF;
- break;
-
- case 4:
- if (__directive[0] == 'e' && __directive == "elif")
- return PP_ELIF;
- else if (__directive[0] == 'e' && __directive == "else")
- return PP_ELSE;
- break;
-
- case 5:
- if (__directive[0] == 'i' && __directive == "ifdef")
- return PP_IFDEF;
- else if (__directive[0] == 'u' && __directive == "undef")
- return PP_UNDEF;
- else if (__directive[0] == 'e' && __directive == "endif")
- return PP_ENDIF;
- break;
-
- case 6:
- if (__directive[0] == 'i' && __directive == "ifndef")
- return PP_IFNDEF;
- else if (__directive[0] == 'd' && __directive == "define")
- return PP_DEFINE;
- break;
-
- case 7:
- if (__directive[0] == 'i' && __directive == "include")
- return PP_INCLUDE;
- break;
-
- case 12:
- if (__directive[0] == 'i' && __directive == "include_next")
- return PP_INCLUDE_NEXT;
- break;
-
- default:
- break;
- }
-
- return PP_UNKNOWN_DIRECTIVE;
-}
-
-bool pp::testIfLevel()
-{
- const bool result = !_skipping[iflevel++];
- _skipping[iflevel] = _skipping[iflevel - 1];
- _true_test[iflevel] = false;
- return result;
-}
-
-int pp::skipping() const
-{ return _skipping[iflevel]; }
-
-Value pp::evalExpression(TokenIterator firstToken, TokenIterator lastToken,
- const QByteArray &source) const
-{
- ExpressionEvaluator eval(&env);
- const Value result = eval(firstToken, lastToken, source);
- return result;
-}
-
-bool pp::isQtReservedWord (const QByteArray &macroId) const
-{
- const int size = macroId.size();
- if (size == 9 && macroId.at(0) == 'Q' && macroId == "Q_SIGNALS")
- return true;
- else if (size == 7 && macroId.at(0) == 'Q' && macroId == "Q_SLOTS")
- return true;
- else if (size == 6 && macroId.at(0) == 'S' && macroId == "SIGNAL")
- return true;
- else if (size == 4 && macroId.at(0) == 'S' && macroId == "SLOT")
- return true;
- else if (size == 7 && macroId.at(0) == 's' && macroId == "signals")
- return true;
- else if (size == 5 && macroId.at(0) == 's' && macroId == "slots")
- return true;
- return false;
-}