Support debugger drivers that use a regular expression to search for the prompt.
[kdbg.git] / kdbg / debugger.cpp
blob9f2a5aa83f695d1222655911b306e2d1574f5b75
1 // $Id$
3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
6 #include "debugger.h"
7 #include "dbgdriver.h"
8 #include "pgmargs.h"
9 #include "typetable.h"
10 #include "exprwnd.h"
11 #include "pgmsettings.h"
12 #include "valarray.h"
13 #include <qregexp.h>
14 #include <qfileinfo.h>
15 #include <qlistbox.h>
16 #include <kapp.h>
17 #include <ksimpleconfig.h>
18 #include <kconfig.h>
19 #if QT_VERSION >= 200
20 #include <klocale.h> /* i18n */
21 #include <kmessagebox.h>
22 #else
23 #include <kmsgbox.h>
24 #endif
25 #include <ctype.h>
26 #include <stdlib.h> /* strtol, atoi */
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h> /* sleep(3) */
29 #endif
30 #include "mydebug.h"
33 KDebugger::KDebugger(QWidget* parent,
34 ExprWnd* localVars,
35 ExprWnd* watchVars,
36 QListBox* backtrace,
37 DebuggerDriver* driver
38 ) :
39 QObject(parent, "debugger"),
40 m_ttyLevel(ttyFull),
41 m_memoryFormat(MDTword | MDThex),
42 m_haveExecutable(false),
43 m_programActive(false),
44 m_programRunning(false),
45 m_sharedLibsListed(false),
46 m_typeTable(0),
47 m_programConfig(0),
48 m_d(driver),
49 m_localVariables(*localVars),
50 m_watchVariables(*watchVars),
51 m_btWindow(*backtrace),
52 m_animationTimer(this),
53 m_animationInterval(0)
55 m_envVars.setAutoDelete(true);
57 connect(&m_localVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
58 SLOT(slotLocalsExpanding(KTreeViewItem*,bool&)));
59 connect(&m_watchVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
60 SLOT(slotWatchExpanding(KTreeViewItem*,bool&)));
62 connect(&m_btWindow, SIGNAL(highlighted(int)), SLOT(gotoFrame(int)));
64 connect(m_d, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)),
65 this, SIGNAL(activateFileLine(const QString&,int,const DbgAddr&)));
67 // debugger process
68 connect(m_d, SIGNAL(processExited(KProcess*)), SLOT(gdbExited(KProcess*)));
69 connect(m_d, SIGNAL(commandReceived(CmdQueueItem*,const char*)),
70 SLOT(parse(CmdQueueItem*,const char*)));
71 connect(m_d, SIGNAL(wroteStdin(KProcess*)), SIGNAL(updateUI()));
72 connect(m_d, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning()));
73 connect(m_d, SIGNAL(enterIdleState()), SLOT(backgroundUpdate()));
74 connect(m_d, SIGNAL(enterIdleState()), SIGNAL(updateUI()));
76 // animation
77 connect(&m_animationTimer, SIGNAL(timeout()), SIGNAL(animationTimeout()));
78 // special update of animation
79 connect(this, SIGNAL(updateUI()), SLOT(slotUpdateAnimation()));
81 emit updateUI();
84 KDebugger::~KDebugger()
86 if (m_programConfig != 0) {
87 saveProgramSettings();
88 m_programConfig->sync();
89 delete m_programConfig;
91 // delete breakpoint objects
92 for (int i = m_brkpts.size()-1; i >= 0; i--) {
93 delete m_brkpts[i];
96 delete m_typeTable;
100 void KDebugger::saveSettings(KConfig* /*config*/)
104 void KDebugger::restoreSettings(KConfig* /*config*/)
109 //////////////////////////////////////////////////////////////////////
110 // external interface
112 const char GeneralGroup[] = "General";
113 const char DebuggerCmdStr[] = "DebuggerCmdStr";
114 const char TTYLevelEntry[] = "TTYLevel";
116 bool KDebugger::debugProgram(const QString& name)
118 if (m_d->isRunning())
120 QApplication::setOverrideCursor(waitCursor);
122 stopDriver();
124 QApplication::restoreOverrideCursor();
126 if (m_d->isRunning() || m_haveExecutable) {
127 /* timed out! We can't really do anything useful now */
128 TRACE("timed out while waiting for gdb to die!");
129 return false;
133 // create the program settings object
134 openProgramConfig(name);
136 // get debugger command from per-program settings
137 if (m_programConfig != 0) {
138 m_programConfig->setGroup(GeneralGroup);
139 m_debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
140 // get terminal emulation level
141 m_ttyLevel = TTYLevel(m_programConfig->readNumEntry(TTYLevelEntry, ttyFull));
143 // the rest is read in later in the handler of DCexecutable
145 if (!startDriver()) {
146 TRACE("startDriver failed");
147 return false;
150 TRACE("before file cmd");
151 m_d->executeCmd(DCexecutable, name);
152 m_executable = name;
154 // set remote target
155 if (!m_remoteDevice.isEmpty()) {
156 m_d->executeCmd(DCtargetremote, m_remoteDevice);
157 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
158 m_d->queueCmd(DCframe, 0, DebuggerDriver::QMnormal);
159 m_programActive = true;
160 m_haveExecutable = true;
163 // create a type table
164 m_typeTable = new ProgramTypeTable;
165 m_sharedLibsListed = false;
167 emit updateUI();
169 return true;
172 void KDebugger::shutdown()
174 // shut down debugger driver
175 if (m_d->isRunning())
177 stopDriver();
181 void KDebugger::useCoreFile(QString corefile, bool batch)
183 m_corefile = corefile;
184 if (!batch) {
185 CmdQueueItem* cmd = loadCoreFile();
186 cmd->m_byUser = true;
190 void KDebugger::programRun()
192 if (!isReady())
193 return;
195 // when program is active, but not a core file, continue
196 // otherwise run the program
197 if (m_programActive && m_corefile.isEmpty()) {
198 // gdb command: continue
199 m_d->executeCmd(DCcont, true);
200 } else {
201 // gdb command: run
202 m_d->executeCmd(DCrun, true);
203 m_corefile = QString();
204 m_programActive = true;
206 m_programRunning = true;
209 void KDebugger::attachProgram(const QString& pid)
211 if (!isReady())
212 return;
214 m_attachedPid = pid;
215 TRACE("Attaching to " + m_attachedPid);
216 m_d->executeCmd(DCattach, m_attachedPid);
217 m_programActive = true;
218 m_programRunning = true;
221 void KDebugger::programRunAgain()
223 if (canSingleStep()) {
224 m_d->executeCmd(DCrun, true);
225 m_corefile = QString();
226 m_programRunning = true;
230 void KDebugger::programStep()
232 if (canSingleStep()) {
233 m_d->executeCmd(DCstep, true);
234 m_programRunning = true;
238 void KDebugger::programNext()
240 if (canSingleStep()) {
241 m_d->executeCmd(DCnext, true);
242 m_programRunning = true;
246 void KDebugger::programStepi()
248 if (canSingleStep()) {
249 m_d->executeCmd(DCstepi, true);
250 m_programRunning = true;
254 void KDebugger::programNexti()
256 if (canSingleStep()) {
257 m_d->executeCmd(DCnexti, true);
258 m_programRunning = true;
262 void KDebugger::programFinish()
264 if (canSingleStep()) {
265 m_d->executeCmd(DCfinish, true);
266 m_programRunning = true;
270 void KDebugger::programKill()
272 if (haveExecutable() && isProgramActive()) {
273 if (m_programRunning) {
274 m_d->interruptInferior();
276 // this is an emergency command; flush queues
277 m_d->flushCommands(true);
278 m_d->executeCmd(DCkill, true);
282 bool KDebugger::runUntil(const QString& fileName, int lineNo)
284 if (isReady() && m_programActive && !m_programRunning) {
285 // strip off directory part of file name
286 QString file = fileName;
287 #if QT_VERSION < 200
288 file.detach();
289 #endif
290 int offset = file.findRev("/");
291 if (offset >= 0) {
292 file.remove(0, offset+1);
294 m_d->executeCmd(DCuntil, file, lineNo, true);
295 m_programRunning = true;
296 return true;
297 } else {
298 return false;
302 void KDebugger::programBreak()
304 if (m_haveExecutable && m_programRunning) {
305 m_d->interruptInferior();
309 void KDebugger::programArgs(QWidget* parent)
311 if (m_haveExecutable) {
312 PgmArgs dlg(parent, m_executable, m_envVars);
313 dlg.setArgs(m_programArgs);
314 dlg.setWd(m_programWD);
315 if (dlg.exec()) {
316 updateProgEnvironment(dlg.args(), dlg.wd(), dlg.envVars());
321 void KDebugger::programSettings(QWidget* parent)
323 if (!m_haveExecutable)
324 return;
326 ProgramSettings dlg(parent, m_executable);
328 dlg.m_chooseDriver.setDebuggerCmd(m_debuggerCmd);
329 dlg.m_output.setTTYLevel(m_ttyLevel);
331 if (dlg.exec() == QDialog::Accepted)
333 m_debuggerCmd = dlg.m_chooseDriver.debuggerCmd();
334 m_ttyLevel = TTYLevel(dlg.m_output.ttyLevel());
338 bool KDebugger::setBreakpoint(QString file, int lineNo,
339 const DbgAddr& address, bool temporary)
341 if (!isReady()) {
342 return false;
345 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
346 if (bp == 0)
349 * No such breakpoint, so set a new one. If we have an address, we
350 * set the breakpoint exactly there. Otherwise we use the file name
351 * plus line no.
353 if (address.isEmpty())
355 // strip off directory part of file name
356 #if QT_VERSION < 200
357 file.detach();
358 #endif
359 int offset = file.findRev("/");
360 if (offset >= 0) {
361 file.remove(0, offset+1);
363 m_d->executeCmd(temporary ? DCtbreakline : DCbreakline,
364 file, lineNo);
366 else
368 m_d->executeCmd(temporary ? DCtbreakaddr : DCbreakaddr,
369 address.asString());
372 else
375 * If the breakpoint is disabled, enable it; if it's enabled,
376 * delete that breakpoint.
378 if (bp->enabled) {
379 m_d->executeCmd(DCdelete, bp->id);
380 } else {
381 m_d->executeCmd(DCenable, bp->id);
384 return true;
387 bool KDebugger::enableDisableBreakpoint(QString file, int lineNo,
388 const DbgAddr& address)
390 if (!isReady()) {
391 return false;
394 Breakpoint* bp = breakpointByFilePos(file, lineNo, address);
395 if (bp == 0)
396 return true;
398 // toggle enabled/disabled state
399 if (bp->enabled) {
400 m_d->executeCmd(DCdisable, bp->id);
401 } else {
402 m_d->executeCmd(DCenable, bp->id);
404 return true;
407 bool KDebugger::canSingleStep()
409 return isReady() && m_programActive && !m_programRunning;
412 bool KDebugger::canChangeBreakpoints()
414 return isReady() && !m_programRunning;
417 bool KDebugger::isReady() const
419 return m_haveExecutable &&
420 m_d->canExecuteImmediately();
423 bool KDebugger::isIdle() const
425 return m_d->isIdle();
429 //////////////////////////////////////////////////////////
430 // debugger driver
432 bool KDebugger::startDriver()
434 emit debuggerStarting(); /* must set m_inferiorTerminal */
437 * If the per-program command string is empty, use the global setting
438 * (which might also be empty, in which case the driver uses its
439 * default).
441 QString debuggerCmd = m_debuggerCmd.isEmpty() ?
442 m_generalDebuggerCmd : m_debuggerCmd;
443 m_explicitKill = false;
444 if (!m_d->startup(debuggerCmd)) {
445 return false;
449 * If we have an output terminal, we use it. Otherwise we will run the
450 * program with input and output redirected to /dev/null. Other
451 * redirections are also necessary depending on the tty emulation
452 * level.
454 int redirect = RDNstdin|RDNstdout|RDNstderr; /* redirect everything */
455 if (!m_inferiorTerminal.isEmpty()) {
456 switch (m_ttyLevel) {
457 default:
458 case ttyNone:
459 // redirect everything
460 break;
461 case ttySimpleOutputOnly:
462 redirect = RDNstdin;
463 break;
464 case ttyFull:
465 redirect = 0;
466 break;
469 m_d->executeCmd(DCtty, m_inferiorTerminal, redirect);
471 return true;
474 void KDebugger::stopDriver()
476 m_explicitKill = true;
478 if (m_attachedPid.isEmpty()) {
479 m_d->terminate();
480 } else {
481 m_d->detachAndTerminate();
485 * We MUST wait until the slot gdbExited() has been called. But to
486 * avoid a deadlock, we wait only for some certain maximum time. Should
487 * this timeout be reached, the only reasonable thing one could do then
488 * is exiting kdbg.
490 kapp->processEvents(1000); /* ideally, this will already shut it down */
491 int maxTime = 20; /* about 20 seconds */
492 while (m_haveExecutable && maxTime > 0) {
493 // give gdb time to die (and send a SIGCLD)
494 ::sleep(1);
495 --maxTime;
496 kapp->processEvents(1000);
500 void KDebugger::gdbExited(KProcess*)
503 * Save settings, but only if gdb has already processed "info line
504 * main", otherwise we would save an empty config file, because it
505 * isn't read in until then!
507 if (m_programConfig != 0) {
508 if (m_haveExecutable) {
509 saveProgramSettings();
510 m_programConfig->sync();
512 delete m_programConfig;
513 m_programConfig = 0;
516 // erase types
517 delete m_typeTable;
518 m_typeTable = 0;
520 if (m_explicitKill) {
521 TRACE("gdb exited normally");
522 } else {
523 QString msg = i18n("gdb exited unexpectedly.\n"
524 "Restart the session (e.g. with File|Executable).");
525 #if QT_VERSION < 200
526 KMsgBox::message(parentWidget(), kapp->appName(), msg, KMsgBox::EXCLAMATION);
527 #else
528 KMessageBox::error(parentWidget(), msg);
529 #endif
532 // reset state
533 m_haveExecutable = false;
534 m_executable = "";
535 m_programActive = false;
536 m_programRunning = false;
537 m_explicitKill = false;
538 m_debuggerCmd = QString(); /* use global setting at next start! */
539 m_attachedPid = QString(); /* we are no longer attached to a process */
540 m_ttyLevel = ttyFull;
542 // stop gear wheel and erase PC
543 stopAnimation();
544 emit updatePC(QString(), -1, DbgAddr(), 0);
547 void KDebugger::openProgramConfig(const QString& name)
549 ASSERT(m_programConfig == 0);
551 QFileInfo fi(name);
552 QString pgmConfigFile = fi.dirPath(true);
553 if (!pgmConfigFile.isEmpty()) {
554 pgmConfigFile += '/';
556 pgmConfigFile += ".kdbgrc." + fi.fileName();
557 TRACE("program config file = " + pgmConfigFile);
558 // check whether we can write to the file
559 QFile file(pgmConfigFile);
560 bool readonly = true;
561 bool openit = true;
562 if (file.open(IO_ReadWrite)) { /* don't truncate! */
563 readonly = false;
564 // the file exists now
565 } else if (!file.open(IO_ReadOnly)) {
566 /* file does not exist and cannot be created: don't use it */
567 openit = false;
569 if (openit) {
570 m_programConfig = new KSimpleConfig(pgmConfigFile, readonly);
574 const char EnvironmentGroup[] = "Environment";
575 const char WatchGroup[] = "Watches";
576 const char FileVersion[] = "FileVersion";
577 const char ProgramArgs[] = "ProgramArgs";
578 const char WorkingDirectory[] = "WorkingDirectory";
579 const char Variable[] = "Var%d";
580 const char Value[] = "Value%d";
581 const char ExprFmt[] = "Expr%d";
583 void KDebugger::saveProgramSettings()
585 ASSERT(m_programConfig != 0);
586 m_programConfig->setGroup(GeneralGroup);
587 m_programConfig->writeEntry(FileVersion, 1);
588 m_programConfig->writeEntry(ProgramArgs, m_programArgs);
589 m_programConfig->writeEntry(WorkingDirectory, m_programWD);
590 m_programConfig->writeEntry(DebuggerCmdStr, m_debuggerCmd);
591 m_programConfig->writeEntry(TTYLevelEntry, int(m_ttyLevel));
593 // write environment variables
594 m_programConfig->deleteGroup(EnvironmentGroup);
595 m_programConfig->setGroup(EnvironmentGroup);
596 QDictIterator<EnvVar> it = m_envVars;
597 EnvVar* var;
598 QString varName;
599 QString varValue;
600 for (int i = 0; (var = it) != 0; ++it, ++i) {
601 varName.sprintf(Variable, i);
602 varValue.sprintf(Value, i);
603 m_programConfig->writeEntry(varName, it.currentKey());
604 m_programConfig->writeEntry(varValue, var->value);
607 saveBreakpoints(m_programConfig);
609 // watch expressions
610 // first get rid of whatever was in this group
611 m_programConfig->deleteGroup(WatchGroup);
612 // then start a new group
613 m_programConfig->setGroup(WatchGroup);
614 KTreeViewItem* item = m_watchVariables.itemAt(0);
615 int watchNum = 0;
616 for (; item != 0; item = item->getSibling(), ++watchNum) {
617 varName.sprintf(ExprFmt, watchNum);
618 m_programConfig->writeEntry(varName, item->getText());
621 // give others a chance
622 emit saveProgramSpecific(m_programConfig);
625 void KDebugger::restoreProgramSettings()
627 ASSERT(m_programConfig != 0);
628 m_programConfig->setGroup(GeneralGroup);
630 * We ignore file version for now we will use it in the future to
631 * distinguish different versions of this configuration file.
633 m_debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
634 // m_ttyLevel has been read in already
635 QString pgmArgs = m_programConfig->readEntry(ProgramArgs);
636 QString pgmWd = m_programConfig->readEntry(WorkingDirectory);
638 // read environment variables
639 m_programConfig->setGroup(EnvironmentGroup);
640 m_envVars.clear();
641 QDict<EnvVar> pgmVars;
642 EnvVar* var;
643 QString varName;
644 QString varValue;
645 for (int i = 0;; ++i) {
646 varName.sprintf(Variable, i);
647 varValue.sprintf(Value, i);
648 if (!m_programConfig->hasKey(varName)) {
649 /* entry not present, assume that we've hit them all */
650 break;
652 QString name = m_programConfig->readEntry(varName);
653 if (name.isEmpty()) {
654 // skip empty names
655 continue;
657 var = new EnvVar;
658 var->value = m_programConfig->readEntry(varValue);
659 var->status = EnvVar::EVnew;
660 pgmVars.insert(name, var);
663 updateProgEnvironment(pgmArgs, pgmWd, pgmVars);
665 restoreBreakpoints(m_programConfig);
667 // watch expressions
668 m_programConfig->setGroup(WatchGroup);
669 m_watchVariables.clear();
670 for (int i = 0;; ++i) {
671 varName.sprintf(ExprFmt, i);
672 if (!m_programConfig->hasKey(varName)) {
673 /* entry not present, assume that we've hit them all */
674 break;
676 QString expr = m_programConfig->readEntry(varName);
677 if (expr.isEmpty()) {
678 // skip empty expressions
679 continue;
681 addWatch(expr);
684 // give others a chance
685 emit restoreProgramSpecific(m_programConfig);
689 * Breakpoints are saved one per group.
691 const char BPGroup[] = "Breakpoint %d";
692 const char File[] = "File";
693 const char Line[] = "Line";
694 const char Address[] = "Address";
695 const char Temporary[] = "Temporary";
696 const char Enabled[] = "Enabled";
697 const char Condition[] = "Condition";
699 void KDebugger::saveBreakpoints(KSimpleConfig* config)
701 QString groupName;
702 int i = 0;
703 for (uint j = 0; j < m_brkpts.size(); j++) {
704 Breakpoint* bp = m_brkpts[j];
705 if (bp->type == Breakpoint::watchpoint)
706 continue; /* don't save watchpoints */
707 groupName.sprintf(BPGroup, i++);
708 config->setGroup(groupName);
709 if (!bp->fileName.isEmpty()) {
710 config->writeEntry(File, bp->fileName);
711 config->writeEntry(Line, bp->lineNo);
713 * Addresses are hardly correct across sessions, so we remove
714 * it since we have a file name and line number.
716 config->deleteEntry(Address, false);
717 } else {
718 config->writeEntry(Address, bp->address.asString());
719 /* remove remmants */
720 config->deleteEntry(File, false);
721 config->deleteEntry(Line, false);
723 config->writeEntry(Temporary, bp->temporary);
724 config->writeEntry(Enabled, bp->enabled);
725 if (bp->condition.isEmpty())
726 config->deleteEntry(Condition, false);
727 else
728 config->writeEntry(Condition, bp->condition);
729 // we do not save the ignore count
731 // delete remaining groups
732 // we recognize that a group is present if there is an Enabled entry
733 for (;; i++) {
734 groupName.sprintf(BPGroup, i);
735 config->setGroup(groupName);
736 if (!config->hasKey(Enabled)) {
737 /* group not present, assume that we've hit them all */
738 break;
740 config->deleteGroup(groupName);
744 void KDebugger::restoreBreakpoints(KSimpleConfig* config)
746 QString groupName;
747 QString fileName;
748 QString address;
749 int lineNo;
750 bool enabled, temporary;
751 QString condition;
753 * We recognize the end of the list if there is no Enabled entry
754 * present.
756 for (int i = 0;; i++) {
757 groupName.sprintf(BPGroup, i);
758 config->setGroup(groupName);
759 if (!config->hasKey(Enabled)) {
760 /* group not present, assume that we've hit them all */
761 break;
763 fileName = config->readEntry(File);
764 lineNo = config->readNumEntry(Line, -1);
765 address = config->readEntry(Address);
766 if ((fileName.isEmpty() || lineNo < 0) && address.isEmpty())
767 continue;
768 enabled = config->readBoolEntry(Enabled, true);
769 temporary = config->readBoolEntry(Temporary, false);
770 condition = config->readEntry(Condition);
772 * Add the breakpoint. We assume that we have started a new
773 * instance of gdb, because we assign the breakpoint ids ourselves,
774 * starting with 1. Then we use this id to disable the breakpoint,
775 * if necessary. If this assignment of ids doesn't work, (maybe
776 * because this isn't a fresh gdb at all), we disable the wrong
777 * breakpoint! Oh well... for now it works.
779 if (!fileName.isEmpty()) {
780 m_d->executeCmd(temporary ? DCtbreakline : DCbreakline,
781 fileName, lineNo);
782 } else {
783 m_d->executeCmd(temporary ? DCtbreakaddr : DCbreakaddr,
784 address);
786 if (!enabled) {
787 m_d->executeCmd(DCdisable, i+1);
789 if (!condition.isEmpty()) {
790 m_d->executeCmd(DCcondition, condition, i+1);
793 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
797 // parse output of command cmd
798 void KDebugger::parse(CmdQueueItem* cmd, const char* output)
800 ASSERT(cmd != 0); /* queue mustn't be empty */
802 TRACE(QString(__PRETTY_FUNCTION__) + " parsing " + output);
804 switch (cmd->m_cmd) {
805 case DCtargetremote:
806 // the output (if any) is uninteresting
807 case DCsetargs:
808 case DCtty:
809 // there is no output
810 case DCsetenv:
811 case DCunsetenv:
812 /* if value is empty, we see output, but we don't care */
813 break;
814 case DCcd:
815 /* display gdb's message in the status bar */
816 m_d->parseChangeWD(output, m_statusMessage);
817 emit updateStatusMessage();
818 break;
819 case DCinitialize:
820 break;
821 case DCexecutable:
822 if (m_d->parseChangeExecutable(output, m_statusMessage))
824 // success; restore breakpoints etc.
825 if (m_programConfig != 0) {
826 restoreProgramSettings();
828 // load file containing main() or core file
829 if (m_corefile.isEmpty()) {
830 if (m_remoteDevice.isEmpty())
831 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
832 } else {
833 // load core file
834 loadCoreFile();
836 if (!m_statusMessage.isEmpty())
837 emit updateStatusMessage();
838 } else {
839 QString msg = "gdb: " + m_statusMessage;
840 #if QT_VERSION < 200
841 KMsgBox::message(parentWidget(), kapp->appName(), msg,
842 KMsgBox::STOP, i18n("OK"));
843 #else
844 KMessageBox::sorry(parentWidget(), msg);
845 #endif
846 m_executable = "";
847 m_corefile = ""; /* don't process core file */
848 m_haveExecutable = false;
850 break;
851 case DCcorefile:
852 // in any event we have an executable at this point
853 m_haveExecutable = true;
854 if (m_d->parseCoreFile(output)) {
855 // loading a core is like stopping at a breakpoint
856 m_programActive = true;
857 handleRunCommands(output);
858 // do not reset m_corefile
859 } else {
860 // report error
861 QString msg = m_d->driverName() + ": " + QString(output);
862 #if QT_VERSION < 200
863 KMsgBox::message(parentWidget(), kapp->appName(), msg,
864 KMsgBox::EXCLAMATION, i18n("OK"));
865 #else
866 KMessageBox::sorry(parentWidget(), msg);
867 #endif
868 // if core file was loaded from command line, revert to info line main
869 if (!cmd->m_byUser) {
870 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
872 m_corefile = QString(); /* core file not available any more */
874 break;
875 case DCinfolinemain:
876 // ignore the output, marked file info follows
877 m_haveExecutable = true;
878 break;
879 case DCinfolocals:
880 // parse local variables
881 if (output[0] != '\0') {
882 handleLocals(output);
884 break;
885 case DCinforegisters:
886 handleRegisters(output);
887 break;
888 case DCexamine:
889 handleMemoryDump(output);
890 break;
891 case DCinfoline:
892 handleInfoLine(cmd, output);
893 break;
894 case DCdisassemble:
895 handleDisassemble(cmd, output);
896 break;
897 case DCframe:
898 handleFrameChange(output);
899 updateAllExprs();
900 break;
901 case DCbt:
902 handleBacktrace(output);
903 updateAllExprs();
904 break;
905 case DCprint:
906 handlePrint(cmd, output);
907 break;
908 case DCattach:
909 case DCrun:
910 case DCcont:
911 case DCstep:
912 case DCstepi:
913 case DCnext:
914 case DCnexti:
915 case DCfinish:
916 case DCuntil:
917 case DCthread:
918 handleRunCommands(output);
919 break;
920 case DCkill:
921 m_programRunning = m_programActive = false;
922 // erase PC
923 emit updatePC(QString(), -1, DbgAddr(), 0);
924 break;
925 case DCbreaktext:
926 case DCbreakline:
927 case DCtbreakline:
928 case DCbreakaddr:
929 case DCtbreakaddr:
930 case DCwatchpoint:
931 newBreakpoint(output);
932 // fall through
933 case DCdelete:
934 case DCenable:
935 case DCdisable:
936 // these commands need immediate response
937 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverrideMoreEqual);
938 break;
939 case DCinfobreak:
940 // note: this handler must not enqueue a command, since
941 // DCinfobreak is used at various different places.
942 updateBreakList(output);
943 emit lineItemsChanged();
944 break;
945 case DCfindType:
946 handleFindType(cmd, output);
947 break;
948 case DCprintStruct:
949 case DCprintQStringStruct:
950 handlePrintStruct(cmd, output);
951 break;
952 case DCinfosharedlib:
953 handleSharedLibs(output);
954 break;
955 case DCcondition:
956 case DCignore:
957 // we are not interested in the output
958 break;
959 case DCinfothreads:
960 handleThreadList(output);
961 break;
965 void KDebugger::backgroundUpdate()
968 * If there are still expressions that need to be updated, then do so.
970 if (m_programActive)
971 evalExpressions();
974 void KDebugger::handleRunCommands(const char* output)
976 uint flags = m_d->parseProgramStopped(output, m_statusMessage);
977 emit updateStatusMessage();
979 m_programActive = flags & DebuggerDriver::SFprogramActive;
981 // refresh files if necessary
982 if (flags & DebuggerDriver::SFrefreshSource) {
983 TRACE("re-reading files");
984 emit executableUpdated();
988 * If we stopped at a breakpoint, we must update the breakpoint list
989 * because the hit count changes. Also, if the breakpoint was temporary
990 * it would go away now.
992 if ((flags & (DebuggerDriver::SFrefreshBreak|DebuggerDriver::SFrefreshSource)) ||
993 stopMayChangeBreakList())
995 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
999 * If we haven't listed the shared libraries yet, do so. We must do
1000 * this before we emit any commands that list variables, since the type
1001 * libraries depend on the shared libraries.
1003 if (!m_sharedLibsListed) {
1004 // must be a high-priority command!
1005 m_d->executeCmd(DCinfosharedlib);
1008 // get the backtrace if the program is running
1009 if (m_programActive) {
1010 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
1011 } else {
1012 // program finished: erase PC
1013 emit updatePC(QString(), -1, DbgAddr(), 0);
1014 // dequeue any commands in the queues
1015 m_d->flushCommands();
1018 /* Update threads list */
1019 if (flags & DebuggerDriver::SFrefreshThreads) {
1020 m_d->queueCmd(DCinfothreads, DebuggerDriver::QMoverride);
1023 m_programRunning = false;
1024 emit programStopped();
1027 void KDebugger::slotInferiorRunning()
1029 m_programRunning = true;
1032 void KDebugger::updateAllExprs()
1034 if (!m_programActive)
1035 return;
1037 // retrieve local variables
1038 m_d->queueCmd(DCinfolocals, DebuggerDriver::QMoverride);
1040 // retrieve registers
1041 m_d->queueCmd(DCinforegisters, DebuggerDriver::QMoverride);
1043 // get new memory dump
1044 if (!m_memoryExpression.isEmpty()) {
1045 queueMemoryDump(false);
1048 // update watch expressions
1049 KTreeViewItem* item = m_watchVariables.itemAt(0);
1050 for (; item != 0; item = item->getSibling()) {
1051 m_watchEvalExpr.append(static_cast<VarTree*>(item));
1055 void KDebugger::updateProgEnvironment(const QString& args, const QString& wd,
1056 const QDict<EnvVar>& newVars)
1058 m_programArgs = args;
1059 m_d->executeCmd(DCsetargs, m_programArgs);
1060 TRACE("new pgm args: " + m_programArgs + "\n");
1062 m_programWD = wd.stripWhiteSpace();
1063 if (!m_programWD.isEmpty()) {
1064 m_d->executeCmd(DCcd, m_programWD);
1065 TRACE("new wd: " + m_programWD + "\n");
1068 QDictIterator<EnvVar> it = newVars;
1069 EnvVar* val;
1070 for (; (val = it) != 0; ++it) {
1071 QString var = it.currentKey();
1072 switch (val->status) {
1073 case EnvVar::EVnew:
1074 m_envVars.insert(var, val);
1075 // fall thru
1076 case EnvVar::EVdirty:
1077 // the value must be in our list
1078 ASSERT(m_envVars[var] == val);
1079 // update value
1080 m_d->executeCmd(DCsetenv, var, val->value);
1081 break;
1082 case EnvVar::EVdeleted:
1083 // must be in our list
1084 ASSERT(m_envVars[var] == val);
1085 // delete value
1086 m_d->executeCmd(DCunsetenv, var);
1087 m_envVars.remove(var);
1088 break;
1089 default:
1090 ASSERT(false);
1091 case EnvVar::EVclean:
1092 // variable not changed
1093 break;
1098 void KDebugger::handleLocals(const char* output)
1100 // retrieve old list of local variables
1101 QStrList oldVars;
1102 m_localVariables.exprList(oldVars);
1105 * Get local variables.
1107 QList<VarTree> newVars;
1108 parseLocals(output, newVars);
1111 * Clear any old VarTree item pointers, so that later we don't access
1112 * dangling pointers.
1114 m_localVariables.clearPendingUpdates();
1116 // reduce flicker
1117 bool autoU = m_localVariables.autoUpdate();
1118 m_localVariables.setAutoUpdate(false);
1119 bool repaintNeeded = false;
1122 * Match old variables against new ones.
1124 for (const char* n = oldVars.first(); n != 0; n = oldVars.next()) {
1125 // lookup this variable in the list of new variables
1126 VarTree* v = newVars.first();
1127 while (v != 0 && strcmp(v->getText(), n) != 0) {
1128 v = newVars.next();
1130 if (v == 0) {
1131 // old variable not in the new variables
1132 TRACE(QString("old var deleted: ") + n);
1133 v = m_localVariables.topLevelExprByName(n);
1134 removeExpr(&m_localVariables, v);
1135 if (v != 0) repaintNeeded = true;
1136 } else {
1137 // variable in both old and new lists: update
1138 TRACE(QString("update var: ") + n);
1139 m_localVariables.updateExpr(newVars.current());
1140 // remove the new variable from the list
1141 newVars.remove();
1142 delete v;
1143 #if QT_VERSION >= 200
1144 repaintNeeded = true;
1145 #endif
1148 // insert all remaining new variables
1149 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1150 TRACE("new var: " + v->getText());
1151 m_localVariables.insertExpr(v);
1152 repaintNeeded = true;
1155 // repaint
1156 m_localVariables.setAutoUpdate(autoU);
1157 if (repaintNeeded && autoU && m_localVariables.isVisible())
1158 m_localVariables.repaint();
1161 void KDebugger::parseLocals(const char* output, QList<VarTree>& newVars)
1163 QList<VarTree> vars;
1164 m_d->parseLocals(output, vars);
1166 QString origName; /* used in renaming variables */
1167 while (vars.count() > 0)
1169 VarTree* variable = vars.take(0);
1170 // get some types
1171 variable->inferTypesOfChildren(*m_typeTable);
1173 * When gdb prints local variables, those from the innermost block
1174 * come first. We run through the list of already parsed variables
1175 * to find duplicates (ie. variables that hide local variables from
1176 * a surrounding block). We keep the name of the inner variable, but
1177 * rename those from the outer block so that, when the value is
1178 * updated in the window, the value of the variable that is
1179 * _visible_ changes the color!
1181 int block = 0;
1182 origName = variable->getText();
1183 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1184 if (variable->getText() == v->getText()) {
1185 // we found a duplicate, change name
1186 block++;
1187 QString newName = origName + " (" + QString().setNum(block) + ")";
1188 variable->setText(newName);
1191 newVars.append(variable);
1195 bool KDebugger::handlePrint(CmdQueueItem* cmd, const char* output)
1197 ASSERT(cmd->m_expr != 0);
1199 VarTree* variable = parseExpr(output, true);
1200 if (variable == 0)
1201 return false;
1203 // set expression "name"
1204 variable->setText(cmd->m_expr->getText());
1206 if (cmd->m_expr->m_varKind == VarTree::VKpointer) {
1208 * We must insert a dummy parent, because otherwise variable's value
1209 * would overwrite cmd->m_expr's value.
1211 VarTree* dummyParent = new VarTree(variable->getText(), VarTree::NKplain);
1212 dummyParent->m_varKind = VarTree::VKdummy;
1213 // the name of the parsed variable is the address of the pointer
1214 QString addr = "*" + cmd->m_expr->m_value;
1215 variable->setText(addr);
1216 variable->m_nameKind = VarTree::NKaddress;
1218 dummyParent->appendChild(variable);
1219 dummyParent->setDeleteChildren(true);
1220 TRACE("update ptr: " + cmd->m_expr->getText());
1221 cmd->m_exprWnd->updateExpr(cmd->m_expr, dummyParent);
1222 delete dummyParent;
1223 } else {
1224 TRACE("update expr: " + cmd->m_expr->getText());
1225 cmd->m_exprWnd->updateExpr(cmd->m_expr, variable);
1226 delete variable;
1229 evalExpressions(); /* enqueue dereferenced pointers */
1231 return true;
1234 VarTree* KDebugger::parseExpr(const char* output, bool wantErrorValue)
1236 VarTree* variable;
1238 // check for error conditions
1239 bool goodValue = m_d->parsePrintExpr(output, wantErrorValue, variable);
1241 if (variable != 0 && goodValue)
1243 // get some types
1244 variable->inferTypesOfChildren(*m_typeTable);
1246 return variable;
1249 // parse the output of bt
1250 void KDebugger::handleBacktrace(const char* output)
1252 // reduce flicker
1253 m_btWindow.setAutoUpdate(false);
1255 m_btWindow.clear();
1257 QList<StackFrame> stack;
1258 m_d->parseBackTrace(output, stack);
1260 if (stack.count() > 0) {
1261 StackFrame* frm = stack.take(0);
1262 // first frame must set PC
1263 // note: frm->lineNo is zero-based
1264 emit updatePC(frm->fileName, frm->lineNo, frm->address, frm->frameNo);
1266 do {
1267 QString func;
1268 if (frm->var != 0)
1269 func = frm->var->getText();
1270 else
1271 func = frm->fileName + ":" + QString().setNum(frm->lineNo+1);
1272 m_btWindow.insertItem(func);
1273 TRACE("frame " + func + " (" + frm->fileName + ":" +
1274 QString().setNum(frm->lineNo+1) + ")");
1275 delete frm;
1277 while ((frm = stack.take()) != 0);
1280 m_btWindow.setAutoUpdate(true);
1281 m_btWindow.repaint();
1284 void KDebugger::gotoFrame(int frame)
1286 m_d->executeCmd(DCframe, frame);
1289 void KDebugger::handleFrameChange(const char* output)
1291 QString fileName;
1292 int frameNo;
1293 int lineNo;
1294 DbgAddr address;
1295 if (m_d->parseFrameChange(output, frameNo, fileName, lineNo, address)) {
1296 /* lineNo can be negative here if we can't find a file name */
1297 emit updatePC(fileName, lineNo, address, frameNo);
1298 } else {
1299 emit updatePC(fileName, -1, address, frameNo);
1303 void KDebugger::evalExpressions()
1305 // evaluate expressions in the following order:
1306 // watch expressions
1307 // pointers in local variables
1308 // pointers in watch expressions
1309 // types in local variables
1310 // types in watch expressions
1311 // pointers in 'this'
1312 // types in 'this'
1314 VarTree* exprItem = m_watchEvalExpr.first();
1315 if (exprItem != 0) {
1316 m_watchEvalExpr.remove();
1317 QString expr = exprItem->computeExpr();
1318 TRACE("watch expr: " + expr);
1319 CmdQueueItem* cmd = m_d->queueCmd(DCprint, expr, DebuggerDriver::QMoverride);
1320 // remember which expr this was
1321 cmd->m_expr = exprItem;
1322 cmd->m_exprWnd = &m_watchVariables;
1323 } else {
1324 ExprWnd* wnd;
1325 VarTree* exprItem;
1326 #define POINTER(widget) \
1327 wnd = &widget; \
1328 exprItem = widget.nextUpdatePtr(); \
1329 if (exprItem != 0) goto pointer
1330 #define STRUCT(widget) \
1331 wnd = &widget; \
1332 exprItem = widget.nextUpdateStruct(); \
1333 if (exprItem != 0) goto ustruct
1334 #define TYPE(widget) \
1335 wnd = &widget; \
1336 exprItem = widget.nextUpdateType(); \
1337 if (exprItem != 0) goto type
1338 repeat:
1339 POINTER(m_localVariables);
1340 POINTER(m_watchVariables);
1341 STRUCT(m_localVariables);
1342 STRUCT(m_watchVariables);
1343 TYPE(m_localVariables);
1344 TYPE(m_watchVariables);
1345 #undef POINTER
1346 #undef STRUCT
1347 #undef TYPE
1348 return;
1350 pointer:
1351 // we have an expression to send
1352 dereferencePointer(wnd, exprItem, false);
1353 return;
1355 ustruct:
1356 // paranoia
1357 if (exprItem->m_type == 0 || exprItem->m_type == TypeInfo::unknownType())
1358 goto repeat;
1359 evalInitialStructExpression(exprItem, wnd, false);
1360 return;
1362 type:
1364 * Sometimes a VarTree gets registered twice for a type update. So
1365 * it may happen that it has already been updated. Hence, we ignore
1366 * it here and go on to the next task.
1368 if (exprItem->m_type != 0)
1369 goto repeat;
1370 determineType(wnd, exprItem);
1374 void KDebugger::dereferencePointer(ExprWnd* wnd, VarTree* exprItem,
1375 bool immediate)
1377 ASSERT(exprItem->m_varKind == VarTree::VKpointer);
1379 QString expr = exprItem->computeExpr();
1380 TRACE("dereferencing pointer: " + expr);
1381 QString queueExpr = "*(" + expr + ")";
1382 CmdQueueItem* cmd;
1383 if (immediate) {
1384 cmd = m_d->queueCmd(DCprint, queueExpr, DebuggerDriver::QMoverrideMoreEqual);
1385 } else {
1386 cmd = m_d->queueCmd(DCprint, queueExpr, DebuggerDriver::QMoverride);
1388 // remember which expr this was
1389 cmd->m_expr = exprItem;
1390 cmd->m_exprWnd = wnd;
1393 void KDebugger::determineType(ExprWnd* wnd, VarTree* exprItem)
1395 ASSERT(exprItem->m_varKind == VarTree::VKstruct);
1397 QString expr = exprItem->computeExpr();
1398 TRACE("get type of: " + expr);
1399 CmdQueueItem* cmd;
1400 cmd = m_d->queueCmd(DCfindType, expr, DebuggerDriver::QMoverride);
1402 // remember which expr this was
1403 cmd->m_expr = exprItem;
1404 cmd->m_exprWnd = wnd;
1407 void KDebugger::handleFindType(CmdQueueItem* cmd, const char* output)
1409 QString type;
1410 if (m_d->parseFindType(output, type))
1412 ASSERT(cmd != 0 && cmd->m_expr != 0);
1414 TypeInfo* info = m_typeTable->lookup(type);
1416 if (info == 0) {
1418 * We've asked gdb for the type of the expression in
1419 * cmd->m_expr, but it returned a name we don't know. The base
1420 * class (and member) types have been checked already (at the
1421 * time when we parsed that particular expression). Now it's
1422 * time to derive the type from the base classes as a last
1423 * resort.
1425 info = cmd->m_expr->inferTypeFromBaseClass();
1426 // if we found a type through this method, register an alias
1427 if (info != 0) {
1428 TRACE("infered alias: " + type);
1429 m_typeTable->registerAlias(type, info);
1432 if (info == 0) {
1433 TRACE("unknown type");
1434 cmd->m_expr->m_type = TypeInfo::unknownType();
1435 } else {
1436 cmd->m_expr->m_type = info;
1437 /* since this node has a new type, we get its value immediately */
1438 evalInitialStructExpression(cmd->m_expr, cmd->m_exprWnd, false);
1439 return;
1443 evalExpressions(); /* queue more of them */
1446 void KDebugger::handlePrintStruct(CmdQueueItem* cmd, const char* output)
1448 VarTree* var = cmd->m_expr;
1449 ASSERT(var != 0);
1450 ASSERT(var->m_varKind == VarTree::VKstruct);
1452 VarTree* partExpr;
1453 if (cmd->m_cmd != DCprintQStringStruct) {
1454 partExpr = parseExpr(output, false);
1455 } else {
1456 partExpr = m_d->parseQCharArray(output, false, m_typeTable->qCharIsShort());
1458 bool errorValue =
1459 partExpr == 0 ||
1460 /* we only allow simple values at the moment */
1461 partExpr->childCount() != 0;
1463 QString partValue;
1464 if (errorValue)
1466 partValue = "?""?""?"; // 2 question marks in a row would be a trigraph
1467 } else {
1468 partValue = partExpr->m_value;
1470 delete partExpr;
1471 partExpr = 0;
1474 * Updating a struct value works like this: var->m_partialValue holds
1475 * the value that we have gathered so far (it's been initialized with
1476 * var->m_type->m_displayString[0] earlier). Each time we arrive here,
1477 * we append the printed result followed by the next
1478 * var->m_type->m_displayString to var->m_partialValue.
1480 * If the expression we just evaluated was a guard expression, and it
1481 * resulted in an error, we must not evaluate the real expression, but
1482 * go on to the next index. (We must still add the question marks to
1483 * the value).
1485 * Next, if this was the length expression, we still have not seen the
1486 * real expression, but the length of a QString.
1488 ASSERT(var->m_exprIndex >= 0 && var->m_exprIndex <= typeInfoMaxExpr);
1490 if (errorValue || !var->m_exprIndexUseGuard)
1492 // add current partValue (which might be the question marks)
1493 #if QT_VERSION < 200
1494 var->m_partialValue.detach();
1495 #endif
1496 var->m_partialValue += partValue;
1497 var->m_exprIndex++; /* next part */
1498 var->m_exprIndexUseGuard = true;
1499 var->m_partialValue += var->m_type->m_displayString[var->m_exprIndex];
1501 else
1503 // this was a guard expression that succeeded
1504 // go for the real expression
1505 var->m_exprIndexUseGuard = false;
1508 /* go for more sub-expressions if needed */
1509 if (var->m_exprIndex < var->m_type->m_numExprs) {
1510 /* queue a new print command with quite high priority */
1511 evalStructExpression(var, cmd->m_exprWnd, true);
1512 return;
1515 cmd->m_exprWnd->updateStructValue(var);
1517 evalExpressions(); /* enqueue dereferenced pointers */
1520 /* queues the first printStruct command for a struct */
1521 void KDebugger::evalInitialStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1523 var->m_exprIndex = 0;
1524 var->m_exprIndexUseGuard = true;
1525 var->m_partialValue = var->m_type->m_displayString[0];
1526 evalStructExpression(var, wnd, immediate);
1529 /* queues a printStruct command; var must have been initialized correctly */
1530 void KDebugger::evalStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1532 QString base = var->computeExpr();
1533 QString exprFmt;
1534 if (var->m_exprIndexUseGuard) {
1535 exprFmt = var->m_type->m_guardStrings[var->m_exprIndex];
1536 if (exprFmt.isEmpty()) {
1537 // no guard, omit it and go to expression
1538 var->m_exprIndexUseGuard = false;
1541 if (!var->m_exprIndexUseGuard) {
1542 exprFmt = var->m_type->m_exprStrings[var->m_exprIndex];
1545 SIZED_QString(expr, exprFmt.length() + base.length() + 10);
1546 expr.sprintf(exprFmt, base.data());
1548 DbgCommand dbgCmd = DCprintStruct;
1549 // check if this is a QString::Data
1550 if (strncmp(expr, "/QString::Data ", 15) == 0)
1552 if (m_typeTable->parseQt2QStrings())
1554 expr = expr.mid(15, expr.length()); /* strip off /QString::Data */
1555 dbgCmd = DCprintQStringStruct;
1556 } else {
1558 * This should not happen: the type libraries should be set up
1559 * in a way that this can't happen. If this happens
1560 * nevertheless it means that, eg., kdecore was loaded but qt2
1561 * was not (only qt2 enables the QString feature).
1563 // TODO: remove this "print"; queue the next printStruct instead
1564 expr = "*0";
1566 } else {
1567 expr = expr;
1569 TRACE("evalStruct: " + expr + (var->m_exprIndexUseGuard ? " // guard" : " // real"));
1570 CmdQueueItem* cmd = m_d->queueCmd(dbgCmd, expr,
1571 immediate ? DebuggerDriver::QMoverrideMoreEqual
1572 : DebuggerDriver::QMnormal);
1574 // remember which expression this was
1575 cmd->m_expr = var;
1576 cmd->m_exprWnd = wnd;
1579 /* removes expression from window */
1580 void KDebugger::removeExpr(ExprWnd* wnd, VarTree* var)
1582 if (var == 0)
1583 return;
1585 // must remove any references to var from command queues
1586 m_d->dequeueCmdByVar(var);
1588 wnd->removeExpr(var);
1591 void KDebugger::handleSharedLibs(const char* output)
1593 // delete all known libraries
1594 m_sharedLibs.clear();
1596 // parse the table of shared libraries
1597 m_d->parseSharedLibs(output, m_sharedLibs);
1598 m_sharedLibsListed = true;
1600 // get type libraries
1601 m_typeTable->loadLibTypes(m_sharedLibs);
1604 CmdQueueItem* KDebugger::loadCoreFile()
1606 return m_d->queueCmd(DCcorefile, m_corefile, DebuggerDriver::QMoverride);
1609 void KDebugger::slotLocalsExpanding(KTreeViewItem* item, bool& allow)
1611 exprExpandingHelper(&m_localVariables, item, allow);
1614 void KDebugger::slotWatchExpanding(KTreeViewItem* item, bool& allow)
1616 exprExpandingHelper(&m_watchVariables, item, allow);
1619 void KDebugger::exprExpandingHelper(ExprWnd* wnd, KTreeViewItem* item, bool&)
1621 VarTree* exprItem = static_cast<VarTree*>(item);
1622 if (exprItem->m_varKind != VarTree::VKpointer) {
1623 return;
1625 dereferencePointer(wnd, exprItem, true);
1628 // add the expression in the edit field to the watch expressions
1629 void KDebugger::addWatch(const QString& t)
1631 QString expr = t.stripWhiteSpace();
1632 if (expr.isEmpty())
1633 return;
1634 VarTree* exprItem = new VarTree(expr, VarTree::NKplain);
1635 m_watchVariables.insertExpr(exprItem);
1637 // if we are boring ourselves, send down the command
1638 if (m_programActive) {
1639 m_watchEvalExpr.append(exprItem);
1640 if (m_d->isIdle()) {
1641 evalExpressions();
1646 // delete a toplevel watch expression
1647 void KDebugger::slotDeleteWatch()
1649 // delete only allowed while debugger is idle; or else we might delete
1650 // the very expression the debugger is currently working on...
1651 if (!m_d->isIdle())
1652 return;
1654 int index = m_watchVariables.currentItem();
1655 if (index < 0)
1656 return;
1658 VarTree* item = static_cast<VarTree*>(m_watchVariables.itemAt(index));
1659 if (!item->isToplevelExpr())
1660 return;
1662 // remove the variable from the list to evaluate
1663 if (m_watchEvalExpr.findRef(item) >= 0) {
1664 m_watchEvalExpr.remove();
1666 removeExpr(&m_watchVariables, item);
1667 // item is invalid at this point!
1670 void KDebugger::startAnimation(bool fast)
1672 int interval = fast ? 50 : 150;
1673 if (!m_animationTimer.isActive()) {
1674 m_animationTimer.start(interval);
1675 } else if (m_animationInterval != interval) {
1676 m_animationTimer.changeInterval(interval);
1678 m_animationInterval = interval;
1681 void KDebugger::stopAnimation()
1683 if (m_animationTimer.isActive()) {
1684 m_animationTimer.stop();
1685 m_animationInterval = 0;
1689 void KDebugger::slotUpdateAnimation()
1691 if (m_d->isIdle()) {
1692 stopAnimation();
1693 } else {
1695 * Slow animation while program is stopped (i.e. while variables
1696 * are displayed)
1698 bool slow = isReady() && m_programActive && !m_programRunning;
1699 startAnimation(!slow);
1703 void KDebugger::handleRegisters(const char* output)
1705 QList<RegisterInfo> regs;
1706 m_d->parseRegisters(output, regs);
1708 emit registersChanged(regs);
1710 // delete them all
1711 regs.setAutoDelete(true);
1715 * The output of the DCbreak* commands has more accurate information about
1716 * the file and the line number.
1718 void KDebugger::newBreakpoint(const char* output)
1720 int id;
1721 QString file;
1722 int lineNo;
1723 if (!m_d->parseBreakpoint(output, id, file, lineNo))
1724 return;
1726 // see if it is new
1727 for (int i = m_brkpts.size()-1; i >= 0; i--) {
1728 if (m_brkpts[i]->id == id) {
1729 // not new; update
1730 m_brkpts[i]->fileName = file;
1731 m_brkpts[i]->lineNo = lineNo;
1732 return;
1735 // yes, new
1736 Breakpoint* bp = new Breakpoint;
1737 bp->id = id;
1738 bp->temporary = false;
1739 bp->enabled = true;
1740 bp->hitCount = 0;
1741 bp->ignoreCount = 0;
1742 bp->fileName = file;
1743 bp->lineNo = lineNo;
1744 int n = m_brkpts.size();
1745 m_brkpts.resize(n+1);
1746 m_brkpts[n] = bp;
1749 void KDebugger::updateBreakList(const char* output)
1751 // get the new list
1752 QList<Breakpoint> brks;
1753 brks.setAutoDelete(false);
1754 m_d->parseBreakList(output, brks);
1756 // merge new information into existing breakpoints
1758 QArray<Breakpoint*> oldbrks = m_brkpts;
1760 // move parsed breakpoints into m_brkpts
1761 m_brkpts.detach();
1762 m_brkpts.resize(brks.count());
1763 int n = 0;
1764 for (Breakpoint* bp = brks.first(); bp != 0; bp = brks.next())
1766 m_brkpts[n++] = bp;
1769 // go through all old breakpoints
1770 for (int i = oldbrks.size()-1; i >= 0; i--) {
1771 // is this one still alive?
1772 for (int j = m_brkpts.size()-1; j >= 0; j--)
1774 if (m_brkpts[j]->id == oldbrks[i]->id) {
1775 // yes, it is
1776 // keep accurate location
1777 m_brkpts[j]->fileName = oldbrks[i]->fileName;
1778 m_brkpts[j]->lineNo = oldbrks[i]->lineNo;
1779 break;
1784 // delete old breakpoints
1785 for (int i = oldbrks.size()-1; i >= 0; i--) {
1786 delete oldbrks[i];
1789 emit breakpointsChanged();
1792 // look if there is at least one temporary breakpoint
1793 // or a watchpoint
1794 bool KDebugger::stopMayChangeBreakList() const
1796 for (int i = m_brkpts.size()-1; i >= 0; i--) {
1797 Breakpoint* bp = m_brkpts[i];
1798 if (bp->temporary || bp->type == Breakpoint::watchpoint)
1799 return true;
1801 return false;
1804 Breakpoint* KDebugger::breakpointByFilePos(QString file, int lineNo,
1805 const DbgAddr& address)
1807 // look for exact file name match
1808 int i;
1809 for (i = m_brkpts.size()-1; i >= 0; i--) {
1810 if (m_brkpts[i]->lineNo == lineNo &&
1811 m_brkpts[i]->fileName == file &&
1812 (address.isEmpty() || m_brkpts[i]->address == address))
1814 return m_brkpts[i];
1817 // not found, so try basename
1818 // strip off directory part of file name
1819 int offset = file.findRev("/");
1820 #if QT_VERSION < 200
1821 file.detach();
1822 #endif
1823 file.remove(0, offset+1);
1825 for (i = m_brkpts.size()-1; i >= 0; i--) {
1826 // get base name of breakpoint's file
1827 QString basename = m_brkpts[i]->fileName;
1828 int offset = basename.findRev("/");
1829 if (offset >= 0) {
1830 #if QT_VERSION < 200
1831 basename.detach();
1832 #endif
1833 basename.remove(0, offset+1);
1836 if (m_brkpts[i]->lineNo == lineNo &&
1837 basename == file &&
1838 (address.isEmpty() || m_brkpts[i]->address == address))
1840 return m_brkpts[i];
1844 // not found
1845 return 0;
1848 void KDebugger::slotValuePopup(const QString& expr)
1850 // search the local variables for a match
1851 VarTree* v = m_localVariables.topLevelExprByName(expr);
1852 if (v == 0) {
1853 // not found, check watch expressions
1854 v = m_watchVariables.topLevelExprByName(expr);
1855 if (v == 0) {
1856 // nothing found; do nothing
1857 return;
1861 // construct the tip
1862 QString tip = v->getText() + " = ";
1863 if (!v->m_value.isEmpty())
1865 tip += v->m_value;
1867 else
1869 // no value: we use some hint
1870 switch (v->m_varKind) {
1871 case VarTree::VKstruct:
1872 tip += "{...}";
1873 break;
1874 case VarTree::VKarray:
1875 tip += "[...]";
1876 break;
1877 default:
1878 tip += "?""?""?"; // 2 question marks in a row would be a trigraph
1879 break;
1882 emit valuePopup(tip);
1885 void KDebugger::slotDisassemble(const QString& fileName, int lineNo)
1887 CmdQueueItem* cmd = m_d->queueCmd(DCinfoline, fileName, lineNo,
1888 DebuggerDriver::QMoverrideMoreEqual);
1889 cmd->m_fileName = fileName;
1890 cmd->m_lineNo = lineNo;
1893 void KDebugger::handleInfoLine(CmdQueueItem* cmd, const char* output)
1895 QString addrFrom, addrTo;
1896 if (m_d->parseInfoLine(output, addrFrom, addrTo)) {
1897 // got the address range, now get the real code
1898 CmdQueueItem* c = m_d->queueCmd(DCdisassemble, addrFrom, addrTo,
1899 DebuggerDriver::QMoverrideMoreEqual);
1900 c->m_fileName = cmd->m_fileName;
1901 c->m_lineNo = cmd->m_lineNo;
1902 } else {
1903 // no code
1904 QList<DisassembledCode> empty;
1905 emit disassembled(cmd->m_fileName, cmd->m_lineNo, empty);
1909 void KDebugger::handleDisassemble(CmdQueueItem* cmd, const char* output)
1911 QList<DisassembledCode> code;
1912 code.setAutoDelete(true);
1913 m_d->parseDisassemble(output, code);
1914 emit disassembled(cmd->m_fileName, cmd->m_lineNo, code);
1917 void KDebugger::handleThreadList(const char* output)
1919 QList<ThreadInfo> threads;
1920 threads.setAutoDelete(true);
1921 m_d->parseThreadList(output, threads);
1922 emit threadsChanged(threads);
1925 void KDebugger::setThread(int id)
1927 m_d->queueCmd(DCthread, id, DebuggerDriver::QMoverrideMoreEqual);
1930 void KDebugger::setMemoryExpression(const QString& memexpr)
1932 m_memoryExpression = memexpr;
1934 // queue the new expression
1935 if (!m_memoryExpression.isEmpty() &&
1936 isProgramActive() &&
1937 !isProgramRunning())
1939 queueMemoryDump(true);
1943 void KDebugger::queueMemoryDump(bool immediate)
1945 m_d->queueCmd(DCexamine, m_memoryExpression, m_memoryFormat,
1946 immediate ? DebuggerDriver::QMoverrideMoreEqual :
1947 DebuggerDriver::QMoverride);
1950 void KDebugger::handleMemoryDump(const char* output)
1952 QList<MemoryDump> memdump;
1953 memdump.setAutoDelete(true);
1954 QString msg = m_d->parseMemoryDump(output, memdump);
1955 emit memoryDumpChanged(msg, memdump);
1959 #include "debugger.moc"