Merge branch 'master' of git@scm.dev.nokia.troll.no:creator/mainline

This commit is contained in:
hjk
2009-02-23 16:07:28 +01:00
42 changed files with 4641 additions and 577 deletions

View File

@@ -117,6 +117,13 @@ Macro *Environment::bind(const Macro &__macro)
return m; return m;
} }
void Environment::addMacros(const QList<Macro> &macros)
{
foreach (const Macro &macro, macros) {
bind(macro);
}
}
Macro *Environment::remove(const QByteArray &name) Macro *Environment::remove(const QByteArray &name)
{ {
Macro macro; Macro macro;
@@ -127,6 +134,23 @@ Macro *Environment::remove(const QByteArray &name)
return bind(macro); return bind(macro);
} }
void Environment::reset()
{
if (_macros) {
qDeleteAll(firstMacro(), lastMacro());
free(_macros);
}
if (_hash)
free(_hash);
_macros = 0;
_allocated_macros = 0;
_macro_count = -1;
_hash = 0;
_hash_count = 401;
}
bool Environment::isBuiltinMacro(const QByteArray &s) const bool Environment::isBuiltinMacro(const QByteArray &s) const
{ {
if (s.length() != 8) if (s.length() != 8)

View File

@@ -56,6 +56,7 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
#include <QVector> #include <QVector>
#include <QList>
#include <QByteArray> #include <QByteArray>
namespace CPlusPlus { namespace CPlusPlus {
@@ -89,6 +90,9 @@ public:
Macro **lastMacro() Macro **lastMacro()
{ return _macros + _macro_count + 1; } { return _macros + _macro_count + 1; }
void reset();
void addMacros(const QList<Macro> &macros);
private: private:
static unsigned hashCode(const QByteArray &s); static unsigned hashCode(const QByteArray &s);
void rehash(); void rehash();

View File

@@ -54,6 +54,11 @@ bool SimpleToken::isKeyword() const
return _kind >= T_FIRST_KEYWORD && _kind < T_FIRST_QT_KEYWORD; return _kind >= T_FIRST_KEYWORD && _kind < T_FIRST_QT_KEYWORD;
} }
bool SimpleToken::isComment() const
{
return _kind == T_COMMENT || _kind == T_DOXY_COMMENT;
}
SimpleLexer::SimpleLexer() SimpleLexer::SimpleLexer()
: _lastState(0), : _lastState(0),
_skipComments(false), _skipComments(false),

View File

@@ -69,6 +69,7 @@ public:
bool isLiteral() const; bool isLiteral() const;
bool isOperator() const; bool isOperator() const;
bool isKeyword() const; bool isKeyword() const;
bool isComment() const;
public: public:
int _kind; int _kind;

View File

@@ -49,6 +49,9 @@ TokenUnderCursor::~TokenUnderCursor()
SimpleToken TokenUnderCursor::operator()(const QTextCursor &cursor) const SimpleToken TokenUnderCursor::operator()(const QTextCursor &cursor) const
{ {
SimpleLexer tokenize; SimpleLexer tokenize;
tokenize.setObjCEnabled(true);
tokenize.setSkipComments(false);
QTextBlock block = cursor.block(); QTextBlock block = cursor.block();
int column = cursor.columnNumber(); int column = cursor.columnNumber();

View File

@@ -43,6 +43,7 @@
<glob pattern="*.c++"/> <glob pattern="*.c++"/>
<glob pattern="*.C"/> <glob pattern="*.C"/>
<glob pattern="*.inl"/> <glob pattern="*.inl"/>
<glob pattern="*.qdoc"/>
</mime-type> </mime-type>
<mime-type type="text/x-objcsrc"> <mime-type type="text/x-objcsrc">

View File

@@ -740,7 +740,9 @@ void CPPEditor::setFontSettings(const TextEditor::FontSettings &fs)
<< QLatin1String(TextEditor::Constants::C_OPERATOR) << QLatin1String(TextEditor::Constants::C_OPERATOR)
<< QLatin1String(TextEditor::Constants::C_PREPROCESSOR) << QLatin1String(TextEditor::Constants::C_PREPROCESSOR)
<< QLatin1String(TextEditor::Constants::C_LABEL) << QLatin1String(TextEditor::Constants::C_LABEL)
<< QLatin1String(TextEditor::Constants::C_COMMENT); << QLatin1String(TextEditor::Constants::C_COMMENT)
<< QLatin1String(TextEditor::Constants::C_DOXYGEN_COMMENT)
<< QLatin1String(TextEditor::Constants::C_DOXYGEN_TAG);
} }
const QVector<QTextCharFormat> formats = fs.toTextCharFormats(categories); const QVector<QTextCharFormat> formats = fs.toTextCharFormats(categories);

View File

@@ -16,6 +16,7 @@ HEADERS += cppplugin.h \
cppeditorenums.h \ cppeditorenums.h \
cppeditor_global.h \ cppeditor_global.h \
cppclasswizard.h cppclasswizard.h
SOURCES += cppplugin.cpp \ SOURCES += cppplugin.cpp \
cppeditoractionhandler.cpp \ cppeditoractionhandler.cpp \
cppeditor.cpp \ cppeditor.cpp \
@@ -23,4 +24,5 @@ SOURCES += cppplugin.cpp \
cpphoverhandler.cpp \ cpphoverhandler.cpp \
cppfilewizard.cpp \ cppfilewizard.cpp \
cppclasswizard.cpp cppclasswizard.cpp
RESOURCES += cppeditor.qrc RESOURCES += cppeditor.qrc

View File

@@ -51,6 +51,8 @@ enum CppFormats {
CppPreprocessorFormat, CppPreprocessorFormat,
CppLabelFormat, CppLabelFormat,
CppCommentFormat, CppCommentFormat,
CppDoxygenCommentFormat,
CppDoxygenTagFormat,
NumCppFormats NumCppFormats
}; };

View File

@@ -32,6 +32,7 @@
***************************************************************************/ ***************************************************************************/
#include "cpphighlighter.h" #include "cpphighlighter.h"
#include <cpptools/cppdoxygen.h>
#include <Token.h> #include <Token.h>
#include <cplusplus/SimpleLexer.h> #include <cplusplus/SimpleLexer.h>
@@ -115,23 +116,35 @@ void CppHighlighter::highlightBlock(const QString &text)
} }
bool highlightCurrentWordAsPreprocessor = highlightAsPreprocessor; bool highlightCurrentWordAsPreprocessor = highlightAsPreprocessor;
if (highlightAsPreprocessor) if (highlightAsPreprocessor)
highlightAsPreprocessor = false; highlightAsPreprocessor = false;
if (i == 0 && tk.is(T_POUND)) { if (i == 0 && tk.is(T_POUND)) {
setFormat(tk.position(), tk.length(), m_formats[CppPreprocessorFormat]); setFormat(tk.position(), tk.length(), m_formats[CppPreprocessorFormat]);
highlightAsPreprocessor = true; highlightAsPreprocessor = true;
} else if (highlightCurrentWordAsPreprocessor && } else if (highlightCurrentWordAsPreprocessor &&
(tk.isKeyword() || tk.is(T_IDENTIFIER)) && isPPKeyword(tk.text())) (tk.isKeyword() || tk.is(T_IDENTIFIER)) && isPPKeyword(tk.text()))
setFormat(tk.position(), tk.length(), m_formats[CppPreprocessorFormat]); setFormat(tk.position(), tk.length(), m_formats[CppPreprocessorFormat]);
else if (tk.is(T_INT_LITERAL) || tk.is(T_FLOAT_LITERAL)) else if (tk.is(T_INT_LITERAL) || tk.is(T_FLOAT_LITERAL))
setFormat(tk.position(), tk.length(), m_formats[CppNumberFormat]); setFormat(tk.position(), tk.length(), m_formats[CppNumberFormat]);
else if (tk.is(T_STRING_LITERAL) || tk.is(T_CHAR_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL)) else if (tk.is(T_STRING_LITERAL) || tk.is(T_CHAR_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL))
setFormat(tk.position(), tk.length(), m_formats[CppStringFormat]); setFormat(tk.position(), tk.length(), m_formats[CppStringFormat]);
else if (tk.is(T_WIDE_STRING_LITERAL) || tk.is(T_WIDE_CHAR_LITERAL)) else if (tk.is(T_WIDE_STRING_LITERAL) || tk.is(T_WIDE_CHAR_LITERAL))
setFormat(tk.position(), tk.length(), m_formats[CppStringFormat]); setFormat(tk.position(), tk.length(), m_formats[CppStringFormat]);
else if (tk.is(T_COMMENT)) {
else if (tk.isComment()) {
if (tk.is(T_COMMENT))
setFormat(tk.position(), tk.length(), m_formats[CppCommentFormat]); setFormat(tk.position(), tk.length(), m_formats[CppCommentFormat]);
else // a doxygen comment
highlightDoxygenComment(text, tk.position(), tk.length());
// we need to insert a close comment parenthesis, if // we need to insert a close comment parenthesis, if
// - the line starts in a C Comment (initalState != 0) // - the line starts in a C Comment (initalState != 0)
// - the first token of the line is a T_COMMENT (i == 0 && tk.is(T_COMMENT)) // - the first token of the line is a T_COMMENT (i == 0 && tk.is(T_COMMENT))
@@ -145,12 +158,16 @@ void CppHighlighter::highlightBlock(const QString &text)
// clear the initial state. // clear the initial state.
initialState = 0; initialState = 0;
} }
} else if (tk.isKeyword() || isQtKeyword(tk.text())) } else if (tk.isKeyword() || isQtKeyword(tk.text()))
setFormat(tk.position(), tk.length(), m_formats[CppKeywordFormat]); setFormat(tk.position(), tk.length(), m_formats[CppKeywordFormat]);
else if (tk.isOperator()) else if (tk.isOperator())
setFormat(tk.position(), tk.length(), m_formats[CppOperatorFormat]); setFormat(tk.position(), tk.length(), m_formats[CppOperatorFormat]);
else if (i == 0 && tokens.size() > 1 && tk.is(T_IDENTIFIER) && tokens.at(1).is(T_COLON)) else if (i == 0 && tokens.size() > 1 && tk.is(T_IDENTIFIER) && tokens.at(1).is(T_COLON))
setFormat(tk.position(), tk.length(), m_formats[CppLabelFormat]); setFormat(tk.position(), tk.length(), m_formats[CppLabelFormat]);
else if (tk.is(T_IDENTIFIER)) else if (tk.is(T_IDENTIFIER))
highlightWord(tk.text(), tk.position(), tk.length()); highlightWord(tk.text(), tk.position(), tk.length());
} }
@@ -304,3 +321,36 @@ void CppHighlighter::highlightWord(QStringRef word, int position, int length)
setFormat(position, length, m_formats[CppTypeFormat]); setFormat(position, length, m_formats[CppTypeFormat]);
} }
} }
void CppHighlighter::highlightDoxygenComment(const QString &text, int position, int)
{
int initial = position;
const QChar *uc = text.unicode();
const QChar *it = uc + position;
const QTextCharFormat &format = m_formats[CppDoxygenCommentFormat];
const QTextCharFormat &kwFormat = m_formats[CppDoxygenTagFormat];
while (! it->isNull()) {
if (it->unicode() == QLatin1Char('\\') ||
it->unicode() == QLatin1Char('@')) {
++it;
const QChar *start = it;
while (it->isLetterOrNumber() || it->unicode() == '_')
++it;
int k = CppTools::classifyDoxygenTag(start, it - start);
if (k != CppTools::T_DOXY_IDENTIFIER) {
setFormat(initial, start - uc - initial, format);
setFormat(start - uc - 1, it - start + 1, kwFormat);
initial = it - uc;
}
} else
++it;
}
setFormat(initial, it - uc - initial, format);
}

View File

@@ -61,6 +61,10 @@ public:
private: private:
void highlightWord(QStringRef word, int position, int length); void highlightWord(QStringRef word, int position, int length);
void highlightDoxygenComment(const QString &text, int position,
int length);
bool isPPKeyword(const QStringRef &text) const; bool isPPKeyword(const QStringRef &text) const;
bool isQtKeyword(const QStringRef &text) const; bool isQtKeyword(const QStringRef &text) const;

View File

