| 
									
										
										
										
											2009-03-20 14:57:12 +01:00
										 |  |  | /**************************************************************************
 | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-01-11 16:28:15 +01:00
										 |  |  | ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** Contact: Nokia Corporation (info@qt.nokia.com) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** GNU Lesser General Public License Usage | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** This file may be used under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  | ** License version 2.1 as published by the Free Software Foundation and | 
					
						
							|  |  |  | ** appearing in the file LICENSE.LGPL included in the packaging of this file. | 
					
						
							|  |  |  | ** Please review the following information to ensure the GNU Lesser General | 
					
						
							|  |  |  | ** Public License version 2.1 requirements will be met: | 
					
						
							|  |  |  | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** In addition, as a special exception, Nokia gives you certain additional | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** rights. These rights are described in the Nokia Qt LGPL Exception | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** Other Usage | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** Alternatively, this file may be used in accordance with the terms and | 
					
						
							|  |  |  | ** conditions contained in a signed written agreement between you and Nokia. | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** If you have questions regarding the use of this file, please contact | 
					
						
							| 
									
										
										
										
											2011-05-06 15:05:37 +02:00
										 |  |  | ** Nokia at info@qt.nokia.com. | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | **************************************************************************/ | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |   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"
 | 
					
						
							| 
									
										
										
										
											2009-05-15 16:01:02 +02:00
										 |  |  | #include "pp-cctype.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-02 15:08:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <Lexer.h>
 | 
					
						
							|  |  |  | #include <Token.h>
 | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  | #include <Literals.h>
 | 
					
						
							| 
									
										
										
										
											2009-03-19 18:15:33 +01:00
										 |  |  | #include <cctype>
 | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <QtDebug>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:57:59 +01:00
										 |  |  | #include <algorithm>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  | namespace CPlusPlus { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct Value | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     enum Kind { | 
					
						
							|  |  |  |         Kind_Long, | 
					
						
							| 
									
										
										
										
											2009-07-27 21:47:03 +02:00
										 |  |  |         Kind_ULong | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         ul = v; | 
					
						
							|  |  |  |         kind = Kind_ULong; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     inline void set_long (long v) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         l = v; | 
					
						
							|  |  |  |         kind = Kind_Long; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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; \ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-04 09:52:39 +01:00
										 |  |  | } // namespace CPlusPlus
 | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | using namespace CPlusPlus; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-12 15:24:45 +01:00
										 |  |  | Macro *macroDefinition(QByteArray name, unsigned offset, Environment *env, Client *client) | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     Macro *m = env->resolve(name); | 
					
						
							|  |  |  |     if (client) { | 
					
						
							|  |  |  |         if (m) | 
					
						
							|  |  |  |             client->passedMacroDefinitionCheck(offset, *m); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             client->failedMacroDefinitionCheck(offset, name); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-03-12 15:24:45 +01:00
										 |  |  |     return m; | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 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: | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |     ExpressionEvaluator(Client *client, Environment *env) | 
					
						
							|  |  |  |         : client(client), env(env), _lex(0) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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, | 
					
						
							| 
									
										
										
										
											2009-07-27 21:47:03 +02:00
										 |  |  |                                                         (*_lex)->f.length); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return text; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |     inline void process_expression() | 
					
						
							|  |  |  |     { process_constant_expression(); } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |     void process_primary() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-07-10 15:44:47 +02:00
										 |  |  |         if ((*_lex)->is(T_NUMERIC_LITERAL)) { | 
					
						
							| 
									
										
										
										
											2008-12-10 10:47:26 +01:00
										 |  |  |             int base = 10; | 
					
						
							| 
									
										
										
										
											2010-04-29 12:33:05 +02:00
										 |  |  |             QByteArray spell = tokenSpell(); | 
					
						
							| 
									
										
										
										
											2008-12-10 10:47:26 +01:00
										 |  |  |             if (spell.at(0) == '0') { | 
					
						
							|  |  |  |                 if (spell.size() > 1 && (spell.at(1) == 'x' || spell.at(1) == 'X')) | 
					
						
							|  |  |  |                     base = 16; | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     base = 8; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-04-29 12:33:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             while (! spell.isEmpty()) { | 
					
						
							|  |  |  |                 const QChar ch = spell.at(spell.length() - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (! (ch == QLatin1Char('u') || ch == QLatin1Char('U') || | 
					
						
							|  |  |  |                        ch == QLatin1Char('l') || ch == QLatin1Char('L'))) | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 spell.chop(1); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             _value.set_long(spell.toLong(0, base)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             ++(*_lex); | 
					
						
							|  |  |  |         } else if (isTokenDefined()) { | 
					
						
							|  |  |  |             ++(*_lex); | 
					
						
							|  |  |  |             if ((*_lex)->is(T_IDENTIFIER)) { | 
					
						
							| 
									
										
										
										
											2010-03-12 15:24:45 +01:00
										 |  |  |                 _value.set_long(macroDefinition(tokenSpell(), (*_lex)->offset, env, client) != 0); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 ++(*_lex); | 
					
						
							|  |  |  |             } else if ((*_lex)->is(T_LPAREN)) { | 
					
						
							|  |  |  |                 ++(*_lex); | 
					
						
							|  |  |  |                 if ((*_lex)->is(T_IDENTIFIER)) { | 
					
						
							| 
									
										
										
										
											2010-03-12 15:24:45 +01:00
										 |  |  |                     _value.set_long(macroDefinition(tokenSpell(), (*_lex)->offset, env, client) != 0); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     ++(*_lex); | 
					
						
							|  |  |  |                     if ((*_lex)->is(T_RPAREN)) { | 
					
						
							|  |  |  |                         ++(*_lex); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if ((*_lex)->is(T_IDENTIFIER)) { | 
					
						
							|  |  |  |             _value.set_long(0); | 
					
						
							|  |  |  |             ++(*_lex); | 
					
						
							|  |  |  |         } else if ((*_lex)->is(T_MINUS)) { | 
					
						
							|  |  |  |             ++(*_lex); | 
					
						
							|  |  |  |             process_primary(); | 
					
						
							|  |  |  |             _value.set_long(- _value.l); | 
					
						
							|  |  |  |         } else if ((*_lex)->is(T_PLUS)) { | 
					
						
							|  |  |  |             ++(*_lex); | 
					
						
							|  |  |  |             process_primary(); | 
					
						
							| 
									
										
										
										
											2010-04-27 09:55:19 +02:00
										 |  |  |         } else if ((*_lex)->is(T_TILDE)) { | 
					
						
							|  |  |  |             ++(*_lex); | 
					
						
							|  |  |  |             process_primary(); | 
					
						
							|  |  |  |             _value.set_long(~ _value.l); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } else if ((*_lex)->is(T_EXCLAIM)) { | 
					
						
							|  |  |  |             ++(*_lex); | 
					
						
							|  |  |  |             process_primary(); | 
					
						
							|  |  |  |             _value.set_long(_value.is_zero()); | 
					
						
							|  |  |  |         } else if ((*_lex)->is(T_LPAREN)) { | 
					
						
							|  |  |  |             ++(*_lex); | 
					
						
							|  |  |  |             process_expression(); | 
					
						
							|  |  |  |             if ((*_lex)->is(T_RPAREN)) | 
					
						
							|  |  |  |                 ++(*_lex); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |     Value process_expression_with_operator_precedence(const Value &lhs, int minPrecedence) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |         Value result = lhs; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |         while (precedence((*_lex)->kind()) >= minPrecedence) { | 
					
						
							|  |  |  |             const int oper = (*_lex)->kind(); | 
					
						
							|  |  |  |             const int operPrecedence = precedence(oper); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             ++(*_lex); | 
					
						
							|  |  |  |             process_primary(); | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |             Value rhs = _value; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |             for (int LA_token_kind = (*_lex)->kind(), LA_precedence = precedence(LA_token_kind); | 
					
						
							| 
									
										
										
										
											2010-01-28 17:05:13 +01:00
										 |  |  |                     LA_precedence > operPrecedence && isBinaryOperator(LA_token_kind); | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |                     LA_token_kind = (*_lex)->kind(), LA_precedence = precedence(LA_token_kind)) { | 
					
						
							|  |  |  |                 rhs = process_expression_with_operator_precedence(rhs, LA_precedence); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |             result = evaluate_expression(oper, result, rhs); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |         return result; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |     void process_constant_expression() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |         process_primary(); | 
					
						
							|  |  |  |         _value = process_expression_with_operator_precedence(_value, precedence(T_PIPE_PIPE)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |         if ((*_lex)->is(T_QUESTION)) { | 
					
						
							|  |  |  |             const Value cond = _value; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             ++(*_lex); | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |             process_constant_expression(); | 
					
						
							|  |  |  |             Value left = _value, right; | 
					
						
							|  |  |  |             if ((*_lex)->is(T_COLON)) { | 
					
						
							|  |  |  |                 ++(*_lex); | 
					
						
							|  |  |  |                 process_constant_expression(); | 
					
						
							|  |  |  |                 right = _value; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             _value = ! cond.is_zero() ? left : right; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  | private: | 
					
						
							|  |  |  |     inline int precedence(int tokenKind) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |         switch (tokenKind) { | 
					
						
							|  |  |  |         case T_PIPE_PIPE:       return 0; | 
					
						
							|  |  |  |         case T_AMPER_AMPER:     return 1; | 
					
						
							|  |  |  |         case T_PIPE:            return 2; | 
					
						
							|  |  |  |         case T_CARET:           return 3; | 
					
						
							|  |  |  |         case T_AMPER:           return 4; | 
					
						
							|  |  |  |         case T_EQUAL_EQUAL: | 
					
						
							|  |  |  |         case T_EXCLAIM_EQUAL:   return 5; | 
					
						
							|  |  |  |         case T_GREATER: | 
					
						
							|  |  |  |         case T_LESS: | 
					
						
							|  |  |  |         case T_LESS_EQUAL: | 
					
						
							|  |  |  |         case T_GREATER_EQUAL:   return 6; | 
					
						
							|  |  |  |         case T_LESS_LESS: | 
					
						
							|  |  |  |         case T_GREATER_GREATER: return 7; | 
					
						
							|  |  |  |         case T_PLUS: | 
					
						
							|  |  |  |         case T_MINUS:           return 8; | 
					
						
							|  |  |  |         case T_STAR: | 
					
						
							|  |  |  |         case T_SLASH: | 
					
						
							|  |  |  |         case T_PERCENT:         return 9; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             return -1; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |     static inline bool isBinaryOperator(int tokenKind) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |         switch (tokenKind) { | 
					
						
							|  |  |  |         case T_PIPE_PIPE: | 
					
						
							|  |  |  |         case T_AMPER_AMPER: | 
					
						
							|  |  |  |         case T_PIPE: | 
					
						
							|  |  |  |         case T_CARET: | 
					
						
							|  |  |  |         case T_AMPER: | 
					
						
							|  |  |  |         case T_EQUAL_EQUAL: | 
					
						
							|  |  |  |         case T_EXCLAIM_EQUAL: | 
					
						
							|  |  |  |         case T_GREATER: | 
					
						
							|  |  |  |         case T_LESS: | 
					
						
							|  |  |  |         case T_LESS_EQUAL: | 
					
						
							|  |  |  |         case T_GREATER_EQUAL: | 
					
						
							|  |  |  |         case T_LESS_LESS: | 
					
						
							|  |  |  |         case T_GREATER_GREATER: | 
					
						
							|  |  |  |         case T_PLUS: | 
					
						
							|  |  |  |         case T_MINUS: | 
					
						
							|  |  |  |         case T_STAR: | 
					
						
							|  |  |  |         case T_SLASH: | 
					
						
							|  |  |  |         case T_PERCENT: | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |         default: | 
					
						
							|  |  |  |             return false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |     static inline Value evaluate_expression(int tokenKind, const Value &lhs, const Value &rhs) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-01-28 15:22:36 +01:00
										 |  |  |         switch (tokenKind) { | 
					
						
							|  |  |  |         case T_PIPE_PIPE:       return lhs || rhs; | 
					
						
							|  |  |  |         case T_AMPER_AMPER:     return lhs && rhs; | 
					
						
							|  |  |  |         case T_PIPE:            return lhs | rhs; | 
					
						
							|  |  |  |         case T_CARET:           return lhs ^ rhs; | 
					
						
							|  |  |  |         case T_AMPER:           return lhs & rhs; | 
					
						
							|  |  |  |         case T_EQUAL_EQUAL:     return lhs == rhs; | 
					
						
							|  |  |  |         case T_EXCLAIM_EQUAL:   return lhs != rhs; | 
					
						
							|  |  |  |         case T_GREATER:         return lhs > rhs; | 
					
						
							|  |  |  |         case T_LESS:            return lhs < rhs; | 
					
						
							|  |  |  |         case T_LESS_EQUAL:      return lhs <= rhs; | 
					
						
							|  |  |  |         case T_GREATER_EQUAL:   return lhs >= rhs; | 
					
						
							|  |  |  |         case T_LESS_LESS:       return lhs << rhs; | 
					
						
							|  |  |  |         case T_GREATER_GREATER: return lhs >> rhs; | 
					
						
							|  |  |  |         case T_PLUS:            return lhs + rhs; | 
					
						
							|  |  |  |         case T_MINUS:           return lhs - rhs; | 
					
						
							|  |  |  |         case T_STAR:            return lhs * rhs; | 
					
						
							|  |  |  |         case T_SLASH:           return rhs.is_zero() ? Value() : lhs / rhs; | 
					
						
							|  |  |  |         case T_PERCENT:         return rhs.is_zero() ? Value() : lhs % rhs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             return Value(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |     Client *client; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     Environment *env; | 
					
						
							|  |  |  |     QByteArray source; | 
					
						
							|  |  |  |     RangeLexer *_lex; | 
					
						
							|  |  |  |     Value _value; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // end of anonymous namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  | Preprocessor::Preprocessor(Client *client, Environment *env) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     : client(client), | 
					
						
							|  |  |  |       env(env), | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |       _expand(env), | 
					
						
							| 
									
										
										
										
											2009-10-21 16:18:34 +02:00
										 |  |  |       _skipping(MAX_LEVEL), | 
					
						
							| 
									
										
										
										
											2009-10-21 16:20:45 +02:00
										 |  |  |       _trueTest(MAX_LEVEL), | 
					
						
							| 
									
										
										
										
											2009-10-21 16:54:59 +02:00
										 |  |  |       _dot(_tokens.end()), | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  |       _result(0), | 
					
						
							| 
									
										
										
										
											2009-07-04 20:54:31 +02:00
										 |  |  |       _markGeneratedTokens(false), | 
					
						
							| 
									
										
										
										
											2011-08-23 14:05:47 +02:00
										 |  |  |       _expandMacros(true), | 
					
						
							|  |  |  |       _keepComments(false) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     resetIfLevel (); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | void Preprocessor::pushState(const State &s) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     _savedStates.append(state()); | 
					
						
							|  |  |  |     _source = s.source; | 
					
						
							|  |  |  |     _tokens = s.tokens; | 
					
						
							|  |  |  |     _dot = s.dot; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | Preprocessor::State Preprocessor::state() const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     State state; | 
					
						
							|  |  |  |     state.source = _source; | 
					
						
							|  |  |  |     state.tokens = _tokens; | 
					
						
							|  |  |  |     state.dot = _dot; | 
					
						
							|  |  |  |     return state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | void Preprocessor::popState() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     const State &state = _savedStates.last(); | 
					
						
							|  |  |  |     _source = state.source; | 
					
						
							|  |  |  |     _tokens = state.tokens; | 
					
						
							|  |  |  |     _dot = state.dot; | 
					
						
							|  |  |  |     _savedStates.removeLast(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-15 15:38:20 +02:00
										 |  |  | QByteArray Preprocessor::operator()(const QString &fileName, const QString &source) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QString previousOriginalSource = _originalSource; | 
					
						
							|  |  |  |     _originalSource = source; | 
					
						
							|  |  |  |     const QByteArray bytes = source.toLatin1(); | 
					
						
							|  |  |  |     const QByteArray preprocessedCode = operator()(fileName, bytes); | 
					
						
							|  |  |  |     _originalSource = previousOriginalSource; | 
					
						
							|  |  |  |     return preprocessedCode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QByteArray Preprocessor::operator()(const QString &fileName, | 
					
						
							| 
									
										
										
										
											2009-03-02 11:30:43 +01:00
										 |  |  |                                     const QByteArray &source) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QByteArray preprocessed; | 
					
						
							| 
									
										
										
										
											2009-06-15 15:38:20 +02:00
										 |  |  |     preprocess(fileName, source, &preprocessed); | 
					
						
							| 
									
										
										
										
											2009-03-02 11:30:43 +01:00
										 |  |  |     return preprocessed; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 10:13:51 +01:00
										 |  |  | QByteArray Preprocessor::expand(const QByteArray &source) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QByteArray result; | 
					
						
							| 
									
										
										
										
											2009-03-03 10:16:43 +01:00
										 |  |  |     result.reserve(256); | 
					
						
							| 
									
										
										
										
											2009-03-03 10:13:51 +01:00
										 |  |  |     expand(source, &result); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  | void Preprocessor::expand(const QByteArray &source, QByteArray *result) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-13 18:16:28 +02:00
										 |  |  |     if (result) | 
					
						
							|  |  |  |         _expand(source, result); | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Preprocessor::expand(const char *first, const char *last, QByteArray *result) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QByteArray source = QByteArray::fromRawData(first, last - first); | 
					
						
							|  |  |  |     return expand(source, result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-13 15:28:11 +02:00
										 |  |  | void Preprocessor::out(const QByteArray &text) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (_result) | 
					
						
							|  |  |  |         _result->append(text); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Preprocessor::out(char ch) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (_result) | 
					
						
							|  |  |  |         _result->append(ch); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Preprocessor::out(const char *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (_result) | 
					
						
							|  |  |  |         _result->append(s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-04 20:54:31 +02:00
										 |  |  | bool Preprocessor::expandMacros() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _expandMacros; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Preprocessor::setExpandMacros(bool expandMacros) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _expandMacros = expandMacros; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-23 14:05:47 +02:00
										 |  |  | bool Preprocessor::keepComments() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return _keepComments; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Preprocessor::setKeepComments(bool keepComments) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _keepComments = keepComments; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | Preprocessor::State Preprocessor::createStateFromSource(const QByteArray &source) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     State state; | 
					
						
							|  |  |  |     state.source = source; | 
					
						
							|  |  |  |     Lexer lex(state.source.constBegin(), state.source.constEnd()); | 
					
						
							|  |  |  |     lex.setScanKeywords(false); | 
					
						
							| 
									
										
										
										
											2011-08-23 14:05:47 +02:00
										 |  |  |     if (_keepComments) | 
					
						
							|  |  |  |         lex.setScanCommentTokens(true); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     Token tok; | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         lex(&tok); | 
					
						
							|  |  |  |         state.tokens.append(tok); | 
					
						
							|  |  |  |     } while (tok.isNot(T_EOF_SYMBOL)); | 
					
						
							|  |  |  |     state.dot = state.tokens.constBegin(); | 
					
						
							|  |  |  |     return state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  | void Preprocessor::processNewline(bool force) | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-17 16:05:55 +01:00
										 |  |  |     if (_dot != _tokens.constBegin()) { | 
					
						
							|  |  |  |         TokenIterator prevTok = _dot - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-23 14:05:47 +02:00
										 |  |  |         // line changes due to multi-line tokens
 | 
					
						
							|  |  |  |         if (prevTok->isLiteral() | 
					
						
							|  |  |  |                 || (_keepComments | 
					
						
							|  |  |  |                     && (prevTok->kind() == T_COMMENT | 
					
						
							|  |  |  |                         || prevTok->kind() == T_DOXY_COMMENT))) { | 
					
						
							| 
									
										
										
										
											2009-12-17 16:05:55 +01:00
										 |  |  |             const char *ptr = _source.constBegin() + prevTok->begin(); | 
					
						
							|  |  |  |             const char *end = ptr + prevTok->length(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (; ptr != end; ++ptr) { | 
					
						
							|  |  |  |                 if (*ptr == '\n') | 
					
						
							|  |  |  |                     ++env->currentLine; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  |     if (! force && env->currentLine == _dot->lineno) | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  |     if (force || env->currentLine > _dot->lineno) { | 
					
						
							| 
									
										
										
										
											2009-05-13 15:28:11 +02:00
										 |  |  |         out("\n# "); | 
					
						
							|  |  |  |         out(QByteArray::number(_dot->lineno)); | 
					
						
							|  |  |  |         out(' '); | 
					
						
							|  |  |  |         out('"'); | 
					
						
							| 
									
										
										
										
											2009-05-27 15:34:13 +02:00
										 |  |  |         out(env->currentFile.toUtf8()); | 
					
						
							| 
									
										
										
										
											2009-05-13 15:28:11 +02:00
										 |  |  |         out('"'); | 
					
						
							|  |  |  |         out('\n'); | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |         for (unsigned i = env->currentLine; i < _dot->lineno; ++i) | 
					
						
							| 
									
										
										
										
											2009-05-13 15:28:11 +02:00
										 |  |  |             out('\n'); | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |     env->currentLine = _dot->lineno; | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Preprocessor::processSkippingBlocks(bool skippingBlocks, | 
					
						
							|  |  |  |                                          TokenIterator start, TokenIterator /*end*/) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (! client) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (skippingBlocks != _skipping[iflevel]) { | 
					
						
							|  |  |  |         unsigned offset = start->offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (_skipping[iflevel]) { | 
					
						
							| 
									
										
										
										
											2009-07-27 21:47:03 +02:00
										 |  |  |             if (_dot->f.newline) | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  |                 ++offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             client->startSkippingBlocks(offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if (offset) | 
					
						
							|  |  |  |                 --offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             client->stopSkippingBlocks(offset); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  | bool Preprocessor::markGeneratedTokens(bool markGeneratedTokens, | 
					
						
							|  |  |  |                                        TokenIterator dot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bool previous = _markGeneratedTokens; | 
					
						
							|  |  |  |     _markGeneratedTokens = markGeneratedTokens; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (previous != _markGeneratedTokens) { | 
					
						
							|  |  |  |         if (! dot) | 
					
						
							|  |  |  |             dot = _dot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (_markGeneratedTokens) | 
					
						
							| 
									
										
										
										
											2009-05-13 15:28:11 +02:00
										 |  |  |             out("\n#gen true"); | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2009-05-13 15:28:11 +02:00
										 |  |  |             out("\n#gen false"); | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         processNewline(/*force = */ true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const char *begin = _source.constBegin(); | 
					
						
							|  |  |  |         const char *end   = begin; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (markGeneratedTokens) | 
					
						
							|  |  |  |             end += dot->begin(); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             end += (dot - 1)->end(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const char *it = end - 1; | 
					
						
							|  |  |  |         for (; it != begin - 1; --it) { | 
					
						
							|  |  |  |             if (*it == '\n') | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         ++it; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (; it != end; ++it) { | 
					
						
							| 
									
										
										
										
											2009-05-15 16:01:02 +02:00
										 |  |  |             if (! pp_isspace(*it)) | 
					
						
							| 
									
										
										
										
											2009-05-13 15:28:11 +02:00
										 |  |  |                 out(' '); | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             else | 
					
						
							| 
									
										
										
										
											2009-05-13 15:28:11 +02:00
										 |  |  |                 out(*it); | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-12-03 15:08:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-03 16:05:53 +01:00
										 |  |  |         if (! markGeneratedTokens && dot->f.newline) | 
					
						
							| 
									
										
										
										
											2009-12-03 15:08:39 +01:00
										 |  |  |             processNewline(/*force = */ true); | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return previous; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:09:38 +01:00
										 |  |  | bool Preprocessor::maybeAfterComment() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned endOfPreviousToken = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (_dot != _tokens.constBegin()) | 
					
						
							|  |  |  |         endOfPreviousToken = (_dot - 1)->end(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const char *start = _source.constBegin() + endOfPreviousToken; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (*start == '/') | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-27 15:34:13 +02:00
										 |  |  | void Preprocessor::preprocess(const QString &fileName, const QByteArray &source, | 
					
						
							| 
									
										
										
										
											2009-03-03 09:58:43 +01:00
										 |  |  |                               QByteArray *result) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-09 16:01:20 +01:00
										 |  |  |     const int previousIfLevel = iflevel; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |     QByteArray *previousResult = _result; | 
					
						
							|  |  |  |     _result = result; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     pushState(createStateFromSource(source)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-27 15:34:13 +02:00
										 |  |  |     const QString previousFileName = env->currentFile; | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |     env->currentFile = fileName; | 
					
						
							| 
									
										
										
										
											2009-03-03 09:58:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |     const unsigned previousCurrentLine = env->currentLine; | 
					
						
							|  |  |  |     env->currentLine = 0; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     while (true) { | 
					
						
							| 
									
										
										
										
											2009-06-29 14:27:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-27 21:47:03 +02:00
										 |  |  |         if (_dot->f.joined) | 
					
						
							| 
									
										
										
										
											2009-06-29 14:27:47 +02:00
										 |  |  |             out("\\"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  |         processNewline(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (_dot->is(T_EOF_SYMBOL)) { | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-27 21:47:03 +02:00
										 |  |  |         } else if (_dot->is(T_POUND) && (! _dot->f.joined && _dot->f.newline)) { | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  |             // handle the preprocessor directive
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             TokenIterator start = _dot; | 
					
						
							|  |  |  |             do { | 
					
						
							|  |  |  |                 ++_dot; | 
					
						
							| 
									
										
										
										
											2009-07-27 21:47:03 +02:00
										 |  |  |             } while (_dot->isNot(T_EOF_SYMBOL) && (_dot->f.joined || ! _dot->f.newline)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             const bool skippingBlocks = _skipping[iflevel]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             processDirective(start, _dot); | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  |             processSkippingBlocks(skippingBlocks, start, _dot); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         } else if (skipping()) { | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  |             // skip the current line
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             do { | 
					
						
							|  |  |  |                 ++_dot; | 
					
						
							| 
									
										
										
										
											2009-07-27 21:47:03 +02:00
										 |  |  |             } while (_dot->isNot(T_EOF_SYMBOL) && (_dot->f.joined || ! _dot->f.newline)); | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:09:38 +01:00
										 |  |  |             if (_dot->f.whitespace || maybeAfterComment()) { | 
					
						
							| 
									
										
										
										
											2009-07-01 10:49:27 +02:00
										 |  |  |                 unsigned endOfPreviousToken = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (_dot != _tokens.constBegin()) | 
					
						
							|  |  |  |                     endOfPreviousToken = (_dot - 1)->end(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 11:14:12 +01:00
										 |  |  |                 const unsigned beginOfToken = _dot->begin(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 11:28:36 +01:00
										 |  |  |                 const char *start = _source.constBegin() + endOfPreviousToken; | 
					
						
							| 
									
										
										
										
											2009-03-03 11:14:12 +01:00
										 |  |  |                 const char *end = _source.constBegin() + beginOfToken; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 11:28:36 +01:00
										 |  |  |                 const char *it = end - 1; | 
					
						
							|  |  |  |                 for (; it != start - 1; --it) { | 
					
						
							|  |  |  |                     if (*it == '\n') | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 ++it; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 11:14:12 +01:00
										 |  |  |                 for (; it != end; ++it) { | 
					
						
							| 
									
										
										
										
											2009-05-15 16:01:02 +02:00
										 |  |  |                     if (pp_isspace(*it)) | 
					
						
							| 
									
										
										
										
											2009-05-13 15:28:11 +02:00
										 |  |  |                         out(*it); | 
					
						
							| 
									
										
										
										
											2009-03-03 11:14:12 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     else | 
					
						
							| 
									
										
										
										
											2009-05-13 15:28:11 +02:00
										 |  |  |                         out(' '); | 
					
						
							| 
									
										
										
										
											2009-03-03 11:14:12 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (_dot->isNot(T_IDENTIFIER)) { | 
					
						
							| 
									
										
										
										
											2009-05-13 15:28:11 +02:00
										 |  |  |                 out(tokenSpell(*_dot)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 ++_dot; | 
					
						
							| 
									
										
										
										
											2009-03-03 10:27:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 const TokenIterator identifierToken = _dot; | 
					
						
							|  |  |  |                 ++_dot; // skip T_IDENTIFIER
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 const QByteArray spell = tokenSpell(*identifierToken); | 
					
						
							| 
									
										
										
										
											2009-07-04 20:54:31 +02:00
										 |  |  |                 if (! _expandMacros) { | 
					
						
							| 
									
										
										
										
											2009-07-09 17:52:31 +02:00
										 |  |  |                     if (! env->isBuiltinMacro(spell)) { | 
					
						
							|  |  |  |                         Macro *m = env->resolve(spell); | 
					
						
							|  |  |  |                         if (m && ! m->isFunctionLike()) { | 
					
						
							| 
									
										
										
										
											2010-05-25 14:53:21 +02:00
										 |  |  |                             // expand object-like macros.
 | 
					
						
							|  |  |  |                             processObjectLikeMacro(identifierToken, spell, m); | 
					
						
							|  |  |  |                             continue; | 
					
						
							| 
									
										
										
										
											2009-07-09 17:52:31 +02:00
										 |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2009-07-04 20:54:31 +02:00
										 |  |  |                     out(spell); | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-04 20:54:31 +02:00
										 |  |  |                 else if (env->isBuiltinMacro(spell)) | 
					
						
							| 
									
										
										
										
											2009-03-03 17:18:12 +01:00
										 |  |  |                     expandBuiltinMacro(identifierToken, spell); | 
					
						
							| 
									
										
										
										
											2008-12-04 12:05:04 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 17:18:12 +01:00
										 |  |  |                 else { | 
					
						
							| 
									
										
										
										
											2010-02-22 13:11:09 +01:00
										 |  |  |                     if (Macro *m = env->resolve(spell)) { | 
					
						
							|  |  |  |                         if (! m->isFunctionLike()) { | 
					
						
							|  |  |  |                             if (0 == (m = processObjectLikeMacro(identifierToken, spell, m))) | 
					
						
							|  |  |  |                                 continue; | 
					
						
							| 
									
										
										
										
											2010-01-19 15:26:08 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 13:11:09 +01:00
										 |  |  |                             // the macro expansion generated something that looks like
 | 
					
						
							|  |  |  |                             // a function-like macro.
 | 
					
						
							|  |  |  |                         } | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 13:11:09 +01:00
										 |  |  |                         // `m' is function-like macro.
 | 
					
						
							|  |  |  |                         if (_dot->is(T_LPAREN)) { | 
					
						
							|  |  |  |                             QVector<MacroArgumentReference> actuals; | 
					
						
							|  |  |  |                             collectActualArguments(&actuals); | 
					
						
							| 
									
										
										
										
											2009-03-03 16:19:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-22 13:11:09 +01:00
										 |  |  |                             if (_dot->is(T_RPAREN)) { | 
					
						
							|  |  |  |                                 expandFunctionLikeMacro(identifierToken, m, actuals); | 
					
						
							|  |  |  |                                 continue; | 
					
						
							| 
									
										
										
										
											2009-03-03 17:18:12 +01:00
										 |  |  |                             } | 
					
						
							| 
									
										
										
										
											2009-03-03 17:06:42 +01:00
										 |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2010-02-22 13:11:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 17:18:12 +01:00
										 |  |  |                     // it's not a function or object-like macro.
 | 
					
						
							| 
									
										
										
										
											2009-05-13 15:28:11 +02:00
										 |  |  |                     out(spell); | 
					
						
							| 
									
										
										
										
											2009-03-03 17:18:12 +01:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     popState(); | 
					
						
							| 
									
										
										
										
											2009-03-03 09:58:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |     env->currentFile = previousFileName; | 
					
						
							|  |  |  |     env->currentLine = previousCurrentLine; | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |     _result = previousResult; | 
					
						
							| 
									
										
										
										
											2009-12-09 16:01:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     iflevel = previousIfLevel; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 11:47:30 +01:00
										 |  |  | void Preprocessor::collectActualArguments(QVector<MacroArgumentReference> *actuals) | 
					
						
							| 
									
										
										
										
											2009-03-03 16:59:55 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-04 11:47:30 +01:00
										 |  |  |     if (_dot->isNot(T_LPAREN)) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2009-03-03 17:06:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 11:47:30 +01:00
										 |  |  |     ++_dot; | 
					
						
							| 
									
										
										
										
											2009-03-03 16:59:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 11:47:30 +01:00
										 |  |  |     if (_dot->is(T_RPAREN)) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     actuals->append(collectOneActualArgument()); | 
					
						
							| 
									
										
										
										
											2009-03-03 16:59:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 11:47:30 +01:00
										 |  |  |     while (_dot->is(T_COMMA)) { | 
					
						
							| 
									
										
										
										
											2009-03-03 16:59:55 +01:00
										 |  |  |         ++_dot; | 
					
						
							| 
									
										
										
										
											2009-03-04 11:47:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         actuals->append(collectOneActualArgument()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MacroArgumentReference Preprocessor::collectOneActualArgument() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const unsigned position = _dot->begin(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (_dot->isNot(T_EOF_SYMBOL)) { | 
					
						
							|  |  |  |         if (_dot->is(T_COMMA) || _dot->is(T_RPAREN)) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (_dot->isNot(T_LPAREN)) | 
					
						
							|  |  |  |             ++_dot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             int count = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (; _dot->isNot(T_EOF_SYMBOL); ++_dot) { | 
					
						
							|  |  |  |                 if (_dot->is(T_LPAREN)) | 
					
						
							|  |  |  |                     ++count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 else if (_dot->is(T_RPAREN)) { | 
					
						
							|  |  |  |                     if (! --count) { | 
					
						
							|  |  |  |                         ++_dot; | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-03-03 16:59:55 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-03-04 11:47:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const unsigned end = _dot->begin(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return MacroArgumentReference(position, end - position); | 
					
						
							| 
									
										
										
										
											2009-03-03 16:59:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 16:56:55 +01:00
										 |  |  | Macro *Preprocessor::processObjectLikeMacro(TokenIterator identifierToken, | 
					
						
							|  |  |  |                                             const QByteArray &spell, | 
					
						
							|  |  |  |                                             Macro *m) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QByteArray tmp; | 
					
						
							|  |  |  |     expandObjectLikeMacro(identifierToken, spell, m, &tmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (_dot->is(T_LPAREN)) { | 
					
						
							|  |  |  |         // check if the expension generated a function-like macro.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         m = 0; // reset the active the macro
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         pushState(createStateFromSource(tmp)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (_dot->is(T_IDENTIFIER)) { | 
					
						
							|  |  |  |             const QByteArray id = tokenSpell(*_dot); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (Macro *macro = env->resolve(id)) { | 
					
						
							|  |  |  |                 if (macro->isFunctionLike()) | 
					
						
							|  |  |  |                     m = macro; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         popState(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (m != 0) | 
					
						
							|  |  |  |             return m; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  |     const bool was = markGeneratedTokens(true, identifierToken); | 
					
						
							| 
									
										
										
										
											2009-05-13 15:28:11 +02:00
										 |  |  |     out(tmp); | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  |     (void) markGeneratedTokens(was); | 
					
						
							| 
									
										
										
										
											2009-03-03 16:56:55 +01:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 17:18:12 +01:00
										 |  |  | void Preprocessor::expandBuiltinMacro(TokenIterator identifierToken, | 
					
						
							|  |  |  |                                       const QByteArray &spell) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  |     const bool was = markGeneratedTokens(true, identifierToken); | 
					
						
							| 
									
										
										
										
											2009-03-03 17:18:12 +01:00
										 |  |  |     expand(spell, _result); | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  |     (void) markGeneratedTokens(was); | 
					
						
							| 
									
										
										
										
											2009-03-03 17:18:12 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 16:46:21 +01:00
										 |  |  | void Preprocessor::expandObjectLikeMacro(TokenIterator identifierToken, | 
					
						
							|  |  |  |                                          const QByteArray &spell, | 
					
						
							|  |  |  |                                          Macro *m, | 
					
						
							|  |  |  |                                          QByteArray *result) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (client) | 
					
						
							|  |  |  |         client->startExpandingMacro(identifierToken->offset, | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |                                     *m, spell, false); | 
					
						
							| 
									
										
										
										
											2009-03-03 16:46:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     m->setHidden(true); | 
					
						
							|  |  |  |     expand(m->definition(), result); | 
					
						
							|  |  |  |     m->setHidden(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (client) | 
					
						
							|  |  |  |         client->stopExpandingMacro(_dot->offset, *m); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 11:47:30 +01:00
										 |  |  | void Preprocessor::expandFunctionLikeMacro(TokenIterator identifierToken, | 
					
						
							|  |  |  |                                            Macro *m, | 
					
						
							|  |  |  |                                            const QVector<MacroArgumentReference> &actuals) | 
					
						
							| 
									
										
										
										
											2009-03-03 16:19:03 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     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, | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |                                     *m, text, false, actuals); | 
					
						
							| 
									
										
										
										
											2009-03-03 16:19:03 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  |     const bool was = markGeneratedTokens(true, identifierToken); | 
					
						
							| 
									
										
										
										
											2009-03-03 16:19:03 +01:00
										 |  |  |     expand(beginOfText, endOfText, _result); | 
					
						
							| 
									
										
										
										
											2009-03-04 14:00:56 +01:00
										 |  |  |     (void) markGeneratedTokens(was); | 
					
						
							| 
									
										
										
										
											2009-03-03 16:19:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (client) | 
					
						
							|  |  |  |         client->stopExpandingMacro(_dot->offset, *m); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | const char *Preprocessor::startOfToken(const Token &token) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { return _source.constBegin() + token.begin(); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | const char *Preprocessor::endOfToken(const Token &token) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { return _source.constBegin() + token.end(); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | QByteArray Preprocessor::tokenSpell(const Token &token) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     const QByteArray text = QByteArray::fromRawData(_source.constBegin() + token.offset, | 
					
						
							| 
									
										
										
										
											2009-07-27 21:47:03 +02:00
										 |  |  |                                                      token.f.length); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     return text; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | QByteArray Preprocessor::tokenText(const Token &token) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     const QByteArray text(_source.constBegin() + token.offset, | 
					
						
							| 
									
										
										
										
											2009-07-27 21:47:03 +02:00
										 |  |  |                           token.f.length); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     return text; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | void Preprocessor::processDirective(TokenIterator firstToken, TokenIterator lastToken) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     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: | 
					
						
							| 
									
										
										
										
											2009-02-05 13:00:50 +01:00
										 |  |  |         case PP_IMPORT: | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             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
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | QVector<Token> Preprocessor::tokenize(const QByteArray &text) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  | void Preprocessor::processInclude(bool, TokenIterator firstToken, | 
					
						
							|  |  |  |                                   TokenIterator lastToken, bool acceptMacros) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-03 09:52:50 +01:00
										 |  |  |     if (! client) | 
					
						
							|  |  |  |         return; // nothing to do.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     RangeLexer tk(firstToken, lastToken); | 
					
						
							|  |  |  |     ++tk; // skip T_POUND
 | 
					
						
							|  |  |  |     ++tk; // skip `include|nclude_next'
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (acceptMacros && tk->is(T_IDENTIFIER)) { | 
					
						
							| 
									
										
										
										
											2009-02-16 18:56:20 +01:00
										 |  |  |         // ### TODO: implement me
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #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
 | 
					
						
							| 
									
										
										
										
											2009-03-03 09:52:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } else if (tk->is(T_LESS)) { | 
					
						
							| 
									
										
										
										
											2009-03-03 09:52:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         TokenIterator start = tk.dot(); | 
					
						
							| 
									
										
										
										
											2009-03-03 09:52:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         for (; tk->isNot(T_EOF_SYMBOL); ++tk) { | 
					
						
							|  |  |  |             if (tk->is(T_GREATER)) | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-03-03 09:52:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         const char *beginOfPath = endOfToken(*start); | 
					
						
							|  |  |  |         const char *endOfPath = startOfToken(*tk); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-15 15:38:20 +02:00
										 |  |  |         QString fn = string(beginOfPath, endOfPath - beginOfPath); | 
					
						
							| 
									
										
										
										
											2009-03-03 09:52:50 +01:00
										 |  |  |         client->sourceNeeded(fn, Client::IncludeGlobal, firstToken->lineno); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     } else if (tk->is(T_ANGLE_STRING_LITERAL) || tk->is(T_STRING_LITERAL)) { | 
					
						
							| 
									
										
										
										
											2009-03-03 09:52:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         const QByteArray spell = tokenSpell(*tk); | 
					
						
							|  |  |  |         const char *beginOfPath = spell.constBegin(); | 
					
						
							|  |  |  |         const char *endOfPath = spell.constEnd(); | 
					
						
							|  |  |  |         const char quote = *beginOfPath; | 
					
						
							| 
									
										
										
										
											2009-03-03 09:52:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         if (beginOfPath + 1 != endOfPath && ((quote == '"' && endOfPath[-1] == '"') || | 
					
						
							| 
									
										
										
										
											2009-03-03 09:52:50 +01:00
										 |  |  |                                               (quote == '<' && endOfPath[-1] == '>'))) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-15 15:38:20 +02:00
										 |  |  |             QString fn = string(beginOfPath + 1, spell.length() - 2); | 
					
						
							| 
									
										
										
										
											2009-03-03 09:52:50 +01:00
										 |  |  |             client->sourceNeeded(fn, Client::IncludeLocal, firstToken->lineno); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | void Preprocessor::processDefine(TokenIterator firstToken, TokenIterator lastToken) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     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; | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |     macro.setFileName(env->currentFile); | 
					
						
							|  |  |  |     macro.setLine(env->currentLine); | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |     macro.setName(tokenText(*tk)); | 
					
						
							| 
									
										
										
										
											2009-12-21 14:47:22 +01:00
										 |  |  |     macro.setOffset(firstToken->offset); | 
					
						
							|  |  |  |     macro.setLength(endOfToken(lastToken[- 1]) - startOfToken(*firstToken)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     ++tk; // skip T_IDENTIFIER
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-27 21:47:03 +02:00
										 |  |  |     if (tk->is(T_LPAREN) && ! tk->f.whitespace) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         // a function-like macro definition
 | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |         macro.setFunctionLike(true); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ++tk; // skip T_LPAREN
 | 
					
						
							|  |  |  |         if (tk->is(T_IDENTIFIER)) { | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |             macro.addFormal(tokenText(*tk)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             ++tk; // skip T_IDENTIFIER
 | 
					
						
							|  |  |  |             while (tk->is(T_COMMA)) { | 
					
						
							|  |  |  |                 ++tk;// skip T_COMMA
 | 
					
						
							|  |  |  |                 if (tk->isNot(T_IDENTIFIER)) | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |                 macro.addFormal(tokenText(*tk)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 ++tk; // skip T_IDENTIFIER
 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (tk->is(T_DOT_DOT_DOT)) { | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |             macro.setVariadic(true); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             ++tk; // skip T_DOT_DOT_DOT
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (tk->isNot(T_RPAREN)) { | 
					
						
							|  |  |  |             // ### warning expected `)'
 | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ++tk; // skip T_RPAREN
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |     if (isQtReservedWord(macro.name())) { | 
					
						
							|  |  |  |         QByteArray macroId = macro.name(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (macro.isFunctionLike()) { | 
					
						
							|  |  |  |             macroId += '('; | 
					
						
							|  |  |  |             bool fst = true; | 
					
						
							| 
									
										
										
										
											2011-04-19 15:42:14 +02:00
										 |  |  |             foreach (const QByteArray &formal, macro.formals()) { | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |                 if (! fst) | 
					
						
							|  |  |  |                     macroId += ", "; | 
					
						
							|  |  |  |                 fst = false; | 
					
						
							|  |  |  |                 macroId += formal; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             macroId += ')'; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |         macro.setDefinition(macroId); | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2008-12-02 15:33:07 +01:00
										 |  |  |         // ### make me fast!
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         const char *startOfDefinition = startOfToken(*tk); | 
					
						
							| 
									
										
										
										
											2009-08-24 14:01:32 +02:00
										 |  |  |         const char *endOfDefinition = endOfToken(lastToken[- 1]); | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |         QByteArray definition(startOfDefinition, | 
					
						
							|  |  |  |                               endOfDefinition - startOfDefinition); | 
					
						
							|  |  |  |         definition.replace("\\\n", " "); | 
					
						
							|  |  |  |         definition.replace('\n', ' '); | 
					
						
							|  |  |  |         macro.setDefinition(definition.trimmed()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |     env->bind(macro); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-08 12:59:33 +01:00
										 |  |  |     if (client) | 
					
						
							|  |  |  |         client->macroAdded(macro); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | void Preprocessor::processIf(TokenIterator firstToken, TokenIterator lastToken) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     RangeLexer tk(firstToken, lastToken); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ++tk; // skip T_POUND
 | 
					
						
							|  |  |  |     ++tk; // skipt `if'
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (testIfLevel()) { | 
					
						
							|  |  |  |         const char *first = startOfToken(*tk); | 
					
						
							|  |  |  |         const char *last = startOfToken(*lastToken); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |         MacroExpander expandCondition (env, 0, client, tk.dot()->offset); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         QByteArray condition; | 
					
						
							|  |  |  |         condition.reserve(256); | 
					
						
							|  |  |  |         expandCondition(first, last, &condition); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QVector<Token> tokens = tokenize(condition); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const Value result = evalExpression(tokens.constBegin(), | 
					
						
							|  |  |  |                                             tokens.constEnd() - 1, | 
					
						
							|  |  |  |                                             condition); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-21 16:20:45 +02:00
										 |  |  |         _trueTest[iflevel] = ! result.is_zero (); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         _skipping[iflevel]  =   result.is_zero (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | void Preprocessor::processElse(TokenIterator firstToken, TokenIterator lastToken) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     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 { | 
					
						
							| 
									
										
										
										
											2009-10-21 16:20:45 +02:00
										 |  |  |         _skipping[iflevel] = _trueTest[iflevel]; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | void Preprocessor::processElif(TokenIterator firstToken, TokenIterator lastToken) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     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;
 | 
					
						
							| 
									
										
										
										
											2009-10-21 16:20:45 +02:00
										 |  |  |     } else if (!_trueTest[iflevel] && !_skipping[iflevel - 1]) { | 
					
						
							| 
									
										
										
										
											2009-01-19 20:06:39 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const char *first = startOfToken(*tk); | 
					
						
							|  |  |  |         const char *last = startOfToken(*lastToken); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |         MacroExpander expandCondition (env, 0, client, tk.dot()->offset); | 
					
						
							| 
									
										
										
										
											2009-01-19 20:06:39 +01:00
										 |  |  |         QByteArray condition; | 
					
						
							|  |  |  |         condition.reserve(256); | 
					
						
							|  |  |  |         expandCondition(first, last, &condition); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QVector<Token> tokens = tokenize(condition); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const Value result = evalExpression(tokens.constBegin(), | 
					
						
							|  |  |  |                                             tokens.constEnd() - 1, | 
					
						
							|  |  |  |                                             condition); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-21 16:20:45 +02:00
										 |  |  |         _trueTest[iflevel] = ! result.is_zero (); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         _skipping[iflevel]  =   result.is_zero (); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         _skipping[iflevel] = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | void Preprocessor::processEndif(TokenIterator, TokenIterator) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (iflevel == 0 && !skipping()) { | 
					
						
							|  |  |  |         // std::cerr << "*** WARNING #endif without #if" << std::endl;
 | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         _skipping[iflevel] = false; | 
					
						
							| 
									
										
										
										
											2009-10-21 16:20:45 +02:00
										 |  |  |         _trueTest[iflevel] = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         --iflevel; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | void Preprocessor::processIfdef(bool checkUndefined, | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |                                 TokenIterator firstToken, | 
					
						
							|  |  |  |                                 TokenIterator lastToken) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     RangeLexer tk(firstToken, lastToken); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ++tk; // skip T_POUND
 | 
					
						
							|  |  |  |     ++tk; // skip `ifdef'
 | 
					
						
							|  |  |  |     if (testIfLevel()) { | 
					
						
							|  |  |  |         if (tk->is(T_IDENTIFIER)) { | 
					
						
							|  |  |  |             const QByteArray macroName = tokenSpell(*tk); | 
					
						
							| 
									
										
										
										
											2010-03-12 15:24:45 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             bool value = false; | 
					
						
							|  |  |  |             if (Macro *macro = macroDefinition(macroName, tk->offset, env, client)) { | 
					
						
							|  |  |  |                 value = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // the macro is a feature constraint(e.g. QT_NO_XXX)
 | 
					
						
							|  |  |  |                 if (checkUndefined && macroName.startsWith("QT_NO_")) { | 
					
						
							|  |  |  |                     if (macro->fileName() == QLatin1String("<configuration>")) { | 
					
						
							|  |  |  |                         // and it' defined in a pro file (e.g. DEFINES += QT_NO_QOBJECT)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         value = false; // take the branch
 | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             } else if (env->isBuiltinMacro(macroName)) { | 
					
						
							|  |  |  |                 value = true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (checkUndefined) | 
					
						
							|  |  |  |                 value = ! value; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-21 16:20:45 +02:00
										 |  |  |             _trueTest[iflevel] =   value; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             _skipping [iflevel] = ! value; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | void Preprocessor::processUndef(TokenIterator firstToken, TokenIterator lastToken) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     RangeLexer tk(firstToken, lastToken); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ++tk; // skip T_POUND
 | 
					
						
							|  |  |  |     ++tk; // skip `undef'
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (tk->is(T_IDENTIFIER)) { | 
					
						
							|  |  |  |         const QByteArray macroName = tokenText(*tk); | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |         const Macro *macro = env->remove(macroName); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-08 12:59:33 +01:00
										 |  |  |         if (client && macro) | 
					
						
							|  |  |  |             client->macroAdded(*macro); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | void Preprocessor::resetIfLevel () | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     iflevel = 0; | 
					
						
							|  |  |  |     _skipping[iflevel] = false; | 
					
						
							| 
									
										
										
										
											2009-10-21 16:20:45 +02:00
										 |  |  |     _trueTest[iflevel] = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  | Preprocessor::PP_DIRECTIVE_TYPE Preprocessor::classifyDirective(const QByteArray &directive) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |     switch (directive.size()) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |     case 2: | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |         if (directive[0] == 'i' && directive[1] == 'f') | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             return PP_IF; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case 4: | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |         if (directive[0] == 'e' && directive == "elif") | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             return PP_ELIF; | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |         else if (directive[0] == 'e' && directive == "else") | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             return PP_ELSE; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case 5: | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |         if (directive[0] == 'i' && directive == "ifdef") | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             return PP_IFDEF; | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |         else if (directive[0] == 'u' && directive == "undef") | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             return PP_UNDEF; | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |         else if (directive[0] == 'e' && directive == "endif") | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             return PP_ENDIF; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case 6: | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |         if (directive[0] == 'i' && directive == "ifndef") | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             return PP_IFNDEF; | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |         else if (directive[0] == 'i' && directive == "import") | 
					
						
							| 
									
										
										
										
											2009-02-05 13:00:50 +01:00
										 |  |  |             return PP_IMPORT; | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |         else if (directive[0] == 'd' && directive == "define") | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             return PP_DEFINE; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case 7: | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |         if (directive[0] == 'i' && directive == "include") | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             return PP_INCLUDE; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case 12: | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |         if (directive[0] == 'i' && directive == "include_next") | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             return PP_INCLUDE_NEXT; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return PP_UNKNOWN_DIRECTIVE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | bool Preprocessor::testIfLevel() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     const bool result = !_skipping[iflevel++]; | 
					
						
							|  |  |  |     _skipping[iflevel] = _skipping[iflevel - 1]; | 
					
						
							| 
									
										
										
										
											2009-10-21 16:20:45 +02:00
										 |  |  |     _trueTest[iflevel] = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | int Preprocessor::skipping() const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { return _skipping[iflevel]; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | Value Preprocessor::evalExpression(TokenIterator firstToken, TokenIterator lastToken, | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  |                                    const QByteArray &source) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |     ExpressionEvaluator eval(client, env); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     const Value result = eval(firstToken, lastToken, source); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 09:52:50 +01:00
										 |  |  | bool Preprocessor::isQtReservedWord(const QByteArray ¯oId) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     const int size = macroId.size(); | 
					
						
							|  |  |  |     if      (size == 9 && macroId.at(0) == 'Q' && macroId == "Q_SIGNALS") | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2009-07-03 09:11:52 +02:00
										 |  |  |     else if (size == 9 && macroId.at(0) == 'Q' && macroId == "Q_FOREACH") | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     else if (size == 7 && macroId.at(0) == 'Q' && macroId == "Q_SLOTS") | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2009-03-25 11:50:17 +01:00
										 |  |  |     else if (size == 8 && macroId.at(0) == 'Q' && macroId == "Q_SIGNAL") | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     else if (size == 6 && macroId.at(0) == 'Q' && macroId == "Q_SLOT") | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2009-11-30 16:30:21 +01:00
										 |  |  |     else if (size == 3 && macroId.at(0) == 'Q' && macroId == "Q_D") | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     else if (size == 3 && macroId.at(0) == 'Q' && macroId == "Q_Q") | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2010-02-22 13:11:09 +01:00
										 |  |  |     else if (size == 10 && macroId.at(0) == 'Q' && macroId == "Q_PROPERTY") | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2010-12-08 15:08:03 +01:00
										 |  |  |     else if (size == 18 && macroId.at(0) == 'Q' && macroId == "Q_PRIVATE_PROPERTY") | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2010-02-22 13:11:09 +01:00
										 |  |  |     else if (size == 7 && macroId.at(0) == 'Q' && macroId == "Q_ENUMS") | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     else if (size == 7 && macroId.at(0) == 'Q' && macroId == "Q_FLAGS") | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2010-03-16 17:29:40 +01:00
										 |  |  |     else if (size == 12 && macroId.at(0) == 'Q' && macroId == "Q_INTERFACES") | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2010-12-03 15:40:08 +01:00
										 |  |  |     else if (size == 11 && macroId.at(0) == 'Q' && macroId == "Q_INVOKABLE") | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     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; | 
					
						
							| 
									
										
										
										
											2009-07-03 11:00:36 +02:00
										 |  |  |     else if (size == 7 && macroId.at(0) == 'f' && macroId == "foreach") | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     else if (size == 5 && macroId.at(0) == 's' && macroId == "slots") | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-06-15 15:38:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | QString Preprocessor::string(const char *first, int length) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (_originalSource.isEmpty()) | 
					
						
							|  |  |  |         return QString::fromUtf8(first, length); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int position = first - _source.constData(); | 
					
						
							|  |  |  |     return _originalSource.mid(position, length); | 
					
						
							|  |  |  | } |