| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | /**************************************************************************
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2010-03-05 11:25:49 +01:00
										 |  |  | ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-06-17 00:01:27 +10:00
										 |  |  | ** Contact: Nokia Corporation (qt-info@nokia.com) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Commercial Usage | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Licensees holding valid Qt Commercial licenses may use this file in | 
					
						
							|  |  |  | ** accordance with the Qt Commercial License Agreement provided with the | 
					
						
							|  |  |  | ** Software or, alternatively, in accordance with the terms contained in | 
					
						
							|  |  |  | ** a written agreement between you and Nokia. | 
					
						
							| 
									
										
										
										
											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
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Alternatively, 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
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** If you are unsure which license is appropriate for your use, please | 
					
						
							| 
									
										
										
										
											2009-08-14 09:30:56 +02:00
										 |  |  | ** contact the sales department at http://qt.nokia.com/contact.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | **************************************************************************/ | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-08 15:45:36 +01:00
										 |  |  | #include "pp-macro-expander.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include "pp.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | #include "pp-cctype.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <QDateTime>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  | namespace CPlusPlus { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct pp_frame | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Macro *expanding_macro; | 
					
						
							|  |  |  |     const QVector<QByteArray> actuals; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pp_frame(Macro *expanding_macro, const QVector<QByteArray> &actuals) | 
					
						
							|  |  |  |         : expanding_macro (expanding_macro), | 
					
						
							|  |  |  |           actuals (actuals) | 
					
						
							|  |  |  |     { } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // end of namespace CPlusPlus
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-08 12:17:39 +01:00
										 |  |  | using namespace CPlusPlus; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  | inline static bool comment_p (const char *__first, const char *__last) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (__first == __last) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (*__first != '/') | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (++__first == __last) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return (*__first == '/' || *__first == '*'); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  | MacroExpander::MacroExpander(Environment *env, pp_frame *frame, Client *client, unsigned start_offset) | 
					
						
							| 
									
										
										
										
											2009-03-03 10:49:14 +01:00
										 |  |  |     : env(env), | 
					
						
							|  |  |  |       frame(frame), | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |       client(client), | 
					
						
							|  |  |  |       start_offset(start_offset), | 
					
						
							| 
									
										
										
										
											2009-03-03 10:49:14 +01:00
										 |  |  |       lines(0) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 15:08:31 +01:00
										 |  |  | const QByteArray *MacroExpander::resolve_formal(const QByteArray &__name) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (! (frame && frame->expanding_macro)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |     const QVector<QByteArray> formals = frame->expanding_macro->formals(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     for (int index = 0; index < formals.size(); ++index) { | 
					
						
							|  |  |  |         const QByteArray formal = formals.at(index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (formal == __name && index < frame->actuals.size()) | 
					
						
							|  |  |  |             return &frame->actuals.at(index); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-02 19:03:07 +01:00
										 |  |  | const char *MacroExpander::operator()(const char *first, const char *last, | 
					
						
							|  |  |  |                                       QByteArray *result) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return expand(first, last, result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const char *MacroExpander::expand(const char *__first, const char *__last, | 
					
						
							|  |  |  |                                   QByteArray *__result) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |     const char *start = __first; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     __first = skip_blanks (__first, __last); | 
					
						
							|  |  |  |     lines = skip_blanks.lines; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (__first != __last) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (*__first == '\n') | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2008-12-02 15:33:07 +01:00
										 |  |  |             __result->append("\n# "); | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |             __result->append(QByteArray::number(env->currentLine)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             __result->append(' '); | 
					
						
							|  |  |  |             __result->append('"'); | 
					
						
							| 
									
										
										
										
											2009-05-27 15:34:13 +02:00
										 |  |  |             __result->append(env->currentFile.toUtf8()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             __result->append('"'); | 
					
						
							|  |  |  |             __result->append('\n'); | 
					
						
							|  |  |  |             ++lines; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             __first = skip_blanks (++__first, __last); | 
					
						
							|  |  |  |             lines += skip_blanks.lines; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (__first != __last && *__first == '#') | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (*__first == '#') | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             __first = skip_blanks (++__first, __last); | 
					
						
							|  |  |  |             lines += skip_blanks.lines; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const char *end_id = skip_identifier (__first, __last); | 
					
						
							|  |  |  |             const QByteArray fast_name(__first, end_id - __first); | 
					
						
							|  |  |  |             __first = end_id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (const QByteArray *actual = resolve_formal (fast_name)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 __result->append('\"'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 const char *actual_begin = actual->constData (); | 
					
						
							|  |  |  |                 const char *actual_end = actual_begin + actual->size (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 for (const char *it = skip_whitespaces (actual_begin, actual_end); | 
					
						
							|  |  |  |                         it != actual_end; ++it) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     if (*it == '"' || *it == '\\') | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         __result->append('\\'); | 
					
						
							|  |  |  |                         __result->append(*it); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     else if (*it == '\n') | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         __result->append('"'); | 
					
						
							|  |  |  |                         __result->append('\n'); | 
					
						
							|  |  |  |                         __result->append('"'); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     else | 
					
						
							|  |  |  |                         __result->append(*it); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 __result->append('\"'); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 __result->append('#'); // ### warning message?
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (*__first == '\"') | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             const char *next_pos = skip_string_literal (__first, __last); | 
					
						
							|  |  |  |             lines += skip_string_literal.lines; | 
					
						
							|  |  |  |             __result->append(__first, next_pos - __first); | 
					
						
							|  |  |  |             __first = next_pos; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (*__first == '\'') | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             const char *next_pos = skip_char_literal (__first, __last); | 
					
						
							|  |  |  |             lines += skip_char_literal.lines; | 
					
						
							|  |  |  |             __result->append(__first, next_pos - __first); | 
					
						
							|  |  |  |             __first = next_pos; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-22 11:40:53 +01:00
										 |  |  |         else if (comment_p (__first, __last)) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         { | 
					
						
							|  |  |  |             __first = skip_comment_or_divop (__first, __last); | 
					
						
							|  |  |  |             int n = skip_comment_or_divop.lines; | 
					
						
							|  |  |  |             lines += n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             while (n-- > 0) | 
					
						
							|  |  |  |                 __result->append('\n'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (pp_isspace (*__first)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             for (; __first != __last; ++__first) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 if (*__first == '\n' || !pp_isspace (*__first)) | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             __result->append(' '); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (pp_isdigit (*__first)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             const char *next_pos = skip_number (__first, __last); | 
					
						
							|  |  |  |             lines += skip_number.lines; | 
					
						
							|  |  |  |             __result->append(__first, next_pos - __first); | 
					
						
							|  |  |  |             __first = next_pos; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (pp_isalpha (*__first) || *__first == '_') | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             const char *name_begin = __first; | 
					
						
							|  |  |  |             const char *name_end = skip_identifier (__first, __last); | 
					
						
							|  |  |  |             __first = name_end; // advance
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // search for the paste token
 | 
					
						
							|  |  |  |             const char *next = skip_blanks (__first, __last); | 
					
						
							|  |  |  |             bool paste = false; | 
					
						
							|  |  |  |             if (next != __last && *next == '#') | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 paste = true; | 
					
						
							|  |  |  |                 ++next; | 
					
						
							|  |  |  |                 if (next != __last && *next == '#') | 
					
						
							|  |  |  |                     __first = skip_blanks(++next, __last); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const QByteArray fast_name(name_begin, name_end - name_begin); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (const QByteArray *actual = resolve_formal (fast_name)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 const char *begin = actual->constData (); | 
					
						
							|  |  |  |                 const char *end = begin + actual->size (); | 
					
						
							|  |  |  |                 if (paste) { | 
					
						
							|  |  |  |                     for (--end; end != begin - 1; --end) { | 
					
						
							|  |  |  |                         if (! pp_isspace(*end)) | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     ++end; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 __result->append(begin, end - begin); | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |             Macro *macro = env->resolve (fast_name); | 
					
						
							|  |  |  |             if (! macro || macro->isHidden() || env->hideNext) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             { | 
					
						
							|  |  |  |                 if (fast_name.size () == 7 && fast_name [0] == 'd' && fast_name == "defined") | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |                     env->hideNext = true; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 else | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |                     env->hideNext = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 if (fast_name.size () == 8 && fast_name [0] == '_' && fast_name [1] == '_') | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     if (fast_name == "__LINE__") | 
					
						
							|  |  |  |                     { | 
					
						
							| 
									
										
										
										
											2009-05-27 15:34:13 +02:00
										 |  |  |                         __result->append(QByteArray::number(env->currentLine + lines)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     else if (fast_name == "__FILE__") | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         __result->append('"'); | 
					
						
							| 
									
										
										
										
											2009-05-27 15:34:13 +02:00
										 |  |  |                         __result->append(env->currentFile.toUtf8()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                         __result->append('"'); | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     else if (fast_name == "__DATE__") | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         __result->append('"'); | 
					
						
							|  |  |  |                         __result->append(QDate::currentDate().toString().toUtf8()); | 
					
						
							|  |  |  |                         __result->append('"'); | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     else if (fast_name == "__TIME__") | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         __result->append('"'); | 
					
						
							|  |  |  |                         __result->append(QTime::currentTime().toString().toUtf8()); | 
					
						
							|  |  |  |                         __result->append('"'); | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 __result->append(name_begin, name_end - name_begin); | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |             if (! macro->isFunctionLike()) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             { | 
					
						
							|  |  |  |                 Macro *m = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |                 if (! macro->definition().isEmpty()) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |                     macro->setHidden(true); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     QByteArray __tmp; | 
					
						
							|  |  |  |                     __tmp.reserve (256); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     MacroExpander expand_macro (env); | 
					
						
							| 
									
										
										
										
											2009-03-03 10:49:14 +01:00
										 |  |  |                     expand_macro(macro->definition(), &__tmp); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     if (! __tmp.isEmpty ()) | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         const char *__tmp_begin = __tmp.constBegin(); | 
					
						
							|  |  |  |                         const char *__tmp_end = __tmp.constEnd(); | 
					
						
							|  |  |  |                         const char *__begin_id = skip_whitespaces (__tmp_begin, __tmp_end); | 
					
						
							|  |  |  |                         const char *__end_id = skip_identifier (__begin_id, __tmp_end); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         if (__end_id == __tmp_end) | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             const QByteArray __id (__begin_id, __end_id - __begin_id); | 
					
						
							| 
									
										
										
										
											2009-03-03 10:41:20 +01:00
										 |  |  |                             m = env->resolve (__id); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         if (! m) | 
					
						
							|  |  |  |                             *__result += __tmp; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |                     macro->setHidden(false); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (! m) | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 macro = m; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // function like macro
 | 
					
						
							|  |  |  |             const char *arg_it = skip_whitespaces (__first, __last); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (arg_it == __last || *arg_it != '(') | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 __result->append(name_begin, name_end - name_begin); | 
					
						
							|  |  |  |                 lines += skip_whitespaces.lines; | 
					
						
							|  |  |  |                 __first = arg_it; | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             QVector<QByteArray> actuals; | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |             QVector<MacroArgumentReference> actuals_ref; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             actuals.reserve (5); | 
					
						
							|  |  |  |             ++arg_it; // skip '('
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             MacroExpander expand_actual (env, frame); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const char *arg_end = skip_argument_variadics (actuals, macro, arg_it, __last); | 
					
						
							|  |  |  |             if (arg_it != arg_end) | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |                 actuals_ref.append(MacroArgumentReference(start_offset + (arg_it-start), arg_end - arg_it)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 const QByteArray actual (arg_it, arg_end - arg_it); | 
					
						
							|  |  |  |                 QByteArray expanded; | 
					
						
							|  |  |  |                 expand_actual (actual.constBegin (), actual.constEnd (), &expanded); | 
					
						
							|  |  |  |                 actuals.push_back (expanded); | 
					
						
							|  |  |  |                 arg_it = arg_end; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             while (arg_it != __last && *arg_end == ',') | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ++arg_it; // skip ','
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 arg_end = skip_argument_variadics (actuals, macro, arg_it, __last); | 
					
						
							| 
									
										
										
										
											2009-09-25 16:00:14 +02:00
										 |  |  |                 actuals_ref.append(MacroArgumentReference(start_offset + (arg_it-start), arg_end - arg_it)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 const QByteArray actual (arg_it, arg_end - arg_it); | 
					
						
							|  |  |  |                 QByteArray expanded; | 
					
						
							|  |  |  |                 expand_actual (actual.constBegin (), actual.constEnd (), &expanded); | 
					
						
							|  |  |  |                 actuals.push_back (expanded); | 
					
						
							|  |  |  |                 arg_it = arg_end; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (! (arg_it != __last && *arg_it == ')')) | 
					
						
							|  |  |  |                 return __last; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             ++arg_it; // skip ')'
 | 
					
						
							|  |  |  |             __first = arg_it; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             pp_frame frame (macro, actuals); | 
					
						
							|  |  |  |             MacroExpander expand_macro (env, &frame); | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |             macro->setHidden(true); | 
					
						
							|  |  |  |             expand_macro (macro->definition(), __result); | 
					
						
							|  |  |  |             macro->setHidden(false); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             __result->append(*__first++); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return __first; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const char *MacroExpander::skip_argument_variadics (QVector<QByteArray> const &__actuals, | 
					
						
							|  |  |  |                                                     Macro *__macro, | 
					
						
							|  |  |  |                                                     const char *__first, const char *__last) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const char *arg_end = skip_argument (__first, __last); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-22 13:55:42 +01:00
										 |  |  |     while (__macro->isVariadic() && __first != arg_end && arg_end != __last && *arg_end == ',' | 
					
						
							|  |  |  |            && (__actuals.size () + 1) == __macro->formals().size ()) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         arg_end = skip_argument (++arg_end, __last); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return arg_end; | 
					
						
							|  |  |  | } |