@@ -32,8 +32,8 @@
***************************************************************************/ ***************************************************************************/
#include "cppcodecompletion.h" #include "cppcodecompletion.h"
#include "cppmodelmanager.h" #include "cppmodelmanager.h"
#include "cppdoxygen.h"
#include <Control.h> #include <Control.h>
#include <AST.h> #include <AST.h>
@@ -371,45 +371,53 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
const QChar ch3 = pos > 1 ? editor->characterAt(pos - 3) : QChar(); const QChar ch3 = pos > 1 ? editor->characterAt(pos - 3) : QChar();
int start = pos; int start = pos;
int k = T_EOF_SYMBOL;
if (ch2 != QLatin1Char('.') && ch == QLatin1Char('.')) { if (ch2 != QLatin1Char('.') && ch == QLatin1Char('.')) {
if (kind) k = T_DOT;
*kind = T_DOT;
--start; --start;
} else if (wantFunctionCall && ch == QLatin1Char('(')) { } else if (wantFunctionCall && ch == QLatin1Char('(')) {
if (kind) k = T_LPAREN;
*kind = T_LPAREN;
--start; --start;
} else if (ch2 == QLatin1Char(':') && ch == QLatin1Char(':')) { } else if (ch2 == QLatin1Char(':') && ch == QLatin1Char(':')) {
if (kind) k = T_COLON_COLON;
*kind = T_COLON_COLON;
start -= 2; start -= 2;
} else if (ch2 == QLatin1Char('-') && ch == QLatin1Char('>')) { } else if (ch2 == QLatin1Char('-') && ch == QLatin1Char('>')) {
if (kind) k = T_ARROW;
*kind = T_ARROW;
start -= 2; start -= 2;
} else if (ch2 == QLatin1Char('.') && ch == QLatin1Char('*')) { } else if (ch2 == QLatin1Char('.') && ch == QLatin1Char('*')) {
if (kind) k = T_DOT_STAR;
*kind = T_DOT_STAR;
start -= 2; start -= 2;
} else if (ch3 == QLatin1Char('-') && ch2 == QLatin1Char('>') && ch == QLatin1Char('*')) { } else if (ch3 == QLatin1Char('-') && ch2 == QLatin1Char('>') && ch == QLatin1Char('*')) {
if (kind) k = T_ARROW_STAR;
*kind = T_ARROW_STAR;
start -= 3; start -= 3;
} else if (ch == QLatin1Char('@') || ch == QLatin1Char('\\')) {
k = T_DOXY_COMMENT;
--start;
} }
if (start != pos) { if (start == pos)
return start;
TextEditor::BaseTextEditor *edit = qobject_cast<TextEditor::BaseTextEditor *>(editor->widget()); TextEditor::BaseTextEditor *edit = qobject_cast<TextEditor::BaseTextEditor *>(editor->widget());
QTextCursor tc(edit->textCursor()); QTextCursor tc(edit->textCursor());
tc.setPosition(pos); tc.setPosition(pos);
static CPlusPlus::TokenUnderCursor tokenUnderCursor; static CPlusPlus::TokenUnderCursor tokenUnderCursor;
const SimpleToken tk = tokenUnderCursor(tc); const SimpleToken tk = tokenUnderCursor(tc);
if (tk.is(T_COMMENT) || tk.isLiteral()) {
if (k == T_DOXY_COMMENT && tk.isNot(T_DOXY_COMMENT)) {
k = T_EOF_SYMBOL;
start = pos;
}
else if (tk.is(T_COMMENT) || tk.isLiteral()) {
k = T_EOF_SYMBOL;
start = pos;
}
if (kind) if (kind)
*kind = T_EOF_SYMBOL; *kind = k;
return pos;
}
}
return start; return start;
} }
@@ -457,15 +465,32 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
ExpressionUnderCursor expressionUnderCursor; ExpressionUnderCursor expressionUnderCursor;
QString expression; QString expression;
if (m_completionOperator == T_DOXY_COMMENT) {
for (int i = 1; i < T_DOXY_LAST_TAG; ++i) {
TextEditor::CompletionItem item(this);
item.m_text.append(QString::fromLatin1(doxygenTagSpell(i)));
item.m_icon = m_icons.keywordIcon();
m_completions.append(item);
}
return m_startPosition;
}
if (m_completionOperator) { if (m_completionOperator) {
QTextCursor tc(edit->document()); QTextCursor tc(edit->document());
tc.setPosition(endOfExpression); tc.setPosition(endOfExpression);
expression = expressionUnderCursor(tc); expression = expressionUnderCursor(tc);
if (m_completionOperator == T_LPAREN) { if (m_completionOperator == T_LPAREN) {
if (expression.endsWith(QLatin1String("SIGNAL"))) if (expression.endsWith(QLatin1String("SIGNAL")))
m_completionOperator = T_SIGNAL; m_completionOperator = T_SIGNAL;
else if (expression.endsWith(QLatin1String("SLOT"))) else if (expression.endsWith(QLatin1String("SLOT")))
m_completionOperator = T_SLOT; m_completionOperator = T_SLOT;
else if (editor->position() != endOfOperator) { else if (editor->position() != endOfOperator) {
// We don't want a function completion when the cursor isn't at the opening brace // We don't want a function completion when the cursor isn't at the opening brace
expression.clear(); expression.clear();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,264 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 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 GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "cpptools_global.h"
namespace CppTools {
enum DoxygenReservedWord {
T_DOXY_IDENTIFIER,
T_DOXY_ARG,
T_DOXY_ATTENTION,
T_DOXY_AUTHOR,
T_DOXY_CALLGRAPH,
T_DOXY_CODE,
T_DOXY_DOT,
T_DOXY_ELSE,
T_DOXY_ENDCODE,
T_DOXY_ENDCOND,
T_DOXY_ENDDOT,
T_DOXY_ENDHTMLONLY,
T_DOXY_ENDIF,
T_DOXY_ENDLATEXONLY,
T_DOXY_ENDLINK,
T_DOXY_ENDMANONLY,
T_DOXY_ENDVERBATIM,
T_DOXY_ENDXMLONLY,
T_DOXY_HIDEINITIALIZER,
T_DOXY_HTMLONLY,
T_DOXY_INTERFACE,
T_DOXY_INTERNAL,
T_DOXY_INVARIANT,
T_DOXY_LATEXONLY,
T_DOXY_LI,
T_DOXY_MANONLY,
T_DOXY_N,
T_DOXY_NOSUBGROUPING,
T_DOXY_NOTE,
T_DOXY_ONLY,
T_DOXY_POST,
T_DOXY_PRE,
T_DOXY_REMARKS,
T_DOXY_RETURN,
T_DOXY_RETURNS,
T_DOXY_SA,
T_DOXY_SEE,
T_DOXY_SHOWINITIALIZER,
T_DOXY_SINCE,
T_DOXY_TEST,
T_DOXY_TODO,
T_DOXY_VERBATIM,
T_DOXY_WARNING,
T_DOXY_XMLONLY,
T_DOXY_A,
T_DOXY_ADDTOGROUP,
T_DOXY_ANCHOR,
T_DOXY_B,
T_DOXY_C,
T_DOXY_CLASS,
T_DOXY_COND,
T_DOXY_COPYDOC,
T_DOXY_DEF,
T_DOXY_DONTINCLUDE,
T_DOXY_DOTFILE,
T_DOXY_E,
T_DOXY_ELSEIF,
T_DOXY_EM,
T_DOXY_ENUM,
T_DOXY_EXAMPLE,
T_DOXY_EXCEPTION,
T_DOXY_EXCEPTIONS,
T_DOXY_FILE,
T_DOXY_HTMLINCLUDE,
T_DOXY_IF,
T_DOXY_IFNOT,
T_DOXY_INCLUDE,
T_DOXY_LINK,
T_DOXY_NAMESPACE,
T_DOXY_P,
T_DOXY_PACKAGE,
T_DOXY_REF,
T_DOXY_RELATES,
T_DOXY_RELATESALSO,
T_DOXY_RETVAL,
T_DOXY_THROW,
T_DOXY_THROWS,
T_DOXY_VERBINCLUDE,
T_DOXY_VERSION,
T_DOXY_XREFITEM,
T_DOXY_PARAM,
T_DOXY_IMAGE,
T_DOXY_DEFGROUP,
T_DOXY_PAGE,
T_DOXY_PARAGRAPH,
T_DOXY_SECTION,
T_DOXY_STRUCT,
T_DOXY_SUBSECTION,
T_DOXY_SUBSUBSECTION,
T_DOXY_UNION,
T_DOXY_WEAKGROUP,
T_DOXY_ADDINDEX,
T_DOXY_BRIEF,
T_DOXY_BUG,
T_DOXY_DATE,
T_DOXY_DEPRECATED,
T_DOXY_FN,
T_DOXY_INGROUP,
T_DOXY_LINE,
T_DOXY_MAINPAGE,
T_DOXY_NAME,
T_DOXY_OVERLOAD,
T_DOXY_PAR,
T_DOXY_SHORT,
T_DOXY_SKIP,
T_DOXY_SKIPLINE,
T_DOXY_TYPEDEF,
T_DOXY_UNTIL,
T_DOXY_VAR,
T_FIRST_QDOC_TAG,
T_DOXY_ABSTRACT = T_FIRST_QDOC_TAG,
T_DOXY_BADCODE,
T_DOXY_BASENAME,
T_DOXY_BOLD,
T_DOXY_CAPTION,
T_DOXY_CHAPTER,
T_DOXY_CODELINE,
T_DOXY_DOTS,
T_DOXY_ENDABSTRACT,
T_DOXY_ENDCHAPTER,
T_DOXY_ENDFOOTNOTE,
T_DOXY_ENDLEGALESE,
T_DOXY_ENDLIST,
T_DOXY_ENDOMIT,
T_DOXY_ENDPART,
T_DOXY_ENDQUOTATION,
T_DOXY_ENDRAW,
T_DOXY_ENDSECTION1,
T_DOXY_ENDSECTION2,
T_DOXY_ENDSECTION3,
T_DOXY_ENDSECTION4,
T_DOXY_ENDSIDEBAR,
T_DOXY_ENDTABLE,
T_DOXY_EXPIRE,
T_DOXY_FOOTNOTE,
T_DOXY_GENERATELIST,
T_DOXY_GRANULARITY,
T_DOXY_HEADER,
T_DOXY_I,
T_DOXY_INDEX,
T_DOXY_INLINEIMAGE,
T_DOXY_KEYWORD,
T_DOXY_L,
T_DOXY_LEGALESE,
T_DOXY_LIST,
T_DOXY_META,
T_DOXY_NEWCODE,
T_DOXY_O,
T_DOXY_OLDCODE,
T_DOXY_OMIT,
T_DOXY_OMITVALUE,
T_DOXY_PART,
T_DOXY_PRINTLINE,
T_DOXY_PRINTTO,
T_DOXY_PRINTUNTIL,
T_DOXY_QUOTATION,
T_DOXY_QUOTEFILE,
T_DOXY_QUOTEFROMFILE,
T_DOXY_QUOTEFUNCTION,
T_DOXY_RAW,
T_DOXY_ROW,
T_DOXY_SECTION1,
T_DOXY_SECTION2,
T_DOXY_SECTION3,
T_DOXY_SECTION4,
T_DOXY_SIDEBAR,
T_DOXY_SKIPTO,
T_DOXY_SKIPUNTIL,
T_DOXY_SNIPPET,
T_DOXY_SUB,
T_DOXY_SUP,
T_DOXY_TABLE,
T_DOXY_TABLEOFCONTENTS,
T_DOXY_TARGET,
T_DOXY_TT,
T_DOXY_UNDERLINE,
T_DOXY_UNICODE,
T_DOXY_VALUE,
T_DOXY_CONTENTSPAGE,
T_DOXY_EXTERNALPAGE,
T_DOXY_GROUP,
T_DOXY_HEADERFILE,
T_DOXY_INDEXPAGE,
T_DOXY_INHEADERFILE,
T_DOXY_MACRO,
T_DOXY_MODULE,
T_DOXY_NEXTPAGE,
T_DOXY_PREVIOUSPAGE,
T_DOXY_PROPERTY,
T_DOXY_REIMP,
T_DOXY_SERVICE,
T_DOXY_STARTPAGE,
T_DOXY_VARIABLE,
T_DOXY_COMPAT,
T_DOXY_INMODULE,
T_DOXY_MAINCLASS,
T_DOXY_NONREENTRANT,
T_DOXY_OBSOLETE,
T_DOXY_PRELIMINARY,
T_DOXY_INPUBLICGROUP,
T_DOXY_REENTRANT,
T_DOXY_SUBTITLE,
T_DOXY_THREADSAFE,
T_DOXY_TITLE,
T_DOXY_CORELIB,
T_DOXY_UITOOLS,
T_DOXY_GUI,
T_DOXY_NETWORK,
T_DOXY_OPENGL,
T_DOXY_QT3SUPPORT,
T_DOXY_SVG,
T_DOXY_SQL,
T_DOXY_QTESTLIB,
T_DOXY_WEBKIT,
T_DOXY_XML,
T_DOXY_LAST_TAG
};
CPPTOOLS_EXPORT int classifyDoxygenTag(const QChar *s, int n);
CPPTOOLS_EXPORT const char *doxygenTagSpell(int index);
} // namespace ::CppTools

View File

@@ -48,6 +48,7 @@
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/uniqueidmanager.h> #include <coreplugin/uniqueidmanager.h>
#include <coreplugin/mimedatabase.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/progressmanager/progressmanager.h>
@@ -140,6 +141,10 @@ static const char pp_configuration[] =
"#define restrict\n" "#define restrict\n"
"#define __restrict\n" "#define __restrict\n"
"#define __complex__\n"
"#define __imag__\n"
"#define __real__\n"
// ### add macros for win32 // ### add macros for win32
"#define __cdecl\n" "#define __cdecl\n"
"#define QT_WA(x) x\n" "#define QT_WA(x) x\n"
@@ -164,9 +169,16 @@ public:
void setIncludePaths(const QStringList &includePaths); void setIncludePaths(const QStringList &includePaths);
void setFrameworkPaths(const QStringList &frameworkPaths); void setFrameworkPaths(const QStringList &frameworkPaths);
void setProjectFiles(const QStringList &files); void setProjectFiles(const QStringList &files);
void setTodo(const QStringList &files);
void run(QString &fileName); void run(QString &fileName);
void operator()(QString &fileName); void operator()(QString &fileName);
void resetEnvironment();
const QSet<QString> &todo() const
{ return m_todo; }
public: // attributes public: // attributes
Snapshot snapshot; Snapshot snapshot;
@@ -200,6 +212,7 @@ private:
QStringList m_frameworkPaths; QStringList m_frameworkPaths;
QSet<QString> m_included; QSet<QString> m_included;
CPlusPlus::Document::Ptr m_currentDoc; CPlusPlus::Document::Ptr m_currentDoc;
QSet<QString> m_todo;
}; };
} // namespace Internal } // namespace Internal
@@ -223,9 +236,15 @@ void CppPreprocessor::setFrameworkPaths(const QStringList &frameworkPaths)
void CppPreprocessor::setProjectFiles(const QStringList &files) void CppPreprocessor::setProjectFiles(const QStringList &files)
{ m_projectFiles = files; } { m_projectFiles = files; }
void CppPreprocessor::setTodo(const QStringList &files)
{ m_todo = QSet<QString>::fromList(files); }
void CppPreprocessor::run(QString &fileName) void CppPreprocessor::run(QString &fileName)
{ sourceNeeded(fileName, IncludeGlobal, /*line = */ 0); } { sourceNeeded(fileName, IncludeGlobal, /*line = */ 0); }
void CppPreprocessor::resetEnvironment()
{ env.reset(); }
void CppPreprocessor::operator()(QString &fileName) void CppPreprocessor::operator()(QString &fileName)
{ run(fileName); } { run(fileName); }
@@ -386,7 +405,7 @@ void CppPreprocessor::mergeEnvironment(Document::Ptr doc, QSet<QString> *process
processed->insert(fn); processed->insert(fn);
foreach (Document::Include incl, doc->includes()) { foreach (const Document::Include &incl, doc->includes()) {
QString includedFile = incl.fileName(); QString includedFile = incl.fileName();
if (Document::Ptr includedDoc = snapshot.value(includedFile)) if (Document::Ptr includedDoc = snapshot.value(includedFile))
@@ -395,9 +414,7 @@ void CppPreprocessor::mergeEnvironment(Document::Ptr doc, QSet<QString> *process
run(includedFile); run(includedFile);
} }
foreach (const Macro macro, doc->definedMacros()) { env.addMacros(doc->definedMacros());
env.bind(macro);
}
} }
void CppPreprocessor::startSkippingBlocks(unsigned offset) void CppPreprocessor::startSkippingBlocks(unsigned offset)
@@ -424,55 +441,59 @@ void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type,
if (m_currentDoc) { if (m_currentDoc) {
m_currentDoc->addIncludeFile(fileName, line); m_currentDoc->addIncludeFile(fileName, line);
if (contents.isEmpty() && ! QFileInfo(fileName).isAbsolute()) { if (contents.isEmpty() && ! QFileInfo(fileName).isAbsolute()) {
QString msg; QString msg;
msg += fileName; msg += fileName;
msg += QLatin1String(": No such file or directory"); msg += QLatin1String(": No such file or directory");
Document::DiagnosticMessage d(Document::DiagnosticMessage::Warning, Document::DiagnosticMessage d(Document::DiagnosticMessage::Warning,
m_currentDoc->fileName(), m_currentDoc->fileName(),
env.currentLine, /*column = */ 0, env.currentLine, /*column = */ 0,
msg); msg);
m_currentDoc->addDiagnosticMessage(d); m_currentDoc->addDiagnosticMessage(d);
//qWarning() << "file not found:" << fileName << m_currentDoc->fileName() << env.current_line; //qWarning() << "file not found:" << fileName << m_currentDoc->fileName() << env.current_line;
return;
} }
} }
if (! contents.isEmpty()) { //qDebug() << "parse file:" << fileName << "contents:" << contents.size();
Document::Ptr cachedDoc = snapshot.value(fileName);
if (cachedDoc && m_currentDoc) {
mergeEnvironment(cachedDoc);
} else {
Document::Ptr previousDoc = switchDocument(Document::create(fileName));
const QByteArray previousFile = env.currentFile; Document::Ptr doc = snapshot.value(fileName);
const unsigned previousLine = env.currentLine; if (doc) {
mergeEnvironment(doc);
return;
}
TranslationUnit *unit = m_currentDoc->translationUnit(); doc = Document::create(fileName);
env.currentFile = QByteArray(unit->fileName(), unit->fileNameLength());
Document::Ptr previousDoc = switchDocument(doc);
QByteArray preprocessedCode; QByteArray preprocessedCode;
m_proc(contents, &preprocessedCode); m_proc(fileName.toUtf8(), contents, &preprocessedCode);
//qDebug() << preprocessedCode;
env.currentFile = previousFile; doc->setSource(preprocessedCode);
env.currentLine = previousLine;
m_currentDoc->setSource(preprocessedCode); doc->parse();
m_currentDoc->parse(); doc->check();
#if defined(QTCREATOR_WITH_DUMP_AST) && defined(Q_CC_GNU) #if defined(QTCREATOR_WITH_DUMP_AST) && defined(Q_CC_GNU)
DumpAST dump(m_currentDoc->control()); DumpAST dump(m_currentDoc->control());
dump(m_currentDoc->translationUnit()->ast()); dump(m_currentDoc->translationUnit()->ast());
#endif #endif
m_currentDoc->check(); doc->releaseTranslationUnit();
m_currentDoc->releaseTranslationUnit(); // release the AST and the token stream.
snapshot[fileName] = doc;
if (m_modelManager) if (m_modelManager)
m_modelManager->emitDocumentUpdated(m_currentDoc); m_modelManager->emitDocumentUpdated(m_currentDoc); // ### TODO: compress
(void) switchDocument(previousDoc); (void) switchDocument(previousDoc);
} m_todo.remove(fileName);
}
} }
Document::Ptr CppPreprocessor::switchDocument(Document::Ptr doc) Document::Ptr CppPreprocessor::switchDocument(Document::Ptr doc)
@@ -737,7 +758,7 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc)
QList<TextEditor::BaseTextEditor::BlockRange> blockRanges; QList<TextEditor::BaseTextEditor::BlockRange> blockRanges;
foreach (const Document::Block block, doc->skippedBlocks()) { foreach (const Document::Block &block, doc->skippedBlocks()) {
blockRanges.append(TextEditor::BaseTextEditor::BlockRange(block.begin(), block.end())); blockRanges.append(TextEditor::BaseTextEditor::BlockRange(block.begin(), block.end()));
} }
ed->setIfdefedOutBlocks(blockRanges); ed->setIfdefedOutBlocks(blockRanges);
@@ -750,7 +771,7 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc)
macroFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline); macroFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
QTextCursor c = ed->textCursor(); QTextCursor c = ed->textCursor();
foreach (const Document::Block block, doc->macroUses()) { foreach (const Document::MacroUse &block, doc->macroUses()) {
QTextEdit::ExtraSelection sel; QTextEdit::ExtraSelection sel;
sel.cursor = c; sel.cursor = c;
sel.cursor.setPosition(block.begin()); sel.cursor.setPosition(block.begin());
@@ -771,7 +792,7 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc)
warningFormat.setUnderlineColor(Qt::darkYellow); warningFormat.setUnderlineColor(Qt::darkYellow);
QSet<int> lines; QSet<int> lines;
foreach (const Document::DiagnosticMessage m, doc->diagnosticMessages()) { foreach (const Document::DiagnosticMessage &m, doc->diagnosticMessages()) {
if (m.fileName() != fileName) if (m.fileName() != fileName)
continue; continue;
else if (lines.contains(m.line())) else if (lines.contains(m.line()))
@@ -799,7 +820,7 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc)
} }
QList<Editor> todo; QList<Editor> todo;
foreach (Editor e, todo) { foreach (const Editor &e, todo) {
if (e.widget != ed) if (e.widget != ed)
todo.append(e); todo.append(e);
} }
@@ -822,7 +843,7 @@ void CppModelManager::postEditorUpdate()
void CppModelManager::updateEditorSelections() void CppModelManager::updateEditorSelections()
{ {
foreach (Editor ed, m_todo) { foreach (const Editor &ed, m_todo) {
if (! ed.widget) if (! ed.widget)
continue; continue;
@@ -872,20 +893,40 @@ void CppModelManager::parse(QFutureInterface<void> &future,
if (files.isEmpty()) if (files.isEmpty())
return; return;
foreach (QString file, files) { Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase();
QStringList headers, sources;
Core::MimeType cSourceTy = db->findByType(QLatin1String("text/x-csrc"));
Core::MimeType cppSourceTy = db->findByType(QLatin1String("text/x-c++src"));
foreach (const QString &file, files) {
const QFileInfo fileInfo(file);
if (cSourceTy.matchesFile(fileInfo) || cppSourceTy.matchesFile(fileInfo))
sources.append(file);
else
headers.append(file);
}
foreach (const QString &file, files) {
preproc->snapshot.remove(file); preproc->snapshot.remove(file);
} }
files = sources;
files += headers;
preproc->setTodo(files);
// Change the priority of the background parser thread to idle. // Change the priority of the background parser thread to idle.
QThread::currentThread()->setPriority(QThread::IdlePriority); QThread::currentThread()->setPriority(QThread::IdlePriority);
future.setProgressRange(0, files.size()); future.setProgressRange(0, files.size());
QString conf = QLatin1String(pp_configuration_file); QString conf = QLatin1String(pp_configuration_file);
(void) preproc->run(conf);
const int STEP = 10; const int STEP = 10;
bool processingHeaders = false;
for (int i = 0; i < files.size(); ++i) { for (int i = 0; i < files.size(); ++i) {
if (future.isPaused()) if (future.isPaused())
future.waitForResume(); future.waitForResume();
@@ -893,16 +934,33 @@ void CppModelManager::parse(QFutureInterface<void> &future,
if (future.isCanceled()) if (future.isCanceled())
break; break;
future.setProgressValue(i);
#ifdef CPPTOOLS_DEBUG_PARSING_TIME #ifdef CPPTOOLS_DEBUG_PARSING_TIME
QTime tm; QTime tm;
tm.start(); tm.start();
#endif #endif
QString fileName = files.at(i); QString fileName = files.at(i);
bool isSourceFile = false;
if (cppSourceTy.matchesFile(fileName) || cSourceTy.matchesFile(fileName))
isSourceFile = true;
if (isSourceFile)
(void) preproc->run(conf);
else if (! processingHeaders) {
(void) preproc->run(conf);
processingHeaders = true;
}
preproc->run(fileName); preproc->run(fileName);
future.setProgressValue(files.size() - preproc->todo().size());
if (isSourceFile)
preproc->resetEnvironment();
if (! (i % STEP)) // Yields execution of the current thread. if (! (i % STEP)) // Yields execution of the current thread.
QThread::yieldCurrentThread(); QThread::yieldCurrentThread();

View File

@@ -8,27 +8,29 @@ include(cpptools_dependencies.pri)
DEFINES += QT_NO_CAST_TO_ASCII DEFINES += QT_NO_CAST_TO_ASCII
INCLUDEPATH += . INCLUDEPATH += .
DEFINES += CPPTOOLS_LIBRARY DEFINES += CPPTOOLS_LIBRARY
HEADERS += cpptools_global.h \ HEADERS += completionsettingspage.h \
cppquickopenfilter.h \
cppclassesfilter.h \ cppclassesfilter.h \
searchsymbols.h \
cppfunctionsfilter.h \
completionsettingspage.h
SOURCES += cppquickopenfilter.cpp \
cpptoolseditorsupport.cpp \
cppclassesfilter.cpp \
searchsymbols.cpp \
cppfunctionsfilter.cpp \
completionsettingspage.cpp
# Input
SOURCES += cpptoolsplugin.cpp \
cppmodelmanager.cpp \
cppcodecompletion.cpp
HEADERS += cpptoolsplugin.h \
cppmodelmanager.h \
cppcodecompletion.h \ cppcodecompletion.h \
cppfunctionsfilter.h \
cppmodelmanager.h \
cppmodelmanagerinterface.h \ cppmodelmanagerinterface.h \
cppquickopenfilter.h \
cpptools_global.h \
cpptoolsconstants.h \
cpptoolseditorsupport.h \ cpptoolseditorsupport.h \
cpptoolsconstants.h cpptoolsplugin.h \
searchsymbols.h \
cppdoxygen.h
SOURCES += completionsettingspage.cpp \
cppclassesfilter.cpp \
cppcodecompletion.cpp \
cppfunctionsfilter.cpp \
cppmodelmanager.cpp \
cppquickopenfilter.cpp \
cpptoolseditorsupport.cpp \
cpptoolsplugin.cpp \
searchsymbols.cpp \
cppdoxygen.cpp
FORMS += completionsettingspage.ui FORMS += completionsettingspage.ui

View File

@@ -34,6 +34,8 @@
#ifndef CPPTOOLS_GLOBAL_H #ifndef CPPTOOLS_GLOBAL_H
#define CPPTOOLS_GLOBAL_H #define CPPTOOLS_GLOBAL_H
#include <QtGlobal>
#if defined(CPPTOOLS_LIBRARY) #if defined(CPPTOOLS_LIBRARY)
# define CPPTOOLS_EXPORT Q_DECL_EXPORT # define CPPTOOLS_EXPORT Q_DECL_EXPORT
#else #else

View File

@@ -0,0 +1,34 @@
win32 {
# ---- Detect Debugging Tools For Windows
CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows/sdk"
exists ($$CDB_PATH) {
message("Experimental: Adding support for $$CDB_PATH")
DEFINES+=CDB_ENABLED
CDB_PLATFORM=i386
INCLUDEPATH*=$$CDB_PATH
INCLUDEPATH*=$$PWD
CDB_LIBPATH=$$CDB_PATH/lib/$$CDB_PLATFORM
HEADERS += \
$$PWD/cdbdebugengine.h \
$$PWD/cdbdebugengine_p.h \
$$PWD/cdbdebugeventcallback.h \
$$PWD/cdbdebugoutput.h
SOURCES += \
$$PWD/cdbdebugengine.cpp \
$$PWD/cdbdebugeventcallback.cpp \
$$PWD/cdbdebugoutput.cpp
LIBS += -L$$CDB_LIBPATH Dbghelp.lib dbgeng.lib
} else {
error("Debugging Tools for Windows could not be found in $$CDB_PATH")
}
}

View File

@@ -1,4 +1,38 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 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 GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "cdbdebugengine.h" #include "cdbdebugengine.h"
#include "cdbdebugengine_p.h"
#include "debuggermanager.h" #include "debuggermanager.h"
#include "breakhandler.h" #include "breakhandler.h"
@@ -6,30 +40,28 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QDebug> #include <QtCore/QDebug>
#include <QTimerEvent> #include <QtCore/QTimerEvent>
#include <QFileInfo> #include <QtCore/QFileInfo>
#include <QtCore/QDir>
#define DBGHELP_TRANSLATE_TCHAR #define DBGHELP_TRANSLATE_TCHAR
#include <Dbghelp.h> #include <inc/Dbghelp.h>
using namespace Debugger; using namespace Debugger;
using namespace Debugger::Internal; using namespace Debugger::Internal;
CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *parent, CdbDebugEngine* engine) :
CdbDebugEngine::CdbDebugEngine(DebuggerManager *parent)
: IDebuggerEngine(parent),
m_hDebuggeeProcess(0), m_hDebuggeeProcess(0),
m_hDebuggeeThread(0), m_hDebuggeeThread(0),
//m_hDebuggeeImage(0),
m_bIgnoreNextDebugEvent(false), m_bIgnoreNextDebugEvent(false),
m_watchTimer(-1), m_watchTimer(-1),
m_debugEventCallBack(this), m_debugEventCallBack(engine),
m_debugOutputCallBack(this) m_debugOutputCallBack(engine),
m_engine(engine),
m_debuggerManager(parent),
m_debuggerManagerAccess(parent->engineInterface())
{ {
q = parent;
qq = parent->engineInterface();
HRESULT hr; HRESULT hr;
hr = DebugCreate( __uuidof(IDebugClient5), reinterpret_cast<void**>(&m_pDebugClient)); hr = DebugCreate( __uuidof(IDebugClient5), reinterpret_cast<void**>(&m_pDebugClient));
if (FAILED(hr)) m_pDebugClient = 0; if (FAILED(hr)) m_pDebugClient = 0;
@@ -51,7 +83,7 @@ CdbDebugEngine::CdbDebugEngine(DebuggerManager *parent)
} }
} }
CdbDebugEngine::~CdbDebugEngine() CdbDebugEnginePrivate::~CdbDebugEnginePrivate()
{ {
if (m_pDebugClient) if (m_pDebugClient)
m_pDebugClient->Release(); m_pDebugClient->Release();
@@ -65,17 +97,28 @@ CdbDebugEngine::~CdbDebugEngine()
m_pDebugRegisters->Release(); m_pDebugRegisters->Release();
} }
CdbDebugEngine::CdbDebugEngine(DebuggerManager *parent)
: IDebuggerEngine(parent),
m_d(new CdbDebugEnginePrivate(parent, this))
{
}
CdbDebugEngine::~CdbDebugEngine()
{
delete m_d;
}
void CdbDebugEngine::startWatchTimer() void CdbDebugEngine::startWatchTimer()
{ {
if (m_watchTimer == -1) if (m_d->m_watchTimer == -1)
m_watchTimer = startTimer(0); m_d->m_watchTimer = startTimer(0);
} }
void CdbDebugEngine::killWatchTimer() void CdbDebugEngine::killWatchTimer()
{ {
if (m_watchTimer != -1) { if (m_d->m_watchTimer != -1) {
killTimer(m_watchTimer); killTimer(m_d->m_watchTimer);
m_watchTimer = -1; m_d->m_watchTimer = -1;
} }
} }
@@ -84,13 +127,13 @@ void CdbDebugEngine::shutdown()
exitDebugger(); exitDebugger();
} }
void CdbDebugEngine::setToolTipExpression(const QPoint &pos, const QString &exp) void CdbDebugEngine::setToolTipExpression(const QPoint & /*pos*/, const QString & /*exp*/)
{ {
} }
bool CdbDebugEngine::startDebugger() bool CdbDebugEngine::startDebugger()
{ {
q->showStatusMessage("Starting Debugger", -1); m_d->m_debuggerManager->showStatusMessage("Starting Debugger", -1);
//if (!q->m_workingDir.isEmpty()) //if (!q->m_workingDir.isEmpty())
// m_gdbProc.setWorkingDirectory(q->m_workingDir); // m_gdbProc.setWorkingDirectory(q->m_workingDir);
@@ -101,19 +144,21 @@ bool CdbDebugEngine::startDebugger()
memset(&dbgopts, 0, sizeof(dbgopts)); memset(&dbgopts, 0, sizeof(dbgopts));
dbgopts.CreateFlags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS; dbgopts.CreateFlags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
HRESULT hr; const QString filename(m_d->m_debuggerManager->m_executable);
if (debugCDB)
qDebug() << Q_FUNC_INFO <<filename;
QString filename(q->m_executable); const QFileInfo fi(filename);
QFileInfo fi(filename); m_d->m_pDebugSymbols->AppendImagePathWide(QDir::toNativeSeparators(fi.absolutePath()).utf16());
m_pDebugSymbols->AppendImagePathWide(fi.absolutePath().replace('/','\\').utf16());
//m_pDebugSymbols->SetSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS); //m_pDebugSymbols->SetSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS);
m_pDebugSymbols->SetSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS); m_d->m_pDebugSymbols->SetSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS);
//m_pDebugSymbols->AddSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS | SYMOPT_NO_IMAGE_SEARCH); //m_pDebugSymbols->AddSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS | SYMOPT_NO_IMAGE_SEARCH);
if (q->startMode() == q->attachExternal) { if (m_d->m_debuggerManager->startMode() == DebuggerManager::AttachExternal) {
qWarning("CdbDebugEngine: attach to process not yet implemented!"); qWarning("CdbDebugEngine: attach to process not yet implemented!");
return false;
} else { } else {
hr = m_pDebugClient->CreateProcess2Wide(NULL, HRESULT hr = m_d->m_pDebugClient->CreateProcess2Wide(NULL,
const_cast<PWSTR>(filename.utf16()), const_cast<PWSTR>(filename.utf16()),
&dbgopts, &dbgopts,
sizeof(dbgopts), sizeof(dbgopts),
@@ -121,19 +166,22 @@ bool CdbDebugEngine::startDebugger()
NULL); // TODO: think about setting the environment NULL); // TODO: think about setting the environment
if (FAILED(hr)) { if (FAILED(hr)) {
//qWarning("CreateProcess2Wide failed"); //qWarning("CreateProcess2Wide failed");
qq->notifyInferiorExited(); m_d->m_debuggerManagerAccess->notifyInferiorExited();
return false; return false;
} }
} }
q->showStatusMessage(tr("Debugger Running"), -1); m_d->m_debuggerManager->showStatusMessage(tr("Debugger Running"), -1);
startWatchTimer(); startWatchTimer();
return true; return true;
} }
void CdbDebugEngine::exitDebugger() void CdbDebugEngine::exitDebugger()
{ {
m_pDebugClient->TerminateCurrentProcess(); if (debugCDB)
qDebug() << Q_FUNC_INFO;
m_d->m_pDebugClient->TerminateCurrentProcess();
killWatchTimer(); killWatchTimer();
} }
@@ -143,18 +191,22 @@ void CdbDebugEngine::updateWatchModel()
void CdbDebugEngine::stepExec() void CdbDebugEngine::stepExec()
{ {
//qDebug() << "CdbDebugEngine::stepExec()"; if (debugCDB)
qDebug() << Q_FUNC_INFO;
//m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0); //m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0);
HRESULT hr; HRESULT hr;
hr = m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_INTO); hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_INTO);
m_bIgnoreNextDebugEvent = true; m_d->m_bIgnoreNextDebugEvent = true;
startWatchTimer(); startWatchTimer();
} }
void CdbDebugEngine::stepOutExec() void CdbDebugEngine::stepOutExec()
{ {
//qDebug() << "CdbDebugEngine::stepOutExec()"; if (debugCDB)
StackHandler* sh = qq->stackHandler(); qDebug() << Q_FUNC_INFO;
StackHandler* sh = m_d->m_debuggerManagerAccess->stackHandler();
const int idx = sh->currentIndex() + 1; const int idx = sh->currentIndex() + 1;
QList<StackFrame> stackframes = sh->frames(); QList<StackFrame> stackframes = sh->frames();
if (idx < 0 || idx >= stackframes.size()) { if (idx < 0 || idx >= stackframes.size()) {
@@ -171,7 +223,7 @@ void CdbDebugEngine::stepOutExec()
} }
IDebugBreakpoint2* pBP; IDebugBreakpoint2* pBP;
HRESULT hr = m_pDebugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &pBP); HRESULT hr = m_d->m_pDebugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &pBP);
if (FAILED(hr) || !pBP) { if (FAILED(hr) || !pBP) {
qWarning("stepOutExec: cannot create temporary breakpoint"); qWarning("stepOutExec: cannot create temporary breakpoint");
return; return;
@@ -194,9 +246,11 @@ void CdbDebugEngine::stepOutExec()
void CdbDebugEngine::nextExec() void CdbDebugEngine::nextExec()
{ {
//qDebug() << "CdbDebugEngine::nextExec()"; if (debugCDB)
qDebug() << Q_FUNC_INFO;
HRESULT hr; HRESULT hr;
hr = m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_OVER); hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_OVER);
startWatchTimer(); startWatchTimer();
} }
@@ -207,68 +261,85 @@ void CdbDebugEngine::stepIExec()
void CdbDebugEngine::nextIExec() void CdbDebugEngine::nextIExec()
{ {
m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0); if (debugCDB)
qDebug() << Q_FUNC_INFO;
m_d->m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0);
startWatchTimer(); startWatchTimer();
} }
void CdbDebugEngine::continueInferior() void CdbDebugEngine::continueInferior()
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO;
killWatchTimer(); killWatchTimer();
q->resetLocation(); m_d->m_debuggerManager->resetLocation();
ULONG executionStatus; ULONG executionStatus;
HRESULT hr = m_pDebugControl->GetExecutionStatus(&executionStatus); HRESULT hr = m_d->m_pDebugControl->GetExecutionStatus(&executionStatus);
if (SUCCEEDED(hr) && executionStatus != DEBUG_STATUS_GO) if (SUCCEEDED(hr) && executionStatus != DEBUG_STATUS_GO)
m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_GO); m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_GO);
startWatchTimer(); startWatchTimer();
qq->notifyInferiorRunning(); m_d->m_debuggerManagerAccess->notifyInferiorRunning();
}
void CdbDebugEngine::runInferior()
{
continueInferior();
} }
void CdbDebugEngine::interruptInferior() void CdbDebugEngine::interruptInferior()
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO;
//TODO: better use IDebugControl::SetInterrupt? //TODO: better use IDebugControl::SetInterrupt?
if (!m_hDebuggeeProcess) if (!m_d->m_hDebuggeeProcess)
return; return;
if (!DebugBreakProcess(m_hDebuggeeProcess)) { if (!DebugBreakProcess(m_d->m_hDebuggeeProcess)) {
qWarning("DebugBreakProcess failed."); qWarning("DebugBreakProcess failed.");
return; return;
} }
qq->notifyInferiorStopped(); m_d->m_debuggerManagerAccess->notifyInferiorStopped();
} }
void CdbDebugEngine::runToLineExec(const QString &fileName, int lineNumber) void CdbDebugEngine::runToLineExec(const QString &fileName, int lineNumber)
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO << fileName << lineNumber;
} }
void CdbDebugEngine::runToFunctionExec(const QString &functionName) void CdbDebugEngine::runToFunctionExec(const QString &functionName)
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO << functionName;
} }
void CdbDebugEngine::jumpToLineExec(const QString &fileName, int lineNumber) void CdbDebugEngine::jumpToLineExec(const QString &fileName, int lineNumber)
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO << fileName << lineNumber;
} }
void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &value) void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &value)
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO << expr << value;
} }
void CdbDebugEngine::executeDebuggerCommand(const QString &/*command*/) void CdbDebugEngine::executeDebuggerCommand(const QString &command)
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO << command;
} }
void CdbDebugEngine::activateFrame(int frameIndex) void CdbDebugEngine::activateFrame(int frameIndex)
{ {
if (q->status() != DebuggerInferiorStopped) if (debugCDB)
qDebug() << Q_FUNC_INFO << frameIndex;
if (m_d->m_debuggerManager->status() != DebuggerInferiorStopped)
return; return;
StackHandler *stackHandler = qq->stackHandler(); StackHandler *stackHandler = m_d->m_debuggerManagerAccess->stackHandler();
int oldIndex = stackHandler->currentIndex(); const int oldIndex = stackHandler->currentIndex();
//qDebug() << "ACTIVATE FRAME: " << frameIndex << oldIndex //qDebug() << "ACTIVATE FRAME: " << frameIndex << oldIndex
// << stackHandler->currentIndex(); // << stackHandler->currentIndex();
@@ -281,42 +352,63 @@ void CdbDebugEngine::activateFrame(int frameIndex)
const StackFrame &frame = stackHandler->currentFrame(); const StackFrame &frame = stackHandler->currentFrame();
bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable(); const bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable();
if (usable) if (usable)
q->gotoLocation(frame.file, frame.line, true); m_d->m_debuggerManager->gotoLocation(frame.file, frame.line, true);
else else
qDebug() << "FULL NAME NOT USABLE: " << frame.file; qDebug() << "FULL NAME NOT USABLE: " << frame.file;
} }
void CdbDebugEngine::selectThread(int index) void CdbDebugEngine::selectThread(int index)
{ {
//reset location arrow if (debugCDB)
q->resetLocation(); qDebug() << Q_FUNC_INFO << index;
ThreadsHandler *threadsHandler = qq->threadsHandler(); //reset location arrow
m_d->m_debuggerManager->resetLocation();
ThreadsHandler *threadsHandler = m_d->m_debuggerManagerAccess->threadsHandler();
threadsHandler->setCurrentThread(index); threadsHandler->setCurrentThread(index);
m_currentThreadId = index; m_d->m_currentThreadId = index;
updateStackTrace(); m_d->updateStackTrace();
}
static inline QString breakPointExpression(const QString &fileName, const QString &lineNumber)
{
QString str;
str += QLatin1Char('`');
str += QDir::toNativeSeparators(fileName);
str += QLatin1Char(':');
str += lineNumber;
str += QLatin1Char('`');
return str;
} }
void CdbDebugEngine::attemptBreakpointSynchronization() void CdbDebugEngine::attemptBreakpointSynchronization()
{ {
BreakHandler *handler = qq->breakHandler(); if (debugCDB)
//qDebug() << "attemptBreakpointSynchronization"; qDebug() << Q_FUNC_INFO;
if (!m_d->m_hDebuggeeProcess) {
qWarning("attemptBreakpointSynchronization() called while debugger is not running");
return;
}
BreakHandler *handler = m_d->m_debuggerManagerAccess->breakHandler();
for (int i=0; i < handler->size(); ++i) { for (int i=0; i < handler->size(); ++i) {
BreakpointData* breakpoint = handler->at(i); BreakpointData* breakpoint = handler->at(i);
if (breakpoint->pending) { if (breakpoint->pending) {
const QString expr = breakPointExpression(breakpoint->fileName, breakpoint->lineNumber);
IDebugBreakpoint2* pBP = 0; IDebugBreakpoint2* pBP = 0;
HRESULT hr = m_pDebugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &pBP); HRESULT hr = m_d->m_pDebugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &pBP);
if (FAILED(hr) || !pBP) { if (FAILED(hr) || !pBP) {
qWarning("m_pDebugControl->AddBreakpoint2 failed"); qWarning("m_pDebugControl->AddBreakpoint2 %s failed.", qPrintable(expr));
continue; continue;
} }
QString str = '`' + breakpoint->fileName + ':' + breakpoint->lineNumber + '`'; hr = pBP->SetOffsetExpressionWide(expr.utf16());
hr = pBP->SetOffsetExpressionWide(str.utf16());
if (FAILED(hr)) { if (FAILED(hr)) {
qWarning("SetOffsetExpressionWide failed"); qWarning("SetOffsetExpressionWide %s failed", qPrintable(expr));
continue; continue;
} }
@@ -352,10 +444,14 @@ void CdbDebugEngine::reloadModules()
void CdbDebugEngine::loadSymbols(const QString &moduleName) void CdbDebugEngine::loadSymbols(const QString &moduleName)
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO << moduleName;
} }
void CdbDebugEngine::loadAllSymbols() void CdbDebugEngine::loadAllSymbols()
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO;
} }
void CdbDebugEngine::reloadRegisters() void CdbDebugEngine::reloadRegisters()
@@ -364,41 +460,52 @@ void CdbDebugEngine::reloadRegisters()
void CdbDebugEngine::timerEvent(QTimerEvent* te) void CdbDebugEngine::timerEvent(QTimerEvent* te)
{ {
if (te->timerId() != m_watchTimer) if (te->timerId() != m_d->m_watchTimer)
return; return;
if (debugCDB > 1)
qDebug() << Q_FUNC_INFO;
HRESULT hr; HRESULT hr;
hr = m_pDebugControl->WaitForEvent(0, 1); hr = m_d->m_pDebugControl->WaitForEvent(0, 1);
switch (hr) { switch (hr) {
case S_OK: case S_OK:
//qDebug() << "WaitForEvent S_OK"; if (debugCDB > 1)
qDebug() << "WaitForEvent S_OK";
killWatchTimer(); killWatchTimer();
handleDebugEvent(); m_d->handleDebugEvent();
break; break;
case S_FALSE: case S_FALSE:
//qDebug() << "S_FALSE"; if (debugCDB > 1)
qDebug() << "WaitForEvent S_FALSE";
break; break;
case E_PENDING: case E_PENDING:
qDebug() << "S_PENDING"; if (debugCDB > 1)
qDebug() << "WaitForEvent E_PENDING";
break; break;
case E_UNEXPECTED: case E_UNEXPECTED:
if (debugCDB > 1)
qDebug() << "WaitForEvent E_UNEXPECTED";
killWatchTimer(); killWatchTimer();
break; break;
case E_FAIL: case E_FAIL:
qDebug() << "E_FAIL"; if (debugCDB > 1)
qDebug() << "WaitForEvent E_FAIL";
break; break;
//default:
// qDebug() << "asser welljuh, schuddnt heppn";
} }
} }
void CdbDebugEngine::handleDebugEvent() void CdbDebugEnginePrivate::handleDebugEvent()
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO;
if (m_bIgnoreNextDebugEvent) { if (m_bIgnoreNextDebugEvent) {
startWatchTimer(); m_engine->startWatchTimer();
m_bIgnoreNextDebugEvent = false; m_bIgnoreNextDebugEvent = false;
} else { } else {
qq->notifyInferiorStopped(); m_debuggerManagerAccess->notifyInferiorStopped();
updateThreadList(); updateThreadList();
updateStackTrace(); updateStackTrace();
} }
@@ -415,9 +522,12 @@ void CdbDebugEngine::handleDebugEvent()
//} //}
} }
void CdbDebugEngine::updateThreadList() void CdbDebugEnginePrivate::updateThreadList()
{ {
ThreadsHandler* th = qq->threadsHandler(); if (debugCDB)
qDebug() << Q_FUNC_INFO;
ThreadsHandler* th = m_debuggerManagerAccess->threadsHandler();
QList<ThreadData> threads; QList<ThreadData> threads;
HRESULT hr; HRESULT hr;
@@ -436,11 +546,13 @@ void CdbDebugEngine::updateThreadList()
th->setThreads(threads); th->setThreads(threads);
} }
void CdbDebugEngine::updateStackTrace() void CdbDebugEnginePrivate::updateStackTrace()
{ {
if (debugCDB)
qDebug() << Q_FUNC_INFO;
//qDebug() << "updateStackTrace()"; //qDebug() << "updateStackTrace()";
HRESULT hr; HRESULT hr = m_pDebugSystemObjects->SetCurrentThreadId(m_currentThreadId);
hr = m_pDebugSystemObjects->SetCurrentThreadId(m_currentThreadId);
//ULONG64 frameOffset, instructionOffset, stackOffset; //ULONG64 frameOffset, instructionOffset, stackOffset;
//if (FAILED(m_pDebugRegisters->GetFrameOffset2(DEBUG_REGSRC_DEBUGGEE, &frameOffset)) || //if (FAILED(m_pDebugRegisters->GetFrameOffset2(DEBUG_REGSRC_DEBUGGEE, &frameOffset)) ||
@@ -466,7 +578,7 @@ void CdbDebugEngine::updateStackTrace()
StackFrame frame; StackFrame frame;
frame.line = 0; frame.line = 0;
frame.level = i; frame.level = i;
frame.address = QString("0x%1").arg(frames[i].InstructionOffset, 0, 16); frame.address = QString::fromLatin1("0x%1").arg(frames[i].InstructionOffset, 0, 16);
m_pDebugSymbols->GetNameByOffsetWide(frames[i].InstructionOffset, wszBuf, MAX_PATH, 0, 0); m_pDebugSymbols->GetNameByOffsetWide(frames[i].InstructionOffset, wszBuf, MAX_PATH, 0, 0);
frame.function = QString::fromUtf16(wszBuf); frame.function = QString::fromUtf16(wszBuf);
@@ -482,15 +594,15 @@ void CdbDebugEngine::updateStackTrace()
stackFrames.append(frame); stackFrames.append(frame);
} }
qq->stackHandler()->setFrames(stackFrames); m_debuggerManagerAccess->stackHandler()->setFrames(stackFrames);
// find the first usable frame and select it // find the first usable frame and select it
for (int i=0; i < stackFrames.count(); ++i) { for (int i=0; i < stackFrames.count(); ++i) {
const StackFrame &frame = stackFrames.at(i); const StackFrame &frame = stackFrames.at(i);
bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable(); const bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable();
if (usable) { if (usable) {
qq->stackHandler()->setCurrentIndex(i); m_debuggerManagerAccess->stackHandler()->setCurrentIndex(i);
q->gotoLocation(frame.file, frame.line, true); m_debuggerManager->gotoLocation(frame.file, frame.line, true);
break; break;
} }
} }
@@ -504,17 +616,33 @@ void CdbDebugEngine::updateStackTrace()
//m_pDebugControl->OutputStackTrace(DEBUG_OUTCTL_THIS_CLIENT, frames, numFramesFilled, DEBUG_STACK_SOURCE_LINE); //m_pDebugControl->OutputStackTrace(DEBUG_OUTCTL_THIS_CLIENT, frames, numFramesFilled, DEBUG_STACK_SOURCE_LINE);
} }
void CdbDebugEngine::handleDebugOutput(const char* szOutputString) void CdbDebugEnginePrivate::handleDebugOutput(const char* szOutputString)
{ {
qq->showApplicationOutput("app-dbgoutput", QString::fromLocal8Bit(szOutputString)); m_debuggerManagerAccess->showApplicationOutput(QString::fromLocal8Bit(szOutputString));
} }
void CdbDebugEngine::handleBreakpointEvent(PDEBUG_BREAKPOINT pBP) void CdbDebugEnginePrivate::handleBreakpointEvent(PDEBUG_BREAKPOINT pBP)
{ {
qDebug() << "CdbDebugEngine::handleBreakpointEvent()"; Q_UNUSED(pBP)
if (debugCDB)
qDebug() << Q_FUNC_INFO;
} }
IDebuggerEngine *createWinEngine(DebuggerManager *parent) IDebuggerEngine *createWinEngine(DebuggerManager *parent)
{ {
return new CdbDebugEngine(parent); return new CdbDebugEngine(parent);
} }
void CdbDebugEngine::setDebugDumpers(bool on)
{
Q_UNUSED(on)
}
void CdbDebugEngine::setUseCustomDumpers(bool on)
{
Q_UNUSED(on)
}
void CdbDebugEngine::reloadSourceFiles()
{
}

