3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
15 #include "exprwnd.h" /* some compilers require this */
23 class ProgramTypeTable
;
29 class GdbProcess
: public KProcess
34 virtual int commSetupDoneC();
37 class KDebugger
: public QObject
41 KDebugger(QWidget
* parent
, /* will be used as the parent for dialogs */
49 * This function starts to debug the specified executable.
50 * @return false if an error occurs, in particular if a program is
51 * currently being debugged
53 bool debugProgram(const QString
& executable
);
56 * Queries the user for an executable file and debugs it. If a program
57 * is currently being debugged, it is terminated first.
59 void fileExecutable();
62 * Queries the user for a core file and uses it to debug the active
68 * Runs the program or continues it if it is stopped at a breakpoint.
73 * Attaches to a process and debugs it.
78 * Restarts the debuggee.
80 void programRunAgain();
83 * Performs a single-step, possibly stepping into a function call.
88 * Performs a single-step, stepping over a function call.
93 * Runs the program until it returns from the current function.
98 * Interrupts the program if it is currently running.
103 * Queries the user for program arguments.
108 * Shows the breakpoint list if it isn't currently visible or hides it
111 void breakListToggleVisible();
114 * Run the debuggee until the specified line in the specified file is
117 * @return false if the command was not executed, e.g. because the
118 * debuggee is running at the moment.
120 bool runUntil(const QString
& fileName
, int lineNo
);
125 * @return false if the command was not executed, e.g. because the
126 * debuggee is running at the moment.
128 bool setBreakpoint(const QString
& fileName
, int lineNo
, bool temporary
);
131 * Enable or disable a breakpoint at the specified location.
133 * @return false if the command was not executed, e.g. because the
134 * debuggee is running at the moment.
136 bool enableDisableBreakpoint(const QString
& fileName
, int lineNo
);
139 * Tells whether one of the single stepping commands can be invoked
140 * (step, next, finish, until, also run).
142 bool canSingleStep();
145 * Tells whether a breakpoints can be set, deleted, enabled, or disabled.
147 bool canChangeBreakpoints();
150 * Tells whether the debuggee can be changed.
152 bool canChangeExecutable() { return isReady() && !m_programActive
; }
155 * Add a watch expression.
157 void addWatch(const QString
& expr
);
160 * Retrieves the current status message.
162 const QString
& statusMessage() const { return m_statusMessage
; }
164 * Is the debugger ready to receive another high-priority command?
166 bool isReady() const { return m_haveExecutable
&&
167 /*(m_state == DSidle || m_state == DSrunningLow)*/
168 m_hipriCmdQueue
.isEmpty(); }
170 * Is the debuggee running (not just active)?
172 bool isProgramRunning() { return m_haveExecutable
&& m_programRunning
; }
175 * Do we have an executable set?
177 bool haveExecutable() { return m_haveExecutable
; }
180 * Is the debuggee active, i.e. was it started by the debugger?
182 bool isProgramActive() { return m_programActive
; }
184 /** Is the breakpoint table visible? */
185 bool isBreakListVisible() { return m_bpTable
.isVisible(); }
187 /** The table of breakpoints. */
188 BreakpointTable
& breakList() { return m_bpTable
; }
190 const QString
& executable() const { return m_executable
; }
192 void setCoreFile(const QString
& corefile
) { m_corefile
= corefile
; }
195 * Sets the command to invoke gdb. If cmd is the empty string, the
196 * default is substituted.
198 void setDebuggerCmd(const QString
& cmd
);
200 /** Retrieves the command to invoke gdb. */
201 QString
debuggerCmd() const { return m_debuggerCmdStr
; }
204 * Sets the command to invoke the terminal that displays the program
205 * output. If cmd is the empty string, the default is substituted.
207 void setTerminalCmd(const QString
& cmd
);
210 * Retrieves the command to invoke ther terminal that displays the
213 QString
terminalCmd() const { return m_outputTermCmdStr
; }
216 void saveSettings(KConfig
*);
217 void restoreSettings(KConfig
*);
245 DCprintQStringStruct
,
254 QString m_outputTermCmdStr
;
255 pid_t m_outputTermPID
;
256 QString m_outputTermName
;
257 QString m_outputTermKeepScript
;
258 bool createOutputWindow();
259 QString m_debuggerCmdStr
;
265 DSidle
, /* gdb waits for input */
266 DSinterrupted
, /* a command was interrupted */
267 DSrunningLow
, /* gdb is running a low-priority command */
268 DSrunning
, /* gdb waits for program */
269 DScommandSent
, /* command has been sent, we wait for wroteStdin signal */
270 DScommandSentLow
, /* low-prioritycommand has been sent */
272 DebuggerState m_state
;
273 char* m_gdbOutput
; /* normal gdb output */
274 int m_gdbOutputLen
; /* current accumulated output */
275 int m_gdbOutputAlloc
; /* space available in m_gdbOutput */
276 QQueue
<QString
> m_delayedOutput
; /* output colleced while we have receivedOutput */
277 /* but before signal wroteStdin arrived */
278 QList
<VarTree
> m_watchEvalExpr
; /* exprs to evaluate for watch windows */
282 * Gdb commands are placed in a queue. Only one command at a time is
283 * sent down to gdb. All other commands in the queue are retained until
284 * the sent command has been processed by gdb. Gdb tells us that it's
285 * done with the command by sending the prompt. The output of gdb is
286 * parsed at that time. Then, if more commands are in the queue, the
287 * next one is sent to gdb.
289 * The active command is kept separately from other pending commands.
295 bool m_committed
; /* just a debugging aid */
296 // remember which expression when printing an expression
299 // whether command was emitted due to direct user request (only set when relevant)
302 CmdQueueItem(DbgCommand cmd
, const QString
& str
) :
312 * Enqueues a high-priority command. High-priority commands are
313 * executed before any low-priority commands. No user interaction is
314 * possible as long as there is a high-priority command in the queue.
316 CmdQueueItem
* executeCmd(DbgCommand cmd
, QString cmdString
, bool clearLow
= false);
318 QMnormal
, /* queues the command last */
319 QMoverride
, /* removes an already queued command */
320 QMoverrideMoreEqual
/* ditto, also puts the command first in the queue */
323 * Enqueues a low-priority command. Low-priority commands are executed
324 * after any high-priority commands.
326 CmdQueueItem
* queueCmd(DbgCommand cmd
, QString cmdString
, QueueMode mode
);
327 /** Removes all commands from the low-priority queue. */
328 void flushLoPriQueue();
329 /** Removes all commands from the high-priority queue. */
330 void flushHiPriQueue();
333 QQueue
<CmdQueueItem
> m_hipriCmdQueue
;
334 QList
<CmdQueueItem
> m_lopriCmdQueue
;
335 CmdQueueItem
* m_activeCmd
; /* the cmd we are working on */
336 void parse(CmdQueueItem
* cmd
);
337 VarTree
* parseExpr(const char* name
, bool wantErrorValue
= true);
338 VarTree
* parseQCharArray(const char* name
, bool wantErrorValue
);
339 void handleRunCommands();
340 void updateAllExprs();
341 void updateBreakptTable();
342 void updateProgEnvironment(const QString
& args
, const QString
& wd
,
343 const QDict
<EnvVar
>& newVars
);
344 void parseLocals(QList
<VarTree
>& newVars
);
346 bool handlePrint(CmdQueueItem
* cmd
);
347 void handleBacktrace();
348 void handleFrameChange();
349 void handleFindType(CmdQueueItem
* cmd
);
350 void handlePrintStruct(CmdQueueItem
* cmd
);
351 void handleSharedLibs();
352 void evalExpressions();
353 void evalInitialStructExpression(VarTree
* var
, ExprWnd
* wnd
, bool immediate
);
354 void evalStructExpression(VarTree
* var
, ExprWnd
* wnd
, bool immediate
);
355 void exprExpandingHelper(ExprWnd
* wnd
, KTreeViewItem
* item
, bool& allow
);
356 void dereferencePointer(ExprWnd
* wnd
, VarTree
* var
, bool immediate
);
357 void determineType(ExprWnd
* wnd
, VarTree
* var
);
358 void removeExpr(ExprWnd
* wnd
, VarTree
* var
);
359 CmdQueueItem
* loadCoreFile();
361 QString m_lastDirectory
; /* the dir of the most recently opened file */
362 bool m_haveExecutable
; /* has an executable been specified */
363 bool m_programActive
; /* is the program active (possibly halting in a brkpt)? */
364 bool m_programRunning
; /* is the program executing (not stopped)? */
365 bool m_sharedLibsListed
; /* do we know the shared libraries loaded by the prog? */
366 QString m_executable
;
368 QString m_attachedPid
; /* user input of attaching to pid */
369 QString m_programArgs
;
370 QString m_programWD
; /* working directory of gdb */
371 QDict
<EnvVar
> m_envVars
; /* environment variables set by user */
372 QStrList m_sharedLibs
; /* shared libraries used by program */
373 ProgramTypeTable
* m_typeTable
; /* known types used by the program */
374 bool m_qstring2nullOk
; /* whether gdb knows about QString::null */
375 KSimpleConfig
* m_programConfig
; /* program-specific settings (brkpts etc) */
376 void saveProgramSettings();
377 void restoreProgramSettings();
381 int m_gdbMajor
, m_gdbMinor
;
382 bool m_explicitKill
; /* whether we are killing gdb ourselves */
384 #ifdef GDB_TRANSCRIPT
389 QString m_statusMessage
;
392 void receiveOutput(KProcess
*, char* buffer
, int buflen
);
393 void commandRead(KProcess
*);
394 void gdbExited(KProcess
*);
396 void slotLocalsExpanding(KTreeViewItem
*, bool&);
397 void slotWatchExpanding(KTreeViewItem
*, bool&);
398 void slotToggleBreak(const QString
&, int);
399 void slotEnaDisBreak(const QString
&, int);
400 void slotUpdateAnimation();
401 void slotDeleteWatch();
405 * This signal is emitted whenever a part of the debugger needs to
406 * highlight the specfied source code line (e.g. when the program
409 * @param file specifies the file; this is not necessarily a full path
410 * name, and if it is relative, you won't know relative to what, you
412 * @param lineNo specifies the line number (0-based!) (this may be
413 * negative, in which case the file should be activated, but the line
414 * should NOT be changed).
416 void activateFileLine(const QString
& file
, int lineNo
);
419 * This signal is emitted when a line decoration item (those thingies
420 * that indicate breakpoints) must be changed.
422 void lineItemsChanged();
425 * This signal is a special case of @ref #lineItemsChanged because it
426 * indicates that only the program counter has changed.
428 * @param filename specifies the filename where the program stopped
429 * @param lineNo specifies the line number (zero-based); it can be -1
431 * @param frameNo specifies the frame number: 0 is the innermost frame,
432 * positive numbers are frames somewhere up the stack (indicates points
433 * where a function was called); the latter cases should be indicated
434 * differently in the source window.
436 void updatePC(const QString
& filename
, int lineNo
, int frameNo
);
439 * This signal is emitted when gdb detects that the executable has been
440 * updated, e.g. recompiled. (You usually need not handle this signal
441 * if you are the editor which changed the executable.)
443 void executableUpdated();
446 * This signal is emitted when the animated icon should advance to the
449 void animationTimeout();
452 * Indicates that a new status message is available.
454 void updateStatusMessage();
457 * Indicates that the internal state of the debugger has changed, and
458 * that this will very likely have an impact on the UI.
463 BreakpointTable m_bpTable
;
464 ExprWnd
& m_localVariables
;
465 ExprWnd
& m_watchVariables
;
466 QListBox
& m_btWindow
;
469 QTimer m_animationTimer
;
470 int m_animationInterval
;
472 // implementation helpers
476 void initAnimation();
477 void startAnimation(bool fast
);
478 void stopAnimation();
480 QWidget
* parentWidget() { return static_cast<QWidget
*>(parent()); }
482 friend class BreakpointTable
;