OSDN Git Service

Debugger: Remove "Change language automatically"
[qt-creator-jp/qt-creator-jp.git] / src / plugins / debugger / debuggerengine.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** Commercial Usage
10 **
11 ** Licensees holding valid Qt Commercial licenses may use this file in
12 ** accordance with the Qt Commercial License Agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and Nokia.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** If you are unsure which license is appropriate for your use, please
26 ** contact the sales department at http://qt.nokia.com/contact.
27 **
28 **************************************************************************/
29
30 #include "debuggerengine.h"
31
32 #include "debuggeractions.h"
33 #include "debuggeragents.h"
34 #include "debuggerrunner.h"
35 #include "debuggeroutputwindow.h"
36 #include "debuggerplugin.h"
37 #include "debuggerstringutils.h"
38
39 #include "breakhandler.h"
40 #include "moduleshandler.h"
41 #include "registerhandler.h"
42 #include "snapshothandler.h"
43 #include "sourcefileshandler.h"
44 #include "stackhandler.h"
45 #include "threadshandler.h"
46 #include "watchhandler.h"
47 #include "watchutils.h"
48
49 #include <coreplugin/icore.h>
50 #include <coreplugin/editormanager/editormanager.h>
51 #include <coreplugin/progressmanager/progressmanager.h>
52 #include <coreplugin/progressmanager/futureprogress.h>
53
54 #include <projectexplorer/debugginghelper.h>
55 #include <projectexplorer/environment.h>
56 #include <projectexplorer/project.h>
57 #include <projectexplorer/projectexplorerconstants.h>
58 #include <projectexplorer/target.h>
59 #include <projectexplorer/buildconfiguration.h>
60 #include <projectexplorer/applicationrunconfiguration.h> // For LocalApplication*
61
62 #include <qt4projectmanager/qt4projectmanagerconstants.h>
63
64 #include <texteditor/itexteditor.h>
65
66 #include <utils/savedaction.h>
67 #include <utils/qtcassert.h>
68
69 #include <QtCore/QDebug>
70 #include <QtCore/QDir>
71 #include <QtCore/QFileInfo>
72 #include <QtCore/QTimer>
73 #include <QtCore/QFutureInterface>
74
75 #include <QtGui/QAbstractItemView>
76 #include <QtGui/QStandardItemModel>
77 #include <QtGui/QAction>
78 #include <QtGui/QMenu>
79 #include <QtGui/QMessageBox>
80 #include <QtGui/QPlainTextEdit>
81 #include <QtGui/QPushButton>
82 #include <QtGui/QTextBlock>
83 #include <QtGui/QTextCursor>
84 #include <QtGui/QTextDocument>
85 #include <QtGui/QTreeWidget>
86
87
88 using namespace Core;
89 using namespace Debugger;
90 using namespace Debugger::Internal;
91 using namespace ProjectExplorer;
92 using namespace TextEditor;
93
94 //#define DEBUG_STATE 1
95 #if DEBUG_STATE
96 #   define SDEBUG(s) qDebug() << s
97 #else
98 #   define SDEBUG(s)
99 #endif
100 # define XSDEBUG(s) qDebug() << s
101
102 ///////////////////////////////////////////////////////////////////////
103 //
104 // DebuggerStartParameters
105 //
106 ///////////////////////////////////////////////////////////////////////
107
108 DebuggerStartParameters::DebuggerStartParameters()
109   : attachPID(-1)
110   , useTerminal(false)
111   , breakAtMain(false)
112   , qmlServerAddress("127.0.0.1")
113   , qmlServerPort(0)
114   , toolChainType(ToolChain::UNKNOWN)
115   , startMode(NoStartMode)
116   , executableUid(0)
117 {}
118
119 void DebuggerStartParameters::clear()
120 {
121     *this = DebuggerStartParameters();
122 }
123
124
125 namespace Debugger {
126
127 QDebug operator<<(QDebug d, DebuggerState state)
128 {
129     //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
130     return d << DebuggerEngine::stateName(state);
131 }
132
133 QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
134 {
135     QDebug nospace = str.nospace();
136     const QString sep = QString(QLatin1Char(','));
137     nospace << "executable=" << sp.executable
138             << " coreFile=" << sp.coreFile
139             << " processArgs=" << sp.processArgs.join(sep)
140             << " environment=<" << sp.environment.size() << " variables>"
141             << " workingDir=" << sp.workingDirectory
142             << " attachPID=" << sp.attachPID
143             << " useTerminal=" << sp.useTerminal
144             << " remoteChannel=" << sp.remoteChannel
145             << " remoteArchitecture=" << sp.remoteArchitecture
146             << " symbolFileName=" << sp.symbolFileName
147             << " serverStartScript=" << sp.serverStartScript
148             << " toolchain=" << sp.toolChainType << '\n';
149     return str;
150 }
151
152
153 namespace Internal {
154
155 const char *DebuggerEngine::stateName(int s)
156 {
157 #    define SN(x) case x: return #x;
158     switch (s) {
159         SN(DebuggerNotReady)
160         SN(EngineSetupRequested)
161         SN(EngineSetupOk)
162         SN(EngineSetupFailed)
163         SN(EngineRunFailed)
164         SN(InferiorSetupRequested)
165         SN(InferiorSetupFailed)
166         SN(EngineRunRequested)
167         SN(InferiorRunRequested)
168         SN(InferiorRunOk)
169         SN(InferiorRunFailed)
170         SN(InferiorUnrunnable)
171         SN(InferiorStopRequested)
172         SN(InferiorStopOk)
173         SN(InferiorStopFailed)
174         SN(InferiorShutdownRequested)
175         SN(InferiorShutdownOk)
176         SN(InferiorShutdownFailed)
177         SN(EngineShutdownRequested)
178         SN(EngineShutdownOk)
179         SN(EngineShutdownFailed)
180         SN(DebuggerFinished)
181     }
182     return "<unknown>";
183 #    undef SN
184 }
185
186
187 //////////////////////////////////////////////////////////////////////
188 //
189 // CommandHandler
190 //
191 //////////////////////////////////////////////////////////////////////
192
193 class CommandHandler : public QStandardItemModel
194 {
195 public:
196     explicit CommandHandler(DebuggerEngine *engine) : m_engine(engine) {}
197     bool setData(const QModelIndex &index, const QVariant &value, int role);
198     QAbstractItemModel *model() { return this; }
199
200 private:
201     QPointer<DebuggerEngine> m_engine;
202 };
203
204 bool CommandHandler::setData(const QModelIndex &, const QVariant &value, int role)
205 {
206     QTC_ASSERT(m_engine, qDebug() << value << role; return false);
207     m_engine->handleCommand(role, value);
208     return true;
209 }
210
211
212 //////////////////////////////////////////////////////////////////////
213 //
214 // DebuggerEnginePrivate
215 //
216 //////////////////////////////////////////////////////////////////////
217
218 class DebuggerEnginePrivate : public QObject
219 {
220     Q_OBJECT
221
222 public:
223     DebuggerEnginePrivate(DebuggerEngine *engine, const DebuggerStartParameters &sp)
224       : m_engine(engine),
225         m_runControl(0),
226         m_isActive(false),
227         m_startParameters(sp),
228         m_state(DebuggerNotReady),
229         m_lastGoodState(DebuggerNotReady),
230         m_breakHandler(engine),
231         m_commandHandler(engine),
232         m_modulesHandler(engine),
233         m_registerHandler(engine),
234         m_sourceFilesHandler(engine),
235         m_stackHandler(engine),
236         m_threadsHandler(engine),
237         m_watchHandler(engine),
238         m_disassemblerViewAgent(engine),
239         m_runInWrapperEngine(false)
240     {}
241
242     ~DebuggerEnginePrivate() {}
243
244 public slots:
245     void breakpointSetRemoveMarginActionTriggered();
246     void breakpointEnableDisableMarginActionTriggered();
247     void handleContextMenuRequest(const QVariant &parameters);
248
249     void doSetupInferior();
250     void doRunEngine();
251     void doShutdownEngine();
252     void doShutdownInferior();
253     void doInterruptInferior();
254     void doFinishDebugger();
255
256     void queueRunEngine() {
257         m_engine->setState(EngineRunRequested);
258         m_engine->showMessage(_("QUEUE: RUN ENGINE"));
259         QTimer::singleShot(0, this, SLOT(doRunEngine()));
260     }
261
262     void queueShutdownEngine() {
263         m_engine->setState(EngineShutdownRequested);
264         m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
265         QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
266     }
267
268     void queueShutdownInferior() {
269         m_engine->setState(InferiorShutdownRequested);
270         m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
271         QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
272     }
273
274     void queueFinishDebugger() {
275         QTC_ASSERT(state() == EngineShutdownOk
276             || state() == EngineShutdownFailed, qDebug() << state());
277         m_engine->setState(DebuggerFinished);
278         m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
279         QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
280     }
281
282     void raiseApplication() {
283         QTC_ASSERT(m_runControl, return);
284         m_runControl->bringApplicationToForeground(m_inferiorPid);
285     }
286
287
288 public:
289     DebuggerState state() const { return m_state; }
290
291     DebuggerEngine *m_engine; // Not owned.
292     DebuggerRunControl *m_runControl;  // Not owned.
293     bool m_isActive;
294
295     DebuggerStartParameters m_startParameters;
296
297     // The current state.
298     DebuggerState m_state;
299
300     // The state we had before something unexpected happend.
301     DebuggerState m_lastGoodState;
302
303     // The state we are aiming for.
304     DebuggerState m_targetState;
305
306     qint64 m_inferiorPid;
307
308     BreakHandler m_breakHandler;
309     CommandHandler m_commandHandler;
310     ModulesHandler m_modulesHandler;
311     RegisterHandler m_registerHandler;
312     SourceFilesHandler m_sourceFilesHandler;
313     StackHandler m_stackHandler;
314     ThreadsHandler m_threadsHandler;
315     WatchHandler m_watchHandler;
316     DisassemblerViewAgent m_disassemblerViewAgent;
317     QFutureInterface<void> m_progress;
318
319     bool m_runInWrapperEngine;
320 };
321
322 void DebuggerEnginePrivate::breakpointSetRemoveMarginActionTriggered()
323 {
324     QAction *act = qobject_cast<QAction *>(sender());
325     QTC_ASSERT(act, return);
326     QList<QVariant> list = act->data().toList();
327     QTC_ASSERT(list.size() == 2, return);
328     const QString fileName = list.at(0).toString();
329     const int lineNumber = list.at(1).toInt();
330     m_breakHandler.toggleBreakpoint(fileName, lineNumber);
331 }
332
333 void DebuggerEnginePrivate::breakpointEnableDisableMarginActionTriggered()
334 {
335     QAction *act = qobject_cast<QAction *>(sender());
336     QTC_ASSERT(act, return);
337     QList<QVariant> list = act->data().toList();
338     QTC_ASSERT(list.size() == 2, return);
339     const QString fileName = list.at(0).toString();
340     const int lineNumber = list.at(1).toInt();
341     m_breakHandler.toggleBreakpointEnabled(fileName, lineNumber);
342 }
343
344 void DebuggerEnginePrivate::handleContextMenuRequest(const QVariant &parameters)
345 {
346     const QList<QVariant> list = parameters.toList();
347     QTC_ASSERT(list.size() == 3, return);
348     TextEditor::ITextEditor *editor =
349         (TextEditor::ITextEditor *)(list.at(0).value<quint64>());
350     int lineNumber = list.at(1).toInt();
351     QMenu *menu = (QMenu *)(list.at(2).value<quint64>());
352
353     BreakpointData *data = 0;
354     QString position;
355     QString fileName;
356     if (editor->property("DisassemblerView").toBool()) {
357         fileName = editor->file()->fileName();
358         QString line = editor->contents()
359             .section('\n', lineNumber - 1, lineNumber - 1);
360         position = _("*") + fileName;
361         BreakpointData needle;
362         needle.bpAddress = line.left(line.indexOf(QLatin1Char(' '))).toLatin1();
363         needle.bpLineNumber = "-1";
364         data = m_breakHandler.findSimilarBreakpoint(&needle);
365     } else {
366         fileName = editor->file()->fileName();
367         position = fileName + QString(":%1").arg(lineNumber);
368         data = m_breakHandler.findBreakpoint(fileName, lineNumber);
369     }
370
371     QList<QVariant> args;
372     args.append(fileName);
373     args.append(lineNumber);
374
375     if (data) {
376         // existing breakpoint
377         QAction *act = new QAction(tr("Remove Breakpoint"), menu);
378         act->setData(args);
379         connect(act, SIGNAL(triggered()),
380             this, SLOT(breakpointSetRemoveMarginActionTriggered()));
381         menu->addAction(act);
382
383         QAction *act2;
384         if (data->enabled)
385             act2 = new QAction(tr("Disable Breakpoint"), menu);
386         else
387             act2 = new QAction(tr("Enable Breakpoint"), menu);
388         act2->setData(args);
389         connect(act2, SIGNAL(triggered()),
390             this, SLOT(breakpointEnableDisableMarginActionTriggered()));
391         menu->addAction(act2);
392     } else {
393         // non-existing
394         QAction *act = new QAction(tr("Set Breakpoint"), menu);
395         act->setData(args);
396         connect(act, SIGNAL(triggered()),
397             this, SLOT(breakpointSetRemoveMarginActionTriggered()));
398         menu->addAction(act);
399     }
400 }
401
402 //////////////////////////////////////////////////////////////////////
403 //
404 // DebuggerEngine
405 //
406 //////////////////////////////////////////////////////////////////////
407
408 DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters)
409   : d(new DebuggerEnginePrivate(this, startParameters))
410 {
411 }
412
413 DebuggerEngine::~DebuggerEngine()
414 {
415     disconnect();
416     delete d;
417 }
418
419 void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
420 {
421     showMessage(msg, StatusBar, timeout);
422 }
423
424 void DebuggerEngine::handleCommand(int role, const QVariant &value)
425 {
426     //qDebug() << "COMMAND: " << role << value;
427
428     switch (role) {
429         case RequestReloadSourceFilesRole:
430             reloadSourceFiles();
431             break;
432
433         case RequestReloadModulesRole:
434             reloadModules();
435             break;
436
437         case RequestReloadRegistersRole:
438             reloadRegisters();
439             break;
440
441         case RequestExecDetachRole:
442             detachDebugger();
443             break;
444
445         case RequestExecContinueRole:
446             continueInferior();
447             break;
448
449         case RequestExecInterruptRole:
450             requestInterruptInferior();
451             break;
452
453         case RequestExecResetRole:
454             notifyEngineIll(); // FIXME: check
455             break;
456
457         case RequestExecStepRole:
458             executeStepX();
459             break;
460
461         case RequestExecStepOutRole:
462             executeStepOutX();
463             break;
464
465         case RequestExecNextRole:
466             executeStepNextX();
467             break;
468
469         case RequestExecRunToLineRole:
470             executeRunToLine();
471             break;
472
473         case RequestExecRunToFunctionRole:
474             executeRunToFunction();
475             break;
476
477         case RequestExecReturnFromFunctionRole:
478             executeReturnX();
479             break;
480
481         case RequestExecJumpToLineRole:
482             executeJumpToLine();
483             break;
484
485         case RequestExecWatchRole:
486             addToWatchWindow();
487             break;
488
489         case RequestExecExitRole:
490             d->queueShutdownInferior();
491             break;
492
493         case RequestCreateSnapshotRole:
494             createSnapshot();
495             break;
496
497         case RequestActivationRole:
498             setActive(value.toBool());
499             break;
500
501         case RequestExecFrameDownRole:
502             frameDown();
503             break;
504
505         case RequestExecFrameUpRole:
506             frameUp();
507             break;
508
509         case RequestOperatedByInstructionTriggeredRole:
510             gotoLocation(stackHandler()->currentFrame(), true);
511             break;
512
513         case RequestExecuteCommandRole:
514             executeDebuggerCommand(value.toString());
515             break;
516
517         case RequestToggleBreakpointRole: {
518             QList<QVariant> list = value.toList();
519             QTC_ASSERT(list.size() == 2, break);
520             const QString fileName = list.at(0).toString();
521             const int lineNumber = list.at(1).toInt();
522             breakHandler()->toggleBreakpoint(fileName, lineNumber);
523             break;
524         }
525
526         case RequestToolTipByExpressionRole: {
527             QList<QVariant> list = value.toList();
528             QTC_ASSERT(list.size() == 3, break);
529             QPoint point = list.at(0).value<QPoint>();
530             TextEditor::ITextEditor *editor = // Eeks.
531                 (TextEditor::ITextEditor *)(list.at(1).value<quint64>());
532             int pos = list.at(2).toInt();
533             setToolTipExpression(point, editor, pos);
534             break;
535         }
536
537         case RequestContextMenuRole: {
538             QList<QVariant> list = value.toList();
539             QTC_ASSERT(list.size() == 3, break);
540             d->handleContextMenuRequest(list);
541             break;
542         }
543     }
544 }
545
546 void DebuggerEngine::showModuleSymbols
547     (const QString &moduleName, const Symbols &symbols)
548 {
549     QTreeWidget *w = new QTreeWidget;
550     w->setColumnCount(3);
551     w->setRootIsDecorated(false);
552     w->setAlternatingRowColors(true);
553     w->setSortingEnabled(true);
554     w->setHeaderLabels(QStringList() << tr("Symbol") << tr("Address") << tr("Code"));
555     w->setWindowTitle(tr("Symbols in \"%1\"").arg(moduleName));
556     foreach (const Symbol &s, symbols) {
557         QTreeWidgetItem *it = new QTreeWidgetItem;
558         it->setData(0, Qt::DisplayRole, s.name);
559         it->setData(1, Qt::DisplayRole, s.address);
560         it->setData(2, Qt::DisplayRole, s.state);
561         w->addTopLevelItem(it);
562     }
563     plugin()->createNewDock(w);
564 }
565
566 void DebuggerEngine::frameUp()
567 {
568     int currentIndex = stackHandler()->currentIndex();
569     activateFrame(qMin(currentIndex + 1, stackHandler()->stackSize() - 1));
570 }
571
572 void DebuggerEngine::frameDown()
573 {
574     int currentIndex = stackHandler()->currentIndex();
575     activateFrame(qMax(currentIndex - 1, 0));
576 }
577
578 ModulesHandler *DebuggerEngine::modulesHandler() const
579 {
580     return &d->m_modulesHandler;
581 }
582
583 BreakHandler *DebuggerEngine::breakHandler() const
584 {
585     return &d->m_breakHandler;
586 }
587
588 RegisterHandler *DebuggerEngine::registerHandler() const
589 {
590     return &d->m_registerHandler;
591 }
592
593 StackHandler *DebuggerEngine::stackHandler() const
594 {
595     return &d->m_stackHandler;
596 }
597
598 ThreadsHandler *DebuggerEngine::threadsHandler() const
599 {
600     return &d->m_threadsHandler;
601 }
602
603 WatchHandler *DebuggerEngine::watchHandler() const
604 {
605     return &d->m_watchHandler;
606 }
607
608 //SnapshotHandler *DebuggerEngine::snapshotHandler() const
609 //{
610 //    return &d->m_snapshotHandler;
611 //}
612
613 SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
614 {
615     return &d->m_sourceFilesHandler;
616 }
617
618 QAbstractItemModel *DebuggerEngine::modulesModel() const
619 {
620     QAbstractItemModel *model = d->m_modulesHandler.model();
621     if (model->objectName().isEmpty()) // Make debugging easier.
622         model->setObjectName(objectName() + QLatin1String("ModulesModel"));
623     return model;
624 }
625
626 QAbstractItemModel *DebuggerEngine::breakModel() const
627 {
628     QAbstractItemModel *model = d->m_breakHandler.model();
629     if (model->objectName().isEmpty()) // Make debugging easier.
630         model->setObjectName(objectName() + QLatin1String("BreakModel"));
631     return model;
632 }
633
634 QAbstractItemModel *DebuggerEngine::registerModel() const
635 {
636     QAbstractItemModel *model = d->m_registerHandler.model();
637     if (model->objectName().isEmpty()) // Make debugging easier.
638         model->setObjectName(objectName() + QLatin1String("RegisterModel"));
639     return model;
640 }
641
642 QAbstractItemModel *DebuggerEngine::stackModel() const
643 {
644     QAbstractItemModel *model = d->m_stackHandler.model();
645     if (model->objectName().isEmpty()) // Make debugging easier.
646         model->setObjectName(objectName() + QLatin1String("StackModel"));
647     return model;
648 }
649
650 QAbstractItemModel *DebuggerEngine::threadsModel() const
651 {
652     QAbstractItemModel *model = d->m_threadsHandler.model();
653     if (model->objectName().isEmpty()) // Make debugging easier.
654         model->setObjectName(objectName() + QLatin1String("ThreadsModel"));
655     return model;
656 }
657
658 QAbstractItemModel *DebuggerEngine::localsModel() const
659 {
660     QAbstractItemModel *model = d->m_watchHandler.model(LocalsWatch);
661     if (model->objectName().isEmpty()) // Make debugging easier.
662         model->setObjectName(objectName() + QLatin1String("LocalsModel"));
663     return model;
664 }
665
666 QAbstractItemModel *DebuggerEngine::watchersModel() const
667 {
668     QAbstractItemModel *model = d->m_watchHandler.model(WatchersWatch);
669     if (model->objectName().isEmpty()) // Make debugging easier.
670         model->setObjectName(objectName() + QLatin1String("WatchersModel"));
671     return model;
672 }
673
674 QAbstractItemModel *DebuggerEngine::returnModel() const
675 {
676     QAbstractItemModel *model = d->m_watchHandler.model(ReturnWatch);
677     if (model->objectName().isEmpty()) // Make debugging easier.
678         model->setObjectName(objectName() + QLatin1String("ReturnModel"));
679     return model;
680 }
681
682 QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
683 {
684     QAbstractItemModel *model = d->m_sourceFilesHandler.model();
685     if (model->objectName().isEmpty()) // Make debugging easier.
686         model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
687     return model;
688 }
689
690 QAbstractItemModel *DebuggerEngine::commandModel() const
691 {
692     QAbstractItemModel *model = d->m_commandHandler.model();
693     if (model->objectName().isEmpty()) // Make debugging easier.
694         model->setObjectName(objectName() + QLatin1String("CommandModel"));
695     return model;
696 }
697
698 void DebuggerEngine::fetchMemory(MemoryViewAgent *, QObject *,
699         quint64 addr, quint64 length)
700 {
701     Q_UNUSED(addr);
702     Q_UNUSED(length);
703 }
704
705 void DebuggerEngine::setRegisterValue(int regnr, const QString &value)
706 {
707     Q_UNUSED(regnr);
708     Q_UNUSED(value);
709 }
710
711 void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const
712 {
713     //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
714     //    qDebug() << qPrintable(msg) << "IN STATE" << state();
715     plugin()->showMessage(msg, channel, timeout);
716     if (d->m_runControl) {
717         d->m_runControl->showMessage(msg, channel);
718     } else {
719         qWarning("Warning: %s (no active run control)", qPrintable(msg));
720     }
721 }
722
723 void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
724 {
725     if (!isSessionEngine()) {
726         d->m_progress.setProgressRange(0, 1000);
727         Core::FutureProgress *fp = Core::ICore::instance()->progressManager()
728             ->addTask(d->m_progress.future(),
729             tr("Launching"), _("Debugger.Launcher"));
730         fp->setKeepOnFinish(false);
731         d->m_progress.reportStarted();
732     }
733     QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
734     QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
735
736     DebuggerEngine *sessionTemplate = plugin()->sessionTemplate();
737     QTC_ASSERT(sessionTemplate, notifyEngineSetupFailed(); return);
738     QTC_ASSERT(sessionTemplate != this, notifyEngineSetupFailed(); return);
739
740     breakHandler()->initializeFromTemplate(sessionTemplate->breakHandler());
741     watchHandler()->initializeFromTemplate(sessionTemplate->watchHandler());
742
743     d->m_runControl = runControl;
744
745     d->m_inferiorPid = d->m_startParameters.attachPID > 0
746         ? d->m_startParameters.attachPID : 0;
747
748     if (d->m_startParameters.environment.empty())
749         d->m_startParameters.environment = Environment().toStringList();
750
751     if (d->m_startParameters.breakAtMain)
752         breakByFunctionMain();
753
754     const unsigned engineCapabilities = debuggerCapabilities();
755     theDebuggerAction(OperateByInstruction)
756         ->setEnabled(engineCapabilities & DisassemblerCapability);
757
758     QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
759          qDebug() << state());
760     setState(EngineSetupRequested);
761
762     d->m_progress.setProgressValue(200);
763     setupEngine();
764 }
765
766 void DebuggerEngine::breakByFunctionMain()
767 {
768 #ifdef Q_OS_WIN
769     // FIXME: wrong on non-Qt based binaries
770     emit breakByFunction("qMain");
771 #else
772     emit breakByFunction("main");
773 #endif
774 }
775
776 void DebuggerEngine::breakByFunction(const QString &functionName)
777 {
778     d->m_breakHandler.breakByFunction(functionName);
779     attemptBreakpointSynchronization();
780 }
781
782 void DebuggerEngine::resetLocation()
783 {
784     d->m_disassemblerViewAgent.resetLocation();
785     d->m_stackHandler.setCurrentIndex(-1);
786     plugin()->resetLocation();
787 }
788
789 void DebuggerEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMarker)
790 {
791     StackFrame frame;
792     frame.file = fileName;
793     frame.line = lineNumber;
794     gotoLocation(frame, setMarker);
795 }
796
797 void DebuggerEngine::gotoLocation(const StackFrame &frame, bool setMarker)
798 {
799     if (theDebuggerBoolSetting(OperateByInstruction) || !frame.isUsable()) {
800         if (setMarker)
801             plugin()->resetLocation();
802         d->m_disassemblerViewAgent.setFrame(frame);
803     } else {
804         plugin()->gotoLocation(frame.file, frame.line, setMarker);
805     }
806 }
807
808 void DebuggerEngine::executeStepX()
809 {
810     resetLocation();
811     if (theDebuggerBoolSetting(OperateByInstruction))
812         executeStepI();
813     else
814         executeStep();
815 }
816
817 void DebuggerEngine::executeStepOutX()
818 {
819     resetLocation();
820     executeStepOut();
821 }
822
823 void DebuggerEngine::executeStepNextX()
824 {
825     resetLocation();
826     if (theDebuggerBoolSetting(OperateByInstruction))
827         executeNextI();
828     else
829         executeNext();
830 }
831
832 void DebuggerEngine::executeReturnX()
833 {
834     resetLocation();
835     executeReturn();
836 }
837
838 static TextEditor::ITextEditor *currentTextEditor()
839 {
840     EditorManager *editorManager = EditorManager::instance();
841     if (!editorManager)
842         return 0;
843     Core::IEditor *editor = editorManager->currentEditor();
844     return qobject_cast<ITextEditor*>(editor);
845 }
846
847 void DebuggerEngine::executeRunToLine()
848 {
849     ITextEditor *textEditor = currentTextEditor();
850     QTC_ASSERT(textEditor, return);
851     QString fileName = textEditor->file()->fileName();
852     if (fileName.isEmpty())
853         return;
854     int lineNumber = textEditor->currentLine();
855     resetLocation();
856     executeRunToLine(fileName, lineNumber);
857 }
858
859 void DebuggerEngine::executeRunToFunction()
860 {
861     ITextEditor *textEditor = currentTextEditor();
862     QTC_ASSERT(textEditor, return);
863     QString fileName = textEditor->file()->fileName();
864     QPlainTextEdit *ed = qobject_cast<QPlainTextEdit*>(textEditor->widget());
865     if (!ed)
866         return;
867     QTextCursor cursor = ed->textCursor();
868     QString functionName = cursor.selectedText();
869     if (functionName.isEmpty()) {
870         const QTextBlock block = cursor.block();
871         const QString line = block.text();
872         foreach (const QString &str, line.trimmed().split('(')) {
873             QString a;
874             for (int i = str.size(); --i >= 0; ) {
875                 if (!str.at(i).isLetterOrNumber())
876                     break;
877                 a = str.at(i) + a;
878             }
879             if (!a.isEmpty()) {
880                 functionName = a;
881                 break;
882             }
883         }
884     }
885
886     if (functionName.isEmpty())
887         return;
888     resetLocation();
889     executeRunToFunction(functionName);
890 }
891
892 void DebuggerEngine::executeJumpToLine()
893 {
894     ITextEditor *textEditor = currentTextEditor();
895     QTC_ASSERT(textEditor, return);
896     QString fileName = textEditor->file()->fileName();
897     int lineNumber = textEditor->currentLine();
898     if (fileName.isEmpty())
899         return;
900     executeJumpToLine(fileName, lineNumber);
901 }
902
903 void DebuggerEngine::addToWatchWindow()
904 {
905     // Requires a selection, but that's the only case we want anyway.
906     EditorManager *editorManager = EditorManager::instance();
907     if (!editorManager)
908         return;
909     IEditor *editor = editorManager->currentEditor();
910     if (!editor)
911         return;
912     ITextEditor *textEditor = qobject_cast<ITextEditor*>(editor);
913     if (!textEditor)
914         return;
915     QTextCursor tc;
916     QPlainTextEdit *ptEdit = qobject_cast<QPlainTextEdit*>(editor->widget());
917     if (ptEdit)
918         tc = ptEdit->textCursor();
919     QString exp;
920     if (tc.hasSelection()) {
921         exp = tc.selectedText();
922     } else {
923         int line, column;
924         exp = cppExpressionAt(textEditor, tc.position(), &line, &column);
925     }
926     if (exp.isEmpty())
927         return;
928     watchHandler()->watchExpression(exp);
929 }
930
931 // Called from RunControl.
932 void DebuggerEngine::handleStartFailed()
933 {
934     showMessage("HANDLE RUNCONTROL START FAILED");
935     d->m_runControl = 0;
936
937     d->m_progress.setProgressValue(900);
938     d->m_progress.reportCanceled();
939     d->m_progress.reportFinished();
940 }
941
942 // Called from RunControl.
943 void DebuggerEngine::handleFinished()
944 {
945     showMessage("HANDLE RUNCONTROL FINISHED");
946     d->m_runControl = 0;
947     modulesHandler()->removeAll();
948     stackHandler()->removeAll();
949     threadsHandler()->removeAll();
950     watchHandler()->cleanup();
951
952     DebuggerEngine *sessionTemplate = plugin()->sessionTemplate();
953     QTC_ASSERT(sessionTemplate != this, /**/);
954     breakHandler()->storeToTemplate(sessionTemplate->breakHandler());
955     watchHandler()->storeToTemplate(sessionTemplate->watchHandler());
956
957     d->m_progress.setProgressValue(1000);
958     d->m_progress.reportFinished();
959 }
960
961 const DebuggerStartParameters &DebuggerEngine::startParameters() const
962 {
963     return d->m_startParameters;
964 }
965
966 DebuggerStartParameters &DebuggerEngine::startParameters()
967 {
968     return d->m_startParameters;
969 }
970
971
972 //////////////////////////////////////////////////////////////////////
973 //
974 // Dumpers. "Custom dumpers" are a library compiled against the current
975 // Qt containing functions to evaluate values of Qt classes
976 // (such as QString, taking pointers to their addresses).
977 // The library must be loaded into the debuggee.
978 //
979 //////////////////////////////////////////////////////////////////////
980
981 bool DebuggerEngine::qtDumperLibraryEnabled() const
982 {
983     return theDebuggerBoolSetting(UseDebuggingHelpers);
984 }
985
986 QStringList DebuggerEngine::qtDumperLibraryLocations() const
987 {
988     if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool()) {
989         const QString customLocation =
990             theDebuggerAction(CustomDebuggingHelperLocation)->value().toString();
991         const QString location =
992             tr("%1 (explicitly set in the Debugger Options)").arg(customLocation);
993         return QStringList(location);
994     }
995     return d->m_startParameters.dumperLibraryLocations;
996 }
997
998 void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
999 {
1000     //QMessageBox dialog(d->m_mainWindow); // FIXME
1001     QMessageBox dialog;
1002     QPushButton *qtPref = dialog.addButton(tr("Open Qt preferences"),
1003         QMessageBox::ActionRole);
1004     QPushButton *helperOff = dialog.addButton(tr("Turn off helper usage"),
1005         QMessageBox::ActionRole);
1006     QPushButton *justContinue = dialog.addButton(tr("Continue anyway"),
1007         QMessageBox::AcceptRole);
1008     dialog.setDefaultButton(justContinue);
1009     dialog.setWindowTitle(tr("Debugging helper missing"));
1010     dialog.setText(tr("The debugger could not load the debugging helper library."));
1011     dialog.setInformativeText(tr(
1012         "The debugging helper is used to nicely format the values of some Qt "
1013         "and Standard Library data types. "
1014         "It must be compiled for each used Qt version separately. "
1015         "This can be done in the Qt preferences page by selecting a Qt installation "
1016         "and clicking on 'Rebuild' in the 'Debugging Helper' row."));
1017     if (!details.isEmpty())
1018         dialog.setDetailedText(details);
1019     dialog.exec();
1020     if (dialog.clickedButton() == qtPref) {
1021         Core::ICore::instance()->showOptionsDialog(
1022             _(Qt4ProjectManager::Constants::QT_SETTINGS_CATEGORY),
1023             _(Qt4ProjectManager::Constants::QTVERSION_SETTINGS_PAGE_ID));
1024     } else if (dialog.clickedButton() == helperOff) {
1025         theDebuggerAction(UseDebuggingHelpers)
1026             ->setValue(qVariantFromValue(false), false);
1027     }
1028 }
1029
1030 QString DebuggerEngine::qtDumperLibraryName() const
1031 {
1032     if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool())
1033         return theDebuggerAction(CustomDebuggingHelperLocation)->value().toString();
1034     return startParameters().dumperLibrary;
1035 }
1036
1037 DebuggerState DebuggerEngine::state() const
1038 {
1039     return d->m_state;
1040 }
1041
1042 DebuggerState DebuggerEngine::lastGoodState() const
1043 {
1044     return d->m_lastGoodState;
1045 }
1046
1047 DebuggerState DebuggerEngine::targetState() const
1048 {
1049     return d->m_targetState;
1050 }
1051
1052 static bool isAllowedTransition(DebuggerState from, DebuggerState to)
1053 {
1054     switch (from) {
1055     case DebuggerNotReady:
1056         return to == EngineSetupRequested;
1057
1058     case EngineSetupRequested:
1059         return to == EngineSetupOk || to == EngineSetupFailed;
1060     case EngineSetupFailed:
1061         // FIXME: In therory it's the engine's task to go into a
1062         // proper "Shutdown" state before calling notifyEngineSetupFailed
1063         //return to == DebuggerFinished;
1064         return to == EngineShutdownRequested;
1065     case EngineSetupOk:
1066         return to == InferiorSetupRequested || to == EngineShutdownRequested;
1067
1068     case InferiorSetupRequested:
1069         return to == EngineRunRequested || to == InferiorSetupFailed;
1070     case InferiorSetupFailed:
1071         return to == EngineShutdownRequested;
1072
1073     case EngineRunRequested:
1074         return to == InferiorRunRequested || to == InferiorStopRequested
1075             || to == InferiorUnrunnable || to == EngineRunFailed;
1076
1077     case EngineRunFailed:
1078         return to == InferiorShutdownRequested;
1079
1080     case InferiorRunRequested:
1081         return to == InferiorRunOk || to == InferiorRunFailed;
1082     case InferiorRunFailed:
1083         return to == InferiorStopOk;
1084     case InferiorRunOk:
1085         return to == InferiorStopRequested || to == InferiorStopOk;
1086
1087     case InferiorStopRequested:
1088         return to == InferiorStopOk || to == InferiorStopFailed;
1089     case InferiorStopOk:
1090         return to == InferiorRunRequested || to == InferiorShutdownRequested
1091             || to == InferiorStopOk;
1092     case InferiorStopFailed:
1093         return to == EngineShutdownRequested;
1094
1095     case InferiorUnrunnable:
1096         return to == InferiorShutdownRequested;
1097     case InferiorShutdownRequested:
1098         return to == InferiorShutdownOk || to == InferiorShutdownFailed;
1099     case InferiorShutdownOk:
1100         return to == EngineShutdownRequested;
1101     case InferiorShutdownFailed:
1102         return to == EngineShutdownRequested;
1103
1104     case EngineShutdownRequested:
1105         return to == EngineShutdownOk;
1106     case EngineShutdownOk:
1107         return to == DebuggerFinished;
1108     case EngineShutdownFailed:
1109         return to == DebuggerFinished;
1110
1111     case DebuggerFinished:
1112         return to == EngineSetupRequested; // Happens on restart.
1113     }
1114
1115     qDebug() << "UNKNOWN STATE:" << from;
1116     return false;
1117 }
1118
1119 void DebuggerEngine::notifyEngineSetupFailed()
1120 {
1121     showMessage(_("NOTE: ENGINE SETUP FAILED"));
1122     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
1123     setState(EngineSetupFailed);
1124     QTC_ASSERT(d->m_runControl, return);
1125     d->m_runControl->startFailed();
1126     d->queueShutdownEngine();
1127 }
1128
1129 void DebuggerEngine::notifyEngineSetupOk()
1130 {
1131     showMessage(_("NOTE: ENGINE SETUP OK"));
1132     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
1133     setState(EngineSetupOk);
1134     QTC_ASSERT(d->m_runControl, return);
1135     showMessage(_("QUEUE: SETUP INFERIOR"));
1136     QTimer::singleShot(0, d, SLOT(doSetupInferior()));
1137 }
1138
1139 void DebuggerEnginePrivate::doSetupInferior()
1140 {
1141     m_engine->showMessage(_("CALL: SETUP INFERIOR"));
1142     QTC_ASSERT(state() == EngineSetupOk, qDebug() << state());
1143     m_progress.setProgressValue(250);
1144     m_engine->setState(InferiorSetupRequested);
1145     m_engine->setupInferior();
1146 }
1147
1148 void DebuggerEngine::notifyInferiorSetupFailed()
1149 {
1150     showMessage(_("NOTE: INFERIOR SETUP FAILED"));
1151     QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
1152     setState(InferiorSetupFailed);
1153     d->queueShutdownEngine();
1154 }
1155
1156 void DebuggerEngine::notifyInferiorSetupOk()
1157 {
1158     showMessage(_("NOTE: INFERIOR SETUP OK"));
1159     QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
1160     d->queueRunEngine();
1161 }
1162
1163 void DebuggerEnginePrivate::doRunEngine()
1164 {
1165     m_engine->showMessage(_("CALL: RUN ENGINE"));
1166     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
1167     m_progress.setProgressValue(300);
1168     m_engine->runEngine();
1169 }
1170
1171 void DebuggerEngine::notifyInferiorUnrunnable()
1172 {
1173     showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
1174     d->m_progress.setProgressValue(1000);
1175     d->m_progress.reportFinished();
1176     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
1177     setState(InferiorUnrunnable);
1178 }
1179
1180 void DebuggerEngine::notifyEngineRunFailed()
1181 {
1182     showMessage(_("NOTE: ENGINE RUN FAILED"));
1183     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
1184     d->m_progress.setProgressValue(900);
1185     d->m_progress.reportCanceled();
1186     d->m_progress.reportFinished();
1187     setState(EngineRunFailed);
1188     d->queueShutdownInferior();
1189 }
1190
1191 void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
1192 {
1193     showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
1194     d->m_progress.setProgressValue(1000);
1195     d->m_progress.reportFinished();
1196     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
1197     setState(InferiorRunRequested);
1198     notifyInferiorRunOk();
1199 }
1200
1201 void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
1202 {
1203     showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK"));
1204     d->m_progress.setProgressValue(1000);
1205     d->m_progress.reportFinished();
1206     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
1207     setState(InferiorStopRequested);
1208     notifyInferiorStopOk();
1209 }
1210
1211 void DebuggerEngine::notifyInferiorRunRequested()
1212 {
1213     showMessage(_("NOTE: INFERIOR RUN REQUESTED"));
1214     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
1215     setState(InferiorRunRequested);
1216 }
1217
1218 void DebuggerEngine::notifyInferiorRunOk()
1219 {
1220     showMessage(_("NOTE: INFERIOR RUN OK"));
1221     QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state());
1222     setState(InferiorRunOk);
1223 }
1224
1225 void DebuggerEngine::notifyInferiorRunFailed()
1226 {
1227     showMessage(_("NOTE: INFERIOR RUN FAILED"));
1228     QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state());
1229     setState(InferiorRunFailed);
1230     setState(InferiorStopOk);
1231     if (isDying())
1232         d->queueShutdownInferior();
1233 }
1234
1235 void DebuggerEngine::notifyInferiorStopOk()
1236 {
1237     showMessage(_("NOTE: INFERIOR STOP OK"));
1238     // Ignore spurious notifications after we are set to die.
1239     if (isDying()) {
1240         showMessage(_("NOTE: ... WHILE DYING. "));
1241         // Forward state to "StopOk" if needed.
1242         if (state() == InferiorStopRequested
1243                 || state() == InferiorRunRequested
1244                 || state() == InferiorRunOk) {
1245             showMessage(_("NOTE: ... FORWARDING TO 'STOP OK'. "));
1246             setState(InferiorStopOk);
1247         }
1248         if (state() == InferiorStopOk || state() == InferiorStopFailed) {
1249             d->queueShutdownInferior();
1250         }
1251         showMessage(_("NOTE: ... IGNORING STOP MESSAGE"));
1252         return;
1253     }
1254     QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
1255     setState(InferiorStopOk);
1256 }
1257
1258 void DebuggerEngine::notifyInferiorSpontaneousStop()
1259 {
1260     showMessage(_("NOTE: INFERIOR SPONTANEOUES STOP"));
1261     QTC_ASSERT(state() == InferiorRunOk, qDebug() << state());
1262     setState(InferiorStopOk);
1263 }
1264
1265 void DebuggerEngine::notifyInferiorStopFailed()
1266 {
1267     showMessage(_("NOTE: INFERIOR STOP FAILED"));
1268     QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
1269     setState(InferiorStopFailed);
1270     d->queueShutdownEngine();
1271 }
1272
1273 void DebuggerEnginePrivate::doInterruptInferior()
1274 {
1275     QTC_ASSERT(state() == InferiorRunOk, qDebug() << state());
1276     m_engine->setState(InferiorStopRequested);
1277     m_engine->showMessage(_("CALL: INTERRUPT INFERIOR"));
1278     m_engine->interruptInferior();
1279 }
1280
1281 void DebuggerEnginePrivate::doShutdownInferior()
1282 {
1283     QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
1284     m_engine->resetLocation();
1285     m_targetState = DebuggerFinished;
1286     m_engine->showMessage(_("CALL: SHUTDOWN INFERIOR"));
1287     m_engine->shutdownInferior();
1288 }
1289
1290 void DebuggerEngine::notifyInferiorShutdownOk()
1291 {
1292     showMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
1293     QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
1294     d->m_lastGoodState = DebuggerNotReady; // A "neutral" value.
1295     setState(InferiorShutdownOk);
1296     d->queueShutdownEngine();
1297 }
1298
1299 void DebuggerEngine::notifyInferiorShutdownFailed()
1300 {
1301     showMessage(_("INFERIOR SHUTDOWN FAILED"));
1302     QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << this << state());
1303     setState(InferiorShutdownFailed);
1304     d->queueShutdownEngine();
1305 }
1306
1307 void DebuggerEngine::notifyInferiorIll()
1308 {
1309     showMessage(_("NOTE: INFERIOR ILL"));
1310     // This can be issued in almost any state. The inferior could still be
1311     // alive as some previous notifications might have been bogus.
1312     d->m_targetState = DebuggerFinished;
1313     d->m_lastGoodState = d->m_state;
1314     if (state() == InferiorRunRequested) {
1315         // We asked for running, but did not see a response.
1316         // Assume the inferior is dead.
1317         // FIXME: Use timeout?
1318         setState(InferiorRunFailed);
1319         setState(InferiorStopOk);
1320     }
1321     d->queueShutdownInferior();
1322 }
1323
1324 void DebuggerEnginePrivate::doShutdownEngine()
1325 {
1326     QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
1327     m_targetState = DebuggerFinished;
1328     m_engine->showMessage(_("CALL: SHUTDOWN ENGINE"));
1329     m_engine->shutdownEngine();
1330 }
1331
1332 void DebuggerEngine::notifyEngineShutdownOk()
1333 {
1334     showMessage(_("NOTE: ENGINE SHUTDOWN OK"));
1335     QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
1336     setState(EngineShutdownOk);
1337     if (!d->m_runInWrapperEngine) {
1338         d->queueFinishDebugger();
1339     } else {
1340         setState(DebuggerFinished);
1341     }
1342 }
1343
1344 void DebuggerEngine::notifyEngineShutdownFailed()
1345 {
1346     showMessage(_("NOTE: ENGINE SHUTDOWN FAILED"));
1347     QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
1348     setState(EngineShutdownFailed);
1349     if (!d->m_runInWrapperEngine) {
1350         d->queueFinishDebugger();
1351     } else {
1352         setState(DebuggerFinished);
1353     }
1354 }
1355
1356 void DebuggerEnginePrivate::doFinishDebugger()
1357 {
1358     m_engine->showMessage(_("NOTE: FINISH DEBUGGER"));
1359     QTC_ASSERT(state() == DebuggerFinished, qDebug() << state());
1360     m_engine->resetLocation();
1361     QTC_ASSERT(m_runControl, return);
1362     m_runControl->debuggingFinished();
1363 }
1364
1365 void DebuggerEngine::notifyEngineIll()
1366 {
1367     showMessage(_("NOTE: ENGINE ILL ******"));
1368     d->m_targetState = DebuggerFinished;
1369     d->m_lastGoodState = d->m_state;
1370     switch (state()) {
1371         case InferiorRunRequested:
1372         case InferiorRunOk:
1373         case InferiorStopRequested:
1374         case InferiorStopOk:
1375             qDebug() << "FORWARDING STATE TO " << InferiorShutdownFailed;
1376             setState(InferiorShutdownFailed, true);
1377             break;
1378         default:
1379             break;
1380     }
1381     d->queueShutdownEngine();
1382 }
1383
1384 void DebuggerEngine::notifyEngineSpontaneousShutdown()
1385 {
1386     showMessage(_("NOTE: ENGINE SPONTANEOUS SHUTDOWN"));
1387     setState(EngineShutdownOk, true);
1388     d->queueFinishDebugger();
1389 }
1390
1391 void DebuggerEngine::notifyInferiorExited()
1392 {
1393     showMessage(_("NOTE: INFERIOR EXITED"));
1394     resetLocation();
1395
1396     // This can be issued in almost any state. We assume, though,
1397     // that at this point of time the inferior is not running anymore,
1398     // even if stop notification were not issued or got lost.
1399     if (state() == InferiorRunOk) {
1400         setState(InferiorStopRequested);
1401         setState(InferiorStopOk);
1402     }
1403     setState(InferiorShutdownRequested);
1404     setState(InferiorShutdownOk);
1405     d->queueShutdownEngine();
1406 }
1407
1408 void DebuggerEngine::setState(DebuggerState state, bool forced)
1409 {
1410     //qDebug() << "STATUS CHANGE: FROM " << stateName(d->m_state)
1411     //         << " TO " << stateName(state);
1412
1413     DebuggerState oldState = d->m_state;
1414     d->m_state = state;
1415
1416     QString msg = _("State changed%5 from %1(%2) to %3(%4).")
1417      .arg(stateName(oldState)).arg(oldState).arg(stateName(state)).arg(state)
1418      .arg(forced ? " BY FORCE" : "");
1419     if (!forced && !isAllowedTransition(oldState, state))
1420         qDebug() << "UNEXPECTED STATE TRANSITION: " << msg;
1421
1422     const bool running = d->m_state == InferiorRunOk;
1423     if (running)
1424         threadsHandler()->notifyRunning();
1425
1426     showMessage(msg, LogDebug);
1427     plugin()->updateState(this);
1428
1429     emit stateChanged(d->m_state);
1430 }
1431
1432 void DebuggerEngine::setRunInWrapperEngine(bool value)
1433 {
1434     d->m_runInWrapperEngine = value;
1435 }
1436
1437 bool DebuggerEngine::debuggerActionsEnabled() const
1438 {
1439     return debuggerActionsEnabled(d->m_state);
1440 }
1441
1442 bool DebuggerEngine::debuggerActionsEnabled(DebuggerState state)
1443 {
1444     switch (state) {
1445     case InferiorSetupRequested:
1446     case InferiorRunOk:
1447     case InferiorUnrunnable:
1448     case InferiorStopOk:
1449         return true;
1450     case InferiorStopRequested:
1451     case InferiorRunRequested:
1452     case InferiorRunFailed:
1453     case DebuggerNotReady:
1454     case EngineSetupRequested:
1455     case EngineSetupOk:
1456     case EngineSetupFailed:
1457     case EngineRunRequested:
1458     case EngineRunFailed:
1459     case InferiorSetupFailed:
1460     case InferiorStopFailed:
1461     case InferiorShutdownRequested:
1462     case InferiorShutdownOk:
1463     case InferiorShutdownFailed:
1464     case EngineShutdownRequested:
1465     case EngineShutdownOk:
1466     case EngineShutdownFailed:
1467     case DebuggerFinished:
1468         return false;
1469     }
1470     return false;
1471 }
1472
1473 void DebuggerEngine::notifyInferiorPid(qint64 pid)
1474 {
1475     showMessage(tr("Taking notice of pid %1").arg(pid));
1476     if (d->m_inferiorPid == pid)
1477         return;
1478     d->m_inferiorPid = pid;
1479     QTimer::singleShot(0, d, SLOT(raiseApplication()));
1480 }
1481
1482 qint64 DebuggerEngine::inferiorPid() const
1483 {
1484     return d->m_inferiorPid;
1485 }
1486
1487 DebuggerPlugin *DebuggerEngine::plugin()
1488 {
1489     return DebuggerPlugin::instance();
1490 }
1491
1492 void DebuggerEngine::openFile(const QString &fileName, int lineNumber)
1493 {
1494     plugin()->gotoLocation(fileName, lineNumber, false);
1495 }
1496
1497 bool DebuggerEngine::isReverseDebugging() const
1498 {
1499     return plugin()->isReverseDebugging();
1500 }
1501
1502 bool DebuggerEngine::isActive() const
1503 {
1504     return d->m_isActive && !isSessionEngine();
1505 }
1506
1507 void DebuggerEngine::setActive(bool on)
1508 {
1509     //qDebug() << "SETTING ACTIVE" << this << on;
1510     d->m_isActive = on;
1511     //breakHandler()->updateMarkers();
1512 }
1513
1514 // called by DebuggerRunControl
1515 void DebuggerEngine::quitDebugger()
1516 {
1517     showMessage("QUIT DEBUGGER REQUESTED");
1518     d->m_targetState = DebuggerFinished;
1519     switch (state()) {
1520     case InferiorStopOk:
1521     case InferiorStopFailed:
1522         d->queueShutdownInferior();
1523         break;
1524     case InferiorRunOk:
1525         d->doInterruptInferior();
1526         break;
1527     default:
1528         // FIXME: We should disable the actions connected to that
1529         notifyInferiorIll();
1530         break;
1531     }
1532 }
1533
1534 void DebuggerEngine::requestInterruptInferior()
1535 {
1536     d->doInterruptInferior();
1537 }
1538
1539 void DebuggerEngine::progressPing()
1540 {
1541     int progress = qMin(d->m_progress.progressValue() + 2, 800);
1542     d->m_progress.setProgressValue(progress);
1543 }
1544
1545 QMessageBox *DebuggerEngine::showMessageBox(int icon, const QString &title,
1546     const QString &text, int buttons)
1547 {
1548     return plugin()->showMessageBox(icon, title, text, buttons);
1549 }
1550
1551 DebuggerRunControl *DebuggerEngine::runControl() const
1552 {
1553     return d->m_runControl;
1554 }
1555
1556 } // namespace Internal
1557 } // namespace Debugger
1558
1559 #include "debuggerengine.moc"