View File

@@ -1,17 +1,48 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 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 GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef DEBUGGER_CDBENGINE_H #ifndef DEBUGGER_CDBENGINE_H
#define DEBUGGER_CDBENGINE_H #define DEBUGGER_CDBENGINE_H
#include "idebuggerengine.h" #include "idebuggerengine.h"
#include "cdbdebugeventcallback.h"
#include "cdbdebugoutput.h"
#include <windows.h>
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
class DebuggerManager; class DebuggerManager;
class IDebuggerManagerAccessForEngines; class CdbDebugEventCallback;
class CdbDebugOutput;
struct CdbDebugEnginePrivate;
class CdbDebugEngine : public IDebuggerEngine class CdbDebugEngine : public IDebuggerEngine
{ {
@@ -33,7 +64,6 @@ public:
virtual void nextIExec(); virtual void nextIExec();
virtual void continueInferior(); virtual void continueInferior();
virtual void runInferior();
virtual void interruptInferior(); virtual void interruptInferior();
virtual void runToLineExec(const QString &fileName, int lineNumber); virtual void runToLineExec(const QString &fileName, int lineNumber);
@@ -58,37 +88,21 @@ public:
virtual void reloadRegisters(); virtual void reloadRegisters();
virtual void setDebugDumpers(bool on);
virtual void setUseCustomDumpers(bool on);
virtual void reloadSourceFiles();
protected: protected:
void timerEvent(QTimerEvent*); void timerEvent(QTimerEvent*);
private: private:
void startWatchTimer(); void startWatchTimer();
void killWatchTimer(); void killWatchTimer();
bool isDebuggeeRunning() const { return m_watchTimer != -1; }
void handleDebugEvent();
void updateThreadList();
void updateStackTrace();
void handleDebugOutput(const char* szOutputString);
void handleBreakpointEvent(PDEBUG_BREAKPOINT pBP);
private: CdbDebugEnginePrivate *m_d;
HANDLE m_hDebuggeeProcess;
HANDLE m_hDebuggeeThread;
int m_currentThreadId;
bool m_bIgnoreNextDebugEvent;
int m_watchTimer;
IDebugClient5* m_pDebugClient;
IDebugControl4* m_pDebugControl;
IDebugSystemObjects4* m_pDebugSystemObjects;
IDebugSymbols3* m_pDebugSymbols;
IDebugRegisters2* m_pDebugRegisters;
CdbDebugEventCallback m_debugEventCallBack;
CdbDebugOutput m_debugOutputCallBack;
DebuggerManager *q;
IDebuggerManagerAccessForEngines *qq;
friend struct CdbDebugEnginePrivate;
friend class CdbDebugEventCallback; friend class CdbDebugEventCallback;
friend class CdbDebugOutput; friend class CdbDebugOutput;
}; };

