aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/scanner
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@nokia.com>2012-02-15 15:56:22 +0100
committerOswald Buddenhagen <oswald.buddenhagen@nokia.com>2012-02-15 21:57:41 +0100
commit5672fa8fd3bd6b09125d9e143a7bb277cea2e87f (patch)
treec945b6ad76bd8c8f6af8b520cf3ce72ef298d4b5 /src/plugins/scanner
Long live qbs!
Diffstat (limited to 'src/plugins/scanner')
-rw-r--r--src/plugins/scanner/cpp/CPlusPlusForwardDeclarations.h151
-rw-r--r--src/plugins/scanner/cpp/Lexer.cpp669
-rw-r--r--src/plugins/scanner/cpp/Lexer.h162
-rw-r--r--src/plugins/scanner/cpp/Token.cpp154
-rw-r--r--src/plugins/scanner/cpp/Token.h371
-rw-r--r--src/plugins/scanner/cpp/cpp.cpp281
-rw-r--r--src/plugins/scanner/cpp/cpp.pro15
-rw-r--r--src/plugins/scanner/cpp/cpp_global.h47
-rw-r--r--src/plugins/scanner/qt/qt.cpp227
-rw-r--r--src/plugins/scanner/qt/qt.pro12
-rw-r--r--src/plugins/scanner/scanner.h93
-rw-r--r--src/plugins/scanner/scanner.pro3
12 files changed, 2185 insertions, 0 deletions
diff --git a/src/plugins/scanner/cpp/CPlusPlusForwardDeclarations.h b/src/plugins/scanner/cpp/CPlusPlusForwardDeclarations.h
new file mode 100644
index 000000000..4b8b1f1d1
--- /dev/null
+++ b/src/plugins/scanner/cpp/CPlusPlusForwardDeclarations.h
@@ -0,0 +1,151 @@
+/**************************************************************************
+**
+** This file is part of the Qt Build Suite
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file.
+** Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** 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.
+**
+**************************************************************************/
+
+// 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.
+
+#ifndef CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H
+#define CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H
+
+#include <cstdlib>
+#include <cstddef>
+
+#ifndef CPLUSPLUS_WITHOUT_QT
+# include <QtCore/qglobal.h>
+
+//# if defined(CPLUSPLUS_BUILD_LIB)
+//# define CPLUSPLUS_EXPORT Q_DECL_EXPORT
+//# elif defined(CPLUSPLUS_BUILD_STATIC_LIB)
+//# define CPLUSPLUS_EXPORT
+//# else
+//# define CPLUSPLUS_EXPORT Q_DECL_IMPORT
+//# endif
+//#else
+# define CPLUSPLUS_EXPORT
+#endif
+
+namespace CPlusPlus {
+
+class TranslationUnit;
+class Control;
+class MemoryPool;
+class DiagnosticClient;
+
+class Identifier;
+class Literal;
+class StringLiteral;
+class NumericLiteral;
+
+class SymbolTable;
+
+// names
+class NameVisitor;
+class Name;
+class Identifier;
+class TemplateNameId;
+class DestructorNameId;
+class OperatorNameId;
+class ConversionNameId;
+class QualifiedNameId;
+class SelectorNameId;
+
+// types
+class TypeMatcher;
+class FullySpecifiedType;
+class TypeVisitor;
+class Type;
+class UndefinedType;
+class VoidType;
+class IntegerType;
+class FloatType;
+class PointerToMemberType;
+class PointerType;
+class ReferenceType;
+class ArrayType;
+class NamedType;
+
+// symbols
+class SymbolVisitor;
+class Symbol;
+class Scope;
+class UsingNamespaceDirective;
+class UsingDeclaration;
+class Declaration;
+class Argument;
+class TypenameArgument;
+class Function;
+class Namespace;
+class NamespaceAlias;
+class Template;
+class BaseClass;
+class Block;
+class Class;
+class Enum;
+class ForwardClassDeclaration;
+
+class Token;
+
+// Objective-C symbols
+class ObjCBaseClass;
+class ObjCBaseProtocol;
+class ObjCClass;
+class ObjCForwardClassDeclaration;
+class ObjCProtocol;
+class ObjCForwardProtocolDeclaration;
+class ObjCMethod;
+class ObjCPropertyDeclaration;
+
+} // end of namespace CPlusPlus
+
+#endif // CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H
diff --git a/src/plugins/scanner/cpp/Lexer.cpp b/src/plugins/scanner/cpp/Lexer.cpp
new file mode 100644
index 000000000..6d6f22e18
--- /dev/null
+++ b/src/plugins/scanner/cpp/Lexer.cpp
@@ -0,0 +1,669 @@
+/**************************************************************************
+**
+** This file is part of the Qt Build Suite
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file.
+** Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** 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.
+**
+**************************************************************************/
+
+// 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 "Lexer.h"
+#include <cctype>
+
+using namespace CPlusPlus;
+
+Lexer::Lexer(const char *firstChar, const char *lastChar)
+ : _state(State_Default),
+ _flags(0),
+ _currentLine(1)
+{
+ setSource(firstChar, lastChar);
+}
+
+Lexer::~Lexer()
+{ }
+
+void Lexer::setSource(const char *firstChar, const char *lastChar)
+{
+ _firstChar = firstChar;
+ _lastChar = lastChar;
+ _currentChar = _firstChar - 1;
+ _tokenStart = _currentChar;
+ _yychar = '\n';
+}
+
+void Lexer::setStartWithNewline(bool enabled)
+{
+ if (enabled)
+ _yychar = '\n';
+ else
+ _yychar = ' ';
+}
+
+int Lexer::state() const
+{ return _state; }
+
+void Lexer::setState(int state)
+{ _state = state; }
+
+bool Lexer::qtMocRunEnabled() const
+{ return f._qtMocRunEnabled; }
+
+void Lexer::setQtMocRunEnabled(bool onoff)
+{ f._qtMocRunEnabled = onoff; }
+
+bool Lexer::cxx0xEnabled() const
+{ return f._cxx0xEnabled; }
+
+void Lexer::setCxxOxEnabled(bool onoff)
+{ f._cxx0xEnabled = onoff; }
+
+bool Lexer::objCEnabled() const
+{ return f._objCEnabled; }
+
+void Lexer::setObjCEnabled(bool onoff)
+{ f._objCEnabled = onoff; }
+
+bool Lexer::isIncremental() const
+{ return f._isIncremental; }
+
+void Lexer::setIncremental(bool isIncremental)
+{ f._isIncremental = isIncremental; }
+
+bool Lexer::scanCommentTokens() const
+{ return f._scanCommentTokens; }
+
+void Lexer::setScanCommentTokens(bool onoff)
+{ f._scanCommentTokens = onoff; }
+
+void Lexer::setScanAngleStringLiteralTokens(bool onoff)
+{ f._scanAngleStringLiteralTokens = onoff; }
+
+void Lexer::pushLineStartOffset()
+{
+ ++_currentLine;
+}
+
+unsigned Lexer::tokenOffset() const
+{ return _tokenStart - _firstChar; }
+
+unsigned Lexer::tokenLength() const
+{ return _currentChar - _tokenStart; }
+
+const char *Lexer::tokenBegin() const
+{ return _tokenStart; }
+
+const char *Lexer::tokenEnd() const
+{ return _currentChar; }
+
+unsigned Lexer::currentLine() const
+{ return _currentLine; }
+
+void Lexer::scan(Token *tok)
+{
+ tok->reset();
+ scan_helper(tok);
+ tok->f.length = _currentChar - _tokenStart;
+}
+
+void Lexer::scan_helper(Token *tok)
+{
+ _Lagain:
+ while (_yychar && std::isspace(_yychar)) {
+ if (_yychar == '\n') {
+ tok->f.joined = false;
+ tok->f.newline = true;
+ } else {
+ tok->f.whitespace = true;
+ }
+ yyinp();
+ }
+
+ tok->lineno = _currentLine;
+ _tokenStart = _currentChar;
+ tok->offset = _currentChar - _firstChar;
+
+ if (_state == State_MultiLineComment || _state == State_MultiLineDoxyComment) {
+ const int originalState = _state;
+
+ if (! _yychar) {
+ tok->f.kind = T_EOF_SYMBOL;
+ return;
+ }
+
+ while (_yychar) {
+ if (_yychar != '*')
+ yyinp();
+ else {
+ yyinp();
+ if (_yychar == '/') {
+ yyinp();
+ _state = State_Default;
+ break;
+ }
+ }
+ }
+
+ if (! f._scanCommentTokens)
+ goto _Lagain;
+
+ else if (originalState == State_MultiLineComment)
+ tok->f.kind = T_COMMENT;
+ else
+ tok->f.kind = T_DOXY_COMMENT;
+ return; // done
+ }
+
+ if (! _yychar) {
+ tok->f.kind = T_EOF_SYMBOL;
+ return;
+ }
+
+ unsigned char ch = _yychar;
+ yyinp();
+
+ switch (ch) {
+ case '\\':
+ while (_yychar != '\n' && std::isspace(_yychar))
+ yyinp();
+ // ### assert(! _yychar || _yychar == '\n');
+ if (_yychar == '\n') {
+ tok->f.joined = true;
+ tok->f.newline = false;
+ yyinp();
+ }
+ goto _Lagain;
+
+ case '"': case '\'': {
+ const char quote = ch;
+
+ tok->f.kind = quote == '"'
+ ? T_STRING_LITERAL
+ : T_CHAR_LITERAL;
+
+ while (_yychar && _yychar != quote) {
+ if (_yychar == '\n')
+ break;
+ else if (_yychar != '\\')
+ yyinp();
+ else {
+ yyinp(); // skip `\\'
+
+ if (_yychar)
+ yyinp();
+ }
+ }
+ // assert(_yychar == quote);
+
+ if (_yychar == quote)
+ yyinp();
+ } break;
+
+ case '{':
+ tok->f.kind = T_LBRACE;
+ break;
+
+ case '}':
+ tok->f.kind = T_RBRACE;
+ break;
+
+ case '[':
+ tok->f.kind = T_LBRACKET;
+ break;
+
+ case ']':
+ tok->f.kind = T_RBRACKET;
+ break;
+
+ case '#':
+ if (_yychar == '#') {
+ tok->f.kind = T_POUND_POUND;
+ yyinp();
+ } else {
+ tok->f.kind = T_POUND;
+ }
+ break;
+
+ case '(':
+ tok->f.kind = T_LPAREN;
+ break;
+
+ case ')':
+ tok->f.kind = T_RPAREN;
+ break;
+
+ case ';':
+ tok->f.kind = T_SEMICOLON;
+ break;
+
+ case ':':
+ if (_yychar == ':') {
+ yyinp();
+ tok->f.kind = T_COLON_COLON;
+ } else {
+ tok->f.kind = T_COLON;
+ }
+ break;
+
+ case '.':
+ if (_yychar == '*') {
+ yyinp();
+ tok->f.kind = T_DOT_STAR;
+ } else if (_yychar == '.') {
+ yyinp();
+ // ### assert(_yychar);
+ if (_yychar == '.') {
+ yyinp();
+ tok->f.kind = T_DOT_DOT_DOT;
+ } else {
+ tok->f.kind = T_ERROR;
+ }
+ } else if (std::isdigit(_yychar)) {
+ do {
+ if (_yychar == 'e' || _yychar == 'E') {
+ yyinp();
+ if (_yychar == '-' || _yychar == '+') {
+ yyinp();
+ // ### assert(std::isdigit(_yychar));
+ }
+ } else if (std::isalnum(_yychar) || _yychar == '.') {
+ yyinp();
+ } else {
+ break;
+ }
+ } while (_yychar);
+ tok->f.kind = T_NUMERIC_LITERAL;
+ } else {
+ tok->f.kind = T_DOT;
+ }
+ break;
+
+ case '?':
+ tok->f.kind = T_QUESTION;
+ break;
+
+ case '+':
+ if (_yychar == '+') {
+ yyinp();
+ tok->f.kind = T_PLUS_PLUS;
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_PLUS_EQUAL;
+ } else {
+ tok->f.kind = T_PLUS;
+ }
+ break;
+
+ case '-':
+ if (_yychar == '-') {
+ yyinp();
+ tok->f.kind = T_MINUS_MINUS;
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_MINUS_EQUAL;
+ } else if (_yychar == '>') {
+ yyinp();
+ if (_yychar == '*') {
+ yyinp();
+ tok->f.kind = T_ARROW_STAR;
+ } else {
+ tok->f.kind = T_ARROW;
+ }
+ } else {
+ tok->f.kind = T_MINUS;
+ }
+ break;
+
+ case '*':
+ if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_STAR_EQUAL;
+ } else {
+ tok->f.kind = T_STAR;
+ }
+ break;
+
+ case '/':
+ if (_yychar == '/') {
+ yyinp();
+
+ bool doxy = false;
+
+ if (_yychar == '/' || _yychar == '!') {
+ yyinp();
+
+ if (_yychar == '<')
+ yyinp();
+
+ if (_yychar != '\n' && std::isspace(_yychar))
+ doxy = true;
+ }
+
+ while (_yychar && _yychar != '\n')
+ yyinp();
+
+ if (! f._scanCommentTokens)
+ goto _Lagain;
+
+ tok->f.kind = doxy ? T_CPP_DOXY_COMMENT : T_CPP_COMMENT;
+
+ } else if (_yychar == '*') {
+ yyinp();
+
+ bool doxy = false;
+
+ if (_yychar == '*' || _yychar == '!') {
+ const char ch = _yychar;
+
+ yyinp();
+
+ if (ch == '*' && _yychar == '/')
+ goto _Ldone;
+
+ if (_yychar == '<')
+ yyinp();
+
+ if (! _yychar || std::isspace(_yychar))
+ doxy = true;
+ }
+
+ while (_yychar) {
+ if (_yychar != '*') {
+ yyinp();
+ } else {
+ yyinp();
+ if (_yychar == '/')
+ break;
+ }
+ }
+
+ _Ldone:
+ if (_yychar)
+ yyinp();
+ else
+ _state = doxy ? State_MultiLineDoxyComment : State_MultiLineComment;
+
+ if (! f._scanCommentTokens)
+ goto _Lagain;
+
+ tok->f.kind = doxy ? T_DOXY_COMMENT : T_COMMENT;
+
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_SLASH_EQUAL;
+ } else {
+ tok->f.kind = T_SLASH;
+ }
+ break;
+
+ case '%':
+ if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_PERCENT_EQUAL;
+ } else {
+ tok->f.kind = T_PERCENT;
+ }
+ break;
+
+ case '^':
+ if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_CARET_EQUAL;
+ } else {
+ tok->f.kind = T_CARET;
+ }
+ break;
+
+ case '&':
+ if (_yychar == '&') {
+ yyinp();
+ tok->f.kind = T_AMPER_AMPER;
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_AMPER_EQUAL;
+ } else {
+ tok->f.kind = T_AMPER;
+ }
+ break;
+
+ case '|':
+ if (_yychar == '|') {
+ yyinp();
+ tok->f.kind = T_PIPE_PIPE;
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_PIPE_EQUAL;
+ } else {
+ tok->f.kind = T_PIPE;
+ }
+ break;
+
+ case '~':
+ if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_TILDE_EQUAL;
+ } else {
+ tok->f.kind = T_TILDE;
+ }
+ break;
+
+ case '!':
+ if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_EXCLAIM_EQUAL;
+ } else {
+ tok->f.kind = T_EXCLAIM;
+ }
+ break;
+
+ case '=':
+ if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_EQUAL_EQUAL;
+ } else {
+ tok->f.kind = T_EQUAL;
+ }
+ break;
+
+ case '<':
+ if (f._scanAngleStringLiteralTokens) {
+ const char *yytext = _currentChar;
+ while (_yychar && _yychar != '>')
+ yyinp();
+ int yylen = _currentChar - yytext;
+ // ### assert(_yychar == '>');
+ if (_yychar == '>')
+ yyinp();
+ tok->f.kind = T_ANGLE_STRING_LITERAL;
+ } else if (_yychar == '<') {
+ yyinp();
+ if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_LESS_LESS_EQUAL;
+ } else
+ tok->f.kind = T_LESS_LESS;
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_LESS_EQUAL;
+ } else {
+ tok->f.kind = T_LESS;
+ }
+ break;
+
+ case '>':
+ if (_yychar == '>') {
+ yyinp();
+ if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_GREATER_GREATER_EQUAL;
+ } else
+ tok->f.kind = T_LESS_LESS;
+ tok->f.kind = T_GREATER_GREATER;
+ } else if (_yychar == '=') {
+ yyinp();
+ tok->f.kind = T_GREATER_EQUAL;
+ } else {
+ tok->f.kind = T_GREATER;
+ }
+ break;
+
+ case ',':
+ tok->f.kind = T_COMMA;
+ break;
+
+ default: {
+ if (f._objCEnabled) {
+ if (ch == '@' && _yychar >= 'a' && _yychar <= 'z') {
+ const char *yytext = _currentChar;
+
+ do {
+ yyinp();
+ if (! (isalnum(_yychar) || _yychar == '_' || _yychar == '$'))
+ break;
+ } while (_yychar);
+
+ const int yylen = _currentChar - yytext;
+ //tok->f.kind = classifyObjCAtKeyword(yytext, yylen); /// ### FIXME
+ break;
+ } else if (ch == '@' && _yychar == '"') {
+ // objc @string literals
+ ch = _yychar;
+ yyinp();
+ tok->f.kind = T_AT_STRING_LITERAL;
+
+ const char *yytext = _currentChar;
+
+ while (_yychar && _yychar != '"') {
+ if (_yychar != '\\')
+ yyinp();
+ else {
+ yyinp(); // skip `\\'
+
+ if (_yychar)
+ yyinp();
+ }
+ }
+ // assert(_yychar == '"');
+
+ int yylen = _currentChar - yytext;
+
+ if (_yychar == '"')
+ yyinp();
+
+ break;
+ }
+ }
+
+ if (ch == 'L' && (_yychar == '"' || _yychar == '\'')) {
+ // wide char/string literals
+ ch = _yychar;
+ yyinp();
+
+ const char quote = ch;
+
+ tok->f.kind = quote == '"'
+ ? T_WIDE_STRING_LITERAL
+ : T_WIDE_CHAR_LITERAL;
+
+ const char *yytext = _currentChar;
+
+ while (_yychar && _yychar != quote) {
+ if (_yychar != '\\')
+ yyinp();
+ else {
+ yyinp(); // skip `\\'
+
+ if (_yychar)
+ yyinp();
+ }
+ }
+ // assert(_yychar == quote);
+
+ int yylen = _currentChar - yytext;
+
+ if (_yychar == quote)
+ yyinp();
+
+ } else if (std::isalpha(ch) || ch == '_' || ch == '$') {
+ const char *yytext = _currentChar - 1;
+ while (std::isalnum(_yychar) || _yychar == '_' || _yychar == '$')
+ yyinp();
+ int yylen = _currentChar - yytext;
+ tok->f.kind = T_IDENTIFIER;
+ break;
+ } else if (std::isdigit(ch)) {
+ const char *yytext = _currentChar - 1;
+ while (_yychar) {
+ if (_yychar == 'e' || _yychar == 'E') {
+ yyinp();
+ if (_yychar == '-' || _yychar == '+') {
+ yyinp();
+ // ### assert(std::isdigit(_yychar));
+ }
+ } else if (std::isalnum(_yychar) || _yychar == '.') {
+ yyinp();
+ } else {
+ break;
+ }
+ }
+ int yylen = _currentChar - yytext;
+ tok->f.kind = T_NUMERIC_LITERAL;
+ break;
+ } else {
+ tok->f.kind = T_ERROR;
+ break;
+ }
+ } // default
+
+ } // switch
+}
+
+
diff --git a/src/plugins/scanner/cpp/Lexer.h b/src/plugins/scanner/cpp/Lexer.h
new file mode 100644
index 000000000..e697bad9a
--- /dev/null
+++ b/src/plugins/scanner/cpp/Lexer.h
@@ -0,0 +1,162 @@
+/**************************************************************************
+**
+** This file is part of the Qt Build Suite
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file.
+** Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** 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.
+**
+**************************************************************************/
+
+// 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.
+
+#ifndef CPLUSPLUS_LEXER_H
+#define CPLUSPLUS_LEXER_H
+
+#include "CPlusPlusForwardDeclarations.h"
+#include "Token.h"
+
+
+namespace CPlusPlus {
+
+class CPLUSPLUS_EXPORT Lexer
+{
+ Lexer(const Lexer &other);
+ void operator =(const Lexer &other);
+
+public:
+ enum State {
+ State_Default,
+ State_MultiLineComment,
+ State_MultiLineDoxyComment
+ };
+
+ Lexer(const char *firstChar, const char *lastChar);
+ ~Lexer();
+
+ bool qtMocRunEnabled() const;
+ void setQtMocRunEnabled(bool onoff);
+
+ bool cxx0xEnabled() const;
+ void setCxxOxEnabled(bool onoff);
+
+ bool objCEnabled() const;
+ void setObjCEnabled(bool onoff);
+
+ void scan(Token *tok);
+
+ inline void operator()(Token *tok)
+ { scan(tok); }
+
+ unsigned tokenOffset() const;
+ unsigned tokenLength() const;
+ const char *tokenBegin() const;
+ const char *tokenEnd() const;
+ unsigned currentLine() const;
+
+ bool scanCommentTokens() const;
+ void setScanCommentTokens(bool onoff);
+
+ bool scanAngleStringLiteralTokens() const;
+ void setScanAngleStringLiteralTokens(bool onoff);
+
+ void setStartWithNewline(bool enabled);
+
+ int state() const;
+ void setState(int state);
+
+ bool isIncremental() const;
+ void setIncremental(bool isIncremental);
+
+private:
+ void scan_helper(Token *tok);
+ void setSource(const char *firstChar, const char *lastChar);
+ static int classify(const char *string, int length, bool q, bool cxx0x);
+ static int classifyObjCAtKeyword(const char *s, int n);
+ static int classifyOperator(const char *string, int length);
+
+ inline void yyinp()
+ {
+ if (++_currentChar == _lastChar)
+ _yychar = 0;
+ else {
+ _yychar = *_currentChar;
+ if (_yychar == '\n')
+ pushLineStartOffset();
+ }
+ }
+
+ void pushLineStartOffset();
+
+private:
+ struct Flags {
+ unsigned _isIncremental: 1;
+ unsigned _scanCommentTokens: 1;
+ unsigned _scanAngleStringLiteralTokens: 1;
+ unsigned _qtMocRunEnabled: 1;
+ unsigned _cxx0xEnabled: 1;
+ unsigned _objCEnabled: 1;
+ };
+
+ const char *_firstChar;
+ const char *_currentChar;
+ const char *_lastChar;
+ const char *_tokenStart;
+ unsigned char _yychar;
+ int _state;
+ union {
+ unsigned _flags;
+ Flags f;
+ };
+ unsigned _currentLine;
+};
+
+} // end of namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_LEXER_H
diff --git a/src/plugins/scanner/cpp/Token.cpp b/src/plugins/scanner/cpp/Token.cpp
new file mode 100644
index 000000000..066e3c469
--- /dev/null
+++ b/src/plugins/scanner/cpp/Token.cpp
@@ -0,0 +1,154 @@
+/**************************************************************************
+**
+** This file is part of the Qt Build Suite
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file.
+** Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** 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.
+**
+**************************************************************************/
+
+// 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 "Token.h"
+#ifndef CPLUSPLUS_NO_PARSER
+# include "Literals.h"
+#endif
+
+using namespace CPlusPlus;
+
+static const char *token_names[] = {
+ (""), ("<error>"),
+
+ ("<C++ comment>"), ("<C++ doxy comment>"),
+ ("<comment>"), ("<doxy comment>"),
+
+ ("<identifier>"), ("<numeric literal>"), ("<char literal>"),
+ ("<wide char literal>"), ("<string literal>"), ("<wide char literal>"),
+ ("<@string literal>"), ("<angle string literal>"),
+
+ ("&"), ("&&"), ("&="), ("->"), ("->*"), ("^"), ("^="), (":"), ("::"),
+ (","), ("/"), ("/="), ("."), ("..."), (".*"), ("="), ("=="), ("!"),
+ ("!="), (">"), (">="), (">>"), (">>="), ("{"), ("["), ("<"), ("<="),
+ ("<<"), ("<<="), ("("), ("-"), ("-="), ("--"), ("%"), ("%="), ("|"),
+ ("|="), ("||"), ("+"), ("+="), ("++"), ("#"), ("##"), ("?"), ("}"),
+ ("]"), (")"), (";"), ("*"), ("*="), ("~"), ("~="),
+
+ ("asm"), ("auto"), ("bool"), ("break"), ("case"), ("catch"), ("char"),
+ ("class"), ("const"), ("const_cast"), ("continue"), ("default"),
+ ("delete"), ("do"), ("double"), ("dynamic_cast"), ("else"), ("enum"),
+ ("explicit"), ("export"), ("extern"), ("false"), ("float"), ("for"),
+ ("friend"), ("goto"), ("if"), ("inline"), ("int"), ("long"),
+ ("mutable"), ("namespace"), ("new"), ("operator"), ("private"),
+ ("protected"), ("public"), ("register"), ("reinterpret_cast"),
+ ("return"), ("short"), ("signed"), ("sizeof"), ("static"),
+ ("static_cast"), ("struct"), ("switch"), ("template"), ("this"),
+ ("throw"), ("true"), ("try"), ("typedef"), ("typeid"), ("typename"),
+ ("union"), ("unsigned"), ("using"), ("virtual"), ("void"),
+ ("volatile"), ("wchar_t"), ("while"),
+
+ // gnu
+ ("__attribute__"), ("__typeof__"),
+
+ // objc @keywords
+ ("@catch"), ("@class"), ("@compatibility_alias"), ("@defs"), ("@dynamic"),
+ ("@encode"), ("@end"), ("@finally"), ("@implementation"), ("@interface"),
+ ("@not_keyword"), ("@optional"), ("@package"), ("@private"), ("@property"),
+ ("@protected"), ("@protocol"), ("@public"), ("@required"), ("@selector"),
+ ("@synchronized"), ("@synthesize"), ("@throw"), ("@try"),
+
+ // Qt keywords
+ ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"),
+ ("Q_FOREACH"), ("Q_D"), ("Q_Q"),
+ ("Q_INVOKABLE"), ("Q_PROPERTY"), ("Q_INTERFACES"), ("Q_ENUMS"), ("Q_FLAGS"),
+ ("Q_PRIVATE_SLOT"), ("Q_DECLARE_INTERFACE"), ("Q_OBJECT"), ("Q_GADGET"),
+
+};
+
+Token::Token() :
+ flags(0), offset(0), ptr(0)
+{
+}
+
+Token::~Token()
+{
+}
+
+void Token::reset()
+{
+ flags = 0;
+ offset = 0;
+ ptr = 0;
+}
+
+const char *Token::name(int kind)
+{ return token_names[kind]; }
+
+#ifndef CPLUSPLUS_NO_PARSER
+const char *Token::spell() const
+{
+ switch (f.kind) {
+ case T_IDENTIFIER:
+ return identifier->chars();
+
+ case T_NUMERIC_LITERAL:
+ case T_CHAR_LITERAL:
+ case T_STRING_LITERAL:
+ case T_AT_STRING_LITERAL:
+ case T_ANGLE_STRING_LITERAL:
+ case T_WIDE_CHAR_LITERAL:
+ case T_WIDE_STRING_LITERAL:
+ return literal->chars();
+
+ default:
+ return token_names[f.kind];
+ } // switch
+}
+#endif
+
+
diff --git a/src/plugins/scanner/cpp/Token.h b/src/plugins/scanner/cpp/Token.h
new file mode 100644
index 000000000..140af2f42
--- /dev/null
+++ b/src/plugins/scanner/cpp/Token.h
@@ -0,0 +1,371 @@
+/**************************************************************************
+**
+** This file is part of the Qt Build Suite
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file.
+** Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** 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.
+**
+**************************************************************************/
+
+// 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.
+
+#ifndef CPLUSPLUS_TOKEN_H
+#define CPLUSPLUS_TOKEN_H
+
+#include "CPlusPlusForwardDeclarations.h"
+
+namespace CPlusPlus {
+
+enum Kind {
+ T_EOF_SYMBOL = 0,
+ T_ERROR,
+
+ T_CPP_COMMENT,
+ T_CPP_DOXY_COMMENT,
+ T_COMMENT,
+ T_DOXY_COMMENT,
+ T_IDENTIFIER,
+
+ T_FIRST_LITERAL,
+ T_NUMERIC_LITERAL = T_FIRST_LITERAL,
+ T_CHAR_LITERAL,
+ T_WIDE_CHAR_LITERAL,
+ T_STRING_LITERAL,
+ T_WIDE_STRING_LITERAL,
+ T_AT_STRING_LITERAL,
+ T_ANGLE_STRING_LITERAL,
+ T_LAST_LITERAL = T_ANGLE_STRING_LITERAL,
+
+ T_FIRST_OPERATOR,
+ T_AMPER = T_FIRST_OPERATOR,
+ T_AMPER_AMPER,
+ T_AMPER_EQUAL,
+ T_ARROW,
+ T_ARROW_STAR,
+ T_CARET,
+ T_CARET_EQUAL,
+ T_COLON,
+ T_COLON_COLON,
+ T_COMMA,
+ T_SLASH,
+ T_SLASH_EQUAL,
+ T_DOT,
+ T_DOT_DOT_DOT,
+ T_DOT_STAR,
+ T_EQUAL,
+ T_EQUAL_EQUAL,
+ T_EXCLAIM,
+ T_EXCLAIM_EQUAL,
+ T_GREATER,
+ T_GREATER_EQUAL,
+ T_GREATER_GREATER,
+ T_GREATER_GREATER_EQUAL,
+ T_LBRACE,
+ T_LBRACKET,
+ T_LESS,
+ T_LESS_EQUAL,
+ T_LESS_LESS,
+ T_LESS_LESS_EQUAL,
+ T_LPAREN,
+ T_MINUS,
+ T_MINUS_EQUAL,
+ T_MINUS_MINUS,
+ T_PERCENT,
+ T_PERCENT_EQUAL,
+ T_PIPE,
+ T_PIPE_EQUAL,
+ T_PIPE_PIPE,
+ T_PLUS,
+ T_PLUS_EQUAL,
+ T_PLUS_PLUS,
+ T_POUND,
+ T_POUND_POUND,
+ T_QUESTION,
+ T_RBRACE,
+ T_RBRACKET,
+ T_RPAREN,
+ T_SEMICOLON,
+ T_STAR,
+ T_STAR_EQUAL,
+ T_TILDE,
+ T_TILDE_EQUAL,
+ T_LAST_OPERATOR = T_TILDE_EQUAL,
+
+ T_FIRST_KEYWORD,
+ T_ASM = T_FIRST_KEYWORD,
+ T_AUTO,
+ T_BOOL,
+ T_BREAK,
+ T_CASE,
+ T_CATCH,
+ T_CHAR,
+ T_CLASS,
+ T_CONST,
+ T_CONST_CAST,
+ T_CONTINUE,
+ T_DEFAULT,
+ T_DELETE,
+ T_DO,
+ T_DOUBLE,
+ T_DYNAMIC_CAST,
+ T_ELSE,
+ T_ENUM,
+ T_EXPLICIT,
+ T_EXPORT,
+ T_EXTERN,
+ T_FALSE,
+ T_FLOAT,
+ T_FOR,
+ T_FRIEND,
+ T_GOTO,
+ T_IF,
+ T_INLINE,
+ T_INT,
+ T_LONG,
+ T_MUTABLE,
+ T_NAMESPACE,
+ T_NEW,
+ T_OPERATOR,
+ T_PRIVATE,
+ T_PROTECTED,
+ T_PUBLIC,
+ T_REGISTER,
+ T_REINTERPRET_CAST,
+ T_RETURN,
+ T_SHORT,
+ T_SIGNED,
+ T_SIZEOF,
+ T_STATIC,
+ T_STATIC_CAST,
+ T_STRUCT,
+ T_SWITCH,
+ T_TEMPLATE,
+ T_THIS,
+ T_THROW,
+ T_TRUE,
+ T_TRY,
+ T_TYPEDEF,
+ T_TYPEID,
+ T_TYPENAME,
+ T_UNION,
+ T_UNSIGNED,
+ T_USING,
+ T_VIRTUAL,
+ T_VOID,
+ T_VOLATILE,
+ T_WCHAR_T,
+ T_WHILE,
+
+ T___ATTRIBUTE__,
+ T___TYPEOF__,
+
+ // obj c++ @ keywords
+ T_FIRST_OBJC_AT_KEYWORD,
+
+ T_AT_CATCH = T_FIRST_OBJC_AT_KEYWORD,
+ T_AT_CLASS,
+ T_AT_COMPATIBILITY_ALIAS,
+ T_AT_DEFS,
+ T_AT_DYNAMIC,
+ T_AT_ENCODE,
+ T_AT_END,
+ T_AT_FINALLY,
+ T_AT_IMPLEMENTATION,
+ T_AT_INTERFACE,
+ T_AT_NOT_KEYWORD,
+ T_AT_OPTIONAL,
+ T_AT_PACKAGE,
+ T_AT_PRIVATE,
+ T_AT_PROPERTY,
+ T_AT_PROTECTED,
+ T_AT_PROTOCOL,
+ T_AT_PUBLIC,
+ T_AT_REQUIRED,
+ T_AT_SELECTOR,
+ T_AT_SYNCHRONIZED,
+ T_AT_SYNTHESIZE,
+ T_AT_THROW,
+ T_AT_TRY,
+
+ T_LAST_OBJC_AT_KEYWORD = T_AT_TRY,
+
+ T_FIRST_QT_KEYWORD,
+
+ // Qt keywords
+ T_SIGNAL = T_FIRST_QT_KEYWORD,
+ T_SLOT,
+ T_Q_SIGNAL,
+ T_Q_SLOT,
+ T_Q_SIGNALS,
+ T_Q_SLOTS,
+ T_Q_FOREACH,
+ T_Q_D,
+ T_Q_Q,
+ T_Q_INVOKABLE,
+ T_Q_PROPERTY,
+ T_Q_INTERFACES,
+ T_Q_ENUMS,
+ T_Q_FLAGS,
+ T_Q_PRIVATE_SLOT,
+ T_Q_DECLARE_INTERFACE,
+ T_Q_OBJECT,
+ T_Q_GADGET,
+ T_LAST_KEYWORD = T_Q_GADGET,
+
+ // aliases
+ T_OR = T_PIPE_PIPE,
+ T_AND = T_AMPER_AMPER,
+ T_NOT = T_EXCLAIM,
+ T_XOR = T_CARET,
+ T_BITOR = T_PIPE,
+ T_COMPL = T_TILDE,
+ T_OR_EQ = T_PIPE_EQUAL,
+ T_AND_EQ = T_AMPER_EQUAL,
+ T_BITAND = T_AMPER,
+ T_NOT_EQ = T_EXCLAIM_EQUAL,
+ T_XOR_EQ = T_CARET_EQUAL,
+
+ T___ASM = T_ASM,
+ T___ASM__ = T_ASM,
+
+ T_TYPEOF = T___TYPEOF__,
+ T___TYPEOF = T___TYPEOF__,
+
+ T___INLINE = T_INLINE,
+ T___INLINE__ = T_INLINE,
+
+ T___CONST = T_CONST,
+ T___CONST__ = T_CONST,
+
+ T___VOLATILE = T_VOLATILE,
+ T___VOLATILE__ = T_VOLATILE,
+
+ T___ATTRIBUTE = T___ATTRIBUTE__
+};
+
+class CPLUSPLUS_EXPORT Token
+{
+public:
+ Token();
+ ~Token();
+
+ inline bool is(unsigned k) const { return f.kind == k; }
+ inline bool isNot(unsigned k) const { return f.kind != k; }
+#ifndef CPLUSPLUS_NO_PARSER
+ const char *spell() const;
+#endif
+ void reset();
+
+ inline unsigned kind() const { return f.kind; }
+ inline bool newline() const { return f.newline; }
+ inline bool whitespace() const { return f.whitespace; }
+ inline bool joined() const { return f.joined; }
+ inline bool expanded() const { return f.expanded; }
+ inline bool generated() const { return f.generated; }
+ inline unsigned length() const { return f.length; }
+
+ inline unsigned begin() const
+ { return offset; }
+
+ inline unsigned end() const
+ { return offset + f.length; }
+
+ inline bool isLiteral() const
+ { return f.kind >= T_FIRST_LITERAL && f.kind <= T_LAST_LITERAL; }
+
+ inline bool isOperator() const
+ { return f.kind >= T_FIRST_OPERATOR && f.kind <= T_LAST_OPERATOR; }
+
+ inline bool isKeyword() const
+ { return f.kind >= T_FIRST_KEYWORD && f.kind < T_FIRST_QT_KEYWORD; }
+
+ inline bool isComment() const
+ { return f.kind == T_COMMENT || f.kind == T_DOXY_COMMENT ||
+ f.kind == T_CPP_COMMENT || f.kind == T_CPP_DOXY_COMMENT; }
+
+ inline bool isObjCAtKeyword() const
+ { return f.kind >= T_FIRST_OBJC_AT_KEYWORD && f.kind <= T_LAST_OBJC_AT_KEYWORD; }
+
+ static const char *name(int kind);
+
+public:
+ struct Flags {
+ unsigned kind : 8;
+ unsigned newline : 1;
+ unsigned whitespace : 1;
+ unsigned joined : 1;
+ unsigned expanded : 1;
+ unsigned generated : 1;
+ unsigned pad : 3;
+ unsigned length : 16;
+ };
+ union {
+ unsigned flags;
+ Flags f;
+ };
+
+ unsigned offset;
+
+ union {
+ void *ptr;
+#ifndef CPLUSPLUS_NO_PARSER
+ const Literal *literal;
+ const NumericLiteral *number;
+ const StringLiteral *string;
+ const Identifier *identifier;
+#endif
+ unsigned close_brace;
+ unsigned lineno;
+ };
+};
+
+} // end of namespace CPlusPlus
+
+
+#endif // CPLUSPLUS_TOKEN_H
diff --git a/src/plugins/scanner/cpp/cpp.cpp b/src/plugins/scanner/cpp/cpp.cpp
new file mode 100644
index 000000000..3fde5b6cc
--- /dev/null
+++ b/src/plugins/scanner/cpp/cpp.cpp
@@ -0,0 +1,281 @@
+/**************************************************************************
+**
+** This file is part of the Qt Build Suite
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file.
+** Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** 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.
+**
+**************************************************************************/
+
+#include "../scanner.h"
+#include "cpp_global.h"
+#include <Lexer.h>
+
+using namespace CPlusPlus;
+
+#ifdef Q_OS_UNIX
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#else
+#include <QtCore/QFile>
+#endif
+
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QString>
+
+struct ScanResult
+{
+ char *fileName;
+ unsigned int size;
+ int flags;
+};
+
+struct Opaq
+{
+ enum FileType
+ {
+ FT_UNKNOWN, FT_HPP, FT_CPP
+ };
+
+ Opaq()
+ :
+#ifdef Q_OS_UNIX
+ fd(0),
+ mapl(0),
+#endif
+ fileContent(0),
+ fileType(FT_UNKNOWN),
+ hasQObjectMacro(false),
+ currentResultIndex(0)
+ {}
+
+ ~Opaq()
+ {
+#ifdef Q_OS_UNIX
+ if (fileContent)
+ munmap(fileContent, mapl);
+ if (fd)
+ close(fd);
+#endif
+ }
+
+#ifdef Q_OS_WIN
+ QFile file;
+#endif
+#ifdef Q_OS_UNIX
+ int fd;
+ size_t mapl;
+#endif
+
+ QString fileName;
+ char *fileContent;
+ FileType fileType;
+ QList<ScanResult> includedFiles;
+ bool hasQObjectMacro;
+ int currentResultIndex;
+};
+
+static void scanCppFile(void *opaq, Lexer &yylex, bool scanForFileTags)
+{
+ static const size_t lengthOfIncludeLiteral = strlen("include");
+ Opaq *opaque = static_cast<Opaq *>(opaq);
+ Token tk;
+ ScanResult scanResult;
+
+ yylex(&tk);
+
+ while (tk.isNot(T_EOF_SYMBOL)) {
+ if (tk.newline() && tk.is(T_POUND)) {
+ yylex(&tk);
+
+ if (!scanForFileTags && !tk.newline() && tk.is(T_IDENTIFIER)) {
+ if (tk.length() >= lengthOfIncludeLiteral
+ && (strncmp(opaque->fileContent + tk.begin(), "include", lengthOfIncludeLiteral) == 0))
+ {
+ yylex.setScanAngleStringLiteralTokens(true);
+ yylex(&tk);
+ yylex.setScanAngleStringLiteralTokens(false);
+
+ if (!tk.newline() && (tk.is(T_STRING_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL))) {
+ scanResult.size = tk.length() - 2;
+ if (tk.is(T_STRING_LITERAL))
+ scanResult.flags = SC_LOCAL_INCLUDE_FLAG;
+ else
+ scanResult.flags = SC_GLOBAL_INCLUDE_FLAG;
+ scanResult.fileName = opaque->fileContent + tk.begin() + 1;
+ opaque->includedFiles.append(scanResult);
+ }
+ }
+ }
+ } else if (tk.is(T_IDENTIFIER) && !opaque->hasQObjectMacro) {
+ if (scanForFileTags
+ && tk.length() == 8
+ && opaque->fileContent[tk.begin()] == 'Q'
+ && opaque->fileContent[tk.begin() + 1] == '_'
+ && (strncmp(opaque->fileContent + tk.begin() + 2, "OBJECT", 6) == 0
+ || strncmp(opaque->fileContent + tk.begin() + 2, "GADGET", 6) == 0))
+ {
+ opaque->hasQObjectMacro = true;
+ break;
+ }
+ }
+ yylex(&tk);
+ }
+}
+
+static void *openScanner(const unsigned short *filePath, char **fileTags, int numFileTags)
+{
+ QScopedPointer<Opaq> opaque(new Opaq);
+ opaque->fileName = QString::fromUtf16(filePath);
+
+ size_t mapl = 0;
+#ifdef Q_OS_UNIX
+ QString filePathS = opaque->fileName;
+
+ opaque->fd = open(qPrintable(filePathS), O_RDONLY);
+ if (opaque->fd == -1) {
+ opaque->fd = 0;
+ return 0;
+ }
+
+ struct stat s;
+ int r = fstat(opaque->fd, &s);
+ if (r != 0)
+ return 0;
+ mapl = s.st_size;
+ opaque->mapl = mapl;
+
+ void *vmap = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, opaque->fd, 0);
+ if (vmap == MAP_FAILED)
+ return 0;
+#else
+ opaque->file.setFileName(opaque->fileName);
+ if (!opaque->file.open(QFile::ReadOnly))
+ return 0;
+
+ uchar *vmap = opaque->file.map(0, opaque->file.size());
+ mapl = opaque->file.size();
+#endif
+ if (!vmap)
+ return 0;
+
+ for (int i=0; i < numFileTags; ++i) {
+ const char *fileTag = fileTags[i];
+ if (strncmp("cpp", fileTag, 3) == 0)
+ opaque->fileType = Opaq::FT_CPP;
+ else if (strncmp("hpp", fileTag, 3) == 0)
+ opaque->fileType = Opaq::FT_HPP;
+ }
+
+ opaque->fileContent = reinterpret_cast<char *>(vmap);
+ Lexer lex(opaque->fileContent, opaque->fileContent + mapl);
+ const bool scanForFileTags = fileTags && numFileTags;
+ scanCppFile(opaque.data(), lex, scanForFileTags);
+ return static_cast<void *>(opaque.take());
+}
+
+static void closeScanner(void *ptr)
+{
+ Opaq *opaque = static_cast<Opaq *>(ptr);
+ delete opaque;
+}
+
+static const char *next(void *opaq, int *size, int *flags)
+{
+ Opaq *opaque = static_cast<Opaq*>(opaq);
+ if (opaque->currentResultIndex < opaque->includedFiles.count()) {
+ const ScanResult &result = opaque->includedFiles.at(opaque->currentResultIndex);
+ ++opaque->currentResultIndex;
+ *size = result.size;
+ *flags = result.flags;
+ return result.fileName;
+ }
+ *size = 0;
+ *flags = 0;
+ return 0;
+}
+
+static const char **additionalFileTags(void *opaq, int *size)
+{
+ static const char *thMocCpp[] = { "moc_cpp" };
+ static const char *thMocHpp[] = { "moc_hpp" };
+
+ Opaq *opaque = static_cast<Opaq*>(opaq);
+ if (opaque->hasQObjectMacro) {
+ *size = 1;
+ switch (opaque->fileType) {
+ case Opaq::FT_CPP:
+ return thMocCpp;
+ case Opaq::FT_HPP:
+ return thMocHpp;
+ default:
+ break;
+ }
+ }
+ *size = 0;
+ return 0;
+}
+
+extern "C" {
+
+ScannerPlugin hppScanner =
+{
+ "include_scanner",
+ "hpp",
+ openScanner,
+ closeScanner,
+ next,
+ additionalFileTags
+};
+
+ScannerPlugin cppScanner =
+{
+ "include_scanner",
+ "cpp",
+ openScanner,
+ closeScanner,
+ next,
+ additionalFileTags
+};
+
+ScannerPlugin *theScanners[3] = {&hppScanner, &cppScanner, NULL};
+
+CPPSCANNER_EXPORT ScannerPlugin **getScanners()
+{
+ return theScanners;
+}
+
+} // extern "C"
diff --git a/src/plugins/scanner/cpp/cpp.pro b/src/plugins/scanner/cpp/cpp.pro
new file mode 100644
index 000000000..e5d4d8381
--- /dev/null
+++ b/src/plugins/scanner/cpp/cpp.pro
@@ -0,0 +1,15 @@
+DEFINES += CPLUSPLUS_NO_PARSER
+
+DESTDIR= ../../../../plugins/
+TEMPLATE = lib
+TARGET = qbs_cpp_scanner
+DEPENDPATH += .
+INCLUDEPATH += .
+
+QT = core
+
+unix: CONFIG += plugin
+
+HEADERS += CPlusPlusForwardDeclarations.h Lexer.h Token.h ../scanner.h \
+ cpp_global.h
+SOURCES += cpp.cpp Lexer.cpp Token.cpp
diff --git a/src/plugins/scanner/cpp/cpp_global.h b/src/plugins/scanner/cpp/cpp_global.h
new file mode 100644
index 000000000..1e57911dd
--- /dev/null
+++ b/src/plugins/scanner/cpp/cpp_global.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+**
+** This file is part of the Qt Build Suite
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file.
+** Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** 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.
+**
+**************************************************************************/
+
+#ifndef CPP_GLOBAL_H
+#define CPP_GLOBAL_H
+
+#if defined(WIN32) || defined(_WIN32)
+#define CPPSCANNER_EXPORT __declspec(dllexport)
+#else
+#define CPPSCANNER_EXPORT
+#endif
+
+#endif // CPP_GLOBAL_H
diff --git a/src/plugins/scanner/qt/qt.cpp b/src/plugins/scanner/qt/qt.cpp
new file mode 100644
index 000000000..66d59e59a
--- /dev/null
+++ b/src/plugins/scanner/qt/qt.cpp
@@ -0,0 +1,227 @@
+/**************************************************************************
+**
+** This file is part of the Qt Build Suite
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file.
+** Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** 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.
+**
+**************************************************************************/
+
+#if defined(WIN32) || defined(_WIN32)
+#define SCANNER_EXPORT __declspec(dllexport)
+#else
+#define SCANNER_EXPORT
+#endif
+
+#include "../scanner.h"
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_UNIX
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#else
+#include <QtCore/QFile>
+#endif
+
+#include <QtCore/QString>
+#include <QtCore/QXmlStreamReader>
+#include <QtCore/QScopedPointer>
+
+
+#include <QDebug>
+
+struct Opaq
+{
+#ifdef Q_OS_UNIX
+ int fd;
+ int mapl;
+#else
+ QFile *file;
+#endif
+
+ char *map;
+ QXmlStreamReader *xml;
+ QByteArray current;
+ Opaq()
+#ifdef Q_OS_UNIX
+ : fd (0),
+#else
+ : file(0),
+#endif
+ map(0),
+ xml(0)
+ {}
+
+ ~Opaq()
+ {
+#ifdef Q_OS_UNIX
+ if (map)
+ munmap (map, mapl);
+ if (fd)
+ close (fd);
+#else
+ delete file;
+#endif
+ delete xml;
+ }
+};
+
+static void *openScanner(const unsigned short *filePath, char **fileTags, int numFileTags)
+{
+ Q_UNUSED(fileTags);
+ Q_UNUSED(numFileTags);
+ QScopedPointer<Opaq> opaque(new Opaq);
+
+#ifdef Q_OS_UNIX
+ QString filePathS = QString::fromUtf16(filePath);
+ opaque->fd = open(qPrintable(filePathS), O_RDONLY);
+ if (opaque->fd == -1) {
+ opaque->fd = 0;
+ return 0;
+ }
+
+ struct stat s;
+ int r = fstat(opaque->fd, &s);
+ if (r != 0)
+ return 0;
+ opaque->mapl = s.st_size;
+
+ void *map = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, opaque->fd, 0);
+ if (map == 0)
+ return 0;
+#else
+ opaque->file = new QFile(QString::fromUtf16(filePath));
+ if (!opaque->file->open(QFile::ReadOnly))
+ return 0;
+
+ uchar *map = opaque->file->map(0, opaque->file->size());
+ if (!map)
+ return 0;
+#endif
+
+ opaque->map = reinterpret_cast<char *>(map);
+ opaque->xml = new QXmlStreamReader(opaque->map);
+
+ return static_cast<void *>(opaque.take());
+}
+
+static void closeScanner(void *ptr)
+{
+ Opaq *opaque = static_cast<Opaq *>(ptr);
+ delete opaque;
+}
+
+static const char *nextUi(void *opaq, int *size, int *flags)
+{
+ Opaq *o= static_cast<Opaq *>(opaq);
+ while (!o->xml->atEnd()) {
+ o->xml->readNext();
+ switch (o->xml->tokenType()) {
+ case QXmlStreamReader::StartElement:
+ if ( o->xml->name() == "include") {
+ o->current = o->xml->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).toUtf8();
+ *flags = SC_GLOBAL_INCLUDE_FLAG;
+ *size = o->current.size();
+ return o->current.data();
+ }
+ break;
+ case QXmlStreamReader::EndDocument:
+ return 0;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+static const char *nextQrc(void *opaq, int *size, int *flags)
+{
+ Opaq *o= static_cast<Opaq *>(opaq);
+ while (!o->xml->atEnd()) {
+ o->xml->readNext();
+ switch (o->xml->tokenType()) {
+ case QXmlStreamReader::StartElement:
+ if ( o->xml->name() == "file") {
+ o->current = o->xml->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).toUtf8();
+ *flags = SC_LOCAL_INCLUDE_FLAG;
+ *size = o->current.size();
+ return o->current.data();
+ }
+ break;
+ case QXmlStreamReader::EndDocument:
+ return 0;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+static const char **additionalFileTags(void *, int *size)
+{
+ *size = 0;
+ return 0;
+}
+
+extern "C" {
+
+ScannerPlugin uiScanner =
+{
+ "qt_ui_scanner",
+ "ui",
+ openScanner,
+ closeScanner,
+ nextUi,
+ additionalFileTags
+};
+
+ScannerPlugin qrcScanner =
+{
+ "qt_qrc_scanner",
+ "qrc",
+ openScanner,
+ closeScanner,
+ nextQrc,
+ additionalFileTags
+};
+
+ScannerPlugin *theScanners[3] = {&uiScanner, &qrcScanner, NULL};
+
+SCANNER_EXPORT ScannerPlugin **getScanners()
+{
+ return theScanners;
+}
+
+} // extern "C"
diff --git a/src/plugins/scanner/qt/qt.pro b/src/plugins/scanner/qt/qt.pro
new file mode 100644
index 000000000..c825e9d15
--- /dev/null
+++ b/src/plugins/scanner/qt/qt.pro
@@ -0,0 +1,12 @@
+DESTDIR= ../../../../plugins
+TEMPLATE = lib
+TARGET = qbs_qt_scanner
+DEPENDPATH += .
+INCLUDEPATH += .
+
+Qt = core xml
+
+unix: CONFIG += plugin
+
+HEADERS += ../scanner.h
+SOURCES += qt.cpp
diff --git a/src/plugins/scanner/scanner.h b/src/plugins/scanner/scanner.h
new file mode 100644
index 000000000..402112d8e
--- /dev/null
+++ b/src/plugins/scanner/scanner.h
@@ -0,0 +1,93 @@
+/**************************************************************************
+**
+** This file is part of the Qt Build Suite
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file.
+** Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** 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.
+**
+**************************************************************************/
+#ifndef SCANNER_H
+#define SCANNER_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SC_LOCAL_INCLUDE_FLAG 0x1
+#define SC_GLOBAL_INCLUDE_FLAG 0x2
+
+/**
+ * Open a file that's going to be scanned.
+ * The file path encoding is UTF-16 on all platforms.
+ *
+ * If the scanner is used for more than one type hint (e.g. C++ header / source)
+ * the scanner can read the parameter fileTag which file type it is going to scan.
+ *
+ * Returns a scanner handle.
+ */
+typedef void *(*scanOpen_f) (const unsigned short *filePath, char **fileTags, int numFileTags);
+
+/**
+ * Closes the given scanner handle.
+ */
+typedef void (*scanClose_f) (void *opaq);
+
+/**
+ * Return the next result (filename) of the scan.
+ */
+typedef const char *(*scanNext_f) (void *opaq, int *size, int *flags);
+
+/**
+ * Returns a list of type hints for the scanned file.
+ * May return null.
+ *
+ * Example: if a C++ header file contains Q_OBJECT,
+ * the type hint 'moc_hpp' is returned.
+ */
+typedef const char** (*scanAdditionalFileTags_f) (void *opaq, int *size);
+
+struct ScannerPlugin
+{
+ const char *name;
+ const char *fileTag;
+ scanOpen_f open;
+ scanClose_f close;
+ scanNext_f next;
+ scanAdditionalFileTags_f additionalFileTags;
+};
+
+typedef ScannerPlugin **(*getScanners_f)();
+
+#ifdef __cplusplus
+}
+#endif
+#endif // SCANNER_H
diff --git a/src/plugins/scanner/scanner.pro b/src/plugins/scanner/scanner.pro
new file mode 100644
index 000000000..68acae7da
--- /dev/null
+++ b/src/plugins/scanner/scanner.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS = cpp qt
+