From ebe17889f41c56364c52b36430fbe1c365198972 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 2 Mar 2009 19:03:07 +0100 Subject: [PATCH] Some refactoring of the preprocessor, it'll simplify my next commits. --- src/libs/cplusplus/pp-engine.cpp | 93 ++++--- src/libs/cplusplus/pp-engine.h | 318 ++++++++++++----------- src/libs/cplusplus/pp-macro-expander.cpp | 10 +- src/libs/cplusplus/pp-macro-expander.h | 3 + 4 files changed, 228 insertions(+), 196 deletions(-) diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index c560451326f..ec15c027f10 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -50,6 +50,8 @@ #include #include +#include + #include #include @@ -450,7 +452,8 @@ private: Preprocessor::Preprocessor(Client *client, Environment &env) : client(client), env(env), - expand(env) + _expand(env), + _result(0) { resetIfLevel (); } @@ -501,13 +504,23 @@ void Preprocessor::preprocess(const QByteArray &filename, QByteArray *result) { const QByteArray previousFile = env.currentFile; + env.currentFile = filename; - preprocess(source, result); - env.currentFile = previousFile; } +void Preprocessor::expand(const QByteArray &source, QByteArray *result) +{ + _expand(source, result); +} + +void Preprocessor::expand(const char *first, const char *last, QByteArray *result) +{ + const QByteArray source = QByteArray::fromRawData(first, last - first); + return expand(source, result); +} + Preprocessor::State Preprocessor::createStateFromSource(const QByteArray &source) const { State state; @@ -525,6 +538,9 @@ Preprocessor::State Preprocessor::createStateFromSource(const QByteArray &source void Preprocessor::preprocess(const QByteArray &source, QByteArray *result) { + QByteArray *previousResult = _result; + _result = result; + pushState(createStateFromSource(source)); const unsigned previousCurrentLine = env.currentLine; @@ -533,16 +549,16 @@ void Preprocessor::preprocess(const QByteArray &source, QByteArray *result) 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.currentFile); - result->append('"'); - result->append('\n'); + _result->append("\n# "); + _result->append(QByteArray::number(_dot->lineno)); + _result->append(' '); + _result->append('"'); + _result->append(env.currentFile); + _result->append('"'); + _result->append('\n'); } else { for (unsigned i = env.currentLine; i < _dot->lineno; ++i) - result->append('\n'); + _result->append('\n'); } env.currentLine = _dot->lineno; } @@ -580,12 +596,12 @@ void Preprocessor::preprocess(const QByteArray &source, QByteArray *result) } while (_dot->isNot(T_EOF_SYMBOL) && (_dot->joined || ! _dot->newline)); } else { if (_dot->joined) - result->append("\\\n"); + _result->append("\\\n"); else if (_dot->whitespace) - result->append(' '); + _result->append(' '); if (_dot->isNot(T_IDENTIFIER)) { - result->append(tokenSpell(*_dot)); + _result->append(tokenSpell(*_dot)); ++_dot; } else { const TokenIterator identifierToken = _dot; @@ -599,7 +615,7 @@ void Preprocessor::preprocess(const QByteArray &source, QByteArray *result) client->startExpandingMacro(identifierToken->offset, trivial, spell); - expand(spell.constBegin(), spell.constEnd(), result); + expand(spell, _result); if (client) client->stopExpandingMacro(_dot->offset, trivial); @@ -609,7 +625,7 @@ void Preprocessor::preprocess(const QByteArray &source, QByteArray *result) Macro *m = env.resolve(spell); if (! m) { - result->append(spell); + _result->append(spell); } else { if (! m->isFunctionLike()) { if (_dot->isNot(T_LPAREN)) { @@ -618,7 +634,7 @@ void Preprocessor::preprocess(const QByteArray &source, QByteArray *result) *m, spell); m->setHidden(true); - expand(m->definition(), result); + expand(m->definition(), _result); m->setHidden(false); if (client) @@ -650,7 +666,7 @@ void Preprocessor::preprocess(const QByteArray &source, QByteArray *result) popState(); if (! m) { - result->append(tmp); + _result->append(tmp); continue; } } @@ -659,7 +675,7 @@ void Preprocessor::preprocess(const QByteArray &source, QByteArray *result) // collect the actual arguments if (_dot->isNot(T_LPAREN)) { // ### warnng expected T_LPAREN - result->append(m->name()); + _result->append(m->name()); continue; } @@ -689,7 +705,7 @@ void Preprocessor::preprocess(const QByteArray &source, QByteArray *result) *m, text); } - expand(beginOfText, endOfText, result); + expand(beginOfText, endOfText, _result); if (client) client->stopExpandingMacro(_dot->offset, *m); @@ -701,6 +717,7 @@ void Preprocessor::preprocess(const QByteArray &source, QByteArray *result) popState(); env.currentLine = previousCurrentLine; + _result = previousResult; } const char *Preprocessor::startOfToken(const Token &token) const @@ -788,9 +805,8 @@ QVector Preprocessor::tokenize(const QByteArray &text) const return tokens; } -void Preprocessor::processInclude(bool, - TokenIterator firstToken, TokenIterator lastToken, - bool acceptMacros) +void Preprocessor::processInclude(bool, TokenIterator firstToken, + TokenIterator lastToken, bool acceptMacros) { RangeLexer tk(firstToken, lastToken); ++tk; // skip T_POUND @@ -1011,7 +1027,8 @@ void Preprocessor::processEndif(TokenIterator, TokenIterator) } void Preprocessor::processIfdef(bool checkUndefined, - TokenIterator firstToken, TokenIterator lastToken) + TokenIterator firstToken, + TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); @@ -1054,47 +1071,47 @@ void Preprocessor::resetIfLevel () _true_test[iflevel] = false; } -Preprocessor::PP_DIRECTIVE_TYPE Preprocessor::classifyDirective (const QByteArray &__directive) const +Preprocessor::PP_DIRECTIVE_TYPE Preprocessor::classifyDirective(const QByteArray &directive) const { - switch (__directive.size()) + switch (directive.size()) { case 2: - if (__directive[0] == 'i' && __directive[1] == 'f') + if (directive[0] == 'i' && directive[1] == 'f') return PP_IF; break; case 4: - if (__directive[0] == 'e' && __directive == "elif") + if (directive[0] == 'e' && directive == "elif") return PP_ELIF; - else if (__directive[0] == 'e' && __directive == "else") + else if (directive[0] == 'e' && directive == "else") return PP_ELSE; break; case 5: - if (__directive[0] == 'i' && __directive == "ifdef") + if (directive[0] == 'i' && directive == "ifdef") return PP_IFDEF; - else if (__directive[0] == 'u' && __directive == "undef") + else if (directive[0] == 'u' && directive == "undef") return PP_UNDEF; - else if (__directive[0] == 'e' && __directive == "endif") + else if (directive[0] == 'e' && directive == "endif") return PP_ENDIF; break; case 6: - if (__directive[0] == 'i' && __directive == "ifndef") + if (directive[0] == 'i' && directive == "ifndef") return PP_IFNDEF; - else if (__directive[0] == 'i' && __directive == "import") + else if (directive[0] == 'i' && directive == "import") return PP_IMPORT; - else if (__directive[0] == 'd' && __directive == "define") + else if (directive[0] == 'd' && directive == "define") return PP_DEFINE; break; case 7: - if (__directive[0] == 'i' && __directive == "include") + if (directive[0] == 'i' && directive == "include") return PP_INCLUDE; break; case 12: - if (__directive[0] == 'i' && __directive == "include_next") + if (directive[0] == 'i' && directive == "include_next") return PP_INCLUDE_NEXT; break; @@ -1117,7 +1134,7 @@ int Preprocessor::skipping() const { return _skipping[iflevel]; } Value Preprocessor::evalExpression(TokenIterator firstToken, TokenIterator lastToken, - const QByteArray &source) const + const QByteArray &source) const { ExpressionEvaluator eval(&env); const Value result = eval(firstToken, lastToken, source); diff --git a/src/libs/cplusplus/pp-engine.h b/src/libs/cplusplus/pp-engine.h index 706983dd120..b07e58187b7 100644 --- a/src/libs/cplusplus/pp-engine.h +++ b/src/libs/cplusplus/pp-engine.h @@ -60,174 +60,180 @@ namespace CPlusPlus { namespace CPlusPlus { - struct Value +struct Value +{ + enum Kind { + Kind_Long, + Kind_ULong, + }; + + Kind kind; + + union { + long l; + unsigned long ul; + }; + + + Value() + : kind(Kind_Long), l(0) + { } + + inline bool is_ulong () const + { return kind == Kind_ULong; } + + inline void set_ulong (unsigned long v) { - enum Kind { - Kind_Long, - Kind_ULong, - }; + ul = v; + kind = Kind_ULong; + } - Kind kind; + inline void set_long (long v) + { + l = v; + kind = Kind_Long; + } - union { - long l; - unsigned long ul; - }; - - - Value() - : kind(Kind_Long), l(0) - { } - - inline bool is_ulong () const - { return kind == Kind_ULong; } - - inline void set_ulong (unsigned long v) - { - ul = v; - kind = Kind_ULong; - } - - inline void set_long (long v) - { - l = v; - kind = Kind_Long; - } - - inline bool is_zero () const - { return l == 0; } + inline bool is_zero () const + { return l == 0; } #define PP_DEFINE_BIN_OP(name, op) \ - inline Value operator op(const Value &other) const \ - { \ - Value v = *this; \ - if (v.is_ulong () || other.is_ulong ()) \ - v.set_ulong (v.ul op other.ul); \ - else \ - v.set_long (v.l op other.l); \ - return v; \ - } + inline Value operator op(const Value &other) const \ + { \ + Value v = *this; \ + if (v.is_ulong () || other.is_ulong ()) \ + v.set_ulong (v.ul op other.ul); \ + else \ + v.set_long (v.l op other.l); \ + return v; \ + } - PP_DEFINE_BIN_OP(op_add, +) - PP_DEFINE_BIN_OP(op_sub, -) - PP_DEFINE_BIN_OP(op_mult, *) - PP_DEFINE_BIN_OP(op_div, /) - PP_DEFINE_BIN_OP(op_mod, %) - PP_DEFINE_BIN_OP(op_lhs, <<) - PP_DEFINE_BIN_OP(op_rhs, >>) - PP_DEFINE_BIN_OP(op_lt, <) - PP_DEFINE_BIN_OP(op_gt, >) - PP_DEFINE_BIN_OP(op_le, <=) - PP_DEFINE_BIN_OP(op_ge, >=) - PP_DEFINE_BIN_OP(op_eq, ==) - PP_DEFINE_BIN_OP(op_ne, !=) - PP_DEFINE_BIN_OP(op_bit_and, &) - PP_DEFINE_BIN_OP(op_bit_or, |) - PP_DEFINE_BIN_OP(op_bit_xor, ^) - PP_DEFINE_BIN_OP(op_and, &&) - PP_DEFINE_BIN_OP(op_or, ||) + PP_DEFINE_BIN_OP(op_add, +) + PP_DEFINE_BIN_OP(op_sub, -) + PP_DEFINE_BIN_OP(op_mult, *) + PP_DEFINE_BIN_OP(op_div, /) + PP_DEFINE_BIN_OP(op_mod, %) + PP_DEFINE_BIN_OP(op_lhs, <<) + PP_DEFINE_BIN_OP(op_rhs, >>) + PP_DEFINE_BIN_OP(op_lt, <) + PP_DEFINE_BIN_OP(op_gt, >) + PP_DEFINE_BIN_OP(op_le, <=) + PP_DEFINE_BIN_OP(op_ge, >=) + PP_DEFINE_BIN_OP(op_eq, ==) + PP_DEFINE_BIN_OP(op_ne, !=) + PP_DEFINE_BIN_OP(op_bit_and, &) + PP_DEFINE_BIN_OP(op_bit_or, |) + PP_DEFINE_BIN_OP(op_bit_xor, ^) + PP_DEFINE_BIN_OP(op_and, &&) + PP_DEFINE_BIN_OP(op_or, ||) #undef PP_DEFINE_BIN_OP - }; +}; - class CPLUSPLUS_EXPORT Preprocessor +class CPLUSPLUS_EXPORT Preprocessor +{ +public: + Preprocessor(Client *client, Environment &env); + + QByteArray operator()(const QByteArray &filename, + const QByteArray &source); + + QByteArray operator()(const QByteArray &source); + +private: + enum { MAX_LEVEL = 512 }; + + enum PP_DIRECTIVE_TYPE { - Client *client; - Environment &env; - MacroExpander expand; - - enum { MAX_LEVEL = 512 }; - - bool _skipping[MAX_LEVEL]; // ### move in state - bool _true_test[MAX_LEVEL]; // ### move in state - int iflevel; // ### move in state - - enum PP_DIRECTIVE_TYPE - { - PP_UNKNOWN_DIRECTIVE, - PP_DEFINE, - PP_IMPORT, - PP_INCLUDE, - PP_INCLUDE_NEXT, - PP_ELIF, - PP_ELSE, - PP_ENDIF, - PP_IF, - PP_IFDEF, - PP_IFNDEF, - PP_UNDEF - }; - - typedef const CPlusPlus::Token *TokenIterator; - - struct State { - QByteArray source; - QVector tokens; - TokenIterator dot; - }; - - QList _savedStates; - - State state() const; - void pushState(const State &state); - void popState(); - - QByteArray _source; - QVector _tokens; - TokenIterator _dot; - - State createStateFromSource(const QByteArray &source) const; - - public: - Preprocessor(Client *client, Environment &env); - - QByteArray operator()(const QByteArray &filename, - const QByteArray &source); - - QByteArray operator()(const QByteArray &source); - - private: - void preprocess(const QByteArray &filename, - const QByteArray &source, - QByteArray *result); - - void preprocess(const QByteArray &source, - QByteArray *result); - - void resetIfLevel(); - bool testIfLevel(); - int skipping() const; - - PP_DIRECTIVE_TYPE classifyDirective(const QByteArray &directive) const; - - Value evalExpression(TokenIterator firstToken, - TokenIterator lastToken, - const QByteArray &source) const; - - QVector tokenize(const QByteArray &text) const; - - const char *startOfToken(const CPlusPlus::Token &token) const; - const char *endOfToken(const CPlusPlus::Token &token) const; - - QByteArray tokenSpell(const CPlusPlus::Token &token) const; - QByteArray tokenText(const CPlusPlus::Token &token) const; // does a deep copy - - void processDirective(TokenIterator dot, TokenIterator lastToken); - void processInclude(bool skipCurrentPath, - TokenIterator dot, TokenIterator lastToken, - bool acceptMacros = true); - void processDefine(TokenIterator dot, TokenIterator lastToken); - void processIf(TokenIterator dot, TokenIterator lastToken); - void processElse(TokenIterator dot, TokenIterator lastToken); - void processElif(TokenIterator dot, TokenIterator lastToken); - void processEndif(TokenIterator dot, TokenIterator lastToken); - void processIfdef(bool checkUndefined, - TokenIterator dot, TokenIterator lastToken); - void processUndef(TokenIterator dot, TokenIterator lastToken); - - bool isQtReservedWord(const QByteArray &name) const; + PP_UNKNOWN_DIRECTIVE, + PP_DEFINE, + PP_IMPORT, + PP_INCLUDE, + PP_INCLUDE_NEXT, + PP_ELIF, + PP_ELSE, + PP_ENDIF, + PP_IF, + PP_IFDEF, + PP_IFNDEF, + PP_UNDEF }; + typedef const CPlusPlus::Token *TokenIterator; + + struct State { + QByteArray source; + QVector tokens; + TokenIterator dot; + }; + + void preprocess(const QByteArray &filename, + const QByteArray &source, + QByteArray *result); + + void preprocess(const QByteArray &source, + QByteArray *result); + + void expand(const QByteArray &source, QByteArray *result); + void expand(const char *first, const char *last, QByteArray *result); + + void resetIfLevel(); + bool testIfLevel(); + int skipping() const; + + PP_DIRECTIVE_TYPE classifyDirective(const QByteArray &directive) const; + + Value evalExpression(TokenIterator firstToken, + TokenIterator lastToken, + const QByteArray &source) const; + + QVector tokenize(const QByteArray &text) const; + + const char *startOfToken(const CPlusPlus::Token &token) const; + const char *endOfToken(const CPlusPlus::Token &token) const; + + QByteArray tokenSpell(const CPlusPlus::Token &token) const; + QByteArray tokenText(const CPlusPlus::Token &token) const; // does a deep copy + + void processDirective(TokenIterator dot, TokenIterator lastToken); + void processInclude(bool skipCurrentPath, + TokenIterator dot, TokenIterator lastToken, + bool acceptMacros = true); + void processDefine(TokenIterator dot, TokenIterator lastToken); + void processIf(TokenIterator dot, TokenIterator lastToken); + void processElse(TokenIterator dot, TokenIterator lastToken); + void processElif(TokenIterator dot, TokenIterator lastToken); + void processEndif(TokenIterator dot, TokenIterator lastToken); + void processIfdef(bool checkUndefined, + TokenIterator dot, TokenIterator lastToken); + void processUndef(TokenIterator dot, TokenIterator lastToken); + + bool isQtReservedWord(const QByteArray &name) const; + + State state() const; + void pushState(const State &state); + void popState(); + + State createStateFromSource(const QByteArray &source) const; + +private: + Client *client; + Environment &env; + MacroExpander _expand; + + bool _skipping[MAX_LEVEL]; // ### move in state + bool _true_test[MAX_LEVEL]; // ### move in state + int iflevel; // ### move in state + + QList _savedStates; + + QByteArray _source; + QVector _tokens; + TokenIterator _dot; + + QByteArray *_result; +}; + } // namespace CPlusPlus #endif // CPLUSPLUS_PP_ENGINE_H diff --git a/src/libs/cplusplus/pp-macro-expander.cpp b/src/libs/cplusplus/pp-macro-expander.cpp index a56f782b263..0502aef4a4d 100644 --- a/src/libs/cplusplus/pp-macro-expander.cpp +++ b/src/libs/cplusplus/pp-macro-expander.cpp @@ -69,8 +69,14 @@ const QByteArray *MacroExpander::resolve_formal(const QByteArray &__name) return 0; } -const char *MacroExpander::operator () (const char *__first, const char *__last, - QByteArray *__result) +const char *MacroExpander::operator()(const char *first, const char *last, + QByteArray *result) +{ + return expand(first, last, result); +} + +const char *MacroExpander::expand(const char *__first, const char *__last, + QByteArray *__result) { generated_lines = 0; __first = skip_blanks (__first, __last); diff --git a/src/libs/cplusplus/pp-macro-expander.h b/src/libs/cplusplus/pp-macro-expander.h index c38ac384b44..25d22aef7b1 100644 --- a/src/libs/cplusplus/pp-macro-expander.h +++ b/src/libs/cplusplus/pp-macro-expander.h @@ -88,6 +88,9 @@ namespace CPlusPlus { QByteArray *result) { return operator()(source.constBegin(), source.constEnd(), result); } + const char *expand(const char *first, const char *last, + QByteArray *result); + const char *skip_argument_variadics (const QVector &actuals, Macro *macro, const char *first, const char *last);