View File

@@ -0,0 +1,82 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 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 GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef DEBUGGER_CDBENGINEPRIVATE_H
#define DEBUGGER_CDBENGINEPRIVATE_H
#include "cdbdebugeventcallback.h"
#include "cdbdebugoutput.h"
namespace Debugger {
namespace Internal {
class DebuggerManager;
class IDebuggerManagerAccessForEngines;
struct CdbDebugEnginePrivate
{
explicit CdbDebugEnginePrivate(DebuggerManager *parent, CdbDebugEngine* engine);
~CdbDebugEnginePrivate();
bool isDebuggeeRunning() const { return m_watchTimer != -1; }
void handleDebugEvent();
void updateThreadList();
void updateStackTrace();
void handleDebugOutput(const char* szOutputString);
void handleBreakpointEvent(PDEBUG_BREAKPOINT pBP);
HANDLE m_hDebuggeeProcess;
HANDLE m_hDebuggeeThread;
int m_currentThreadId;
bool m_bIgnoreNextDebugEvent;
int m_watchTimer;
IDebugClient5* m_pDebugClient;
IDebugControl4* m_pDebugControl;
IDebugSystemObjects4* m_pDebugSystemObjects;
IDebugSymbols3* m_pDebugSymbols;
IDebugRegisters2* m_pDebugRegisters;
CdbDebugEventCallback m_debugEventCallBack;
CdbDebugOutput m_debugOutputCallBack;
CdbDebugEngine* m_engine;
DebuggerManager *m_debuggerManager;
IDebuggerManagerAccessForEngines *m_debuggerManagerAccess;
};
enum { debugCDB = 0 };
} // namespace Internal
} // namespace Debugger
#endif // DEBUGGER_CDBENGINEPRIVATE_H

