From kde-commits Sat Jul 31 23:51:33 2010 From: Ian Wakeling Date: Sat, 31 Jul 2010 23:51:33 +0000 To: kde-commits Subject: playground/devtools/kategdbplugin Message-Id: <20100731235133.A7970AC783 () svn ! kde ! org> X-MARC-Message: https://marc.info/?l=kde-commits&m=128062025016865 SVN commit 1157717 by ianwakeling: Ensure that breakpoints have been successfully set before going on to jump/continue commands in move-pc and run-to-cursor. Build on that to add tracking of breakpoints being set / cleared, etc and use it to hook in slighty restructured version of code from Kare for displaying breakpoints in editor window. M +109 -9 debugview.cpp M +30 -3 debugview.h M +100 -3 plugin_kategdb.cpp M +4 -0 plugin_kategdb.h --- trunk/playground/devtools/kategdbplugin/debugview.cpp #1157716:1157717 @@ -170,7 +170,7 @@ { QString cmd( "break " ); QString lineNum; - lineNum.setNum( line ); + lineNum.setNum( line + 1 ); cmd += url.path() + ":" + lineNum; issueCommand( cmd ); } @@ -182,7 +182,7 @@ { QString cmd( "tbreak " ); QString lineNum; - lineNum.setNum( line ); + lineNum.setNum( line + 1 ); cmd += url.path() + ":" + lineNum; issueCommand( cmd, new MovePCCompletion( url, line ) ); } @@ -194,7 +194,7 @@ { QString cmd( "tbreak " ); QString lineNum; - lineNum.setNum( line ); + lineNum.setNum( line + 1 ); cmd += url.path() + ":" + lineNum; issueCommand( cmd, new RunToCursorCompletion() ); } @@ -314,8 +314,9 @@ } DebugView::MovePCCompletion::MovePCCompletion( KUrl const& url, int line ) -: url( url ), - line( line ) +: destUrl( url ), + destLine( line ), + tbreakOK( false ) { } @@ -325,14 +326,28 @@ void DebugView::MovePCCompletion::operator()( DebugView* view ) { + if( tbreakOK ) + { QString cmd( "jump " ); QString lineNum; - lineNum.setNum( line ); - cmd += url.path() + ":" + lineNum; + lineNum.setNum( destLine ); + cmd += destUrl.path() + ":" + lineNum; view->issueCommand( cmd ); } + else + { + view->outputText( "tbreak failed: aborting move-pc" ); + view->promptInput(); + } +} +void DebugView::MovePCCompletion::breakpointSet() +{ + tbreakOK = true; +} + DebugView::RunToCursorCompletion::RunToCursorCompletion() +: tbreakOK( false ) { } @@ -342,9 +357,22 @@ void DebugView::RunToCursorCompletion::operator()( DebugView* view ) { + if( tbreakOK ) + { view->issueCommand( "continue" ); } + else + { + view->outputText( "tbreak failed: aborting run-to-cursor" ); + view->promptInput(); + } +} +void DebugView::RunToCursorCompletion::breakpointSet() +{ + tbreakOK = true; +} + void DebugView::processOutput( QString const& output ) { QRegExp prompt( "\\(gdb\\).*" ); @@ -352,6 +380,7 @@ QRegExp stackFrame( "#\\d+\\s+(?:0x[\\da-f]+\\s*in\\s*)?[^\\s]+\\s*\\([^)]*\\)\\s*at\\s*([^:]+):\\d+.*" ); QRegExp changeFile( "(?:Breakpoint\\s*\\d+,\\s*|0x[\\da-f]+\\s*in\\s*)?[^\\s]+\\s*\\([^)]*\\)\\s*at\\s*([^:]+):(\\d+).*" ); QRegExp changeLine( "(\\d+)\\s+.*" ); + QRegExp breakpointConfirmation( "Breakpoint\\s*(\\d+)\\s*at\\s*0x[\\da-f]+:\\s*file\\s*([^,]+),\\s*line\\s*(\\d+).*" ); QStringList lines = output.split( '\n' ); for( QStringList::Iterator it = lines.begin(); @@ -434,7 +463,7 @@ int lineNum = changeFile.cap( 2 ).toInt(); // GDB uses 1 based line numbers, kate uses 0 based... - emit debugLocationChanged( currentFile.toLatin1(), lineNum - 1 ); + emit debugLocationChanged( currentFile.toLocal8Bit(), lineNum - 1 ); } else if( changeLine.exactMatch( line ) ) { @@ -448,8 +477,26 @@ } // GDB uses 1 based line numbers, kate uses 0 based... - emit debugLocationChanged( currentFile.toLatin1(), lineNum - 1 ); + emit debugLocationChanged( currentFile.toLocal8Bit(), lineNum - 1 ); } + else if( breakpointConfirmation.exactMatch( line ) ) + { + int bpNum = breakpointConfirmation.cap( 1 ).toInt(); + QString file = breakpointConfirmation.cap( 2 ).trimmed(); + int lineNum = breakpointConfirmation.cap( 3 ).toInt(); + + breakpoints.append( Breakpoint( bpNum, file, lineNum ) ); + + // GDB uses 1 based line numbers, kate uses 0 based... + emit breakpointSet( file.toLocal8Bit(), lineNum - 1 ); + + if( commandCompletion != NULL ) + { + commandCompletion->breakpointSet(); + } + + outputText( line ); + } else if( prompt.exactMatch( line ) ) { if( commandCompletion != NULL ) @@ -508,6 +555,14 @@ void DebugView::issueCommand( QString const& cmd, CommandCompletion* completion ) { + QRegExp breakpointCmd( "(de?l?e?t?e?|disa?b?l?e?|ena?b?l?e?)(?:\\s*(\\d+))?.*" ); + + if( breakpointCmd.exactMatch( cmd ) ) + { + updateBreakpointState( breakpointCmd.cap( 1 ), + breakpointCmd.cap( 2 ) ); + } + commandCompletion = completion; outputText( "(gdb) " + cmd ); inputArea->clear(); @@ -517,3 +572,48 @@ debugProcess->write( cmd.toLocal8Bit() ); debugProcess->write( "\n" ); } + +void DebugView::updateBreakpointState( QString const& cmd, QString const& bpNum ) +{ + QList::iterator iter = breakpoints.begin(); + + // d[elete], dis[able] and en[able] without a breakpoint number all mean + // do that command for all breakpoints + while( iter != breakpoints.end() ) + { + if( bpNum.isEmpty() || + bpNum.toInt() == iter->bpNum ) + { + if( cmd.length() < 2 || cmd.at(1) == 'e' ) + { + emit breakpointClear( iter->fileName.toLocal8Bit(), + iter->lineNum - 1 ); + iter = breakpoints.erase( iter ); + } + else + { + if( cmd.at(1) == 'i' ) + { + emit breakpointDisable( iter->fileName.toLocal8Bit(), + iter->lineNum - 1 ); + } + else if( cmd.at(1) == 'n' ) + { + emit breakpointEnable( iter->fileName.toLocal8Bit(), + iter->lineNum - 1 ); + } + ++iter; + } + + if( !bpNum.isEmpty() ) + { + // only supposed to be doing one and we've found it + iter = breakpoints.end(); + } + } + else + { + ++iter; + } + } +} --- trunk/playground/devtools/kategdbplugin/debugview.h #1157716:1157717 @@ -60,6 +60,10 @@ //Signals signals: void debugLocationChanged( const char* filename, int lineNum ); + void breakpointSet( const char* filename, int lineNum ); + void breakpointClear( const char* filename, int lineNum ); + void breakpointDisable( const char* filename, int lineNum ); + void breakpointEnable( const char* filename, int lineNum ); private: enum State @@ -84,6 +88,7 @@ CommandCompletion() {} virtual ~CommandCompletion() {} virtual void operator()( DebugView* view ) = 0; + virtual void breakpointSet() {} }; class MovePCCompletion : public CommandCompletion @@ -92,20 +97,40 @@ MovePCCompletion( KUrl const& url, int line ); virtual ~MovePCCompletion(); virtual void operator()( DebugView* view ); + virtual void breakpointSet(); private: - KUrl url; - int line; + KUrl destUrl; + int destLine; + bool tbreakOK; }; - struct RunToCursorCompletion : public CommandCompletion + class RunToCursorCompletion : public CommandCompletion { public: RunToCursorCompletion(); virtual ~RunToCursorCompletion(); virtual void operator()( DebugView* view ); + virtual void breakpointSet(); + + private: + bool tbreakOK; }; + struct Breakpoint + { + Breakpoint( int bpNum, QString const& fileName, int lineNum ) + : bpNum( bpNum ), + fileName( fileName ), + lineNum( lineNum ) + { + } + + int bpNum; + QString fileName; + int lineNum; + }; + private: void processOutput( QString const& output ); void echoOutput( QString const& line ); @@ -113,6 +138,7 @@ void outputText( QString const& text ); void issueCommand( QString const& cmd, class CommandCompletion* completion = NULL ); + void updateBreakpointState( QString const& cmd, QString const& bpNum ); private: QVBoxLayout* layout; @@ -130,6 +156,7 @@ QPoint outputLength; QString lastCommand; CommandCompletion* commandCompletion; + QList breakpoints; }; #endif --- trunk/playground/devtools/kategdbplugin/plugin_kategdb.cpp #1157716:1157717 @@ -3,6 +3,7 @@ // // // Copyright (c) 2010 Ian Wakeling +// Copyright (c) 2010 Kåre Särs // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -34,6 +35,7 @@ #include #include #include +#include K_PLUGIN_FACTORY(KatePluginGDBFactory, registerPlugin();) K_EXPORT_PLUGIN(KatePluginGDBFactory( @@ -75,6 +77,14 @@ connect( debugView, SIGNAL( debugLocationChanged( const char*, int ) ), this, SLOT( slotGoTo( const char*, int ) ) ); + connect( debugView, SIGNAL( breakpointSet( const char*, int ) ), + this, SLOT( slotBreakpointSet( const char*, int ) ) ); + connect( debugView, SIGNAL( breakpointClear( const char*, int ) ), + this, SLOT( slotBreakpointClear( const char*, int ) ) ); + connect( debugView, SIGNAL( breakpointDisable( const char*, int ) ), + this, SLOT( slotBreakpointDisable( const char*, int ) ) ); + connect( debugView, SIGNAL( breakpointEnable( const char*, int ) ), + this, SLOT( slotBreakpointEnable( const char*, int ) ) ); KAction* a = actionCollection()->addAction( "debug" ); a->setText( i18n( "Start Debugging" ) ); @@ -177,13 +187,100 @@ KUrl url = debugView->resolveFileName( fileName ); // skip not existing files - if (!QFile::exists (url.toLocalFile ())) - return; - + if( QFile::exists( url.toLocalFile() ) ) + { KTextEditor::View* editView = mainWindow()->openUrl( url ); editView->setCursorPosition( KTextEditor::Cursor( lineNum, 0 ) ); } +} +void KatePluginGDBView::slotBreakpointSet( const char* fileName, int lineNum ) +{ + KUrl url = debugView->resolveFileName( fileName ); + + // skip not existing files + if( QFile::exists( url.toLocalFile() ) ) + { + KTextEditor::View* editView = mainWindow()->openUrl( url ); + KTextEditor::MarkInterface* mark = + qobject_cast( editView->document() ); + + if( mark != NULL ) + { + mark->setMarkDescription( + KTextEditor::MarkInterface::BreakpointActive, + i18n("Breakpoint") ); + mark->setMarkPixmap( KTextEditor::MarkInterface::BreakpointActive, + KIcon("media-playback-pause").pixmap(10,10) ); + mark->addMark( lineNum, + KTextEditor::MarkInterface::BreakpointActive ); + } + } +} + +void KatePluginGDBView::slotBreakpointClear( const char* fileName, int lineNum ) +{ + KUrl url = debugView->resolveFileName( fileName ); + + // skip not existing files + if( QFile::exists( url.toLocalFile() ) ) + { + KTextEditor::View* editView = mainWindow()->openUrl( url ); + KTextEditor::MarkInterface* mark = + qobject_cast( editView->document() ); + + if( mark != NULL ) + { + mark->removeMark( lineNum, + KTextEditor::MarkInterface::BreakpointActive | + KTextEditor::MarkInterface::BreakpointDisabled ); + } + } +} + +void KatePluginGDBView::slotBreakpointDisable( const char* fileName, int lineNum ) +{ + KUrl url = debugView->resolveFileName( fileName ); + + // skip not existing files + if( QFile::exists( url.toLocalFile() ) ) + { + KTextEditor::View* editView = mainWindow()->openUrl( url ); + KTextEditor::MarkInterface* mark = + qobject_cast( editView->document() ); + + if( mark != NULL ) + { + mark->setMarkDescription( + KTextEditor::MarkInterface::BreakpointDisabled, + i18n("Disabled Breakpoint") ); + mark->setMarkPixmap( KTextEditor::MarkInterface::BreakpointDisabled, + KIcon("media-playback-pause").pixmap(10,10) ); + mark->addMark( lineNum, + KTextEditor::MarkInterface::BreakpointDisabled ); + } + } +} + +void KatePluginGDBView::slotBreakpointEnable( const char* fileName, int lineNum ) +{ + KUrl url = debugView->resolveFileName( fileName ); + + // skip not existing files + if( QFile::exists( url.toLocalFile() ) ) + { + KTextEditor::View* editView = mainWindow()->openUrl( url ); + KTextEditor::MarkInterface* mark = + qobject_cast( editView->document() ); + + if( mark != NULL ) + { + mark->removeMark( lineNum, + KTextEditor::MarkInterface::BreakpointDisabled ); + } + } +} + void KatePluginGDBView::enableDebugActions( bool enable ) { static char const* actions[] = --- trunk/playground/devtools/kategdbplugin/plugin_kategdb.h #1157716:1157717 @@ -75,6 +75,10 @@ void slotMovePC(); void slotRunToCursor(); void slotGoTo( const char* fileName, int lineNum ); + void slotBreakpointSet( const char* fileName, int lineNum ); + void slotBreakpointClear( const char* fileName, int lineNum ); + void slotBreakpointEnable( const char* fileName, int lineNum ); + void slotBreakpointDisable( const char* fileName, int lineNum ); private: void enableDebugActions( bool enable );