| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | /**************************************************************************
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ** Contact:  Qt Software Information (qt-info@nokia.com) | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | ** contact the sales department at qt-sales@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 (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
					
						
							|  |  |  | // of this software and associated documentation files (the "Software"), to deal
 | 
					
						
							|  |  |  | // in the Software without restriction, including without limitation the rights
 | 
					
						
							|  |  |  | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
					
						
							|  |  |  | // copies of the Software, and to permit persons to whom the Software is
 | 
					
						
							|  |  |  | // furnished to do so, subject to the following conditions:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 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
 | 
					
						
							|  |  |  | // AUTHORS OR COPYRIGHT HOLDERS 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 "TranslationUnit.h"
 | 
					
						
							|  |  |  | #include "Control.h"
 | 
					
						
							|  |  |  | #include "Parser.h"
 | 
					
						
							|  |  |  | #include "Lexer.h"
 | 
					
						
							|  |  |  | #include "MemoryPool.h"
 | 
					
						
							|  |  |  | #include "AST.h"
 | 
					
						
							|  |  |  | #include "Literals.h"
 | 
					
						
							|  |  |  | #include "DiagnosticClient.h"
 | 
					
						
							|  |  |  | #include <stack>
 | 
					
						
							|  |  |  | #include <cstdlib>
 | 
					
						
							|  |  |  | #include <cstdarg>
 | 
					
						
							|  |  |  | #include <algorithm>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CPLUSPLUS_BEGIN_NAMESPACE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TranslationUnit::TranslationUnit(Control *control, StringLiteral *fileId) | 
					
						
							|  |  |  |     : _control(control), | 
					
						
							|  |  |  |       _fileId(fileId), | 
					
						
							|  |  |  |       _firstSourceChar(0), | 
					
						
							|  |  |  |       _lastSourceChar(0), | 
					
						
							|  |  |  |       _pool(0), | 
					
						
							|  |  |  |       _ast(0), | 
					
						
							|  |  |  |       _flags(0) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _tokens = new Array<Token, 8>(); | 
					
						
							|  |  |  |     _previousTranslationUnit = control->switchTranslationUnit(this); | 
					
						
							|  |  |  |     _pool = new MemoryPool(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TranslationUnit::~TranslationUnit() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     (void) _control->switchTranslationUnit(_previousTranslationUnit); | 
					
						
							|  |  |  |     delete _tokens; | 
					
						
							|  |  |  |     delete _pool; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool TranslationUnit::qtMocRunEnabled() const | 
					
						
							|  |  |  | { return _qtMocRunEnabled; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::setQtMocRunEnabled(bool onoff) | 
					
						
							|  |  |  | { _qtMocRunEnabled = onoff; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-09 16:55:25 +01:00
										 |  |  | bool TranslationUnit::objCEnabled() const | 
					
						
							|  |  |  | { return _objCEnabled; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::setObjCEnabled(bool onoff) | 
					
						
							|  |  |  | { _objCEnabled = onoff; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | Control *TranslationUnit::control() const | 
					
						
							|  |  |  | { return _control; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | StringLiteral *TranslationUnit::fileId() const | 
					
						
							|  |  |  | { return _fileId; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const char *TranslationUnit::fileName() const | 
					
						
							|  |  |  | { return _fileId->chars(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned TranslationUnit::fileNameLength() const | 
					
						
							|  |  |  | { return _fileId->size(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const char *TranslationUnit::firstSourceChar() const | 
					
						
							|  |  |  | { return _firstSourceChar; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const char *TranslationUnit::lastSourceChar() const | 
					
						
							|  |  |  | { return _lastSourceChar; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned TranslationUnit::sourceLength() const | 
					
						
							|  |  |  | { return _lastSourceChar - _firstSourceChar; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::setSource(const char *source, unsigned size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _firstSourceChar = source; | 
					
						
							|  |  |  |     _lastSourceChar = source + size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned TranslationUnit::tokenCount() const | 
					
						
							|  |  |  | { return _tokens->size(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const Token &TranslationUnit::tokenAt(unsigned index) const | 
					
						
							|  |  |  | { return _tokens->at(index); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int TranslationUnit::tokenKind(unsigned index) const | 
					
						
							|  |  |  | { return _tokens->at(index).kind; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 13:01:01 +01:00
										 |  |  | const char *TranslationUnit::spell(unsigned index) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (! index) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return _tokens->at(index).spell(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | Identifier *TranslationUnit::identifier(unsigned index) const | 
					
						
							|  |  |  | { return _tokens->at(index).identifier; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Literal *TranslationUnit::literal(unsigned index) const | 
					
						
							|  |  |  | { return _tokens->at(index).literal; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | StringLiteral *TranslationUnit::stringLiteral(unsigned index) const | 
					
						
							|  |  |  | { return _tokens->at(index).string; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NumericLiteral *TranslationUnit::numericLiteral(unsigned index) const | 
					
						
							|  |  |  | { return _tokens->at(index).number; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned TranslationUnit::matchingBrace(unsigned index) const | 
					
						
							|  |  |  | { return _tokens->at(index).close_brace; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MemoryPool *TranslationUnit::memoryPool() const | 
					
						
							|  |  |  | { return _pool; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-03 14:01:19 +01:00
										 |  |  | AST *TranslationUnit::ast() const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { return _ast; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool TranslationUnit::isTokenized() const | 
					
						
							|  |  |  | { return _tokenized; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool TranslationUnit::isParsed() const | 
					
						
							|  |  |  | { return _parsed; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::tokenize() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (isTokenized()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _tokenized = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Lexer lex(this); | 
					
						
							|  |  |  |     lex.setQtMocRunEnabled(_qtMocRunEnabled); | 
					
						
							| 
									
										
										
										
											2009-01-09 16:55:25 +01:00
										 |  |  |     lex.setObjCEnabled(_objCEnabled); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     std::stack<unsigned> braces; | 
					
						
							|  |  |  |     _tokens->push_back(Token()); // the first token needs to be invalid!
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pushLineOffset(0); | 
					
						
							|  |  |  |     pushPreprocessorLine(0, 1, fileId()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 14:35:59 +01:00
										 |  |  |     Identifier *lineId   = control()->findOrInsertIdentifier("line"); | 
					
						
							|  |  |  |     Identifier *genId    = control()->findOrInsertIdentifier("gen"); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 14:35:59 +01:00
										 |  |  |     bool generated = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     Token tk; | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         lex(&tk); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       _Lrecognize: | 
					
						
							|  |  |  |         if (tk.is(T_POUND)) { | 
					
						
							|  |  |  |             unsigned offset = tk.offset; | 
					
						
							|  |  |  |             lex(&tk); | 
					
						
							| 
									
										
										
										
											2009-03-04 14:35:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (! tk.newline && tk.is(T_IDENTIFIER) && tk.identifier == genId) { | 
					
						
							|  |  |  |                 // it's a gen directive.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 lex(&tk); | 
					
						
							| 
									
										
										
										
											2009-03-04 14:35:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 if (! tk.newline && tk.is(T_TRUE)) { | 
					
						
							|  |  |  |                     lex(&tk); | 
					
						
							|  |  |  |                     generated = true; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     generated = false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 if (! tk.newline && tk.is(T_IDENTIFIER) && tk.identifier == lineId) | 
					
						
							|  |  |  |                     lex(&tk); | 
					
						
							|  |  |  |                 if (! tk.newline && tk.is(T_INT_LITERAL)) { | 
					
						
							|  |  |  |                     unsigned line = (unsigned) strtoul(tk.spell(), 0, 0); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     lex(&tk); | 
					
						
							| 
									
										
										
										
											2009-03-04 14:35:59 +01:00
										 |  |  |                     if (! tk.newline && tk.is(T_STRING_LITERAL)) { | 
					
						
							|  |  |  |                         StringLiteral *fileName = control()->findOrInsertFileName(tk.string->chars(), | 
					
						
							|  |  |  |                                                                                   tk.string->size()); | 
					
						
							|  |  |  |                         pushPreprocessorLine(offset, line, fileName); | 
					
						
							|  |  |  |                         lex(&tk); | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             while (tk.isNot(T_EOF_SYMBOL) && ! tk.newline) | 
					
						
							|  |  |  |                 lex(&tk); | 
					
						
							|  |  |  |             goto _Lrecognize; | 
					
						
							|  |  |  |         } else if (tk.kind == T_LBRACE) { | 
					
						
							|  |  |  |             braces.push(_tokens->size()); | 
					
						
							|  |  |  |         } else if (tk.kind == T_RBRACE && ! braces.empty()) { | 
					
						
							|  |  |  |             const unsigned open_brace_index = braces.top(); | 
					
						
							|  |  |  |             braces.pop(); | 
					
						
							|  |  |  |             (*_tokens)[open_brace_index].close_brace = _tokens->size(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-03-04 14:35:59 +01:00
										 |  |  |         tk.generated = generated; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         _tokens->push_back(tk); | 
					
						
							|  |  |  |     } while (tk.kind); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (; ! braces.empty(); braces.pop()) { | 
					
						
							|  |  |  |         unsigned open_brace_index = braces.top(); | 
					
						
							|  |  |  |         (*_tokens)[open_brace_index].close_brace = _tokens->size(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool TranslationUnit::skipFunctionBody() const | 
					
						
							|  |  |  | { return _skipFunctionBody; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::setSkipFunctionBody(bool skipFunctionBody) | 
					
						
							|  |  |  | { _skipFunctionBody = skipFunctionBody; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-03 14:01:19 +01:00
										 |  |  | bool TranslationUnit::parse(ParseMode mode) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (isParsed()) | 
					
						
							| 
									
										
										
										
											2008-12-03 14:01:19 +01:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (! isTokenized()) | 
					
						
							|  |  |  |         tokenize(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Parser parser(this); | 
					
						
							|  |  |  |     parser.setQtMocRunEnabled(_qtMocRunEnabled); | 
					
						
							| 
									
										
										
										
											2009-01-09 16:55:25 +01:00
										 |  |  |     parser.setObjCEnabled(_objCEnabled); | 
					
						
							| 
									
										
										
										
											2008-12-03 14:01:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bool parsed = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (mode) { | 
					
						
							|  |  |  |     case ParseTranlationUnit: { | 
					
						
							|  |  |  |         TranslationUnitAST *node = 0; | 
					
						
							|  |  |  |         parsed = parser.parseTranslationUnit(node); | 
					
						
							|  |  |  |         _ast = node; | 
					
						
							|  |  |  |     } break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case ParseDeclaration: { | 
					
						
							|  |  |  |         DeclarationAST *node = 0; | 
					
						
							|  |  |  |         parsed = parser.parseDeclaration(node); | 
					
						
							|  |  |  |         _ast = node; | 
					
						
							|  |  |  |     } break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case ParseExpression: { | 
					
						
							|  |  |  |         ExpressionAST *node = 0; | 
					
						
							|  |  |  |         parsed = parser.parseExpression(node); | 
					
						
							|  |  |  |         _ast = node; | 
					
						
							|  |  |  |     } break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-30 15:07:30 +02:00
										 |  |  |     case ParseDeclarator: { | 
					
						
							|  |  |  |         DeclaratorAST *node = 0; | 
					
						
							|  |  |  |         parsed = parser.parseDeclarator(node); | 
					
						
							|  |  |  |         _ast = node; | 
					
						
							|  |  |  |     } break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-03 14:01:19 +01:00
										 |  |  |     case ParseStatement: { | 
					
						
							|  |  |  |         StatementAST *node = 0; | 
					
						
							|  |  |  |         parsed = parser.parseStatement(node); | 
					
						
							|  |  |  |         _ast = node; | 
					
						
							|  |  |  |     } break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } // switch
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return parsed; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::pushLineOffset(unsigned offset) | 
					
						
							|  |  |  | { _lineOffsets.push_back(offset); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::pushPreprocessorLine(unsigned offset, | 
					
						
							|  |  |  |                                            unsigned line, | 
					
						
							|  |  |  |                                            StringLiteral *fileName) | 
					
						
							|  |  |  | { _ppLines.push_back(PPLine(offset, line, fileName)); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned TranslationUnit::findLineNumber(unsigned offset) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     std::vector<unsigned>::const_iterator it = | 
					
						
							|  |  |  |         std::lower_bound(_lineOffsets.begin(), _lineOffsets.end(), offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (it != _lineOffsets.begin()) | 
					
						
							|  |  |  |         --it; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return it - _lineOffsets.begin(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TranslationUnit::PPLine TranslationUnit::findPreprocessorLine(unsigned offset) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     std::vector<PPLine>::const_iterator it = | 
					
						
							|  |  |  |         std::lower_bound(_ppLines.begin(), _ppLines.end(), PPLine(offset)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (it != _ppLines.begin()) | 
					
						
							|  |  |  |         --it; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return *it; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned TranslationUnit::findColumnNumber(unsigned offset, unsigned lineNumber) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (! offset) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return offset - _lineOffsets[lineNumber]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::getTokenPosition(unsigned index, | 
					
						
							|  |  |  |                                        unsigned *line, | 
					
						
							|  |  |  |                                        unsigned *column, | 
					
						
							|  |  |  |                                        StringLiteral **fileName) const | 
					
						
							|  |  |  | { return getPosition(tokenAt(index).offset, line, column, fileName); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::getPosition(unsigned tokenOffset, | 
					
						
							|  |  |  |                                   unsigned *line, | 
					
						
							|  |  |  |                                   unsigned *column, | 
					
						
							|  |  |  |                                   StringLiteral **fileName) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned lineNumber = findLineNumber(tokenOffset); | 
					
						
							|  |  |  |     unsigned columnNumber = findColumnNumber(tokenOffset, lineNumber); | 
					
						
							|  |  |  |     const PPLine ppLine = findPreprocessorLine(tokenOffset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lineNumber -= findLineNumber(ppLine.offset) + 1; | 
					
						
							|  |  |  |     lineNumber += ppLine.line; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (line) | 
					
						
							|  |  |  |         *line = lineNumber; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (column) | 
					
						
							|  |  |  |         *column = columnNumber; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (fileName) | 
					
						
							|  |  |  |        *fileName = ppLine.fileName; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool TranslationUnit::blockErrors(bool block) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bool previous = _blockErrors; | 
					
						
							|  |  |  |     _blockErrors = block; | 
					
						
							|  |  |  |     return previous; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::warning(unsigned index, const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (_blockErrors) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     index = std::min(index, tokenCount() - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     unsigned line = 0, column = 0; | 
					
						
							|  |  |  |     StringLiteral *fileName = 0; | 
					
						
							|  |  |  |     getTokenPosition(index, &line, &column, &fileName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (DiagnosticClient *client = control()->diagnosticClient()) { | 
					
						
							|  |  |  |         va_list args; | 
					
						
							|  |  |  |         va_start(args, format); | 
					
						
							|  |  |  |         client->report(DiagnosticClient::Warning, fileName, line, column, | 
					
						
							|  |  |  |                        format, args); | 
					
						
							|  |  |  |         va_end(args); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         fprintf(stderr, "%s:%d: ", fileName->chars(), line); | 
					
						
							|  |  |  |         fprintf(stderr, "warning: "); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         va_list args; | 
					
						
							|  |  |  |         va_start(args, format); | 
					
						
							|  |  |  |         vfprintf(stderr, format, args); | 
					
						
							|  |  |  |         va_end(args); | 
					
						
							|  |  |  |         fputc('\n', stderr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         showErrorLine(index, column, stderr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::error(unsigned index, const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (_blockErrors) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     index = std::min(index, tokenCount() - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     unsigned line = 0, column = 0; | 
					
						
							|  |  |  |     StringLiteral *fileName = 0; | 
					
						
							|  |  |  |     getTokenPosition(index, &line, &column, &fileName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (DiagnosticClient *client = control()->diagnosticClient()) { | 
					
						
							|  |  |  |         va_list args; | 
					
						
							|  |  |  |         va_start(args, format); | 
					
						
							|  |  |  |         client->report(DiagnosticClient::Error, fileName, line, column, | 
					
						
							|  |  |  |                        format, args); | 
					
						
							|  |  |  |         va_end(args); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         fprintf(stderr, "%s:%d: ", fileName->chars(), line); | 
					
						
							|  |  |  |         fprintf(stderr, "error: "); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         va_list args; | 
					
						
							|  |  |  |         va_start(args, format); | 
					
						
							|  |  |  |         vfprintf(stderr, format, args); | 
					
						
							|  |  |  |         va_end(args); | 
					
						
							|  |  |  |         fputc('\n', stderr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         showErrorLine(index, column, stderr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::fatal(unsigned index, const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (_blockErrors) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     index = std::min(index, tokenCount() - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     unsigned line = 0, column = 0; | 
					
						
							|  |  |  |     StringLiteral *fileName = 0; | 
					
						
							|  |  |  |     getTokenPosition(index, &line, &column, &fileName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (DiagnosticClient *client = control()->diagnosticClient()) { | 
					
						
							|  |  |  |         va_list args; | 
					
						
							|  |  |  |         va_start(args, format); | 
					
						
							|  |  |  |         client->report(DiagnosticClient::Fatal, fileName, line, column, | 
					
						
							|  |  |  |                        format, args); | 
					
						
							|  |  |  |         va_end(args); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         fprintf(stderr, "%s:%d: ", fileName->chars(), line); | 
					
						
							|  |  |  |         fprintf(stderr, "fatal: "); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         va_list args; | 
					
						
							|  |  |  |         va_start(args, format); | 
					
						
							|  |  |  |         vfprintf(stderr, format, args); | 
					
						
							|  |  |  |         va_end(args); | 
					
						
							|  |  |  |         fputc('\n', stderr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         showErrorLine(index, column, stderr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     exit(EXIT_FAILURE); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::showErrorLine(unsigned index, unsigned column, FILE *out) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned lineOffset = _lineOffsets[findLineNumber(_tokens->at(index).offset)]; | 
					
						
							|  |  |  |     for (const char *cp = _firstSourceChar + lineOffset + 1; *cp && *cp != '\n'; ++cp) { | 
					
						
							|  |  |  |         fputc(*cp, out); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     fputc('\n', out); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const char *end = _firstSourceChar + lineOffset + 1 + column - 1; | 
					
						
							|  |  |  |     for (const char *cp = _firstSourceChar + lineOffset + 1; cp != end; ++cp) { | 
					
						
							|  |  |  |         if (*cp != '\t') | 
					
						
							|  |  |  |             fputc(' ', out); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             fputc('\t', out); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     fputc('^', out); | 
					
						
							|  |  |  |     fputc('\n', out); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::resetAST() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     delete _pool; | 
					
						
							|  |  |  |     _pool = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TranslationUnit::release() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     resetAST(); | 
					
						
							|  |  |  |     delete _tokens; | 
					
						
							|  |  |  |     _tokens = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CPLUSPLUS_END_NAMESPACE |