View File

@@ -0,0 +1,288 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 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 GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "cdbdebugeventcallback.h"
#include "cdbdebugengine.h"
#include "cdbdebugengine_p.h"
#include "debuggermanager.h"
#include <QtCore/QDebug>
namespace Debugger {
namespace Internal {
CdbDebugEventCallback::CdbDebugEventCallback(CdbDebugEngine* dbg) :
m_pEngine(dbg)
{
}
STDMETHODIMP CdbDebugEventCallback::QueryInterface(
THIS_
IN REFIID InterfaceId,
OUT PVOID* Interface)
{
*Interface = NULL;
if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks))) {
*Interface = (IDebugOutputCallbacks *)this;
AddRef();
return S_OK;
} else {
return E_NOINTERFACE;
}
}
STDMETHODIMP_(ULONG) CdbDebugEventCallback::AddRef(THIS)
{
// This class is designed to be static so
// there's no true refcount.
return 1;
}
STDMETHODIMP_(ULONG) CdbDebugEventCallback::Release(THIS)
{
// This class is designed to be static so
// there's no true refcount.
return 0;
}
STDMETHODIMP CdbDebugEventCallback::GetInterestMask(THIS_ __out PULONG mask)
{
*mask = DEBUG_EVENT_CREATE_PROCESS | DEBUG_EVENT_EXIT_PROCESS
//| DEBUG_EVENT_CREATE_THREAD | DEBUG_EVENT_EXIT_THREAD
| DEBUG_EVENT_BREAKPOINT
| DEBUG_EVENT_EXCEPTION
;
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT Bp)
{
if (debugCDB)
qDebug() << Q_FUNC_INFO;
m_pEngine->m_d->handleBreakpointEvent(Bp);
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::Exception(
THIS_
__in PEXCEPTION_RECORD64 Exception,
__in ULONG FirstChance
)
{
Q_UNUSED(Exception)
if (debugCDB)
qDebug() << Q_FUNC_INFO << FirstChance;
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::CreateThread(
THIS_
__in ULONG64 Handle,
__in ULONG64 DataOffset,
__in ULONG64 StartOffset
)
{
Q_UNUSED(Handle)
Q_UNUSED(DataOffset)
Q_UNUSED(StartOffset)
if (debugCDB)
qDebug() << Q_FUNC_INFO;
//Debugger::ThreadInfo ti;
//ti.handle = Handle;
//ti.dataOffset = DataOffset;
//ti.startOffset = StartOffset;
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::ExitThread(
THIS_
__in ULONG ExitCode
)
{
if (debugCDB)
qDebug() << Q_FUNC_INFO << ExitCode;
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::CreateProcess(
THIS_
__in ULONG64 ImageFileHandle,
__in ULONG64 Handle,
__in ULONG64 BaseOffset,
__in ULONG ModuleSize,
__in_opt PCSTR ModuleName,
__in_opt PCSTR ImageName,
__in ULONG CheckSum,
__in ULONG TimeDateStamp,
__in ULONG64 InitialThreadHandle,
__in ULONG64 ThreadDataOffset,
__in ULONG64 StartOffset
)
{
Q_UNUSED(ImageFileHandle)
Q_UNUSED(BaseOffset)
Q_UNUSED(ModuleSize)
Q_UNUSED(ModuleName)
Q_UNUSED(ImageName)
Q_UNUSED(CheckSum)
Q_UNUSED(TimeDateStamp)
Q_UNUSED(ThreadDataOffset)
Q_UNUSED(StartOffset)
if (debugCDB)
qDebug() << Q_FUNC_INFO << ModuleName;
m_pEngine->m_d->m_hDebuggeeProcess = (HANDLE)Handle;
m_pEngine->m_d->m_hDebuggeeThread = (HANDLE)InitialThreadHandle;
m_pEngine->m_d->m_debuggerManagerAccess->notifyInferiorRunning();
ULONG currentThreadId;
if (SUCCEEDED(m_pEngine->m_d->m_pDebugSystemObjects->GetThreadIdByHandle(InitialThreadHandle, &currentThreadId)))
m_pEngine->m_d->m_currentThreadId = currentThreadId;
else
m_pEngine->m_d->m_currentThreadId = 0;
m_pEngine->attemptBreakpointSynchronization();
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::ExitProcess(
THIS_
__in ULONG ExitCode
)
{
if (debugCDB)
qDebug() << Q_FUNC_INFO << ExitCode;
m_pEngine->m_d->m_hDebuggeeProcess = 0;
m_pEngine->m_d->m_hDebuggeeThread = 0;
m_pEngine->m_d->m_debuggerManagerAccess->notifyInferiorExited();
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::LoadModule(
THIS_
__in ULONG64 ImageFileHandle,
__in ULONG64 BaseOffset,
__in ULONG ModuleSize,
__in_opt PCSTR ModuleName,
__in_opt PCSTR ImageName,
__in ULONG CheckSum,
__in ULONG TimeDateStamp
)
{
Q_UNUSED(ImageFileHandle)
Q_UNUSED(BaseOffset)
Q_UNUSED(ModuleSize)
Q_UNUSED(ModuleName)
Q_UNUSED(ImageName)
Q_UNUSED(CheckSum)
Q_UNUSED(TimeDateStamp)
if (debugCDB)
qDebug() << Q_FUNC_INFO << ModuleName;
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::UnloadModule(
THIS_
__in_opt PCSTR ImageBaseName,
__in ULONG64 BaseOffset
)
{
Q_UNUSED(ImageBaseName)
Q_UNUSED(BaseOffset)
if (debugCDB)
qDebug() << Q_FUNC_INFO << ImageBaseName;
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::SystemError(
THIS_
__in ULONG Error,
__in ULONG Level
)
{
if (debugCDB)
qDebug() << Q_FUNC_INFO << Error << Level;
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::SessionStatus(
THIS_
__in ULONG Status
)
{
Q_UNUSED(Status)
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::ChangeDebuggeeState(
THIS_
__in ULONG Flags,
__in ULONG64 Argument
)
{
Q_UNUSED(Flags)
Q_UNUSED(Argument)
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::ChangeEngineState(
THIS_
__in ULONG Flags,
__in ULONG64 Argument
)
{
Q_UNUSED(Flags)
Q_UNUSED(Argument)
return S_OK;
}
STDMETHODIMP CdbDebugEventCallback::ChangeSymbolState(
THIS_
__in ULONG Flags,
__in ULONG64 Argument
)
{
Q_UNUSED(Flags)
Q_UNUSED(Argument)
return S_OK;
}
} // namespace Internal
} // namespace Debugger

View File

@@ -1,8 +1,41 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 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 GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef DEBUGGER_CDBDEBUGEVENTCALLBACK_H #ifndef DEBUGGER_CDBDEBUGEVENTCALLBACK_H
#define DEBUGGER_CDBDEBUGEVENTCALLBACK_H #define DEBUGGER_CDBDEBUGEVENTCALLBACK_H
#include <windows.h> #include <windows.h>
#include <dbgeng.h> #include <inc/dbgeng.h>
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -12,9 +45,7 @@ class CdbDebugEngine;
class CdbDebugEventCallback : public IDebugEventCallbacks class CdbDebugEventCallback : public IDebugEventCallbacks
{ {
public: public:
CdbDebugEventCallback(CdbDebugEngine* dbg) explicit CdbDebugEventCallback(CdbDebugEngine* dbg);
: m_pEngine(dbg)
{}
// IUnknown. // IUnknown.
STDMETHOD(QueryInterface)( STDMETHOD(QueryInterface)(
@@ -125,7 +156,7 @@ public:
); );
private: private:
CdbDebugEngine* m_pEngine; CdbDebugEngine *m_pEngine;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -0,0 +1,95 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 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 GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "cdbdebugoutput.h"
#include "cdbdebugengine.h"
#include "cdbdebugengine_p.h"
#include <windows.h>
#include <inc/dbgeng.h>
namespace Debugger {
namespace Internal {
CdbDebugOutput::CdbDebugOutput(CdbDebugEngine* engine) :
m_pEngine(engine)
{
}
STDMETHODIMP CdbDebugOutput::QueryInterface(
THIS_
IN REFIID InterfaceId,
OUT PVOID* Interface
)
{
*Interface = NULL;
if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))
{
*Interface = (IDebugOutputCallbacks *)this;
AddRef();
return S_OK;
} else {
return E_NOINTERFACE;
}
}
STDMETHODIMP_(ULONG) CdbDebugOutput::AddRef(THIS)
{
// This class is designed to be static so
// there's no true refcount.
return 1;
}
STDMETHODIMP_(ULONG) CdbDebugOutput::Release(THIS)
{
// This class is designed to be static so
// there's no true refcount.
return 0;
}
STDMETHODIMP CdbDebugOutput::Output(
THIS_
IN ULONG mask,
IN PCSTR text
)
{
UNREFERENCED_PARAMETER(mask);
m_pEngine->m_d->handleDebugOutput(text);
return S_OK;
}
} // namespace Internal
} // namespace Debugger

View File

@@ -0,0 +1,77 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 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 GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef DEBUGGER_CDBOUTPUT_H
#define DEBUGGER_CDBOUTPUT_H
#include <windows.h>
#include <inc/dbgeng.h>
namespace Debugger {
namespace Internal {
class CdbDebugEngine;
class CdbDebugOutput : public IDebugOutputCallbacks
{
public:
explicit CdbDebugOutput(CdbDebugEngine* engine);
// IUnknown.
STDMETHOD(QueryInterface)(
THIS_
IN REFIID InterfaceId,
OUT PVOID* Interface
);
STDMETHOD_(ULONG, AddRef)(
THIS
);
STDMETHOD_(ULONG, Release)(
THIS
);
// IDebugOutputCallbacks.
STDMETHOD(Output)(
THIS_
IN ULONG mask,
IN PCSTR text
);
private:
CdbDebugEngine* m_pEngine;
};
} // namespace Internal
} // namespace Debugger
#endif // DEBUGGER_CDBOUTPUT_H

View File

@@ -1,203 +0,0 @@
#include "cdbdebugeventcallback.h"
#include "cdbcdebugengine.h"
#include "debuggermanager.h"
#include <QtCore/QDebug>
namespace Debugger {
namespace Internal {
STDMETHODIMP MSVCDebugEventCallback::QueryInterface(
THIS_
IN REFIID InterfaceId,
OUT PVOID* Interface)
{
*Interface = NULL;
if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))
{
*Interface = (IDebugOutputCallbacks *)this;
AddRef();
return S_OK;
}
else
{
return E_NOINTERFACE;
}
}
STDMETHODIMP_(ULONG) MSVCDebugEventCallback::AddRef(THIS)
{
// This class is designed to be static so
// there's no true refcount.
return 1;
}
STDMETHODIMP_(ULONG) MSVCDebugEventCallback::Release(THIS)
{
// This class is designed to be static so
// there's no true refcount.
return 0;
}
STDMETHODIMP MSVCDebugEventCallback::GetInterestMask(THIS_ __out PULONG mask)
{
*mask = DEBUG_EVENT_CREATE_PROCESS | DEBUG_EVENT_EXIT_PROCESS
//| DEBUG_EVENT_CREATE_THREAD | DEBUG_EVENT_EXIT_THREAD
| DEBUG_EVENT_BREAKPOINT
| DEBUG_EVENT_EXCEPTION
;
return S_OK;
}
STDMETHODIMP MSVCDebugEventCallback::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT Bp)
{
qDebug() << "MSVCDebugEventCallback::Breakpoint";
m_pEngine->handleBreakpointEvent(Bp);
return S_OK;
}
STDMETHODIMP MSVCDebugEventCallback::Exception(
THIS_
__in PEXCEPTION_RECORD64 Exception,
__in ULONG FirstChance
)
{
qDebug() << "MSVCDebugEventCallback::Exception";
return S_OK;
}
STDMETHODIMP MSVCDebugEventCallback::CreateThread(
THIS_
__in ULONG64 Handle,
__in ULONG64 DataOffset,
__in ULONG64 StartOffset
)
{
//Debugger::ThreadInfo ti;
//ti.handle = Handle;
//ti.dataOffset = DataOffset;
//ti.startOffset = StartOffset;
return S_OK;
}
STDMETHODIMP MSVCDebugEventCallback::ExitThread(
THIS_
__in ULONG ExitCode
)
{
return S_OK;
}
STDMETHODIMP MSVCDebugEventCallback::CreateProcess(
THIS_
__in ULONG64 ImageFileHandle,
__in ULONG64 Handle,
__in ULONG64 BaseOffset,
__in ULONG ModuleSize,
__in_opt PCSTR ModuleName,
__in_opt PCSTR ImageName,
__in ULONG CheckSum,
__in ULONG TimeDateStamp,
__in ULONG64 InitialThreadHandle,
__in ULONG64 ThreadDataOffset,
__in ULONG64 StartOffset
)
{
m_pEngine->m_hDebuggeeProcess = (HANDLE)Handle;
m_pEngine->m_hDebuggeeThread = (HANDLE)InitialThreadHandle;
//m_pEngine->qq->notifyStartupFinished();
m_pEngine->qq->notifyInferiorRunning();
ULONG currentThreadId;
if (SUCCEEDED(m_pEngine->m_pDebugSystemObjects->GetThreadIdByHandle(InitialThreadHandle, &currentThreadId)))
m_pEngine->m_currentThreadId = currentThreadId;
else
m_pEngine->m_currentThreadId = 0;
m_pEngine->attemptBreakpointSynchronization();
return S_OK;
}
STDMETHODIMP MSVCDebugEventCallback::ExitProcess(
THIS_
__in ULONG ExitCode
)
{
UNREFERENCED_PARAMETER(ExitCode);
m_pEngine->m_hDebuggeeProcess = 0;
m_pEngine->m_hDebuggeeThread = 0;
m_pEngine->qq->notifyInferiorExited();
return S_OK;
}
STDMETHODIMP MSVCDebugEventCallback::LoadModule(
THIS_
__in ULONG64 ImageFileHandle,
__in ULONG64 BaseOffset,
__in ULONG ModuleSize,
__in_opt PCSTR ModuleName,
__in_opt PCSTR ImageName,
__in ULONG CheckSum,
__in ULONG TimeDateStamp
)
{
return S_OK;
}
STDMETHODIMP MSVCDebugEventCallback::UnloadModule(
THIS_
__in_opt PCSTR ImageBaseName,
__in ULONG64 BaseOffset
)
{
return S_OK;
}
STDMETHODIMP MSVCDebugEventCallback::SystemError(
THIS_
__in ULONG Error,
__in ULONG Level
)
{
return S_OK;
}
STDMETHODIMP MSVCDebugEventCallback::SessionStatus(
THIS_
__in ULONG Status
)
{
return S_OK;
}
STDMETHODIMP MSVCDebugEventCallback::ChangeDebuggeeState(
THIS_
__in ULONG Flags,
__in ULONG64 Argument
)
{
return S_OK;
}
STDMETHODIMP MSVCDebugEventCallback::ChangeEngineState(
THIS_
__in ULONG Flags,
__in ULONG64 Argument
)
{
return S_OK;
}
STDMETHODIMP MSVCDebugEventCallback::ChangeSymbolState(
THIS_
__in ULONG Flags,
__in ULONG64 Argument
)
{
return S_OK;
}
} // namespace Internal
} // namespace Debugger

View File

@@ -1,57 +0,0 @@
#include <windows.h>
#include <dbgeng.h>
#include "cdbdebugoutput.h"
#include "cdbdebugengine.h"
namespace Debugger {
namespace Internal {
STDMETHODIMP MSVCDebugOutput::QueryInterface(
THIS_
IN REFIID InterfaceId,
OUT PVOID* Interface
)
{
*Interface = NULL;
if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))
{
*Interface = (IDebugOutputCallbacks *)this;
AddRef();
return S_OK;
}
else
{
return E_NOINTERFACE;
}
}
STDMETHODIMP_(ULONG) MSVCDebugOutput::AddRef(THIS)
{
// This class is designed to be static so
// there's no true refcount.
return 1;
}
STDMETHODIMP_(ULONG) MSVCDebugOutput::Release(THIS)
{
// This class is designed to be static so
// there's no true refcount.
return 0;
}
STDMETHODIMP MSVCDebugOutput::Output(
THIS_
IN ULONG mask,
IN PCSTR text
)
{
UNREFERENCED_PARAMETER(mask);
m_pEngine->handleDebugOutput(text);
return S_OK;
}
} // namespace Internal
} // namespace Debugger

View File

@@ -1,43 +0,0 @@
#ifndef DEBUGGER_CDBOUTPUT_H
#define DEBUGGER_CDBOUTPUT_H
namespace Debugger {
namespace Internal {
class CdbDebugEngine;
class CdbDebugOutput : public IDebugOutputCallbacks
{
public:
CdbDebugOutput(CdbDebugEngine* engine)
: m_pEngine(engine)
{}
// IUnknown.
STDMETHOD(QueryInterface)(
THIS_
IN REFIID InterfaceId,
OUT PVOID* Interface
);
STDMETHOD_(ULONG, AddRef)(
THIS
);
STDMETHOD_(ULONG, Release)(
THIS
);
// IDebugOutputCallbacks.
STDMETHOD(Output)(
THIS_
IN ULONG mask,
IN PCSTR text
);
private:
CdbDebugEngine* m_pEngine;
};
} // namespace Internal
} // namespace Debugger
#endif // DEBUGGER_CDBOUTPUT_H

View File

@@ -85,19 +85,4 @@ HEADERS += $$PWD/modeltest.h
DEFINES += USE_MODEL_TEST=1 DEFINES += USE_MODEL_TEST=1
} }
false { CONFIG(cdbdebugger):include(cdb\cdb.pri)
HEADERS += \
cdbdebugengine.h \
cdbdebugeventcallback.h \
cdbdebugoutput.h
SOURCES += \
cdbdebugengine.cpp \
cdbdebugeventcallback.cpp \
cdbdebugoutput.cpp
LIBS += dbgeng.lib
}

View File

@@ -132,7 +132,12 @@ static IDebuggerEngine *winEngine = 0;
static IDebuggerEngine *scriptEngine = 0; static IDebuggerEngine *scriptEngine = 0;
extern IDebuggerEngine *createGdbEngine(DebuggerManager *parent); extern IDebuggerEngine *createGdbEngine(DebuggerManager *parent);
extern IDebuggerEngine *createWinEngine(DebuggerManager *) { return 0; } extern IDebuggerEngine *createWinEngine(DebuggerManager *)
#ifdef CDB_ENABLED
;
#else
{ return 0; }
#endif
extern IDebuggerEngine *createScriptEngine(DebuggerManager *parent); extern IDebuggerEngine *createScriptEngine(DebuggerManager *parent);
DebuggerManager::DebuggerManager() DebuggerManager::DebuggerManager()

View File

@@ -106,11 +106,11 @@ enum DebuggerStatus
DebuggerInferiorStopped, // Debuggee stopped DebuggerInferiorStopped, // Debuggee stopped
}; };
class IDebuggerEngine; class IDebuggerEngine;
class GdbEngine; class GdbEngine;
class ScriptEngine; class ScriptEngine;
class WinEngine; class CdbDebugEngine;
struct CdbDebugEnginePrivate;
// The construct below is not nice but enforces a bit of order. The // The construct below is not nice but enforces a bit of order. The
// DebuggerManager interfaces a lots of thing: The DebuggerPlugin, // DebuggerManager interfaces a lots of thing: The DebuggerPlugin,
@@ -131,10 +131,12 @@ public:
private: private:
// This is the part of the interface that's exclusively seen by the // This is the part of the interface that's exclusively seen by the
// debugger engines. // debugger engines
friend class GdbEngine; friend class GdbEngine;
friend class CdbDebugEngine;
friend class CdbDebugEventCallback;
friend class ScriptEngine; friend class ScriptEngine;
friend class WinEngine; friend struct CdbDebugEnginePrivate;
// called from the engines after successful startup // called from the engines after successful startup
virtual void notifyInferiorStopRequested() = 0; virtual void notifyInferiorStopRequested() = 0;

