Updated documentation.
[kdbg.git] / kdbg / debugger.cpp
blob838dc7024c0312be8763c9ac8dd0a01b64bd37a7
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 "valarray.h"
12 #include <qregexp.h>
13 #include <qfileinfo.h>
14 #include <qlistbox.h>
15 #include <kapp.h>
16 #include <ksimpleconfig.h>
17 #include <kconfig.h>
18 #include <kwm.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_haveExecutable(false),
42 m_programActive(false),
43 m_programRunning(false),
44 m_sharedLibsListed(false),
45 m_typeTable(0),
46 m_programConfig(0),
47 m_d(driver),
48 m_localVariables(*localVars),
49 m_watchVariables(*watchVars),
50 m_btWindow(*backtrace),
51 m_animationTimer(this),
52 m_animationInterval(0)
54 m_envVars.setAutoDelete(true);
56 connect(&m_localVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
57 SLOT(slotLocalsExpanding(KTreeViewItem*,bool&)));
58 connect(&m_watchVariables, SIGNAL(expanding(KTreeViewItem*,bool&)),
59 SLOT(slotWatchExpanding(KTreeViewItem*,bool&)));
61 connect(&m_btWindow, SIGNAL(highlighted(int)), SLOT(gotoFrame(int)));
63 connect(m_d, SIGNAL(activateFileLine(const QString&,int)),
64 this, SIGNAL(activateFileLine(const QString&,int)));
66 // debugger process
67 connect(m_d, SIGNAL(processExited(KProcess*)), SLOT(gdbExited(KProcess*)));
68 connect(m_d, SIGNAL(commandReceived(CmdQueueItem*,const char*)),
69 SLOT(parse(CmdQueueItem*,const char*)));
70 // we shouldn't do this, it's very unsafe (different arg lists):
71 connect(m_d, SIGNAL(receivedStdout(KProcess*,char*,int)),
72 SIGNAL(updateUI()));
73 connect(m_d, SIGNAL(wroteStdin(KProcess*)), SIGNAL(updateUI()));
74 connect(m_d, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning()));
75 connect(m_d, SIGNAL(enterIdleState()), SLOT(backgroundUpdate()));
77 // animation
78 connect(&m_animationTimer, SIGNAL(timeout()), SIGNAL(animationTimeout()));
79 // special update of animation
80 connect(this, SIGNAL(updateUI()), SLOT(slotUpdateAnimation()));
82 emit updateUI();
85 KDebugger::~KDebugger()
87 if (m_programConfig != 0) {
88 saveProgramSettings();
89 m_programConfig->sync();
90 delete m_programConfig;
92 // delete breakpoint objects
93 for (int i = m_brkpts.size()-1; i >= 0; i--) {
94 delete m_brkpts[i];
97 delete m_typeTable;
101 void KDebugger::saveSettings(KConfig* /*config*/)
105 void KDebugger::restoreSettings(KConfig* /*config*/)
110 //////////////////////////////////////////////////////////////////////
111 // external interface
113 const char GeneralGroup[] = "General";
114 const char DebuggerCmdStr[] = "DebuggerCmdStr";
115 const char TTYLevelEntry[] = "TTYLevel";
117 bool KDebugger::debugProgram(const QString& name)
119 if (m_d->isRunning())
121 QApplication::setOverrideCursor(waitCursor);
123 stopGdb();
125 * We MUST wait until the slot gdbExited() has been called. But to
126 * avoid a deadlock, we wait only for some certain maximum time.
127 * Should this timeout be reached, the only reasonable thing one
128 * could do then is exiting kdbg.
130 int maxTime = 20; /* about 20 seconds */
131 while (m_haveExecutable && maxTime > 0) {
132 kapp->processEvents(1000);
133 // give gdb time to die (and send a SIGCLD)
134 ::sleep(1);
135 --maxTime;
138 QApplication::restoreOverrideCursor();
140 if (m_d->isRunning() || m_haveExecutable) {
141 /* timed out! We can't really do anything useful now */
142 TRACE("timed out while waiting for gdb to die!");
143 return false;
147 // create the program settings object
148 openProgramConfig(name);
150 // get debugger command from per-program settings
151 if (m_programConfig != 0) {
152 m_programConfig->setGroup(GeneralGroup);
153 m_debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
154 // get terminal emulation level
155 m_ttyLevel = TTYLevel(m_programConfig->readNumEntry(TTYLevelEntry, ttyFull));
157 // the rest is read in later in the handler of DCexecutable
159 if (!startGdb()) {
160 TRACE("startGdb failed");
161 return false;
164 TRACE("before file cmd");
165 m_d->executeCmd(DCexecutable, name);
166 m_executable = name;
168 // set remote target
169 if (!m_remoteDevice.isEmpty()) {
170 m_d->executeCmd(DCtargetremote, m_remoteDevice);
171 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
172 m_d->queueCmd(DCframe, 0, DebuggerDriver::QMnormal);
173 m_programActive = true;
174 m_haveExecutable = true;
177 // create a type table
178 m_typeTable = new ProgramTypeTable;
179 m_sharedLibsListed = false;
181 emit updateUI();
183 return true;
186 void KDebugger::useCoreFile(QString corefile, bool batch)
188 m_corefile = corefile;
189 if (!batch) {
190 CmdQueueItem* cmd = loadCoreFile();
191 cmd->m_byUser = true;
195 void KDebugger::programRun()
197 if (!isReady())
198 return;
200 // when program is active, but not a core file, continue
201 // otherwise run the program
202 if (m_programActive && m_corefile.isEmpty()) {
203 // gdb command: continue
204 m_d->executeCmd(DCcont, true);
205 } else {
206 // gdb command: run
207 m_d->executeCmd(DCrun, true);
208 m_corefile = QString();
209 m_programActive = true;
211 m_programRunning = true;
214 void KDebugger::attachProgram(const QString& pid)
216 if (!isReady())
217 return;
219 m_attachedPid = pid;
220 TRACE("Attaching to " + m_attachedPid);
221 m_d->executeCmd(DCattach, m_attachedPid);
222 m_programActive = true;
223 m_programRunning = true;
226 void KDebugger::programRunAgain()
228 if (canSingleStep()) {
229 m_d->executeCmd(DCrun, true);
230 m_corefile = QString();
231 m_programRunning = true;
235 void KDebugger::programStep()
237 if (canSingleStep()) {
238 m_d->executeCmd(DCstep, true);
239 m_programRunning = true;
243 void KDebugger::programNext()
245 if (canSingleStep()) {
246 m_d->executeCmd(DCnext, true);
247 m_programRunning = true;
251 void KDebugger::programFinish()
253 if (canSingleStep()) {
254 m_d->executeCmd(DCfinish, true);
255 m_programRunning = true;
259 void KDebugger::programKill()
261 if (haveExecutable() && isProgramActive()) {
262 if (m_programRunning) {
263 m_d->interruptInferior();
265 // this is an emergency command; flush queues
266 m_d->flushCommands(true);
267 m_d->executeCmd(DCkill, true);
271 bool KDebugger::runUntil(const QString& fileName, int lineNo)
273 if (isReady() && m_programActive && !m_programRunning) {
274 // strip off directory part of file name
275 QString file = fileName;
276 #if QT_VERSION < 200
277 file.detach();
278 #endif
279 int offset = file.findRev("/");
280 if (offset >= 0) {
281 file.remove(0, offset+1);
283 m_d->executeCmd(DCuntil, file, lineNo, true);
284 m_programRunning = true;
285 return true;
286 } else {
287 return false;
291 void KDebugger::programBreak()
293 if (m_haveExecutable && m_programRunning) {
294 m_d->interruptInferior();
298 void KDebugger::programArgs()
300 if (m_haveExecutable) {
301 PgmArgs dlg(parentWidget(), m_executable, m_envVars);
302 dlg.setArgs(m_programArgs);
303 dlg.setWd(m_programWD);
304 if (dlg.exec()) {
305 updateProgEnvironment(dlg.args(), dlg.wd(), dlg.envVars());
310 bool KDebugger::setBreakpoint(QString file, int lineNo, bool temporary)
312 if (!isReady()) {
313 return false;
316 Breakpoint* bp = breakpointByFilePos(file, lineNo);
317 if (bp == 0)
319 // no such breakpoint, so set a new one
320 // strip off directory part of file name
321 #if QT_VERSION < 200
322 file.detach();
323 #endif
324 int offset = file.findRev("/");
325 if (offset >= 0) {
326 file.remove(0, offset+1);
328 m_d->executeCmd(temporary ? DCtbreakline : DCbreakline,
329 file, lineNo);
331 else
334 * If the breakpoint is disabled, enable it; if it's enabled,
335 * delete that breakpoint.
337 if (bp->enabled) {
338 m_d->executeCmd(DCdelete, bp->id);
339 } else {
340 m_d->executeCmd(DCenable, bp->id);
343 return true;
346 bool KDebugger::enableDisableBreakpoint(QString file, int lineNo)
348 if (!isReady()) {
349 return false;
352 Breakpoint* bp = breakpointByFilePos(file, lineNo);
353 if (bp == 0)
354 return true;
356 // toggle enabled/disabled state
357 if (bp->enabled) {
358 m_d->executeCmd(DCdisable, bp->id);
359 } else {
360 m_d->executeCmd(DCenable, bp->id);
362 return true;
365 bool KDebugger::canSingleStep()
367 return isReady() && m_programActive && !m_programRunning;
370 bool KDebugger::canChangeBreakpoints()
372 return isReady() && !m_programRunning;
375 bool KDebugger::isReady() const
377 return m_haveExecutable &&
378 m_d->canExecuteImmediately();
381 bool KDebugger::isIdle() const
383 return m_d->isIdle();
387 //////////////////////////////////////////////////////////
388 // debugger driver
390 bool KDebugger::startGdb()
392 emit debuggerStarting(); /* must set m_inferiorTerminal */
395 * If the per-program command string is empty, use the global setting
396 * (which might also be empty, in which case the driver uses its
397 * default).
399 QString debuggerCmd = m_debuggerCmd.isEmpty() ?
400 m_generalDebuggerCmd : m_debuggerCmd;
401 m_explicitKill = false;
402 if (!m_d->startup(debuggerCmd)) {
403 return false;
407 * If we have an output terminal, we use it. Otherwise we will run the
408 * program with input and output redirected to /dev/null. Other
409 * redirections are also necessary depending on the tty emulation
410 * level.
412 int redirect = RDNstdin|RDNstdout|RDNstderr; /* redirect everything */
413 if (!m_inferiorTerminal.isEmpty()) {
414 switch (m_ttyLevel) {
415 default:
416 case ttyNone:
417 // redirect everything
418 break;
419 case ttySimpleOutputOnly:
420 redirect = RDNstdin;
421 break;
422 case ttyFull:
423 redirect = 0;
424 break;
427 m_d->executeCmd(DCtty, m_inferiorTerminal, redirect);
429 return true;
432 void KDebugger::stopGdb()
434 m_explicitKill = true;
435 m_d->terminate();
438 void KDebugger::gdbExited(KProcess*)
441 * Save settings, but only if gdb has already processed "info line
442 * main", otherwise we would save an empty config file, because it
443 * isn't read in until then!
445 if (m_programConfig != 0) {
446 if (m_haveExecutable) {
447 saveProgramSettings();
448 m_programConfig->sync();
450 delete m_programConfig;
451 m_programConfig = 0;
454 // erase types
455 delete m_typeTable;
456 m_typeTable = 0;
458 if (m_explicitKill) {
459 TRACE("gdb exited normally");
460 } else {
461 QString msg = i18n("gdb exited unexpectedly.\n"
462 "Restart the session (e.g. with File|Executable).");
463 #if QT_VERSION < 200
464 KMsgBox::message(parentWidget(), kapp->appName(), msg, KMsgBox::EXCLAMATION);
465 #else
466 KMessageBox::error(parentWidget(), msg);
467 #endif
470 // reset state
471 m_haveExecutable = false;
472 m_executable = "";
473 m_programActive = false;
474 m_programRunning = false;
475 m_explicitKill = false;
476 m_debuggerCmd = QString(); /* use global setting at next start! */
477 m_attachedPid = QString(); /* we are no longer attached to a process */
479 // stop gear wheel and erase PC
480 stopAnimation();
481 emit updatePC(QString(), -1, 0);
484 void KDebugger::openProgramConfig(const QString& name)
486 ASSERT(m_programConfig = 0);
488 QFileInfo fi(name);
489 QString pgmConfigFile = fi.dirPath(true);
490 if (!pgmConfigFile.isEmpty()) {
491 pgmConfigFile += '/';
493 pgmConfigFile += ".kdbgrc." + fi.fileName();
494 TRACE("program config file = " + pgmConfigFile);
495 // check whether we can write to the file
496 QFile file(pgmConfigFile);
497 bool readonly = true;
498 bool openit = true;
499 if (file.open(IO_ReadWrite)) { /* don't truncate! */
500 readonly = false;
501 // the file exists now
502 } else if (!file.open(IO_ReadOnly)) {
503 /* file does not exist and cannot be created: don't use it */
504 openit = false;
506 if (openit) {
507 m_programConfig = new KSimpleConfig(pgmConfigFile, readonly);
511 const char EnvironmentGroup[] = "Environment";
512 const char WatchGroup[] = "Watches";
513 const char FileVersion[] = "FileVersion";
514 const char ProgramArgs[] = "ProgramArgs";
515 const char WorkingDirectory[] = "WorkingDirectory";
516 const char Variable[] = "Var%d";
517 const char Value[] = "Value%d";
518 const char ExprFmt[] = "Expr%d";
520 void KDebugger::saveProgramSettings()
522 ASSERT(m_programConfig != 0);
523 m_programConfig->setGroup(GeneralGroup);
524 m_programConfig->writeEntry(FileVersion, 1);
525 m_programConfig->writeEntry(ProgramArgs, m_programArgs);
526 m_programConfig->writeEntry(WorkingDirectory, m_programWD);
527 m_programConfig->writeEntry(DebuggerCmdStr, m_debuggerCmd);
528 m_programConfig->writeEntry(TTYLevelEntry, int(m_ttyLevel));
530 // write environment variables
531 m_programConfig->deleteGroup(EnvironmentGroup);
532 m_programConfig->setGroup(EnvironmentGroup);
533 QDictIterator<EnvVar> it = m_envVars;
534 EnvVar* var;
535 QString varName;
536 QString varValue;
537 for (int i = 0; (var = it) != 0; ++it, ++i) {
538 varName.sprintf(Variable, i);
539 varValue.sprintf(Value, i);
540 m_programConfig->writeEntry(varName, it.currentKey());
541 m_programConfig->writeEntry(varValue, var->value);
544 saveBreakpoints(m_programConfig);
546 // watch expressions
547 // first get rid of whatever was in this group
548 m_programConfig->deleteGroup(WatchGroup);
549 // then start a new group
550 m_programConfig->setGroup(WatchGroup);
551 KTreeViewItem* item = m_watchVariables.itemAt(0);
552 int watchNum = 0;
553 for (; item != 0; item = item->getSibling(), ++watchNum) {
554 varName.sprintf(ExprFmt, watchNum);
555 m_programConfig->writeEntry(varName, item->getText());
559 void KDebugger::restoreProgramSettings()
561 ASSERT(m_programConfig != 0);
562 m_programConfig->setGroup(GeneralGroup);
564 * We ignore file version for now we will use it in the future to
565 * distinguish different versions of this configuration file.
567 m_debuggerCmd = m_programConfig->readEntry(DebuggerCmdStr);
568 // m_ttyLevel has been read in already
569 QString pgmArgs = m_programConfig->readEntry(ProgramArgs);
570 QString pgmWd = m_programConfig->readEntry(WorkingDirectory);
572 // read environment variables
573 m_programConfig->setGroup(EnvironmentGroup);
574 m_envVars.clear();
575 QDict<EnvVar> pgmVars;
576 EnvVar* var;
577 QString varName;
578 QString varValue;
579 for (int i = 0;; ++i) {
580 varName.sprintf(Variable, i);
581 varValue.sprintf(Value, i);
582 if (!m_programConfig->hasKey(varName)) {
583 /* entry not present, assume that we've hit them all */
584 break;
586 QString name = m_programConfig->readEntry(varName);
587 if (name.isEmpty()) {
588 // skip empty names
589 continue;
591 var = new EnvVar;
592 var->value = m_programConfig->readEntry(varValue);
593 var->status = EnvVar::EVnew;
594 pgmVars.insert(name, var);
597 updateProgEnvironment(pgmArgs, pgmWd, pgmVars);
599 restoreBreakpoints(m_programConfig);
601 // watch expressions
602 m_programConfig->setGroup(WatchGroup);
603 m_watchVariables.clear();
604 for (int i = 0;; ++i) {
605 varName.sprintf(ExprFmt, i);
606 if (!m_programConfig->hasKey(varName)) {
607 /* entry not present, assume that we've hit them all */
608 break;
610 QString expr = m_programConfig->readEntry(varName);
611 if (expr.isEmpty()) {
612 // skip empty expressions
613 continue;
615 addWatch(expr);
620 * Breakpoints are saved one per group.
622 const char BPGroup[] = "Breakpoint %d";
623 const char File[] = "File";
624 const char Line[] = "Line";
625 const char Temporary[] = "Temporary";
626 const char Enabled[] = "Enabled";
627 const char Condition[] = "Condition";
629 void KDebugger::saveBreakpoints(KSimpleConfig* config)
631 QString groupName;
632 int i;
633 for (i = 0; uint(i) < m_brkpts.size(); i++) {
634 groupName.sprintf(BPGroup, i);
635 config->setGroup(groupName);
636 Breakpoint* bp = m_brkpts[i];
637 config->writeEntry(File, bp->fileName);
638 config->writeEntry(Line, bp->lineNo);
639 config->writeEntry(Temporary, bp->temporary);
640 config->writeEntry(Enabled, bp->enabled);
641 if (bp->condition.isEmpty())
642 config->deleteEntry(Condition, false);
643 else
644 config->writeEntry(Condition, bp->condition);
645 // we do not save the ignore count
647 // delete remaining groups
648 // we recognize that a group is present if there is an Enabled entry
649 for (;; i++) {
650 groupName.sprintf(BPGroup, i);
651 config->setGroup(groupName);
652 if (!config->hasKey(Enabled)) {
653 /* group not present, assume that we've hit them all */
654 break;
656 config->deleteGroup(groupName);
660 void KDebugger::restoreBreakpoints(KSimpleConfig* config)
662 QString groupName;
663 QString fileName;
664 int lineNo;
665 bool enabled, temporary;
666 QString condition;
668 * We recognize the end of the list if there is no Enabled entry
669 * present.
671 for (int i = 0;; i++) {
672 groupName.sprintf(BPGroup, i);
673 config->setGroup(groupName);
674 if (!config->hasKey(Enabled)) {
675 /* group not present, assume that we've hit them all */
676 break;
678 fileName = config->readEntry(File);
679 lineNo = config->readNumEntry(Line, -1);
680 if (lineNo < 0 || fileName.isEmpty())
681 continue;
682 enabled = config->readBoolEntry(Enabled, true);
683 temporary = config->readBoolEntry(Temporary, false);
684 condition = config->readEntry(Condition);
686 * Add the breakpoint. We assume that we have started a new
687 * instance of gdb, because we assign the breakpoint ids ourselves,
688 * starting with 1. Then we use this id to disable the breakpoint,
689 * if necessary. If this assignment of ids doesn't work, (maybe
690 * because this isn't a fresh gdb at all), we disable the wrong
691 * breakpoint! Oh well... for now it works.
693 m_d->executeCmd(temporary ? DCtbreakline : DCbreakline,
694 fileName, lineNo);
695 if (!enabled) {
696 m_d->executeCmd(DCdisable, i+1);
698 if (!condition.isEmpty()) {
699 m_d->executeCmd(DCcondition, condition, i+1);
702 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
706 // parse output of command cmd
707 void KDebugger::parse(CmdQueueItem* cmd, const char* output)
709 ASSERT(cmd != 0); /* queue mustn't be empty */
711 TRACE(QString(__PRETTY_FUNCTION__) + " parsing " + output);
713 switch (cmd->m_cmd) {
714 case DCtargetremote:
715 // the output (if any) is uninteresting
716 case DCsetargs:
717 case DCtty:
718 // there is no output
719 case DCsetenv:
720 case DCunsetenv:
721 /* if value is empty, we see output, but we don't care */
722 break;
723 case DCcd:
724 /* display gdb's message in the status bar */
725 m_d->parseChangeWD(output, m_statusMessage);
726 emit updateStatusMessage();
727 break;
728 case DCinitialize:
729 break;
730 case DCexecutable:
731 if (m_d->parseChangeExecutable(output, m_statusMessage))
733 // success; restore breakpoints etc.
734 if (m_programConfig != 0) {
735 restoreProgramSettings();
737 // load file containing main() or core file
738 if (m_corefile.isEmpty()) {
739 if (m_remoteDevice.isEmpty())
740 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
741 } else {
742 // load core file
743 loadCoreFile();
745 if (!m_statusMessage.isEmpty())
746 emit updateStatusMessage();
747 } else {
748 QString msg = "gdb: " + m_statusMessage;
749 #if QT_VERSION < 200
750 KMsgBox::message(parentWidget(), kapp->appName(), msg,
751 KMsgBox::STOP, i18n("OK"));
752 #else
753 KMessageBox::sorry(parentWidget(), msg);
754 #endif
755 m_executable = "";
756 m_corefile = ""; /* don't process core file */
757 m_haveExecutable = false;
759 break;
760 case DCcorefile:
761 // in any event we have an executable at this point
762 m_haveExecutable = true;
763 if (m_d->parseCoreFile(output)) {
764 // loading a core is like stopping at a breakpoint
765 m_programActive = true;
766 handleRunCommands(output);
767 // do not reset m_corefile
768 } else {
769 // report error
770 QString msg = m_d->driverName() + ": " + QString(output);
771 #if QT_VERSION < 200
772 KMsgBox::message(parentWidget(), kapp->appName(), msg,
773 KMsgBox::EXCLAMATION, i18n("OK"));
774 #else
775 KMessageBox::sorry(parentWidget(), msg);
776 #endif
777 // if core file was loaded from command line, revert to info line main
778 if (!cmd->m_byUser) {
779 m_d->queueCmd(DCinfolinemain, DebuggerDriver::QMnormal);
781 m_corefile = QString(); /* core file not available any more */
783 break;
784 case DCinfolinemain:
785 // ignore the output, marked file info follows
786 m_haveExecutable = true;
787 break;
788 case DCinfolocals:
789 // parse local variables
790 if (output[0] != '\0') {
791 handleLocals(output);
793 break;
794 case DCinforegisters:
795 handleRegisters(output);
796 break;
797 case DCframe:
798 handleFrameChange(output);
799 updateAllExprs();
800 break;
801 case DCbt:
802 handleBacktrace(output);
803 updateAllExprs();
804 break;
805 case DCprint:
806 handlePrint(cmd, output);
807 break;
808 case DCattach:
809 case DCrun:
810 case DCcont:
811 case DCstep:
812 case DCnext:
813 case DCfinish:
814 case DCuntil:
815 handleRunCommands(output);
816 break;
817 case DCkill:
818 m_programRunning = m_programActive = false;
819 // erase PC
820 emit updatePC(QString(), -1, 0);
821 break;
822 case DCbreaktext:
823 case DCbreakline:
824 case DCtbreakline:
825 newBreakpoint(output);
826 // fall through
827 case DCdelete:
828 case DCenable:
829 case DCdisable:
830 // these commands need immediate response
831 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverrideMoreEqual);
832 break;
833 case DCinfobreak:
834 // note: this handler must not enqueue a command, since
835 // DCinfobreak is used at various different places.
836 updateBreakList(output);
837 emit lineItemsChanged();
838 break;
839 case DCfindType:
840 handleFindType(cmd, output);
841 break;
842 case DCprintStruct:
843 case DCprintQStringStruct:
844 handlePrintStruct(cmd, output);
845 break;
846 case DCinfosharedlib:
847 handleSharedLibs(output);
848 break;
849 case DCcondition:
850 case DCignore:
851 // we are not interested in the output
852 break;
856 void KDebugger::backgroundUpdate()
859 * If there are still expressions that need to be updated, then do so.
861 if (m_programActive)
862 evalExpressions();
865 void KDebugger::handleRunCommands(const char* output)
867 uint flags = m_d->parseProgramStopped(output, m_statusMessage);
868 emit updateStatusMessage();
870 m_programActive = flags & DebuggerDriver::SFprogramActive;
872 // refresh files if necessary
873 if (flags & DebuggerDriver::SFrefreshSource) {
874 TRACE("re-reading files");
875 emit executableUpdated();
879 * If we stopped at a breakpoint, we must update the breakpoint list
880 * because the hit count changes. Also, if the breakpoint was temporary
881 * it would go away now.
883 if ((flags & (DebuggerDriver::SFrefreshBreak|DebuggerDriver::SFrefreshSource)) ||
884 haveTemporaryBP())
886 m_d->queueCmd(DCinfobreak, DebuggerDriver::QMoverride);
890 * If we haven't listed the shared libraries yet, do so. We must do
891 * this before we emit any commands that list variables, since the type
892 * libraries depend on the shared libraries.
894 if (!m_sharedLibsListed) {
895 // must be a high-priority command!
896 m_d->executeCmd(DCinfosharedlib);
899 // get the backtrace if the program is running
900 if (m_programActive) {
901 m_d->queueCmd(DCbt, DebuggerDriver::QMoverride);
902 } else {
903 // program finished: erase PC
904 emit updatePC(QString(), -1, 0);
905 // dequeue any commands in the queues
906 m_d->flushCommands();
909 m_programRunning = false;
912 void KDebugger::slotInferiorRunning()
914 m_programRunning = true;
917 void KDebugger::updateAllExprs()
919 if (!m_programActive)
920 return;
922 // retrieve local variables
923 m_d->queueCmd(DCinfolocals, DebuggerDriver::QMoverride);
925 // retrieve registers
926 m_d->queueCmd(DCinforegisters, DebuggerDriver::QMoverride);
928 // update watch expressions
929 KTreeViewItem* item = m_watchVariables.itemAt(0);
930 for (; item != 0; item = item->getSibling()) {
931 m_watchEvalExpr.append(static_cast<VarTree*>(item));
935 void KDebugger::updateProgEnvironment(const QString& args, const QString& wd,
936 const QDict<EnvVar>& newVars)
938 m_programArgs = args;
939 m_d->executeCmd(DCsetargs, m_programArgs);
940 TRACE("new pgm args: " + m_programArgs + "\n");
942 m_programWD = wd.stripWhiteSpace();
943 if (!m_programWD.isEmpty()) {
944 m_d->executeCmd(DCcd, m_programWD);
945 TRACE("new wd: " + m_programWD + "\n");
948 QDictIterator<EnvVar> it = newVars;
949 EnvVar* val;
950 for (; (val = it) != 0; ++it) {
951 switch (val->status) {
952 case EnvVar::EVnew:
953 m_envVars.insert(it.currentKey(), val);
954 // fall thru
955 case EnvVar::EVdirty:
956 // the value must be in our list
957 ASSERT(m_envVars[it.currentKey()] == val);
958 // update value
959 m_d->executeCmd(DCsetenv, it.currentKey(), val->value);
960 break;
961 case EnvVar::EVdeleted:
962 // must be in our list
963 ASSERT(m_envVars[it.currentKey()] == val);
964 // delete value
965 m_d->executeCmd(DCsetenv, it.currentKey());
966 m_envVars.remove(it.currentKey());
967 break;
968 default:
969 ASSERT(false);
970 case EnvVar::EVclean:
971 // variable not changed
972 break;
977 void KDebugger::handleLocals(const char* output)
979 // retrieve old list of local variables
980 QStrList oldVars;
981 m_localVariables.exprList(oldVars);
984 * Get local variables.
986 QList<VarTree> newVars;
987 parseLocals(output, newVars);
990 * Clear any old VarTree item pointers, so that later we don't access
991 * dangling pointers.
993 m_localVariables.clearPendingUpdates();
995 // reduce flicker
996 bool autoU = m_localVariables.autoUpdate();
997 m_localVariables.setAutoUpdate(false);
998 bool repaintNeeded = false;
1001 * Match old variables against new ones.
1003 for (const char* n = oldVars.first(); n != 0; n = oldVars.next()) {
1004 // lookup this variable in the list of new variables
1005 VarTree* v = newVars.first();
1006 while (v != 0 && strcmp(v->getText(), n) != 0) {
1007 v = newVars.next();
1009 if (v == 0) {
1010 // old variable not in the new variables
1011 TRACE(QString("old var deleted: ") + n);
1012 v = m_localVariables.topLevelExprByName(n);
1013 removeExpr(&m_localVariables, v);
1014 if (v != 0) repaintNeeded = true;
1015 } else {
1016 // variable in both old and new lists: update
1017 TRACE(QString("update var: ") + n);
1018 m_localVariables.updateExpr(newVars.current());
1019 // remove the new variable from the list
1020 newVars.remove();
1021 delete v;
1022 #if QT_VERSION >= 200
1023 repaintNeeded = true;
1024 #endif
1027 // insert all remaining new variables
1028 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1029 TRACE("new var: " + v->getText());
1030 m_localVariables.insertExpr(v);
1031 repaintNeeded = true;
1034 // repaint
1035 m_localVariables.setAutoUpdate(autoU);
1036 if (repaintNeeded && autoU && m_localVariables.isVisible())
1037 m_localVariables.repaint();
1040 void KDebugger::parseLocals(const char* output, QList<VarTree>& newVars)
1042 QList<VarTree> vars;
1043 m_d->parseLocals(output, vars);
1045 QString origName; /* used in renaming variables */
1046 while (vars.count() > 0)
1048 VarTree* variable = vars.take(0);
1049 // get some types
1050 variable->inferTypesOfChildren(*m_typeTable);
1052 * When gdb prints local variables, those from the innermost block
1053 * come first. We run through the list of already parsed variables
1054 * to find duplicates (ie. variables that hide local variables from
1055 * a surrounding block). We keep the name of the inner variable, but
1056 * rename those from the outer block so that, when the value is
1057 * updated in the window, the value of the variable that is
1058 * _visible_ changes the color!
1060 int block = 0;
1061 origName = variable->getText();
1062 for (VarTree* v = newVars.first(); v != 0; v = newVars.next()) {
1063 if (variable->getText() == v->getText()) {
1064 // we found a duplicate, change name
1065 block++;
1066 QString newName = origName + " (" + QString().setNum(block) + ")";
1067 variable->setText(newName);
1070 newVars.append(variable);
1074 bool KDebugger::handlePrint(CmdQueueItem* cmd, const char* output)
1076 ASSERT(cmd->m_expr != 0);
1078 VarTree* variable = parseExpr(output, true);
1079 if (variable == 0)
1080 return false;
1082 // set expression "name"
1083 variable->setText(cmd->m_expr->getText());
1085 if (cmd->m_expr->m_varKind == VarTree::VKpointer) {
1087 * We must insert a dummy parent, because otherwise variable's value
1088 * would overwrite cmd->m_expr's value.
1090 VarTree* dummyParent = new VarTree(variable->getText(), VarTree::NKplain);
1091 dummyParent->m_varKind = VarTree::VKdummy;
1092 // the name of the parsed variable is the address of the pointer
1093 QString addr = "*" + cmd->m_expr->m_value;
1094 variable->setText(addr);
1095 variable->m_nameKind = VarTree::NKaddress;
1097 dummyParent->appendChild(variable);
1098 dummyParent->setDeleteChildren(true);
1099 TRACE("update ptr: " + cmd->m_expr->getText());
1100 cmd->m_exprWnd->updateExpr(cmd->m_expr, dummyParent);
1101 delete dummyParent;
1102 } else {
1103 TRACE("update expr: " + cmd->m_expr->getText());
1104 cmd->m_exprWnd->updateExpr(cmd->m_expr, variable);
1105 delete variable;
1108 evalExpressions(); /* enqueue dereferenced pointers */
1110 return true;
1113 VarTree* KDebugger::parseExpr(const char* output, bool wantErrorValue)
1115 VarTree* variable;
1117 // check for error conditions
1118 bool goodValue = m_d->parsePrintExpr(output, wantErrorValue, variable);
1120 if (variable != 0 && goodValue)
1122 // get some types
1123 variable->inferTypesOfChildren(*m_typeTable);
1125 return variable;
1128 // parse the output of bt
1129 void KDebugger::handleBacktrace(const char* output)
1131 // reduce flicker
1132 m_btWindow.setAutoUpdate(false);
1134 m_btWindow.clear();
1136 QList<StackFrame> stack;
1137 m_d->parseBackTrace(output, stack);
1139 if (stack.count() > 0) {
1140 StackFrame* frm = stack.take(0);
1141 // first frame must set PC
1142 // note: frm->lineNo is zero-based
1143 emit updatePC(frm->fileName, frm->lineNo, frm->frameNo);
1145 do {
1146 QString func;
1147 if (frm->var != 0)
1148 func = frm->var->getText();
1149 else
1150 func = frm->fileName + ":" + QString().setNum(frm->lineNo+1);
1151 m_btWindow.insertItem(func);
1152 TRACE("frame " + func + " (" + frm->fileName + ":" +
1153 QString().setNum(frm->lineNo+1) + ")");
1154 delete frm;
1156 while ((frm = stack.take()) != 0);
1159 m_btWindow.setAutoUpdate(true);
1160 m_btWindow.repaint();
1163 void KDebugger::gotoFrame(int frame)
1165 m_d->executeCmd(DCframe, frame);
1168 void KDebugger::handleFrameChange(const char* output)
1170 QString fileName;
1171 int frameNo;
1172 int lineNo;
1173 if (m_d->parseFrameChange(output, frameNo, fileName, lineNo)) {
1174 /* lineNo can be negative here if we can't find a file name */
1175 emit updatePC(fileName, lineNo, frameNo);
1176 } else {
1177 emit updatePC(fileName, -1, frameNo);
1181 void KDebugger::evalExpressions()
1183 // evaluate expressions in the following order:
1184 // watch expressions
1185 // pointers in local variables
1186 // pointers in watch expressions
1187 // types in local variables
1188 // types in watch expressions
1189 // pointers in 'this'
1190 // types in 'this'
1192 VarTree* exprItem = m_watchEvalExpr.first();
1193 if (exprItem != 0) {
1194 m_watchEvalExpr.remove();
1195 QString expr = exprItem->computeExpr();
1196 TRACE("watch expr: " + expr);
1197 CmdQueueItem* cmd = m_d->queueCmd(DCprint, expr, DebuggerDriver::QMoverride);
1198 // remember which expr this was
1199 cmd->m_expr = exprItem;
1200 cmd->m_exprWnd = &m_watchVariables;
1201 } else {
1202 ExprWnd* wnd;
1203 VarTree* exprItem;
1204 #define POINTER(widget) \
1205 wnd = &widget; \
1206 exprItem = widget.nextUpdatePtr(); \
1207 if (exprItem != 0) goto pointer
1208 #define STRUCT(widget) \
1209 wnd = &widget; \
1210 exprItem = widget.nextUpdateStruct(); \
1211 if (exprItem != 0) goto ustruct
1212 #define TYPE(widget) \
1213 wnd = &widget; \
1214 exprItem = widget.nextUpdateType(); \
1215 if (exprItem != 0) goto type
1216 repeat:
1217 POINTER(m_localVariables);
1218 POINTER(m_watchVariables);
1219 STRUCT(m_localVariables);
1220 STRUCT(m_watchVariables);
1221 TYPE(m_localVariables);
1222 TYPE(m_watchVariables);
1223 #undef POINTER
1224 #undef STRUCT
1225 #undef TYPE
1226 return;
1228 pointer:
1229 // we have an expression to send
1230 dereferencePointer(wnd, exprItem, false);
1231 return;
1233 ustruct:
1234 // paranoia
1235 if (exprItem->m_type == 0 || exprItem->m_type == TypeInfo::unknownType())
1236 goto repeat;
1237 evalInitialStructExpression(exprItem, wnd, false);
1238 return;
1240 type:
1242 * Sometimes a VarTree gets registered twice for a type update. So
1243 * it may happen that it has already been updated. Hence, we ignore
1244 * it here and go on to the next task.
1246 if (exprItem->m_type != 0)
1247 goto repeat;
1248 determineType(wnd, exprItem);
1252 void KDebugger::dereferencePointer(ExprWnd* wnd, VarTree* exprItem,
1253 bool immediate)
1255 ASSERT(exprItem->m_varKind == VarTree::VKpointer);
1257 QString expr = exprItem->computeExpr();
1258 TRACE("dereferencing pointer: " + expr);
1259 QString queueExpr = "*(" + expr + ")";
1260 CmdQueueItem* cmd;
1261 if (immediate) {
1262 cmd = m_d->queueCmd(DCprint, queueExpr, DebuggerDriver::QMoverrideMoreEqual);
1263 } else {
1264 cmd = m_d->queueCmd(DCprint, queueExpr, DebuggerDriver::QMoverride);
1266 // remember which expr this was
1267 cmd->m_expr = exprItem;
1268 cmd->m_exprWnd = wnd;
1271 void KDebugger::determineType(ExprWnd* wnd, VarTree* exprItem)
1273 ASSERT(exprItem->m_varKind == VarTree::VKstruct);
1275 QString expr = exprItem->computeExpr();
1276 TRACE("get type of: " + expr);
1277 CmdQueueItem* cmd;
1278 cmd = m_d->queueCmd(DCfindType, expr, DebuggerDriver::QMoverride);
1280 // remember which expr this was
1281 cmd->m_expr = exprItem;
1282 cmd->m_exprWnd = wnd;
1285 void KDebugger::handleFindType(CmdQueueItem* cmd, const char* output)
1287 QString type;
1288 if (m_d->parseFindType(output, type))
1290 ASSERT(cmd != 0 && cmd->m_expr != 0);
1292 TypeInfo* info = m_typeTable->lookup(type);
1294 if (info == 0) {
1296 * We've asked gdb for the type of the expression in
1297 * cmd->m_expr, but it returned a name we don't know. The base
1298 * class (and member) types have been checked already (at the
1299 * time when we parsed that particular expression). Now it's
1300 * time to derive the type from the base classes as a last
1301 * resort.
1303 info = cmd->m_expr->inferTypeFromBaseClass();
1304 // if we found a type through this method, register an alias
1305 if (info != 0) {
1306 TRACE("infered alias: " + type);
1307 m_typeTable->registerAlias(type, info);
1310 if (info == 0) {
1311 TRACE("unknown type");
1312 cmd->m_expr->m_type = TypeInfo::unknownType();
1313 } else {
1314 cmd->m_expr->m_type = info;
1315 /* since this node has a new type, we get its value immediately */
1316 evalInitialStructExpression(cmd->m_expr, cmd->m_exprWnd, false);
1317 return;
1321 evalExpressions(); /* queue more of them */
1324 void KDebugger::handlePrintStruct(CmdQueueItem* cmd, const char* output)
1326 VarTree* var = cmd->m_expr;
1327 ASSERT(var != 0);
1328 ASSERT(var->m_varKind == VarTree::VKstruct);
1330 VarTree* partExpr;
1331 if (cmd->m_cmd != DCprintQStringStruct) {
1332 partExpr = parseExpr(output, false);
1333 } else {
1334 partExpr = m_d->parseQCharArray(output, false);
1336 bool errorValue =
1337 partExpr == 0 ||
1338 /* we only allow simple values at the moment */
1339 partExpr->childCount() != 0;
1341 QString partValue;
1342 if (errorValue)
1344 partValue = "???";
1345 } else {
1346 partValue = partExpr->m_value;
1348 delete partExpr;
1349 partExpr = 0;
1352 * Updating a struct value works like this: var->m_partialValue holds
1353 * the value that we have gathered so far (it's been initialized with
1354 * var->m_type->m_displayString[0] earlier). Each time we arrive here,
1355 * we append the printed result followed by the next
1356 * var->m_type->m_displayString to var->m_partialValue.
1358 * If the expression we just evaluated was a guard expression, and it
1359 * resulted in an error, we must not evaluate the real expression, but
1360 * go on to the next index. (We must still add the ??? to the value).
1362 * Next, if this was the length expression, we still have not seen the
1363 * real expression, but the length of a QString.
1365 ASSERT(var->m_exprIndex >= 0 && var->m_exprIndex <= typeInfoMaxExpr);
1367 if (errorValue || !var->m_exprIndexUseGuard)
1369 // add current partValue (which might be ???)
1370 #if QT_VERSION < 200
1371 var->m_partialValue.detach();
1372 #endif
1373 var->m_partialValue += partValue;
1374 var->m_exprIndex++; /* next part */
1375 var->m_exprIndexUseGuard = true;
1376 var->m_partialValue += var->m_type->m_displayString[var->m_exprIndex];
1378 else
1380 // this was a guard expression that succeeded
1381 // go for the real expression
1382 var->m_exprIndexUseGuard = false;
1385 /* go for more sub-expressions if needed */
1386 if (var->m_exprIndex < var->m_type->m_numExprs) {
1387 /* queue a new print command with quite high priority */
1388 evalStructExpression(var, cmd->m_exprWnd, true);
1389 return;
1392 cmd->m_exprWnd->updateStructValue(var);
1394 evalExpressions(); /* enqueue dereferenced pointers */
1397 /* queues the first printStruct command for a struct */
1398 void KDebugger::evalInitialStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1400 var->m_exprIndex = 0;
1401 var->m_exprIndexUseGuard = true;
1402 var->m_partialValue = var->m_type->m_displayString[0];
1403 evalStructExpression(var, wnd, immediate);
1406 /* queues a printStruct command; var must have been initialized correctly */
1407 void KDebugger::evalStructExpression(VarTree* var, ExprWnd* wnd, bool immediate)
1409 QString base = var->computeExpr();
1410 QString exprFmt;
1411 if (var->m_exprIndexUseGuard) {
1412 exprFmt = var->m_type->m_guardStrings[var->m_exprIndex];
1413 if (exprFmt.isEmpty()) {
1414 // no guard, omit it and go to expression
1415 var->m_exprIndexUseGuard = false;
1418 if (!var->m_exprIndexUseGuard) {
1419 exprFmt = var->m_type->m_exprStrings[var->m_exprIndex];
1422 SIZED_QString(expr, exprFmt.length() + base.length() + 10);
1423 expr.sprintf(exprFmt, base.data());
1425 DbgCommand dbgCmd = DCprintStruct;
1426 // check if this is a QString::Data
1427 if (strncmp(expr, "/QString::Data ", 15) == 0)
1429 if (m_typeTable->parseQt2QStrings())
1431 expr = expr.mid(15, expr.length()); /* strip off /QString::Data */
1432 dbgCmd = DCprintQStringStruct;
1433 } else {
1435 * This should not happen: the type libraries should be set up
1436 * in a way that this can't happen. If this happens
1437 * nevertheless it means that, eg., kdecore was loaded but qt2
1438 * was not (only qt2 enables the QString feature).
1440 // TODO: remove this "print"; queue the next printStruct instead
1441 expr = "*0";
1443 } else {
1444 expr = expr;
1446 TRACE("evalStruct: " + expr + (var->m_exprIndexUseGuard ? " // guard" : " // real"));
1447 CmdQueueItem* cmd = m_d->queueCmd(dbgCmd, expr,
1448 immediate ? DebuggerDriver::QMoverrideMoreEqual
1449 : DebuggerDriver::QMnormal);
1451 // remember which expression this was
1452 cmd->m_expr = var;
1453 cmd->m_exprWnd = wnd;
1456 /* removes expression from window */
1457 void KDebugger::removeExpr(ExprWnd* wnd, VarTree* var)
1459 if (var == 0)
1460 return;
1462 // must remove any references to var from command queues
1463 m_d->dequeueCmdByVar(var);
1465 wnd->removeExpr(var);
1468 void KDebugger::handleSharedLibs(const char* output)
1470 // delete all known libraries
1471 m_sharedLibs.clear();
1473 // parse the table of shared libraries
1474 m_d->parseSharedLibs(output, m_sharedLibs);
1475 m_sharedLibsListed = true;
1477 // get type libraries
1478 m_typeTable->loadLibTypes(m_sharedLibs);
1481 CmdQueueItem* KDebugger::loadCoreFile()
1483 return m_d->queueCmd(DCcorefile, m_corefile, DebuggerDriver::QMoverride);
1486 void KDebugger::slotLocalsExpanding(KTreeViewItem* item, bool& allow)
1488 exprExpandingHelper(&m_localVariables, item, allow);
1491 void KDebugger::slotWatchExpanding(KTreeViewItem* item, bool& allow)
1493 exprExpandingHelper(&m_watchVariables, item, allow);
1496 void KDebugger::exprExpandingHelper(ExprWnd* wnd, KTreeViewItem* item, bool&)
1498 VarTree* exprItem = static_cast<VarTree*>(item);
1499 if (exprItem->m_varKind != VarTree::VKpointer) {
1500 return;
1502 dereferencePointer(wnd, exprItem, true);
1505 // add the expression in the edit field to the watch expressions
1506 void KDebugger::addWatch(const QString& t)
1508 QString expr = t.stripWhiteSpace();
1509 if (expr.isEmpty())
1510 return;
1511 VarTree* exprItem = new VarTree(expr, VarTree::NKplain);
1512 m_watchVariables.insertExpr(exprItem);
1514 // if we are boring ourselves, send down the command
1515 if (m_programActive) {
1516 m_watchEvalExpr.append(exprItem);
1517 if (m_d->isIdle()) {
1518 evalExpressions();
1523 // delete a toplevel watch expression
1524 void KDebugger::slotDeleteWatch()
1526 // delete only allowed while debugger is idle; or else we might delete
1527 // the very expression the debugger is currently working on...
1528 if (!m_d->isIdle())
1529 return;
1531 int index = m_watchVariables.currentItem();
1532 if (index < 0)
1533 return;
1535 VarTree* item = static_cast<VarTree*>(m_watchVariables.itemAt(index));
1536 if (!item->isToplevelExpr())
1537 return;
1539 // remove the variable from the list to evaluate
1540 if (m_watchEvalExpr.findRef(item) >= 0) {
1541 m_watchEvalExpr.remove();
1543 removeExpr(&m_watchVariables, item);
1544 // item is invalid at this point!
1547 void KDebugger::startAnimation(bool fast)
1549 int interval = fast ? 50 : 150;
1550 if (!m_animationTimer.isActive()) {
1551 m_animationTimer.start(interval);
1552 } else if (m_animationInterval != interval) {
1553 m_animationTimer.changeInterval(interval);
1555 m_animationInterval = interval;
1558 void KDebugger::stopAnimation()
1560 if (m_animationTimer.isActive()) {
1561 m_animationTimer.stop();
1562 m_animationInterval = 0;
1566 void KDebugger::slotUpdateAnimation()
1568 if (m_d->isIdle()) {
1569 stopAnimation();
1570 } else {
1572 * Slow animation while program is stopped (i.e. while variables
1573 * are displayed)
1575 bool slow = isReady() && m_programActive && !m_programRunning;
1576 startAnimation(!slow);
1580 void KDebugger::handleRegisters(const char* output)
1582 QList<RegisterInfo> regs;
1583 m_d->parseRegisters(output, regs);
1585 emit registersChanged(regs);
1587 // delete them all
1588 regs.setAutoDelete(true);
1592 * The output of the DCbreak* commands has more accurate information about
1593 * the file and the line number.
1595 void KDebugger::newBreakpoint(const char* output)
1597 int id;
1598 QString file;
1599 int lineNo;
1600 if (!m_d->parseBreakpoint(output, id, file, lineNo))
1601 return;
1603 // see if it is new
1604 for (int i = m_brkpts.size()-1; i >= 0; i--) {
1605 if (m_brkpts[i]->id == id) {
1606 // not new; update
1607 m_brkpts[i]->fileName = file;
1608 m_brkpts[i]->lineNo = lineNo;
1609 return;
1612 // yes, new
1613 Breakpoint* bp = new Breakpoint;
1614 bp->id = id;
1615 bp->temporary = false;
1616 bp->enabled = true;
1617 bp->hitCount = 0;
1618 bp->ignoreCount = 0;
1619 bp->fileName = file;
1620 bp->lineNo = lineNo;
1621 int n = m_brkpts.size();
1622 m_brkpts.resize(n+1);
1623 m_brkpts[n] = bp;
1626 void KDebugger::updateBreakList(const char* output)
1628 // get the new list
1629 QList<Breakpoint> brks;
1630 brks.setAutoDelete(false);
1631 m_d->parseBreakList(output, brks);
1633 // merge new information into existing breakpoints
1635 QArray<Breakpoint*> oldbrks = m_brkpts;
1637 // move parsed breakpoints into m_brkpts
1638 m_brkpts.detach();
1639 m_brkpts.resize(brks.count());
1640 int n = 0;
1641 for (Breakpoint* bp = brks.first(); bp != 0; bp = brks.next())
1643 m_brkpts[n++] = bp;
1646 // go through all old breakpoints
1647 for (int i = oldbrks.size()-1; i >= 0; i--) {
1648 // is this one still alive?
1649 for (int j = m_brkpts.size()-1; j >= 0; j--)
1651 if (m_brkpts[j]->id == oldbrks[i]->id) {
1652 // yes, it is
1653 // keep accurate location
1654 m_brkpts[j]->fileName = oldbrks[i]->fileName;
1655 m_brkpts[j]->lineNo = oldbrks[i]->lineNo;
1656 break;
1661 // delete old breakpoints
1662 for (int i = oldbrks.size()-1; i >= 0; i--) {
1663 delete oldbrks[i];
1666 emit breakpointsChanged();
1669 // look if there is at least one temporary breakpoint
1670 bool KDebugger::haveTemporaryBP() const
1672 for (int i = m_brkpts.size()-1; i >= 0; i--) {
1673 if (m_brkpts[i]->temporary)
1674 return true;
1676 return false;
1679 Breakpoint* KDebugger::breakpointByFilePos(QString file, int lineNo)
1681 // look for exact file name match
1682 int i;
1683 for (i = m_brkpts.size()-1; i >= 0; i--) {
1684 if (m_brkpts[i]->lineNo == lineNo &&
1685 m_brkpts[i]->fileName == file)
1687 return m_brkpts[i];
1690 // not found, so try basename
1691 // strip off directory part of file name
1692 int offset = file.findRev("/");
1693 if (offset < 0) {
1694 // that was already the basename, no need to scan the list again
1695 return 0;
1697 #if QT_VERSION < 200
1698 file.detach();
1699 #endif
1700 file.remove(0, offset+1);
1702 for (i = m_brkpts.size()-1; i >= 0; i--) {
1703 if (m_brkpts[i]->lineNo == lineNo &&
1704 m_brkpts[i]->fileName == file)
1706 return m_brkpts[i];
1710 // not found
1711 return 0;
1714 void KDebugger::slotValuePopup(const QString& expr)
1716 // search the local variables for a match
1717 VarTree* v = m_localVariables.topLevelExprByName(expr);
1718 if (v == 0) {
1719 // not found, check watch expressions
1720 v = m_watchVariables.topLevelExprByName(expr);
1721 if (v == 0) {
1722 // nothing found; do nothing
1723 return;
1727 // construct the tip
1728 QString tip = v->getText() + " = ";
1729 if (!v->m_value.isEmpty())
1731 tip += v->m_value;
1733 else
1735 // no value: we use some hint
1736 switch (v->m_varKind) {
1737 case VarTree::VKstruct:
1738 tip += "{...}";
1739 break;
1740 case VarTree::VKarray:
1741 tip += "[...]";
1742 break;
1743 default:
1744 tip += "???";
1745 break;
1748 emit valuePopup(tip);
1752 #include "debugger.moc"