View File

@@ -234,15 +234,6 @@ static bool isLeavableFunction(const QString &funcName, const QString &fileName)
return false; return false;
} }
static QString startSymbolName()
{
#ifdef Q_OS_WIN
return "WinMainCRTStartup";
#else
return "_start";
#endif
}
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// //
@@ -1555,9 +1546,7 @@ bool GdbEngine::startDebugger()
qDebug() << "ExeFile: " << q->m_executable; qDebug() << "ExeFile: " << q->m_executable;
#endif #endif
q->showStatusMessage(tr("Starting Debugger")); q->showStatusMessage(tr("Starting Debugger: ") + q->settings()->m_gdbCmd + ' ' + gdbArgs.join(" "));
emit gdbInputAvailable(QString(), q->settings()->m_gdbCmd + ' ' + gdbArgs.join(" "));
m_gdbProc.start(q->settings()->m_gdbCmd, gdbArgs); m_gdbProc.start(q->settings()->m_gdbCmd, gdbArgs);
m_gdbProc.waitForStarted(); m_gdbProc.waitForStarted();
@@ -1655,7 +1644,7 @@ bool GdbEngine::startDebugger()
if (!q->m_processArgs.isEmpty()) if (!q->m_processArgs.isEmpty())
sendCommand("-exec-arguments " + q->m_processArgs.join(" ")); sendCommand("-exec-arguments " + q->m_processArgs.join(" "));
sendCommand("set auto-solib-add off"); sendCommand("set auto-solib-add off");
sendCommand("x/2i " + startSymbolName(), GdbStart); sendCommand("info target", GdbStart);
} }
// set all to "pending" // set all to "pending"
@@ -1678,14 +1667,14 @@ void GdbEngine::continueInferior()
void GdbEngine::handleStart(const GdbResultRecord &response) void GdbEngine::handleStart(const GdbResultRecord &response)
{ {
if (response.resultClass == GdbResultDone) { if (response.resultClass == GdbResultDone) {
// stdout:&"x/2i _start\n" // [some leading stdout here]
// stdout:~"0x404540 <_start>:\txor %ebp,%ebp\n" // stdout:&" Entry point: 0x80831f0 0x08048134 - 0x08048147 is .interp\n"
// stdout:~"0x404542 <_start+2>:\tmov %rdx,%r9\n" // [some trailing stdout here]
QString msg = response.data.findChild("consolestreamoutput").data(); QString msg = response.data.findChild("consolestreamoutput").data();
QRegExp needle("0x([0-9a-f]+) <" + startSymbolName() + "\\+.*>:"); QRegExp needle("\\bEntry point: (0x[0-9a-f]+)\\b");
if (needle.indexIn(msg) != -1) { if (needle.indexIn(msg) != -1) {
//debugMessage("STREAM: " + msg + " " + needle.cap(1)); //debugMessage("STREAM: " + msg + " " + needle.cap(1));
sendCommand("tbreak *0x" + needle.cap(1)); sendCommand("tbreak *" + needle.cap(1));
m_waitingForFirstBreakpointToBeHit = true; m_waitingForFirstBreakpointToBeHit = true;
qq->notifyInferiorRunningRequested(); qq->notifyInferiorRunningRequested();
sendCommand("-exec-run"); sendCommand("-exec-run");
@@ -1693,7 +1682,7 @@ void GdbEngine::handleStart(const GdbResultRecord &response)
debugMessage("PARSING START ADDRESS FAILED: " + msg); debugMessage("PARSING START ADDRESS FAILED: " + msg);
} }
} else if (response.resultClass == GdbResultError) { } else if (response.resultClass == GdbResultError) {
debugMessage("PARSING START ADDRESS FAILED: " + response.toString()); debugMessage("FETCHING START ADDRESS FAILED: " + response.toString());
} }
} }

View File

@@ -39,6 +39,8 @@
#include <QtNetwork/QLocalSocket> #include <QtNetwork/QLocalSocket>
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
#include <stdlib.h>
#else #else
#include <QtCore/QFile> #include <QtCore/QFile>
@@ -80,7 +82,9 @@ bool OutputCollector::listen()
return m_server->isListening(); return m_server->isListening();
m_server = new QLocalServer(this); m_server = new QLocalServer(this);
connect(m_server, SIGNAL(newConnection()), SLOT(newConnectionAvailable())); connect(m_server, SIGNAL(newConnection()), SLOT(newConnectionAvailable()));
return m_server->listen(QString::fromLatin1("creator-%1").arg(QCoreApplication::applicationPid())); // XXX how to make that secure? return m_server->listen(QString::fromLatin1("creator-%1-%2")
.arg(QCoreApplication::applicationPid())
.arg(rand()));
#else #else
if (!m_serverPath.isEmpty()) if (!m_serverPath.isEmpty())
return true; return true;
@@ -156,7 +160,7 @@ void OutputCollector::newConnectionAvailable()
if (m_socket) if (m_socket)
return; return;
m_socket = m_server->nextPendingConnection(); m_socket = m_server->nextPendingConnection();
connect(m_socket, SIGNAL(bytesAvailable()), SLOT(bytesAvailable())); connect(m_socket, SIGNAL(readyRead()), SLOT(bytesAvailable()));
} }
#endif #endif

View File

@@ -111,7 +111,7 @@ QWidget *ApplicationRunConfigurationRunner::configurationWidget(QSharedPointer<R
// ApplicationRunControl // ApplicationRunControl
ApplicationRunControl::ApplicationRunControl(QSharedPointer<ApplicationRunConfiguration> runConfiguration) ApplicationRunControl::ApplicationRunControl(QSharedPointer<ApplicationRunConfiguration> runConfiguration)
: RunControl(runConfiguration), m_applicationLauncher() : RunControl(runConfiguration)
{ {
connect(&m_applicationLauncher, SIGNAL(applicationError(QString)), connect(&m_applicationLauncher, SIGNAL(applicationError(QString)),
this, SLOT(slotError(QString))); this, SLOT(slotError(QString)));

View File

@@ -84,6 +84,9 @@ const char * const C_OPERATOR = "Operator";
const char * const C_PREPROCESSOR = "Preprocessor"; const char * const C_PREPROCESSOR = "Preprocessor";
const char * const C_LABEL = "Label"; const char * const C_LABEL = "Label";
const char * const C_COMMENT = "Comment"; const char * const C_COMMENT = "Comment";
const char * const C_DOXYGEN_COMMENT = "Doxygen.Comment";
const char * const C_DOXYGEN_TAG = "Doxygen.Tag";
const char * const C_DISABLED_CODE = "DisabledCode"; const char * const C_DISABLED_CODE = "DisabledCode";
const char * const C_ADDED_LINE = "AddedLine"; const char * const C_ADDED_LINE = "AddedLine";

View File

@@ -84,6 +84,8 @@ TextEditorSettings::TextEditorSettings(QObject *parent)
formatDescriptions.push_back(FormatDescription(QLatin1String(C_PREPROCESSOR), tr("Preprocessor"), Qt::darkBlue)); formatDescriptions.push_back(FormatDescription(QLatin1String(C_PREPROCESSOR), tr("Preprocessor"), Qt::darkBlue));
formatDescriptions.push_back(FormatDescription(QLatin1String(C_LABEL), tr("Label"), Qt::darkRed)); formatDescriptions.push_back(FormatDescription(QLatin1String(C_LABEL), tr("Label"), Qt::darkRed));
formatDescriptions.push_back(FormatDescription(QLatin1String(C_COMMENT), tr("Comment"), Qt::darkGreen)); formatDescriptions.push_back(FormatDescription(QLatin1String(C_COMMENT), tr("Comment"), Qt::darkGreen));
formatDescriptions.push_back(FormatDescription(QLatin1String(C_DOXYGEN_COMMENT), tr("Doxygen Comment"), Qt::darkBlue));
formatDescriptions.push_back(FormatDescription(QLatin1String(C_DOXYGEN_TAG), tr("Doxygen Tag"), Qt::blue));
formatDescriptions.push_back(FormatDescription(QLatin1String(C_DISABLED_CODE), tr("Disabled Code"), Qt::gray)); formatDescriptions.push_back(FormatDescription(QLatin1String(C_DISABLED_CODE), tr("Disabled Code"), Qt::gray));
// Diff categories // Diff categories

View File

@@ -60,7 +60,7 @@ CPLUSPLUS_BEGIN_NAMESPACE
Lexer::Lexer(TranslationUnit *unit) Lexer::Lexer(TranslationUnit *unit)
: _translationUnit(unit), : _translationUnit(unit),
_state(Lexer::DefaultState), _state(State_Default),
_flags(0), _flags(0),
_currentLine(1) _currentLine(1)
{ {
@@ -71,7 +71,7 @@ Lexer::Lexer(TranslationUnit *unit)
Lexer::Lexer(const char *firstChar, const char *lastChar) Lexer::Lexer(const char *firstChar, const char *lastChar)
: _translationUnit(0), : _translationUnit(0),
_state(Lexer::DefaultState), _state(State_Default),
_flags(0), _flags(0),
_currentLine(1) _currentLine(1)
{ {
@@ -196,7 +196,9 @@ void Lexer::scan_helper(Token *tok)
_tokenStart = _currentChar; _tokenStart = _currentChar;
tok->offset = _currentChar - _firstChar; tok->offset = _currentChar - _firstChar;
if (_state == MultiLineCommentState) { if (_state == State_MultiLineComment || _state == State_MultiLineDoxyComment) {
const int originalState = _state;
if (! _yychar) { if (! _yychar) {
tok->kind = T_EOF_SYMBOL; tok->kind = T_EOF_SYMBOL;
return; return;
@@ -209,7 +211,7 @@ void Lexer::scan_helper(Token *tok)
yyinp(); yyinp();
if (_yychar == '/') { if (_yychar == '/') {
yyinp(); yyinp();
_state = DefaultState; _state = State_Default;
break; break;
} }
} }
@@ -218,7 +220,10 @@ void Lexer::scan_helper(Token *tok)
if (! _scanCommentTokens) if (! _scanCommentTokens)
goto _Lagain; goto _Lagain;
else if (originalState == State_MultiLineComment)
tok->kind = T_COMMENT; tok->kind = T_COMMENT;
else
tok->kind = T_DOXY_COMMENT;
return; // done return; // done
} }
@@ -402,14 +407,30 @@ void Lexer::scan_helper(Token *tok)
case '/': case '/':
if (_yychar == '/') { if (_yychar == '/') {
do {
yyinp(); yyinp();
} while (_yychar && _yychar != '\n');
bool doxy = false;
if (_yychar == '/' || _yychar == '!') {
yyinp();
if (_yychar != '\n' && std::isspace(_yychar))
doxy = true;
}
while (_yychar && _yychar != '\n')
yyinp();
if (! _scanCommentTokens) if (! _scanCommentTokens)
goto _Lagain; goto _Lagain;
tok->kind = T_COMMENT;
tok->kind = doxy ? T_DOXY_COMMENT : T_COMMENT;
} else if (_yychar == '*') { } else if (_yychar == '*') {
yyinp(); yyinp();
const bool doxy = _yychar == '*' || _yychar == '!';
while (_yychar) { while (_yychar) {
if (_yychar != '*') { if (_yychar != '*') {
yyinp(); yyinp();
@@ -423,11 +444,13 @@ void Lexer::scan_helper(Token *tok)
if (_yychar) if (_yychar)
yyinp(); yyinp();
else else
_state = MultiLineCommentState; _state = doxy ? State_MultiLineDoxyComment : State_MultiLineComment;
if (! _scanCommentTokens) if (! _scanCommentTokens)
goto _Lagain; goto _Lagain;
tok->kind = T_COMMENT;
tok->kind = doxy ? T_DOXY_COMMENT : T_COMMENT;
} else if (_yychar == '=') { } else if (_yychar == '=') {
yyinp(); yyinp();
tok->kind = T_SLASH_EQUAL; tok->kind = T_SLASH_EQUAL;

View File

@@ -66,8 +66,9 @@ class CPLUSPLUS_EXPORT Lexer
public: public:
enum State { enum State {
DefaultState, State_Default,
MultiLineCommentState State_MultiLineComment,
State_MultiLineDoxyComment
}; };
Lexer(TranslationUnit *unit); Lexer(TranslationUnit *unit);

View File

@@ -58,7 +58,7 @@ CPLUSPLUS_BEGIN_NAMESPACE
static const char *token_names[] = { static const char *token_names[] = {
(""), ("<error>"), (""), ("<error>"),
("<comment>"), ("<comment>"), ("<doxy comment>"),
("<identifier>"), ("<int literal>"), ("<float literal>"), ("<char literal>"), ("<identifier>"), ("<int literal>"), ("<float literal>"), ("<char literal>"),
("<wide char literal>"), ("<string literal>"), ("<wide char literal>"), ("<wide char literal>"), ("<string literal>"), ("<wide char literal>"),

View File

@@ -64,6 +64,7 @@ enum Kind {
T_ERROR, T_ERROR,
T_COMMENT, T_COMMENT,
T_DOXY_COMMENT,
T_IDENTIFIER, T_IDENTIFIER,
T_FIRST_LITERAL, T_FIRST_LITERAL,
@@ -297,6 +298,9 @@ public:
inline bool isKeyword() const inline bool isKeyword() const
{ return kind >= T_FIRST_KEYWORD && kind < T_FIRST_QT_KEYWORD; } { return kind >= T_FIRST_KEYWORD && kind < T_FIRST_QT_KEYWORD; }
inline bool isComment() const
{ return kind == T_COMMENT || kind == T_DOXY_COMMENT; }
inline bool isObjCAtKeyword() const inline bool isObjCAtKeyword() const
{ return kind >= T_FIRST_OBJC_AT_KEYWORD && kind < T_LAST_OBJC_AT_KEYWORD; } { return kind >= T_FIRST_OBJC_AT_KEYWORD && kind < T_LAST_OBJC_AT_KEYWORD; }

View File

@@ -5,4 +5,3 @@ echo "Generating $t"
${CPP-gcc} -xc++ -E -include $me/conf.c++ $* > $t ${CPP-gcc} -xc++ -E -include $me/conf.c++ $* > $t
echo "Parsing $t" echo "Parsing $t"
$me/cplusplus0 $t $me/cplusplus0 $t

View File

@@ -6,3 +6,6 @@
#define restrict #define restrict
#define __restrict #define __restrict
#define __weak #define __weak
#define __complex__
#define __imag__
#define __real__