]> code.delx.au - gnu-emacs/blob - lisp/progmodes/gdb-ui.el
Merge from emacs--rel--22
[gnu-emacs] / lisp / progmodes / gdb-ui.el
1 ;;; gdb-ui.el --- User Interface for running GDB
2
3 ;; Author: Nick Roberts <nickrob@gnu.org>
4 ;; Maintainer: FSF
5 ;; Keywords: unix, tools
6
7 ;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
8 ;; Free Software Foundation, Inc.
9
10 ;; This file is part of GNU Emacs.
11
12 ;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 3, or (at your option)
15 ;; any later version.
16
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
26
27 ;;; Commentary:
28
29 ;; This mode acts as a graphical user interface to GDB. You can interact with
30 ;; GDB through the GUD buffer in the usual way, but there are also further
31 ;; buffers which control the execution and describe the state of your program.
32 ;; It separates the input/output of your program from that of GDB, if
33 ;; required, and watches expressions in the speedbar. It also uses features of
34 ;; Emacs 21 such as the fringe/display margin for breakpoints, and the toolbar
35 ;; (see the GDB Graphical Interface section in the Emacs info manual).
36
37 ;; By default, M-x gdb will start the debugger.
38
39 ;; This file has evolved from gdba.el that was included with GDB 5.0 and
40 ;; written by Tom Lord and Jim Kingdon. It uses GDB's annotation interface.
41 ;; You don't need to know about annotations to use this mode as a debugger,
42 ;; but if you are interested developing the mode itself, see the Annotations
43 ;; section in the GDB info manual.
44
45 ;; GDB developers plan to make the annotation interface obsolete. A new
46 ;; interface called GDB/MI (machine interface) has been designed to replace it.
47 ;; Some GDB/MI commands are used in this file through the CLI command
48 ;; 'interpreter mi <mi-command>'. To help with the process of fully migrating
49 ;; Emacs from annotations to GDB/MI, there is an experimental package called
50 ;; gdb-mi in the Emacs Lisp Package Archive ("http://tromey.com/elpa/"). It
51 ;; comprises of modified gud.el and a file called gdb-mi.el which replaces
52 ;; gdb-ui.el. When installed, this overrides the current files and invoking
53 ;; M-x gdb will use GDB/MI directly (starts with "gdb -i=mi"). When deleted
54 ;; ('d' followed by 'x' in Package Menu mode), the files are deleted and old
55 ;; functionality restored. This provides a convenient way to review the
56 ;; current status/contribute to its improvement. For someone who just wants to
57 ;; use GDB, however, the current mode in Emacs 22 is a much better option.
58 ;; There is also a file, also called gdb-mi.el, a version of which is included
59 ;; the GDB distribution. This will probably only work with versions
60 ;; distributed with GDB 6.5 or later. Unlike the version in ELPA it works on
61 ;; top of gdb-ui.el and you can only start it with M-x gdbmi.
62
63 ;; This mode SHOULD WORK WITH GDB 5.0 or later but you will NEED AT LEAST
64 ;; GDB 6.0 to use watch expressions. It works best with GDB 6.4 or later
65 ;; where watch expressions will update more quickly.
66
67 ;;; Windows Platforms:
68
69 ;; If you are using Emacs and GDB on Windows you will need to flush the buffer
70 ;; explicitly in your program if you want timely display of I/O in Emacs.
71 ;; Alternatively you can make the output stream unbuffered, for example, by
72 ;; using a macro:
73
74 ;; #ifdef UNBUFFERED
75 ;; setvbuf (stdout, (char *) NULL, _IONBF, 0);
76 ;; #endif
77
78 ;; and compiling with -DUNBUFFERED while debugging.
79
80 ;;; Known Bugs:
81
82 ;; 1) Cannot handle multiple debug sessions.
83 ;; 2) If you wish to call procedures from your program in GDB
84 ;; e.g "call myproc ()", "p mysquare (5)" then use level 2 annotations
85 ;; "gdb --annotate=2 myprog" to keep source buffer/selected frame fixed.
86 ;; 3) After detaching from a process, clicking on the "GO" icon on toolbar
87 ;; (gud-go) sends "continue" to GDB (should be "run").
88
89 ;;; TODO:
90
91 ;; 1) Use MI command -data-read-memory for memory window.
92 ;; 2) Use tree-widget.el instead of the speedbar for watch-expressions?
93 ;; 3) Mark breakpoint locations on scroll-bar of source buffer?
94
95 ;;; Code:
96
97 (require 'gud)
98
99 (defvar tool-bar-map)
100 (defvar speedbar-initial-expansion-list-name)
101
102 (defvar gdb-pc-address nil "Initialization for Assembler buffer.
103 Set to \"main\" at start if gdb-show-main is t.")
104 (defvar gdb-frame-address nil "Identity of frame for watch expression.")
105 (defvar gdb-previous-frame-address nil)
106 (defvar gdb-memory-address "main")
107 (defvar gdb-previous-frame nil)
108 (defvar gdb-selected-frame nil)
109 (defvar gdb-frame-number nil)
110 (defvar gdb-current-language nil)
111 (defvar gdb-var-list nil
112 "List of variables in watch window.
113 Each element has the form (VARNUM EXPRESSION NUMCHILD TYPE VALUE STATUS FP)
114 where STATUS is nil (`unchanged'), `changed' or `out-of-scope', FP the frame
115 address for root variables.")
116 (defvar gdb-main-file nil "Source file from which program execution begins.")
117 (defvar gud-old-arrow nil)
118 (defvar gdb-overlay-arrow-position nil)
119 (defvar gdb-stack-position nil)
120 (defvar gdb-server-prefix nil)
121 (defvar gdb-flush-pending-output nil)
122 (defvar gdb-location-alist nil
123 "Alist of breakpoint numbers and full filenames. Only used for files that
124 Emacs can't find.")
125 (defvar gdb-active-process nil
126 "GUD tooltips display variable values when t, and macro definitions otherwise.")
127 (defvar gdb-error "Non-nil when GDB is reporting an error.")
128 (defvar gdb-macro-info nil
129 "Non-nil if GDB knows that the inferior includes preprocessor macro info.")
130 (defvar gdb-buffer-fringe-width nil)
131 (defvar gdb-signalled nil)
132 (defvar gdb-source-window nil)
133 (defvar gdb-inferior-status nil)
134 (defvar gdb-continuation nil)
135 (defvar gdb-look-up-stack nil)
136 (defvar gdb-frame-begin nil
137 "Non-nil when GDB generates frame-begin annotation.")
138 (defvar gdb-printing t)
139 (defvar gdb-parent-bptno-enabled nil)
140 (defvar gdb-ready nil)
141 (defvar gdb-early-user-input nil)
142
143 (defvar gdb-buffer-type nil
144 "One of the symbols bound in `gdb-buffer-rules'.")
145 (make-variable-buffer-local 'gdb-buffer-type)
146
147 (defvar gdb-input-queue ()
148 "A list of gdb command objects.")
149
150 (defvar gdb-prompting nil
151 "True when gdb is idle with no pending input.")
152
153 (defvar gdb-output-sink nil
154 "The disposition of the output of the current gdb command.
155 Possible values are these symbols:
156
157 `user' -- gdb output should be copied to the GUD buffer
158 for the user to see.
159
160 `inferior' -- gdb output should be copied to the inferior-io buffer.
161
162 `pre-emacs' -- output should be ignored util the post-prompt
163 annotation is received. Then the output-sink
164 becomes:...
165 `emacs' -- output should be collected in the partial-output-buffer
166 for subsequent processing by a command. This is the
167 disposition of output generated by commands that
168 gdb mode sends to gdb on its own behalf.
169 `post-emacs' -- ignore output until the prompt annotation is
170 received, then go to USER disposition.
171
172 gdba (gdb-ui.el) uses all five values, gdbmi (gdb-mi.el) only two
173 \(`user' and `emacs').")
174
175 (defvar gdb-current-item nil
176 "The most recent command item sent to gdb.")
177
178 (defvar gdb-pending-triggers '()
179 "A list of trigger functions that have run later than their output
180 handlers.")
181
182 (defvar gdb-first-post-prompt nil)
183 (defvar gdb-version nil)
184 (defvar gdb-locals-font-lock-keywords nil)
185 (defvar gdb-source-file-list nil
186 "List of source files for the current executable")
187 (defconst gdb-error-regexp "\\^error,msg=\"\\(.+\\)\"")
188
189 (defvar gdb-locals-font-lock-keywords-1
190 '(
191 ;; var = (struct struct_tag) value
192 ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +(\\(struct\\) \\(\\(\\sw\\|[_.]\\)+\\)"
193 (1 font-lock-variable-name-face)
194 (3 font-lock-keyword-face)
195 (4 font-lock-type-face))
196 ;; var = (type) value
197 ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +(\\(\\(\\sw\\|[_.]\\)+\\)"
198 (1 font-lock-variable-name-face)
199 (3 font-lock-type-face))
200 ;; var = val
201 ( "\\(^\\(\\sw\\|[_.]\\)+\\) += +[^(]"
202 (1 font-lock-variable-name-face))
203 )
204 "Font lock keywords used in `gdb-local-mode'.")
205
206 (defvar gdb-locals-font-lock-keywords-2
207 '(
208 ;; var = type value
209 ( "\\(^\\(\\sw\\|[_.]\\)+\\)\t+\\(\\(\\sw\\|[_.]\\)+\\)"
210 (1 font-lock-variable-name-face)
211 (3 font-lock-type-face))
212 )
213 "Font lock keywords used in `gdb-local-mode'.")
214
215 ;; Variables for GDB 6.4+
216 (defvar gdb-register-names nil "List of register names.")
217 (defvar gdb-changed-registers nil
218 "List of changed register numbers (strings).")
219
220 ;;;###autoload
221 (defun gdb (command-line)
222 "Run gdb on program FILE in buffer *gud-FILE*.
223 The directory containing FILE becomes the initial working
224 directory and source-file directory for your debugger.
225
226 If `gdb-many-windows' is nil (the default value) then gdb just
227 pops up the GUD buffer unless `gdb-show-main' is t. In this case
228 it starts with two windows: one displaying the GUD buffer and the
229 other with the source file with the main routine of the inferior.
230
231 If `gdb-many-windows' is t, regardless of the value of
232 `gdb-show-main', the layout below will appear unless
233 `gdb-use-separate-io-buffer' is nil when the source buffer
234 occupies the full width of the frame. Keybindings are shown in
235 some of the buffers.
236
237 Watch expressions appear in the speedbar/slowbar.
238
239 The following commands help control operation :
240
241 `gdb-many-windows' - Toggle the number of windows gdb uses.
242 `gdb-restore-windows' - To restore the window layout.
243
244 See Info node `(emacs)GDB Graphical Interface' for a more
245 detailed description of this mode.
246
247
248 +----------------------------------------------------------------------+
249 | GDB Toolbar |
250 +-----------------------------------+----------------------------------+
251 | GUD buffer (I/O of GDB) | Locals buffer |
252 | | |
253 | | |
254 | | |
255 +-----------------------------------+----------------------------------+
256 | Source buffer | I/O buffer (of debugged program) |
257 | | (comint-mode) |
258 | | |
259 | | |
260 | | |
261 | | |
262 | | |
263 | | |
264 +-----------------------------------+----------------------------------+
265 | Stack buffer | Breakpoints buffer |
266 | RET gdb-frames-select | SPC gdb-toggle-breakpoint |
267 | | RET gdb-goto-breakpoint |
268 | | D gdb-delete-breakpoint |
269 +-----------------------------------+----------------------------------+
270
271 To run GDB in text command mode, replace the GDB \"--annotate=3\"
272 option with \"--fullname\" either in the minibuffer for the
273 current Emacs session, or the custom variable
274 `gud-gdb-command-name' for all future sessions. You need to use
275 text command mode to debug multiple programs within one Emacs
276 session."
277 (interactive (list (gud-query-cmdline 'gdb)))
278
279 (when (and gud-comint-buffer
280 (buffer-name gud-comint-buffer)
281 (get-buffer-process gud-comint-buffer)
282 (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba)))
283 (gdb-restore-windows)
284 (error
285 "Multiple debugging requires restarting in text command mode"))
286
287 (gud-common-init command-line nil 'gud-gdba-marker-filter)
288 (set (make-local-variable 'gud-minor-mode) 'gdba)
289 (setq comint-input-sender 'gdb-send)
290
291 (gud-def gud-break "break %f:%l" "\C-b" "Set breakpoint at current line.")
292 (gud-def gud-tbreak "tbreak %f:%l" "\C-t"
293 "Set temporary breakpoint at current line.")
294 (gud-def gud-remove "clear %f:%l" "\C-d" "Remove breakpoint at current line")
295 (gud-def gud-step "step %p" "\C-s" "Step one source line with display.")
296 (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.")
297 (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).")
298 (gud-def gud-nexti "nexti %p" nil "Step one instruction (skip functions).")
299 (gud-def gud-cont "cont" "\C-r" "Continue with display.")
300 (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
301 (gud-def gud-jump
302 (progn (gud-call "tbreak %f:%l") (gud-call "jump %f:%l"))
303 "\C-j" "Set execution address to current line.")
304
305 (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
306 (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
307 (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.")
308 (gud-def gud-pstar "print* %e" nil
309 "Evaluate C dereferenced pointer expression at point.")
310
311 ;; For debugging Emacs only.
312 (gud-def gud-pv "pv1 %e" "\C-v" "Print the value of the lisp variable.")
313
314 (gud-def gud-until "until %l" "\C-u" "Continue to current line.")
315 (gud-def gud-run "run" nil "Run the program.")
316
317 (local-set-key "\C-i" 'gud-gdb-complete-command)
318 (setq comint-prompt-regexp "^(.*gdb[+]?) *")
319 (setq paragraph-start comint-prompt-regexp)
320 (setq gdb-output-sink 'user)
321 (setq gdb-first-prompt t)
322 (setq gud-running nil)
323 (setq gdb-ready nil)
324 (setq gdb-flush-pending-output nil)
325 (setq gdb-early-user-input nil)
326 (setq gud-filter-pending-text nil)
327 (run-hooks 'gdb-mode-hook))
328
329 ;; Keep as an alias for compatibility with Emacs 22.1.
330 ;;;###autoload
331 (defalias 'gdba 'gdb)
332
333 (defcustom gdb-debug-log-max 128
334 "Maximum size of `gdb-debug-log'. If nil, size is unlimited."
335 :group 'gud
336 :type '(choice (integer :tag "Number of elements")
337 (const :tag "Unlimited" nil))
338 :version "22.1")
339
340 (defvar gdb-debug-log nil
341 "List of commands sent to and replies received from GDB. Most
342 recent commands are listed first. This list stores only the last
343 'gdb-debug-log-max' values. This variable is used to debug
344 GDB-UI.")
345
346 ;;;###autoload
347 (defcustom gdb-enable-debug nil
348 "Non-nil means record the process input and output in `gdb-debug-log'."
349 :type 'boolean
350 :group 'gud
351 :version "22.1")
352
353 (defcustom gdb-cpp-define-alist-program "gcc -E -dM -"
354 "Shell command for generating a list of defined macros in a source file.
355 This list is used to display the #define directive associated
356 with an identifier as a tooltip. It works in a debug session with
357 GDB, when gud-tooltip-mode is t.
358
359 Set `gdb-cpp-define-alist-flags' for any include paths or
360 predefined macros."
361 :type 'string
362 :group 'gud
363 :version "22.1")
364
365 (defcustom gdb-cpp-define-alist-flags ""
366 "Preprocessor flags for `gdb-cpp-define-alist-program'."
367 :type 'string
368 :group 'gud
369 :version "22.1")
370
371 (defcustom gdb-show-main nil
372 "Non-nil means display source file containing the main routine at startup.
373 Also display the main routine in the disassembly buffer if present."
374 :type 'boolean
375 :group 'gud
376 :version "22.1")
377
378 (defcustom gdb-many-windows nil
379 "If nil, just pop up the GUD buffer unless `gdb-show-main' is t.
380 In this case start with two windows: one displaying the GUD
381 buffer and the other with the source file with the main routine
382 of the debugged program. Non-nil means display the layout shown
383 for `gdba'."
384 :type 'boolean
385 :group 'gud
386 :version "22.1")
387
388 (defcustom gdb-use-separate-io-buffer nil
389 "Non-nil means display output from the debugged program in a separate buffer."
390 :type 'boolean
391 :group 'gud
392 :version "22.1")
393
394 (defun gdb-force-mode-line-update (status)
395 (let ((buffer gud-comint-buffer))
396 (if (and buffer (buffer-name buffer))
397 (with-current-buffer buffer
398 (setq mode-line-process
399 (format ":%s [%s]"
400 (process-status (get-buffer-process buffer)) status))
401 ;; Force mode line redisplay soon.
402 (force-mode-line-update)))))
403
404 (defun gdb-many-windows (arg)
405 "Toggle the number of windows in the basic arrangement.
406 With prefix argument ARG, display additional buffers if ARG is positive,
407 otherwise use a single window."
408 (interactive "P")
409 (setq gdb-many-windows
410 (if (null arg)
411 (not gdb-many-windows)
412 (> (prefix-numeric-value arg) 0)))
413 (message (format "Display of other windows %sabled"
414 (if gdb-many-windows "en" "dis")))
415 (if (and gud-comint-buffer
416 (buffer-name gud-comint-buffer))
417 (condition-case nil
418 (gdb-restore-windows)
419 (error nil))))
420
421 (defun gdb-use-separate-io-buffer (arg)
422 "Toggle separate IO for debugged program.
423 With prefix argument ARG, use separate IO if ARG is positive,
424 otherwise do not."
425 (interactive "P")
426 (setq gdb-use-separate-io-buffer
427 (if (null arg)
428 (not gdb-use-separate-io-buffer)
429 (> (prefix-numeric-value arg) 0)))
430 (message (format "Separate IO %sabled"
431 (if gdb-use-separate-io-buffer "en" "dis")))
432 (if (and gud-comint-buffer
433 (buffer-name gud-comint-buffer))
434 (condition-case nil
435 (if gdb-use-separate-io-buffer
436 (if gdb-many-windows (gdb-restore-windows))
437 (kill-buffer (gdb-inferior-io-name)))
438 (error nil))))
439
440 (defvar gdb-define-alist nil "Alist of #define directives for GUD tooltips.")
441
442 (defun gdb-create-define-alist ()
443 "Create an alist of #define directives for GUD tooltips."
444 (let* ((file (buffer-file-name))
445 (output
446 (with-output-to-string
447 (with-current-buffer standard-output
448 (and file (file-exists-p file)
449 (call-process shell-file-name file
450 (list t nil) nil "-c"
451 (concat gdb-cpp-define-alist-program " "
452 gdb-cpp-define-alist-flags))))))
453 (define-list (split-string output "\n" t)) (name))
454 (setq gdb-define-alist nil)
455 (dolist (define define-list)
456 (setq name (nth 1 (split-string define "[( ]")))
457 (push (cons name define) gdb-define-alist))))
458
459 (defun gdb-tooltip-print (expr)
460 (tooltip-show
461 (with-current-buffer (gdb-get-buffer 'gdb-partial-output-buffer)
462 (goto-char (point-min))
463 (let ((string
464 (if (search-forward "=" nil t)
465 (concat expr (buffer-substring (- (point) 2) (point-max)))
466 (buffer-string))))
467 ;; remove newline for gud-tooltip-echo-area
468 (substring string 0 (- (length string) 1))))
469 (or gud-tooltip-echo-area tooltip-use-echo-area)))
470
471 ;; If expr is a macro for a function don't print because of possible dangerous
472 ;; side-effects. Also printing a function within a tooltip generates an
473 ;; unexpected starting annotation (phase error).
474 (defun gdb-tooltip-print-1 (expr)
475 (with-current-buffer (gdb-get-buffer 'gdb-partial-output-buffer)
476 (goto-char (point-min))
477 (if (search-forward "expands to: " nil t)
478 (unless (looking-at "\\S-+.*(.*).*")
479 (gdb-enqueue-input
480 (list (concat gdb-server-prefix "print " expr "\n")
481 `(lambda () (gdb-tooltip-print ,expr))))))))
482
483 (defconst gdb-source-file-regexp "\\(.+?\\), \\|\\([^, \n].*$\\)")
484
485 (defun gdb-set-gud-minor-mode-existing-buffers ()
486 "Create list of source files for current GDB session."
487 (goto-char (point-min))
488 (when (search-forward "read in on demand:" nil t)
489 (while (re-search-forward gdb-source-file-regexp nil t)
490 (push (file-name-nondirectory (or (match-string 1) (match-string 2)))
491 gdb-source-file-list))
492 (dolist (buffer (buffer-list))
493 (with-current-buffer buffer
494 (when (and buffer-file-name
495 (member (file-name-nondirectory buffer-file-name)
496 gdb-source-file-list))
497 (set (make-local-variable 'gud-minor-mode) 'gdba)
498 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
499 (when gud-tooltip-mode
500 (make-local-variable 'gdb-define-alist)
501 (gdb-create-define-alist)
502 (add-hook 'after-save-hook 'gdb-create-define-alist nil t))))))
503 (gdb-force-mode-line-update
504 (propertize "ready" 'face font-lock-variable-name-face)))
505
506 (defun gdb-find-watch-expression ()
507 (let* ((var (nth (- (line-number-at-pos (point)) 2) gdb-var-list))
508 (varnum (car var)) expr array)
509 (string-match "\\(var[0-9]+\\)\\.\\(.*\\)" varnum)
510 (let ((var1 (assoc (match-string 1 varnum) gdb-var-list)) var2 varnumlet
511 (component-list (split-string (match-string 2 varnum) "\\." t)))
512 (setq expr (nth 1 var1))
513 (setq varnumlet (car var1))
514 (dolist (component component-list)
515 (setq var2 (assoc varnumlet gdb-var-list))
516 (setq expr (concat expr
517 (if (string-match ".*\\[[0-9]+\\]$" (nth 3 var2))
518 (concat "[" component "]")
519 (concat "." component))))
520 (setq varnumlet (concat varnumlet "." component)))
521 expr)))
522
523 (defun gdb-init-1 ()
524 (gud-def gud-break (if (not (string-match "Machine" mode-name))
525 (gud-call "break %f:%l" arg)
526 (save-excursion
527 (beginning-of-line)
528 (forward-char 2)
529 (gud-call "break *%a" arg)))
530 "\C-b" "Set breakpoint at current line or address.")
531 ;;
532 (gud-def gud-remove (if (not (string-match "Machine" mode-name))
533 (gud-call "clear %f:%l" arg)
534 (save-excursion
535 (beginning-of-line)
536 (forward-char 2)
537 (gud-call "clear *%a" arg)))
538 "\C-d" "Remove breakpoint at current line or address.")
539 ;;
540 (gud-def gud-until (if (not (string-match "Machine" mode-name))
541 (gud-call "until %f:%l" arg)
542 (save-excursion
543 (beginning-of-line)
544 (forward-char 2)
545 (gud-call "until *%a" arg)))
546 "\C-u" "Continue to current line or address.")
547 ;;
548 (gud-def gud-go (gud-call (if gdb-active-process "continue" "run") arg)
549 nil "Start or continue execution.")
550
551 ;; For debugging Emacs only.
552 (gud-def gud-pp
553 (gud-call
554 (concat
555 "pp1 " (if (eq (buffer-local-value
556 'major-mode (window-buffer)) 'speedbar-mode)
557 (gdb-find-watch-expression) "%e")) arg)
558 nil "Print the emacs s-expression.")
559
560 (define-key gud-minor-mode-map [left-margin mouse-1]
561 'gdb-mouse-set-clear-breakpoint)
562 (define-key gud-minor-mode-map [left-fringe mouse-1]
563 'gdb-mouse-set-clear-breakpoint)
564 (define-key gud-minor-mode-map [left-margin C-mouse-1]
565 'gdb-mouse-toggle-breakpoint-margin)
566 (define-key gud-minor-mode-map [left-fringe C-mouse-1]
567 'gdb-mouse-toggle-breakpoint-fringe)
568
569 (define-key gud-minor-mode-map [left-margin drag-mouse-1]
570 'gdb-mouse-until)
571 (define-key gud-minor-mode-map [left-fringe drag-mouse-1]
572 'gdb-mouse-until)
573 (define-key gud-minor-mode-map [left-margin mouse-3]
574 'gdb-mouse-until)
575 (define-key gud-minor-mode-map [left-fringe mouse-3]
576 'gdb-mouse-until)
577
578 (define-key gud-minor-mode-map [left-margin C-drag-mouse-1]
579 'gdb-mouse-jump)
580 (define-key gud-minor-mode-map [left-fringe C-drag-mouse-1]
581 'gdb-mouse-jump)
582 (define-key gud-minor-mode-map [left-fringe C-mouse-3]
583 'gdb-mouse-jump)
584 (define-key gud-minor-mode-map [left-margin C-mouse-3]
585 'gdb-mouse-jump)
586
587 ;; (re-)initialize
588 (setq gdb-pc-address (if gdb-show-main "main" nil))
589 (setq gdb-previous-frame-address nil
590 gdb-memory-address "main"
591 gdb-previous-frame nil
592 gdb-selected-frame nil
593 gdb-current-language nil
594 gdb-frame-number nil
595 gdb-var-list nil
596 gdb-main-file nil
597 gdb-first-post-prompt t
598 gdb-prompting nil
599 gdb-input-queue nil
600 gdb-current-item nil
601 gdb-pending-triggers nil
602 gdb-output-sink 'user
603 gdb-server-prefix "server "
604 gdb-location-alist nil
605 gdb-source-file-list nil
606 gdb-error nil
607 gdb-macro-info nil
608 gdb-buffer-fringe-width (car (window-fringes))
609 gdb-debug-log nil
610 gdb-signalled nil
611 gdb-source-window nil
612 gdb-inferior-status nil
613 gdb-continuation nil
614 gdb-look-up-stack nil
615 gdb-frame-begin nil
616 gdb-printing t
617 gud-old-arrow nil)
618
619 (setq gdb-buffer-type 'gdba)
620
621 (if gdb-use-separate-io-buffer (gdb-clear-inferior-io))
622
623 ;; Hack to see test for GDB 6.4+ (-stack-info-frame was implemented in 6.4)
624 (gdb-enqueue-input (list "server interpreter mi -stack-info-frame\n"
625 'gdb-get-version)))
626
627 (defun gdb-init-2 ()
628 (if (eq window-system 'w32)
629 (gdb-enqueue-input (list "set new-console off\n" 'ignore)))
630 (gdb-enqueue-input (list "set height 0\n" 'ignore))
631 (gdb-enqueue-input (list "set width 0\n" 'ignore))
632
633 (if (string-equal gdb-version "pre-6.4")
634 (progn
635 (gdb-enqueue-input (list (concat gdb-server-prefix "info sources\n")
636 'gdb-set-gud-minor-mode-existing-buffers))
637 (setq gdb-locals-font-lock-keywords gdb-locals-font-lock-keywords-1))
638 (gdb-enqueue-input
639 (list "server interpreter mi -data-list-register-names\n"
640 'gdb-get-register-names))
641 ; Needs GDB 6.2 onwards.
642 (gdb-enqueue-input
643 (list "server interpreter mi \"-file-list-exec-source-files\"\n"
644 'gdb-set-gud-minor-mode-existing-buffers-1))
645 (setq gdb-locals-font-lock-keywords gdb-locals-font-lock-keywords-2))
646
647 ;; Find source file and compilation directory here.
648 ;; Works for C, C++, Fortran and Ada but not Java (GDB 6.4)
649 (gdb-enqueue-input (list "server list\n" 'ignore))
650 (gdb-enqueue-input (list "server info source\n" 'gdb-source-info))
651
652 (run-hooks 'gdb-mode-hook))
653
654 (defun gdb-get-version ()
655 (goto-char (point-min))
656 (if (re-search-forward "Undefined\\( mi\\)* command:" nil t)
657 (setq gdb-version "pre-6.4")
658 (setq gdb-version "6.4+"))
659 (gdb-init-2))
660
661 (defmacro gdb-if-arrow (arrow-position &rest body)
662 `(if ,arrow-position
663 (let ((buffer (marker-buffer ,arrow-position)) (line))
664 (if (equal buffer (window-buffer (posn-window end)))
665 (with-current-buffer buffer
666 (when (or (equal start end)
667 (equal (posn-point start)
668 (marker-position ,arrow-position)))
669 ,@body))))))
670
671 (defun gdb-mouse-until (event)
672 "Continue running until a source line past the current line.
673 The destination source line can be selected either by clicking
674 with mouse-3 on the fringe/margin or dragging the arrow
675 with mouse-1 (default bindings)."
676 (interactive "e")
677 (let ((start (event-start event))
678 (end (event-end event)))
679 (gdb-if-arrow gud-overlay-arrow-position
680 (setq line (line-number-at-pos (posn-point end)))
681 (gud-call (concat "until " (number-to-string line))))
682 (gdb-if-arrow gdb-overlay-arrow-position
683 (save-excursion
684 (goto-line (line-number-at-pos (posn-point end)))
685 (forward-char 2)
686 (gud-call (concat "until *%a"))))))
687
688 (defun gdb-mouse-jump (event)
689 "Set execution address/line.
690 The destination source line can be selected either by clicking with C-mouse-3
691 on the fringe/margin or dragging the arrow with C-mouse-1 (default bindings).
692 Unlike gdb-mouse-until the destination address can be before the current
693 line, and no execution takes place."
694 (interactive "e")
695 (let ((start (event-start event))
696 (end (event-end event)))
697 (gdb-if-arrow gud-overlay-arrow-position
698 (setq line (line-number-at-pos (posn-point end)))
699 (progn
700 (gud-call (concat "tbreak " (number-to-string line)))
701 (gud-call (concat "jump " (number-to-string line)))))
702 (gdb-if-arrow gdb-overlay-arrow-position
703 (save-excursion
704 (goto-line (line-number-at-pos (posn-point end)))
705 (forward-char 2)
706 (progn
707 (gud-call (concat "tbreak *%a"))
708 (gud-call (concat "jump *%a")))))))
709
710 (defcustom gdb-speedbar-auto-raise nil
711 "If non-nil raise speedbar every time display of watch expressions is\
712 updated."
713 :type 'boolean
714 :group 'gud
715 :version "22.1")
716
717 (defun gdb-speedbar-auto-raise (arg)
718 "Toggle automatic raising of the speedbar for watch expressions.
719 With prefix argument ARG, automatically raise speedbar if ARG is
720 positive, otherwise don't automatically raise it."
721 (interactive "P")
722 (setq gdb-speedbar-auto-raise
723 (if (null arg)
724 (not gdb-speedbar-auto-raise)
725 (> (prefix-numeric-value arg) 0)))
726 (message (format "Auto raising %sabled"
727 (if gdb-speedbar-auto-raise "en" "dis"))))
728
729 (defcustom gdb-use-colon-colon-notation nil
730 "If non-nil use FUN::VAR format to display variables in the speedbar."
731 :type 'boolean
732 :group 'gud
733 :version "22.1")
734
735 (define-key gud-minor-mode-map "\C-c\C-w" 'gud-watch)
736 (define-key global-map (concat gud-key-prefix "\C-w") 'gud-watch)
737
738 (defun gud-watch (&optional arg event)
739 "Watch expression at point.
740 With arg, enter name of variable to be watched in the minibuffer."
741 (interactive (list current-prefix-arg last-input-event))
742 (let ((minor-mode (buffer-local-value 'gud-minor-mode gud-comint-buffer)))
743 (if (memq minor-mode '(gdbmi gdba))
744 (progn
745 (if event (posn-set-point (event-end event)))
746 (require 'tooltip)
747 (save-selected-window
748 (let ((expr
749 (if arg
750 (completing-read "Name of variable: "
751 'gud-gdb-complete-command)
752 (if (and transient-mark-mode mark-active)
753 (buffer-substring (region-beginning) (region-end))
754 (tooltip-identifier-from-point (point))))))
755 (speedbar 1)
756 (set-text-properties 0 (length expr) nil expr)
757 (gdb-enqueue-input
758 (list
759 (if (eq minor-mode 'gdba)
760 (concat
761 "server interpreter mi \"-var-create - * " expr "\"\n")
762 (concat"-var-create - * " expr "\n"))
763 `(lambda () (gdb-var-create-handler ,expr)))))))
764 (message "gud-watch is a no-op in this mode."))))
765
766 (defconst gdb-var-create-regexp
767 "name=\"\\(.*?\\)\",.*numchild=\"\\(.*?\\)\",\\(?:.*value=\\(\".*\"\\),\\)?.*type=\"\\(.*?\\)\"")
768
769 (defun gdb-var-create-handler (expr)
770 (goto-char (point-min))
771 (if (re-search-forward gdb-var-create-regexp nil t)
772 (let ((var (list
773 (match-string 1)
774 (if (and (string-equal gdb-current-language "c")
775 gdb-use-colon-colon-notation gdb-selected-frame)
776 (setq expr (concat gdb-selected-frame "::" expr))
777 expr)
778 (match-string 2)
779 (match-string 4)
780 (if (match-string 3) (read (match-string 3)))
781 nil gdb-frame-address)))
782 (push var gdb-var-list)
783 (unless (string-equal
784 speedbar-initial-expansion-list-name "GUD")
785 (speedbar-change-initial-expansion-list "GUD"))
786 (unless (nth 4 var)
787 (gdb-enqueue-input
788 (list
789 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer)
790 'gdba)
791 (concat "server interpreter mi \"0-var-evaluate-expression "
792 (car var) "\"\n")
793 (concat "0-var-evaluate-expression " (car var) "\n"))
794 `(lambda () (gdb-var-evaluate-expression-handler
795 ,(car var) nil))))))
796 (if (search-forward "Undefined command" nil t)
797 (message-box "Watching expressions requires GDB 6.0 onwards")
798 (message-box "No symbol \"%s\" in current context." expr))))
799
800 (defun gdb-speedbar-update ()
801 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)
802 (not (member 'gdb-speedbar-timer gdb-pending-triggers)))
803 ;; Dummy command to update speedbar even when idle.
804 (gdb-enqueue-input (list "server pwd\n" 'gdb-speedbar-timer-fn))
805 ;; Keep gdb-pending-triggers non-nil till end.
806 (push 'gdb-speedbar-timer gdb-pending-triggers)))
807
808 (defun gdb-speedbar-timer-fn ()
809 (setq gdb-pending-triggers
810 (delq 'gdb-speedbar-timer gdb-pending-triggers))
811 (speedbar-timer-fn))
812
813 (defun gdb-var-evaluate-expression-handler (varnum changed)
814 (goto-char (point-min))
815 (re-search-forward "\\(.+\\)\\^done,value=\\(\".*\"\\)" nil t)
816 (setq gdb-pending-triggers
817 (delq (string-to-number (match-string 1)) gdb-pending-triggers))
818 (let ((var (assoc varnum gdb-var-list)))
819 (when var
820 (if changed (setcar (nthcdr 5 var) 'changed))
821 (setcar (nthcdr 4 var) (read (match-string 2)))))
822 (gdb-speedbar-update))
823
824 (defun gdb-var-list-children (varnum)
825 (gdb-enqueue-input
826 (list (concat "server interpreter mi \"-var-list-children " varnum "\"\n")
827 `(lambda () (gdb-var-list-children-handler ,varnum)))))
828
829 (defconst gdb-var-list-children-regexp
830 "child={.*?name=\"\\(.*?\\)\",.*?exp=\"\\(.*?\\)\",.*?\
831 numchild=\"\\(.*?\\)\"\\(}\\|,.*?\\(type=\"\\(.*?\\)\"\\)?.*?}\\)")
832
833 (defun gdb-var-list-children-handler (varnum)
834 (goto-char (point-min))
835 (let ((var-list nil))
836 (catch 'child-already-watched
837 (dolist (var gdb-var-list)
838 (if (string-equal varnum (car var))
839 (progn
840 (push var var-list)
841 (while (re-search-forward gdb-var-list-children-regexp nil t)
842 (let ((varchild (list (match-string 1)
843 (match-string 2)
844 (match-string 3)
845 (match-string 6)
846 nil nil)))
847 (if (assoc (car varchild) gdb-var-list)
848 (throw 'child-already-watched nil))
849 (push varchild var-list)
850 (gdb-enqueue-input
851 (list
852 (concat
853 "server interpreter mi \"0-var-evaluate-expression "
854 (car varchild) "\"\n")
855 `(lambda () (gdb-var-evaluate-expression-handler
856 ,(car varchild) nil)))))))
857 (push var var-list)))
858 (setq gdb-var-list (nreverse var-list)))))
859
860 (defun gdb-var-update ()
861 (when (not (member 'gdb-var-update gdb-pending-triggers))
862 (gdb-enqueue-input
863 (list "server interpreter mi \"-var-update *\"\n"
864 'gdb-var-update-handler))
865 (push 'gdb-var-update gdb-pending-triggers)))
866
867 (defconst gdb-var-update-regexp
868 "{.*?name=\"\\(.*?\\)\",.*?in_scope=\"\\(.*?\\)\",.*?\
869 type_changed=\".*?\".*?}")
870
871 (defun gdb-var-update-handler ()
872 (dolist (var gdb-var-list)
873 (setcar (nthcdr 5 var) nil))
874 (goto-char (point-min))
875 (let ((n 0))
876 (while (re-search-forward gdb-var-update-regexp nil t)
877 (let ((varnum (match-string 1)))
878 (if (string-equal (match-string 2) "false")
879 (let ((var (assoc varnum gdb-var-list)))
880 (if var (setcar (nthcdr 5 var) 'out-of-scope)))
881 (setq n (1+ n))
882 (push n gdb-pending-triggers)
883 (gdb-enqueue-input
884 (list
885 (concat "server interpreter mi \"" (number-to-string n)
886 "-var-evaluate-expression " varnum "\"\n")
887 `(lambda () (gdb-var-evaluate-expression-handler ,varnum t))))))))
888 (setq gdb-pending-triggers
889 (delq 'gdb-var-update gdb-pending-triggers)))
890
891 (defun gdb-var-set-format (format)
892 "Set the output format for a variable displayed in the speedbar."
893 (let* ((var (nth (- (count-lines (point-min) (point)) 2) gdb-var-list))
894 (varnum (car var)))
895 (gdb-enqueue-input
896 (list
897 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
898 (concat "server interpreter mi \"-var-set-format "
899 varnum " " format "\"\n")
900 (concat "-var-set-format " varnum " " format "\n"))
901 `(lambda () (gdb-var-set-format-handler ,varnum))))))
902
903 (defconst gdb-var-set-format-regexp
904 "format=\"\\(.*?\\)\",.*value=\"\\(.*?\\)\"")
905
906 (defun gdb-var-set-format-handler (varnum)
907 (goto-char (point-min))
908 (if (re-search-forward gdb-var-set-format-regexp nil t)
909 (let ((var (assoc varnum gdb-var-list)))
910 (setcar (nthcdr 4 var) (match-string 2))
911 (gdb-var-update-1))))
912
913 (defun gdb-var-delete-1 (varnum)
914 (gdb-enqueue-input
915 (list
916 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
917 (concat "server interpreter mi \"-var-delete " varnum "\"\n")
918 (concat "-var-delete " varnum "\n"))
919 'ignore))
920 (setq gdb-var-list (delq var gdb-var-list))
921 (dolist (varchild gdb-var-list)
922 (if (string-match (concat (car var) "\\.") (car varchild))
923 (setq gdb-var-list (delq varchild gdb-var-list)))))
924
925 (defun gdb-var-delete ()
926 "Delete watch expression at point from the speedbar."
927 (interactive)
928 (if (memq (buffer-local-value 'gud-minor-mode gud-comint-buffer)
929 '(gdbmi gdba))
930 (let* ((var (nth (- (count-lines (point-min) (point)) 2) gdb-var-list))
931 (varnum (car var)))
932 (if (string-match "\\." (car var))
933 (message-box "Can only delete a root expression")
934 (gdb-var-delete-1 varnum)))))
935
936 (defun gdb-var-delete-children (varnum)
937 "Delete children of variable object at point from the speedbar."
938 (gdb-enqueue-input
939 (list
940 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
941 (concat "server interpreter mi \"-var-delete -c " varnum "\"\n")
942 (concat "-var-delete -c " varnum "\n")) 'ignore)))
943
944 (defun gdb-edit-value (text token indent)
945 "Assign a value to a variable displayed in the speedbar."
946 (let* ((var (nth (- (count-lines (point-min) (point)) 2) gdb-var-list))
947 (varnum (car var)) (value))
948 (setq value (read-string "New value: "))
949 (gdb-enqueue-input
950 (list
951 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
952 (concat "server interpreter mi \"-var-assign "
953 varnum " " value "\"\n")
954 (concat "-var-assign " varnum " " value "\n"))
955 `(lambda () (gdb-edit-value-handler ,value))))))
956
957 (defun gdb-edit-value-handler (value)
958 (goto-char (point-min))
959 (if (re-search-forward gdb-error-regexp nil t)
960 (message-box "Invalid number or expression (%s)" value)))
961
962 (defcustom gdb-show-changed-values t
963 "If non-nil change the face of out of scope variables and changed values.
964 Out of scope variables are suppressed with `shadow' face.
965 Changed values are highlighted with the face `font-lock-warning-face'."
966 :type 'boolean
967 :group 'gud
968 :version "22.1")
969
970 (defcustom gdb-max-children 40
971 "Maximum number of children before expansion requires confirmation."
972 :type 'integer
973 :group 'gud
974 :version "22.1")
975
976 (defcustom gdb-delete-out-of-scope t
977 "If non-nil delete watch expressions automatically when they go out of scope."
978 :type 'boolean
979 :group 'gud
980 :version "22.2")
981
982 (defun gdb-speedbar-expand-node (text token indent)
983 "Expand the node the user clicked on.
984 TEXT is the text of the button we clicked on, a + or - item.
985 TOKEN is data related to this node.
986 INDENT is the current indentation depth."
987 (if (and gud-comint-buffer (buffer-name gud-comint-buffer))
988 (progn
989 (cond ((string-match "+" text) ;expand this node
990 (let* ((var (assoc token gdb-var-list))
991 (expr (nth 1 var)) (children (nth 2 var)))
992 (if (or (<= (string-to-number children) gdb-max-children)
993 (y-or-n-p
994 (format
995 "%s has %s children. Continue? " expr children)))
996 (if (and (eq (buffer-local-value
997 'gud-minor-mode gud-comint-buffer) 'gdba)
998 (string-equal gdb-version "pre-6.4"))
999 (gdb-var-list-children token)
1000 (gdb-var-list-children-1 token)))))
1001 ((string-match "-" text) ;contract this node
1002 (dolist (var gdb-var-list)
1003 (if (string-match (concat token "\\.") (car var))
1004 (setq gdb-var-list (delq var gdb-var-list))))
1005 (gdb-var-delete-children token)
1006 (speedbar-change-expand-button-char ?+)
1007 (speedbar-delete-subblock indent))
1008 (t (error "Ooops... not sure what to do")))
1009 (speedbar-center-buffer-smartly))
1010 (message-box "GUD session has been killed")))
1011
1012 (defun gdb-get-target-string ()
1013 (with-current-buffer gud-comint-buffer
1014 gud-target-name))
1015 \f
1016
1017 ;;
1018 ;; gdb buffers.
1019 ;;
1020 ;; Each buffer has a TYPE -- a symbol that identifies the function
1021 ;; of that particular buffer.
1022 ;;
1023 ;; The usual gdb interaction buffer is given the type `gdba' and
1024 ;; is constructed specially.
1025 ;;
1026 ;; Others are constructed by gdb-get-buffer-create and
1027 ;; named according to the rules set forth in the gdb-buffer-rules-assoc
1028
1029 (defvar gdb-buffer-rules-assoc '())
1030
1031 (defun gdb-get-buffer (key)
1032 "Return the gdb buffer tagged with type KEY.
1033 The key should be one of the cars in `gdb-buffer-rules-assoc'."
1034 (save-excursion
1035 (gdb-look-for-tagged-buffer key (buffer-list))))
1036
1037 (defun gdb-get-buffer-create (key)
1038 "Create a new gdb buffer of the type specified by KEY.
1039 The key should be one of the cars in `gdb-buffer-rules-assoc'."
1040 (or (gdb-get-buffer key)
1041 (let* ((rules (assoc key gdb-buffer-rules-assoc))
1042 (name (funcall (gdb-rules-name-maker rules)))
1043 (new (get-buffer-create name)))
1044 (with-current-buffer new
1045 (let ((trigger))
1046 (if (cdr (cdr rules))
1047 (setq trigger (funcall (car (cdr (cdr rules))))))
1048 (setq gdb-buffer-type key)
1049 (set (make-local-variable 'gud-minor-mode)
1050 (buffer-local-value 'gud-minor-mode gud-comint-buffer))
1051 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
1052 (if trigger (funcall trigger)))
1053 new))))
1054
1055 (defun gdb-rules-name-maker (rules) (car (cdr rules)))
1056
1057 (defun gdb-look-for-tagged-buffer (key bufs)
1058 (let ((retval nil))
1059 (while (and (not retval) bufs)
1060 (set-buffer (car bufs))
1061 (if (eq gdb-buffer-type key)
1062 (setq retval (car bufs)))
1063 (setq bufs (cdr bufs)))
1064 retval))
1065
1066 ;;
1067 ;; This assoc maps buffer type symbols to rules. Each rule is a list of
1068 ;; at least one and possible more functions. The functions have these
1069 ;; roles in defining a buffer type:
1070 ;;
1071 ;; NAME - Return a name for this buffer type.
1072 ;;
1073 ;; The remaining function(s) are optional:
1074 ;;
1075 ;; MODE - called in a new buffer with no arguments, should establish
1076 ;; the proper mode for the buffer.
1077 ;;
1078
1079 (defun gdb-set-buffer-rules (buffer-type &rest rules)
1080 (let ((binding (assoc buffer-type gdb-buffer-rules-assoc)))
1081 (if binding
1082 (setcdr binding rules)
1083 (push (cons buffer-type rules)
1084 gdb-buffer-rules-assoc))))
1085
1086 ;; GUD buffers are an exception to the rules
1087 (gdb-set-buffer-rules 'gdba 'error)
1088
1089 ;; Partial-output buffer : This accumulates output from a command executed on
1090 ;; behalf of emacs (rather than the user).
1091 ;;
1092 (gdb-set-buffer-rules 'gdb-partial-output-buffer
1093 'gdb-partial-output-name)
1094
1095 (defun gdb-partial-output-name ()
1096 (concat " *partial-output-"
1097 (gdb-get-target-string)
1098 "*"))
1099
1100 \f
1101 (gdb-set-buffer-rules 'gdb-inferior-io
1102 'gdb-inferior-io-name
1103 'gdb-inferior-io-mode)
1104
1105 (defun gdb-inferior-io-name ()
1106 (concat "*input/output of "
1107 (gdb-get-target-string)
1108 "*"))
1109
1110 (defun gdb-display-separate-io-buffer ()
1111 "Display IO of debugged program in a separate window."
1112 (interactive)
1113 (if gdb-use-separate-io-buffer
1114 (gdb-display-buffer
1115 (gdb-get-buffer-create 'gdb-inferior-io) t)))
1116
1117 (defconst gdb-frame-parameters
1118 '((height . 14) (width . 80)
1119 (unsplittable . t)
1120 (tool-bar-lines . nil)
1121 (menu-bar-lines . nil)
1122 (minibuffer . nil)))
1123
1124 (defun gdb-frame-separate-io-buffer ()
1125 "Display IO of debugged program in a new frame."
1126 (interactive)
1127 (if gdb-use-separate-io-buffer
1128 (let ((special-display-regexps (append special-display-regexps '(".*")))
1129 (special-display-frame-alist gdb-frame-parameters))
1130 (display-buffer (gdb-get-buffer-create 'gdb-inferior-io)))))
1131
1132 (defvar gdb-inferior-io-mode-map
1133 (let ((map (make-sparse-keymap)))
1134 (define-key map "\C-c\C-c" 'gdb-separate-io-interrupt)
1135 (define-key map "\C-c\C-z" 'gdb-separate-io-stop)
1136 (define-key map "\C-c\C-\\" 'gdb-separate-io-quit)
1137 (define-key map "\C-c\C-d" 'gdb-separate-io-eof)
1138 (define-key map "\C-d" 'gdb-separate-io-eof)
1139 map))
1140
1141 (define-derived-mode gdb-inferior-io-mode comint-mode "Inferior I/O"
1142 "Major mode for gdb inferior-io."
1143 :syntax-table nil :abbrev-table nil
1144 ;; We want to use comint because it has various nifty and familiar
1145 ;; features. We don't need a process, but comint wants one, so create
1146 ;; a dummy one.
1147 (make-comint-in-buffer
1148 (substring (buffer-name) 1 (- (length (buffer-name)) 1))
1149 (current-buffer) "hexl")
1150 (setq comint-input-sender 'gdb-inferior-io-sender))
1151
1152 (defun gdb-inferior-io-sender (proc string)
1153 ;; PROC is the pseudo-process created to satisfy comint.
1154 (with-current-buffer (process-buffer proc)
1155 (setq proc (get-buffer-process gud-comint-buffer))
1156 (process-send-string proc string)
1157 (process-send-string proc "\n")))
1158
1159 (defun gdb-separate-io-interrupt ()
1160 "Interrupt the program being debugged."
1161 (interactive)
1162 (interrupt-process
1163 (get-buffer-process gud-comint-buffer) comint-ptyp))
1164
1165 (defun gdb-separate-io-quit ()
1166 "Send quit signal to the program being debugged."
1167 (interactive)
1168 (quit-process
1169 (get-buffer-process gud-comint-buffer) comint-ptyp))
1170
1171 (defun gdb-separate-io-stop ()
1172 "Stop the program being debugged."
1173 (interactive)
1174 (stop-process
1175 (get-buffer-process gud-comint-buffer) comint-ptyp))
1176
1177 (defun gdb-separate-io-eof ()
1178 "Send end-of-file to the program being debugged."
1179 (interactive)
1180 (process-send-eof
1181 (get-buffer-process gud-comint-buffer)))
1182 \f
1183
1184 ;; gdb communications
1185 ;;
1186
1187 ;; INPUT: things sent to gdb
1188 ;;
1189 ;; The queues are lists. Each element is either a string (indicating user or
1190 ;; user-like input) or a list of the form:
1191 ;;
1192 ;; (INPUT-STRING HANDLER-FN)
1193 ;;
1194 ;; The handler function will be called from the partial-output buffer when the
1195 ;; command completes. This is the way to write commands which invoke gdb
1196 ;; commands autonomously.
1197 ;;
1198 ;; These lists are consumed tail first.
1199 ;;
1200
1201 (defun gdb-send (proc string)
1202 "A comint send filter for gdb.
1203 This filter may simply queue input for a later time."
1204 (if gdb-ready
1205 (progn
1206 (with-current-buffer gud-comint-buffer
1207 (let ((inhibit-read-only t))
1208 (remove-text-properties (point-min) (point-max) '(face))))
1209 (if gud-running
1210 (progn
1211 (let ((item (concat string "\n")))
1212 (if gdb-enable-debug (push (cons 'send item) gdb-debug-log))
1213 (process-send-string proc item)))
1214 (if (string-match "\\\\\\'" string)
1215 (setq gdb-continuation (concat gdb-continuation string "\n"))
1216 (let ((item (concat
1217 gdb-continuation string
1218 (if (not comint-input-sender-no-newline) "\n"))))
1219 (gdb-enqueue-input item)
1220 (setq gdb-continuation nil)))))
1221 (push (concat string "\n") gdb-early-user-input)))
1222
1223 ;; Note: Stuff enqueued here will be sent to the next prompt, even if it
1224 ;; is a query, or other non-top-level prompt.
1225
1226 (defun gdb-enqueue-input (item)
1227 (if (not gud-running)
1228 (if gdb-prompting
1229 (progn
1230 (gdb-send-item item)
1231 (setq gdb-prompting nil))
1232 (push item gdb-input-queue))))
1233
1234 (defun gdb-dequeue-input ()
1235 (let ((queue gdb-input-queue))
1236 (if queue
1237 (let ((last (car (last queue))))
1238 (unless (nbutlast queue) (setq gdb-input-queue '()))
1239 last)
1240 ;; This should be nil here anyway but set it just to make sure.
1241 (setq gdb-pending-triggers nil))))
1242
1243 (defun gdb-send-item (item)
1244 (setq gdb-flush-pending-output nil)
1245 (if gdb-enable-debug (push (cons 'send-item item) gdb-debug-log))
1246 (setq gdb-current-item item)
1247 (let ((process (get-buffer-process gud-comint-buffer)))
1248 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
1249 (if (stringp item)
1250 (progn
1251 (setq gdb-output-sink 'user)
1252 (process-send-string process item))
1253 (progn
1254 (gdb-clear-partial-output)
1255 (setq gdb-output-sink 'pre-emacs)
1256 (process-send-string process
1257 (car item))))
1258 ;; case: eq gud-minor-mode 'gdbmi
1259 (gdb-clear-partial-output)
1260 (setq gdb-output-sink 'emacs)
1261 (process-send-string process (car item)))))
1262 \f
1263 ;;
1264 ;; output -- things gdb prints to emacs
1265 ;;
1266 ;; GDB output is a stream interrupted by annotations.
1267 ;; Annotations can be recognized by their beginning
1268 ;; with \C-j\C-z\C-z<tag><opt>\C-j
1269 ;;
1270 ;; The tag is a string obeying symbol syntax.
1271 ;;
1272 ;; The optional part `<opt>' can be either the empty string
1273 ;; or a space followed by more data relating to the annotation.
1274 ;; For example, the SOURCE annotation is followed by a filename,
1275 ;; line number and various useless goo. This data must not include
1276 ;; any newlines.
1277 ;;
1278
1279 (defcustom gud-gdb-command-name "gdb --annotate=3"
1280 "Default command to execute an executable under the GDB debugger.
1281 The option \"--annotate=3\" must be included in this value if you
1282 want the GDB Graphical Interface."
1283 :type 'string
1284 :group 'gud
1285 :version "22.1")
1286
1287 (defvar gdb-annotation-rules
1288 '(("pre-prompt" gdb-pre-prompt)
1289 ("prompt" gdb-prompt)
1290 ("commands" gdb-subprompt)
1291 ("overload-choice" gdb-subprompt)
1292 ("query" gdb-subprompt)
1293 ;; Need this prompt for GDB 6.1
1294 ("nquery" gdb-subprompt)
1295 ("prompt-for-continue" gdb-subprompt)
1296 ("post-prompt" gdb-post-prompt)
1297 ("source" gdb-source)
1298 ("starting" gdb-starting)
1299 ("exited" gdb-exited)
1300 ("signalled" gdb-signalled)
1301 ("signal" gdb-signal)
1302 ("breakpoint" gdb-stopping)
1303 ("watchpoint" gdb-stopping)
1304 ("frame-begin" gdb-frame-begin)
1305 ("stopped" gdb-stopped)
1306 ("error-begin" gdb-error)
1307 ("error" gdb-error)
1308 ) "An assoc mapping annotation tags to functions which process them.")
1309
1310 (defun gdb-resync()
1311 (setq gdb-flush-pending-output t)
1312 (setq gud-running nil)
1313 (gdb-force-mode-line-update
1314 (propertize "stopped"'face font-lock-warning-face))
1315 (setq gdb-output-sink 'user)
1316 (setq gdb-input-queue nil)
1317 (setq gdb-pending-triggers nil)
1318 (setq gdb-prompting t))
1319
1320 (defconst gdb-source-spec-regexp
1321 "\\(.*\\):\\([0-9]*\\):[0-9]*:[a-z]*:0x0*\\([a-f0-9]*\\)")
1322
1323 ;; Do not use this except as an annotation handler.
1324 (defun gdb-source (args)
1325 (string-match gdb-source-spec-regexp args)
1326 ;; Extract the frame position from the marker.
1327 (setq gud-last-frame
1328 (cons
1329 (match-string 1 args)
1330 (string-to-number (match-string 2 args))))
1331 (setq gdb-pc-address (match-string 3 args))
1332 ;; cover for auto-display output which comes *before*
1333 ;; stopped annotation
1334 (if (eq gdb-output-sink 'inferior) (setq gdb-output-sink 'user)))
1335
1336 (defun gdb-pre-prompt (ignored)
1337 "An annotation handler for `pre-prompt'.
1338 This terminates the collection of output from a previous command if that
1339 happens to be in effect."
1340 (setq gdb-error nil)
1341 (let ((sink gdb-output-sink))
1342 (cond
1343 ((eq sink 'user) t)
1344 ((eq sink 'emacs)
1345 (setq gdb-output-sink 'post-emacs))
1346 (t
1347 (gdb-resync)
1348 (error "Phase error in gdb-pre-prompt (got %s)" sink)))))
1349
1350 (defun gdb-prompt (ignored)
1351 "An annotation handler for `prompt'.
1352 This sends the next command (if any) to gdb."
1353 (when gdb-first-prompt
1354 (gdb-force-mode-line-update
1355 (propertize "initializing..." 'face font-lock-variable-name-face))
1356 (gdb-init-1)
1357 (setq gdb-first-prompt nil))
1358 (let ((sink gdb-output-sink))
1359 (cond
1360 ((eq sink 'user) t)
1361 ((eq sink 'post-emacs)
1362 (setq gdb-output-sink 'user)
1363 (let ((handler
1364 (car (cdr gdb-current-item))))
1365 (with-current-buffer (gdb-get-buffer-create 'gdb-partial-output-buffer)
1366 (funcall handler))))
1367 (t
1368 (gdb-resync)
1369 (error "Phase error in gdb-prompt (got %s)" sink))))
1370 (let ((input (gdb-dequeue-input)))
1371 (if input
1372 (gdb-send-item input)
1373 (progn
1374 (setq gdb-prompting t)
1375 (gud-display-frame)
1376 (setq gdb-early-user-input (nreverse gdb-early-user-input))
1377 (while gdb-early-user-input
1378 (gdb-enqueue-input (car gdb-early-user-input))
1379 (setq gdb-early-user-input (cdr gdb-early-user-input)))))))
1380
1381 (defun gdb-subprompt (ignored)
1382 "An annotation handler for non-top-level prompts."
1383 (setq gdb-prompting t))
1384
1385 (defun gdb-starting (ignored)
1386 "An annotation handler for `starting'.
1387 This says that I/O for the subprocess is now the program being debugged,
1388 not GDB."
1389 (setq gdb-active-process t)
1390 (setq gdb-printing t)
1391 (let ((sink gdb-output-sink))
1392 (cond
1393 ((eq sink 'user)
1394 (progn
1395 (setq gud-running t)
1396 (setq gdb-inferior-status "running")
1397 (setq gdb-signalled nil)
1398 (gdb-force-mode-line-update
1399 (propertize gdb-inferior-status 'face font-lock-type-face))
1400 (gdb-remove-text-properties)
1401 (setq gud-old-arrow gud-overlay-arrow-position)
1402 (setq gud-overlay-arrow-position nil)
1403 (setq gdb-overlay-arrow-position nil)
1404 (setq gdb-stack-position nil)
1405 (if gdb-use-separate-io-buffer
1406 (setq gdb-output-sink 'inferior))))
1407 (t
1408 (gdb-resync)
1409 (error "Unexpected `starting' annotation")))))
1410
1411 (defun gdb-signal (ignored)
1412 (setq gdb-inferior-status "signal")
1413 (gdb-force-mode-line-update
1414 (propertize gdb-inferior-status 'face font-lock-warning-face))
1415 (gdb-stopping ignored))
1416
1417 (defun gdb-stopping (ignored)
1418 "An annotation handler for `breakpoint' and other annotations.
1419 They say that I/O for the subprocess is now GDB, not the program
1420 being debugged."
1421 (if gdb-use-separate-io-buffer
1422 (let ((sink gdb-output-sink))
1423 (cond
1424 ((eq sink 'inferior)
1425 (setq gdb-output-sink 'user))
1426 (t
1427 (gdb-resync)
1428 (error "Unexpected stopping annotation"))))))
1429
1430 (defun gdb-exited (ignored)
1431 "An annotation handler for `exited' and `signalled'.
1432 They say that I/O for the subprocess is now GDB, not the program
1433 being debugged and that the program is no longer running. This
1434 function is used to change the focus of GUD tooltips to #define
1435 directives."
1436 (setq gdb-active-process nil)
1437 (setq gud-overlay-arrow-position nil)
1438 (setq gdb-overlay-arrow-position nil)
1439 (setq gdb-stack-position nil)
1440 (setq gud-old-arrow nil)
1441 (setq gdb-inferior-status "exited")
1442 (gdb-force-mode-line-update
1443 (propertize gdb-inferior-status 'face font-lock-warning-face))
1444 (gdb-stopping ignored))
1445
1446 (defun gdb-signalled (ignored)
1447 (setq gdb-signalled t))
1448
1449 (defun gdb-frame-begin (ignored)
1450 (setq gdb-frame-begin t)
1451 (setq gdb-printing nil)
1452 (let ((sink gdb-output-sink))
1453 (cond
1454 ((eq sink 'inferior)
1455 (setq gdb-output-sink 'user))
1456 ((eq sink 'user) t)
1457 ((eq sink 'emacs) t)
1458 (t
1459 (gdb-resync)
1460 (error "Unexpected frame-begin annotation (%S)" sink)))))
1461
1462 (defcustom gdb-same-frame focus-follows-mouse
1463 "Non-nil means pop up GUD buffer in same frame."
1464 :group 'gud
1465 :type 'boolean
1466 :version "22.1")
1467
1468 (defcustom gdb-find-source-frame nil
1469 "Non-nil means try to find a source frame further up stack e.g after signal."
1470 :group 'gud
1471 :type 'boolean
1472 :version "22.1")
1473
1474 (defun gdb-find-source-frame (arg)
1475 "Toggle trying to find a source frame further up stack.
1476 With prefix argument ARG, look for a source frame further up
1477 stack if ARG is positive, otherwise don't look further up."
1478 (interactive "P")
1479 (setq gdb-find-source-frame
1480 (if (null arg)
1481 (not gdb-find-source-frame)
1482 (> (prefix-numeric-value arg) 0)))
1483 (message (format "Looking for source frame %sabled"
1484 (if gdb-find-source-frame "en" "dis"))))
1485
1486 (defun gdb-stopped (ignored)
1487 "An annotation handler for `stopped'.
1488 It is just like `gdb-stopping', except that if we already set the output
1489 sink to `user' in `gdb-stopping', that is fine."
1490 (setq gud-running nil)
1491 (unless (or gud-overlay-arrow-position gud-last-frame)
1492 (if (and gdb-frame-begin gdb-printing)
1493 (setq gud-overlay-arrow-position gud-old-arrow)
1494 ;;Pop up GUD buffer to display current frame when it doesn't have source
1495 ;;information i.e if not compiled with -g as with libc routines generally.
1496 (if gdb-same-frame
1497 (gdb-display-gdb-buffer)
1498 (gdb-frame-gdb-buffer))
1499 (if gdb-find-source-frame
1500 ;;Try to find source further up stack e.g after signal.
1501 (setq gdb-look-up-stack
1502 (if (gdb-get-buffer 'gdb-stack-buffer)
1503 'keep
1504 (progn
1505 (gdb-get-buffer-create 'gdb-stack-buffer)
1506 (gdb-invalidate-frames)
1507 'delete))))))
1508 (unless (member gdb-inferior-status '("exited" "signal"))
1509 (setq gdb-active-process t) ;Just for attaching case.
1510 (setq gdb-inferior-status "stopped")
1511 (gdb-force-mode-line-update
1512 (propertize gdb-inferior-status 'face font-lock-warning-face)))
1513 (let ((sink gdb-output-sink))
1514 (cond
1515 ((eq sink 'inferior)
1516 (setq gdb-output-sink 'user))
1517 ((eq sink 'user) t)
1518 (t
1519 (gdb-resync)
1520 (error "Unexpected stopped annotation"))))
1521 (if gdb-signalled (gdb-exited ignored)))
1522
1523 (defun gdb-error (ignored)
1524 (setq gdb-error (not gdb-error)))
1525
1526 (defun gdb-post-prompt (ignored)
1527 "An annotation handler for `post-prompt'.
1528 This begins the collection of output from the current command if that
1529 happens to be appropriate."
1530 ;; Don't add to queue if there outstanding items or gdb-version is not known
1531 ;; yet.
1532 (unless (or gdb-pending-triggers gdb-first-post-prompt)
1533 (gdb-get-selected-frame)
1534 (gdb-invalidate-frames)
1535 ;; Regenerate breakpoints buffer in case it has been inadvertantly deleted.
1536 (gdb-get-buffer-create 'gdb-breakpoints-buffer)
1537 (gdb-invalidate-breakpoints)
1538 ;; Do this through gdb-get-selected-frame -> gdb-frame-handler
1539 ;; so gdb-pc-address is updated.
1540 ;; (gdb-invalidate-assembler)
1541
1542 (if (string-equal gdb-version "pre-6.4")
1543 (gdb-invalidate-registers)
1544 (gdb-get-changed-registers)
1545 (gdb-invalidate-registers-1))
1546
1547 (gdb-invalidate-memory)
1548 (if (string-equal gdb-version "pre-6.4")
1549 (gdb-invalidate-locals)
1550 (gdb-invalidate-locals-1))
1551
1552 (gdb-invalidate-threads)
1553 (unless (eq system-type 'darwin) ;Breaks on Darwin's GDB-5.3.
1554 ;; FIXME: with GDB-6 on Darwin, this might very well work.
1555 ;; Only needed/used with speedbar/watch expressions.
1556 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame))
1557 (if (string-equal gdb-version "pre-6.4")
1558 (gdb-var-update)
1559 (gdb-var-update-1)))))
1560 (setq gdb-first-post-prompt nil)
1561 (let ((sink gdb-output-sink))
1562 (cond
1563 ((eq sink 'user) t)
1564 ((eq sink 'pre-emacs)
1565 (setq gdb-output-sink 'emacs))
1566 (t
1567 (gdb-resync)
1568 (error "Phase error in gdb-post-prompt (got %s)" sink)))))
1569
1570 (defconst gdb-buffer-list
1571 '(gdb-stack-buffer gdb-locals-buffer gdb-registers-buffer gdb-threads-buffer))
1572
1573 (defun gdb-remove-text-properties ()
1574 (dolist (buffertype gdb-buffer-list)
1575 (let ((buffer (gdb-get-buffer buffertype)))
1576 (if buffer
1577 (with-current-buffer buffer
1578 (let ((inhibit-read-only t))
1579 (remove-text-properties
1580 (point-min) (point-max) '(mouse-face nil help-echo nil))))))))
1581
1582 ;; GUD displays the selected GDB frame. This might might not be the current
1583 ;; GDB frame (after up, down etc). If no GDB frame is visible but the last
1584 ;; visited breakpoint is, use that window.
1585 (defun gdb-display-source-buffer (buffer)
1586 (let* ((last-window (if gud-last-last-frame
1587 (get-buffer-window
1588 (gud-find-file (car gud-last-last-frame)))))
1589 (source-window (or last-window
1590 (if (and gdb-source-window
1591 (window-live-p gdb-source-window))
1592 gdb-source-window))))
1593 (when source-window
1594 (setq gdb-source-window source-window)
1595 (set-window-buffer source-window buffer))
1596 source-window))
1597
1598 ;; Derived from gud-gdb-marker-regexp
1599 (defvar gdb-fullname-regexp
1600 (concat "\\(.:?[^" ":" "\n]*\\)" ":" "\\([0-9]*\\)" ":" ".*"))
1601
1602 (defun gud-gdba-marker-filter (string)
1603 "A gud marker filter for gdb. Handle a burst of output from GDB."
1604 (if gdb-flush-pending-output
1605 nil
1606 (when gdb-enable-debug
1607 (push (cons 'recv string) gdb-debug-log)
1608 (if (and gdb-debug-log-max
1609 (> (length gdb-debug-log) gdb-debug-log-max))
1610 (setcdr (nthcdr (1- gdb-debug-log-max) gdb-debug-log) nil)))
1611 ;; Recall the left over gud-marker-acc from last time.
1612 (setq gud-marker-acc (concat gud-marker-acc string))
1613 ;; Start accumulating output for the GUD buffer.
1614 (let ((output ""))
1615 ;;
1616 ;; Process all the complete markers in this chunk.
1617 (while (string-match "\n\032\032\\(.*\\)\n" gud-marker-acc)
1618 (let ((annotation (match-string 1 gud-marker-acc))
1619 (before (substring gud-marker-acc 0 (match-beginning 0)))
1620 (after (substring gud-marker-acc (match-end 0))))
1621 ;;
1622 ;; Parse the tag from the annotation, and maybe its arguments.
1623 (string-match "\\(\\S-*\\) ?\\(.*\\)" annotation)
1624 (let* ((annotation-type (match-string 1 annotation))
1625 (annotation-arguments (match-string 2 annotation))
1626 (annotation-rule (assoc annotation-type
1627 gdb-annotation-rules))
1628 (fullname (string-match gdb-fullname-regexp annotation-type)))
1629
1630 ;; Stuff prior to the match is just ordinary output.
1631 ;; It is either concatenated to OUTPUT or directed
1632 ;; elsewhere.
1633 (setq output
1634 (gdb-concat-output output
1635 (concat before (if fullname "\n"))))
1636
1637 ;; Take that stuff off the gud-marker-acc.
1638 (setq gud-marker-acc after)
1639
1640 ;; Call the handler for this annotation.
1641 (if annotation-rule
1642 (funcall (car (cdr annotation-rule))
1643 annotation-arguments)
1644
1645 ;; Switch to gud-gdb-marker-filter if appropriate.
1646 (when fullname
1647
1648 ;; Extract the frame position from the marker.
1649 (setq gud-last-frame (cons (match-string 1 annotation)
1650 (string-to-number
1651 (match-string 2 annotation))))
1652
1653 (set (make-local-variable 'gud-minor-mode) 'gdb)
1654 (set (make-local-variable 'gud-marker-filter)
1655 'gud-gdb-marker-filter)))
1656
1657 ;; Else the annotation is not recognized. Ignore it silently,
1658 ;; so that GDB can add new annotations without causing
1659 ;; us to blow up.
1660 )))
1661
1662 ;; Does the remaining text end in a partial line?
1663 ;; If it does, then keep part of the gud-marker-acc until we get more.
1664 (if (string-match "\n\\'\\|\n\032\\'\\|\n\032\032.*\\'"
1665 gud-marker-acc)
1666 (progn
1667 ;; Everything before the potential marker start can be output.
1668 (setq output
1669 (gdb-concat-output output
1670 (substring gud-marker-acc 0
1671 (match-beginning 0))))
1672 ;;
1673 ;; Everything after, we save, to combine with later input.
1674 (setq gud-marker-acc (substring gud-marker-acc
1675 (match-beginning 0))))
1676 ;;
1677 ;; In case we know the gud-marker-acc contains no partial annotations:
1678 (progn
1679 (setq output (gdb-concat-output output gud-marker-acc))
1680 (setq gud-marker-acc "")))
1681 output)))
1682
1683 (defun gdb-concat-output (so-far new)
1684 (if gdb-error
1685 (put-text-property 0 (length new) 'face font-lock-warning-face new))
1686 (let ((sink gdb-output-sink))
1687 (cond
1688 ((eq sink 'user) (concat so-far new))
1689 ((or (eq sink 'pre-emacs) (eq sink 'post-emacs)) so-far)
1690 ((eq sink 'emacs)
1691 (gdb-append-to-partial-output new)
1692 so-far)
1693 ((eq sink 'inferior)
1694 (gdb-append-to-inferior-io new)
1695 so-far)
1696 (t
1697 (gdb-resync)
1698 (error "Bogon output sink %S" sink)))))
1699
1700 (defun gdb-append-to-partial-output (string)
1701 (with-current-buffer (gdb-get-buffer-create 'gdb-partial-output-buffer)
1702 (goto-char (point-max))
1703 (insert string)))
1704
1705 (defun gdb-clear-partial-output ()
1706 (with-current-buffer (gdb-get-buffer-create 'gdb-partial-output-buffer)
1707 (erase-buffer)))
1708
1709 (defun gdb-append-to-inferior-io (string)
1710 (with-current-buffer (gdb-get-buffer-create 'gdb-inferior-io)
1711 (goto-char (point-max))
1712 (insert-before-markers string))
1713 (if (not (string-equal string ""))
1714 (gdb-display-buffer (gdb-get-buffer-create 'gdb-inferior-io) t)))
1715
1716 (defun gdb-clear-inferior-io ()
1717 (with-current-buffer (gdb-get-buffer-create 'gdb-inferior-io)
1718 (erase-buffer)))
1719 \f
1720
1721 ;; One trick is to have a command who's output is always available in a buffer
1722 ;; of it's own, and is always up to date. We build several buffers of this
1723 ;; type.
1724 ;;
1725 ;; There are two aspects to this: gdb has to tell us when the output for that
1726 ;; command might have changed, and we have to be able to run the command
1727 ;; behind the user's back.
1728 ;;
1729 ;; The output phasing associated with the variable gdb-output-sink
1730 ;; help us to run commands behind the user's back.
1731 ;;
1732 ;; Below is the code for specificly managing buffers of output from one
1733 ;; command.
1734 ;;
1735
1736 ;; The trigger function is suitable for use in the assoc GDB-ANNOTATION-RULES
1737 ;; It adds an input for the command we are tracking. It should be the
1738 ;; annotation rule binding of whatever gdb sends to tell us this command
1739 ;; might have changed it's output.
1740 ;;
1741 ;; NAME is the function name. DEMAND-PREDICATE tests if output is really needed.
1742 ;; GDB-COMMAND is a string of such. OUTPUT-HANDLER is the function bound to the
1743 ;; input in the input queue (see comment about ``gdb communications'' above).
1744
1745 (defmacro def-gdb-auto-update-trigger (name demand-predicate gdb-command
1746 output-handler)
1747 `(defun ,name (&optional ignored)
1748 (if (and ,demand-predicate
1749 (not (member ',name
1750 gdb-pending-triggers)))
1751 (progn
1752 (gdb-enqueue-input
1753 (list ,gdb-command ',output-handler))
1754 (push ',name gdb-pending-triggers)))))
1755
1756 (defmacro def-gdb-auto-update-handler (name trigger buf-key custom-defun)
1757 `(defun ,name ()
1758 (setq gdb-pending-triggers
1759 (delq ',trigger
1760 gdb-pending-triggers))
1761 (let ((buf (gdb-get-buffer ',buf-key)))
1762 (and buf
1763 (with-current-buffer buf
1764 (let* ((window (get-buffer-window buf 0))
1765 (start (window-start window))
1766 (p (window-point window))
1767 (buffer-read-only nil))
1768 (erase-buffer)
1769 (insert-buffer-substring (gdb-get-buffer-create
1770 'gdb-partial-output-buffer))
1771 (set-window-start window start)
1772 (set-window-point window p)))))
1773 ;; put customisation here
1774 (,custom-defun)))
1775
1776 (defmacro def-gdb-auto-updated-buffer (buffer-key
1777 trigger-name gdb-command
1778 output-handler-name custom-defun)
1779 `(progn
1780 (def-gdb-auto-update-trigger ,trigger-name
1781 ;; The demand predicate:
1782 (gdb-get-buffer ',buffer-key)
1783 ,gdb-command
1784 ,output-handler-name)
1785 (def-gdb-auto-update-handler ,output-handler-name
1786 ,trigger-name ,buffer-key ,custom-defun)))
1787
1788 \f
1789 ;;
1790 ;; Breakpoint buffer : This displays the output of `info breakpoints'.
1791 ;;
1792 (gdb-set-buffer-rules 'gdb-breakpoints-buffer
1793 'gdb-breakpoints-buffer-name
1794 'gdb-breakpoints-mode)
1795
1796 (def-gdb-auto-updated-buffer gdb-breakpoints-buffer
1797 ;; This defines the auto update rule for buffers of type
1798 ;; `gdb-breakpoints-buffer'.
1799 ;;
1800 ;; It defines a function to serve as the annotation handler that
1801 ;; handles the `foo-invalidated' message. That function is called:
1802 gdb-invalidate-breakpoints
1803 ;;
1804 ;; To update the buffer, this command is sent to gdb.
1805 "server info breakpoints\n"
1806 ;;
1807 ;; This also defines a function to be the handler for the output
1808 ;; from the command above. That function will copy the output into
1809 ;; the appropriately typed buffer. That function will be called:
1810 gdb-info-breakpoints-handler
1811 ;; buffer specific functions
1812 gdb-info-breakpoints-custom)
1813
1814 (defconst breakpoint-xpm-data
1815 "/* XPM */
1816 static char *magick[] = {
1817 /* columns rows colors chars-per-pixel */
1818 \"10 10 2 1\",
1819 \" c red\",
1820 \"+ c None\",
1821 /* pixels */
1822 \"+++ +++\",
1823 \"++ ++\",
1824 \"+ +\",
1825 \" \",
1826 \" \",
1827 \" \",
1828 \" \",
1829 \"+ +\",
1830 \"++ ++\",
1831 \"+++ +++\",
1832 };"
1833 "XPM data used for breakpoint icon.")
1834
1835 (defconst breakpoint-enabled-pbm-data
1836 "P1
1837 10 10\",
1838 0 0 0 0 1 1 1 1 0 0 0 0
1839 0 0 0 1 1 1 1 1 1 0 0 0
1840 0 0 1 1 1 1 1 1 1 1 0 0
1841 0 1 1 1 1 1 1 1 1 1 1 0
1842 0 1 1 1 1 1 1 1 1 1 1 0
1843 0 1 1 1 1 1 1 1 1 1 1 0
1844 0 1 1 1 1 1 1 1 1 1 1 0
1845 0 0 1 1 1 1 1 1 1 1 0 0
1846 0 0 0 1 1 1 1 1 1 0 0 0
1847 0 0 0 0 1 1 1 1 0 0 0 0"
1848 "PBM data used for enabled breakpoint icon.")
1849
1850 (defconst breakpoint-disabled-pbm-data
1851 "P1
1852 10 10\",
1853 0 0 1 0 1 0 1 0 0 0
1854 0 1 0 1 0 1 0 1 0 0
1855 1 0 1 0 1 0 1 0 1 0
1856 0 1 0 1 0 1 0 1 0 1
1857 1 0 1 0 1 0 1 0 1 0
1858 0 1 0 1 0 1 0 1 0 1
1859 1 0 1 0 1 0 1 0 1 0
1860 0 1 0 1 0 1 0 1 0 1
1861 0 0 1 0 1 0 1 0 1 0
1862 0 0 0 1 0 1 0 1 0 0"
1863 "PBM data used for disabled breakpoint icon.")
1864
1865 (defvar breakpoint-enabled-icon nil
1866 "Icon for enabled breakpoint in display margin.")
1867
1868 (defvar breakpoint-disabled-icon nil
1869 "Icon for disabled breakpoint in display margin.")
1870
1871 (and (display-images-p)
1872 ;; Bitmap for breakpoint in fringe
1873 (define-fringe-bitmap 'breakpoint
1874 "\x3c\x7e\xff\xff\xff\xff\x7e\x3c")
1875 ;; Bitmap for gud-overlay-arrow in fringe
1876 (define-fringe-bitmap 'hollow-right-triangle
1877 "\xe0\x90\x88\x84\x84\x88\x90\xe0"))
1878
1879 (defface breakpoint-enabled
1880 '((t
1881 :foreground "red1"
1882 :weight bold))
1883 "Face for enabled breakpoint icon in fringe."
1884 :group 'gud)
1885
1886 (defface breakpoint-disabled
1887 '((((class color) (min-colors 88)) :foreground "grey70")
1888 ;; Ensure that on low-color displays that we end up something visible.
1889 (((class color) (min-colors 8) (background light))
1890 :foreground "black")
1891 (((class color) (min-colors 8) (background dark))
1892 :foreground "white")
1893 (((type tty) (class mono))
1894 :inverse-video t)
1895 (t :background "gray"))
1896 "Face for disabled breakpoint icon in fringe."
1897 :group 'gud)
1898
1899 (defconst gdb-breakpoint-regexp
1900 "\\(?:\\([0-9]+\\).*?\\(?:point\\|catch\\s-+\\S-+\\)\\s-+\\S-+\\|\\([0-9]+\\.[0-9]+\\)\\)\\s-+\\(.\\)\\s-+")
1901
1902 ;; Put breakpoint icons in relevant margins (even those set in the GUD buffer).
1903 (defun gdb-info-breakpoints-custom ()
1904 (let ((flag) (bptno))
1905 ;; Remove all breakpoint-icons in source buffers but not assembler buffer.
1906 (dolist (buffer (buffer-list))
1907 (with-current-buffer buffer
1908 (if (and (memq gud-minor-mode '(gdba gdbmi))
1909 (not (string-match "\\` ?\\*.+\\*\\'" (buffer-name))))
1910 (gdb-remove-breakpoint-icons (point-min) (point-max)))))
1911 (with-current-buffer (gdb-get-buffer 'gdb-breakpoints-buffer)
1912 (save-excursion
1913 (let ((buffer-read-only nil))
1914 (goto-char (point-min))
1915 (while (< (point) (- (point-max) 1))
1916 (forward-line 1)
1917 (if (looking-at gdb-breakpoint-regexp)
1918 (progn
1919 (setq bptno (or (match-string 1) (match-string 2)))
1920 (setq flag (char-after (match-beginning 3)))
1921 (if (match-string 1)
1922 (setq gdb-parent-bptno-enabled (eq flag ?y)))
1923 (add-text-properties
1924 (match-beginning 3) (match-end 3)
1925 (if (eq flag ?y)
1926 '(face font-lock-warning-face)
1927 '(face font-lock-type-face)))
1928 (let ((bl (point))
1929 (el (line-end-position)))
1930 (if (re-search-forward " in \\(.*\\) at\\s-+" el t)
1931 (progn
1932 (add-text-properties
1933 (match-beginning 1) (match-end 1)
1934 '(face font-lock-function-name-face))
1935 (looking-at "\\(\\S-+\\):\\([0-9]+\\)")
1936 (let ((line (match-string 2))
1937 (file (match-string 1)))
1938 (add-text-properties bl el
1939 '(mouse-face highlight
1940 help-echo "mouse-2, RET: visit breakpoint"))
1941 (unless (file-exists-p file)
1942 (setq file (cdr (assoc bptno gdb-location-alist))))
1943 (if (and file
1944 (not (string-equal file "File not found")))
1945 (with-current-buffer
1946 (find-file-noselect file 'nowarn)
1947 (set (make-local-variable 'gud-minor-mode)
1948 'gdba)
1949 (set (make-local-variable 'tool-bar-map)
1950 gud-tool-bar-map)
1951 ;; Only want one breakpoint icon at each
1952 ;; location.
1953 (save-excursion
1954 (goto-line (string-to-number line))
1955 (gdb-put-breakpoint-icon (eq flag ?y) bptno)))
1956 (gdb-enqueue-input
1957 (list
1958 (concat gdb-server-prefix "list "
1959 (match-string-no-properties 1) ":1\n")
1960 'ignore))
1961 (gdb-enqueue-input
1962 (list (concat gdb-server-prefix "info source\n")
1963 `(lambda () (gdb-get-location
1964 ,bptno ,line ,flag)))))))
1965 (if (re-search-forward
1966 "<\\(\\(\\sw\\|[_.]\\)+\\)\\(\\+[0-9]+\\)?>"
1967 el t)
1968 (add-text-properties
1969 (match-beginning 1) (match-end 1)
1970 '(face font-lock-function-name-face))
1971 (end-of-line)
1972 (re-search-backward "\\s-\\(\\S-*\\)"
1973 bl t)
1974 (add-text-properties
1975 (match-beginning 1) (match-end 1)
1976 '(face font-lock-variable-name-face)))))))
1977 (end-of-line))))))
1978 (if (gdb-get-buffer 'gdb-assembler-buffer) (gdb-assembler-custom)))
1979
1980 (declare-function gud-remove "gdb-ui" t t) ; gud-def
1981 (declare-function gud-break "gdb-ui" t t) ; gud-def
1982
1983 (defun gdb-mouse-set-clear-breakpoint (event)
1984 "Set/clear breakpoint in left fringe/margin with mouse click."
1985 (interactive "e")
1986 (mouse-minibuffer-check event)
1987 (let ((posn (event-end event)))
1988 (if (buffer-file-name)
1989 (if (numberp (posn-point posn))
1990 (with-selected-window (posn-window posn)
1991 (save-excursion
1992 (goto-char (posn-point posn))
1993 (if (or (posn-object posn)
1994 (eq (car (fringe-bitmaps-at-pos (posn-point posn)))
1995 'breakpoint))
1996 (gud-remove nil)
1997 (gud-break nil)))))
1998 (posn-set-point posn))))
1999
2000 (defun gdb-mouse-toggle-breakpoint-margin (event)
2001 "Enable/disable breakpoint in left margin with mouse click."
2002 (interactive "e")
2003 (mouse-minibuffer-check event)
2004 (let ((posn (event-end event)))
2005 (if (numberp (posn-point posn))
2006 (with-selected-window (posn-window posn)
2007 (save-excursion
2008 (goto-char (posn-point posn))
2009 (if (posn-object posn)
2010 (let* ((bptno (get-text-property
2011 0 'gdb-bptno (car (posn-string posn)))))
2012 (string-match "\\([0-9+]\\)*" bptno)
2013 (gdb-enqueue-input
2014 (list
2015 (concat gdb-server-prefix
2016 (if (get-text-property
2017 0 'gdb-enabled (car (posn-string posn)))
2018 "disable "
2019 "enable ")
2020 (match-string 1 bptno) "\n")
2021 'ignore)))))))))
2022
2023 (defun gdb-mouse-toggle-breakpoint-fringe (event)
2024 "Enable/disable breakpoint in left fringe with mouse click."
2025 (interactive "e")
2026 (mouse-minibuffer-check event)
2027 (let* ((posn (event-end event))
2028 (pos (posn-point posn))
2029 obj)
2030 (when (numberp pos)
2031 (with-selected-window (posn-window posn)
2032 (save-excursion
2033 (set-buffer (window-buffer (selected-window)))
2034 (goto-char pos)
2035 (dolist (overlay (overlays-in pos pos))
2036 (when (overlay-get overlay 'put-break)
2037 (setq obj (overlay-get overlay 'before-string))))
2038 (when (stringp obj)
2039 (let* ((bptno (get-text-property 0 'gdb-bptno obj)))
2040 (string-match "\\([0-9+]\\)*" bptno)
2041 (gdb-enqueue-input
2042 (list
2043 (concat gdb-server-prefix
2044 (if (get-text-property 0 'gdb-enabled obj)
2045 "disable "
2046 "enable ")
2047 (match-string 1 bptno) "\n")
2048 'ignore)))))))))
2049
2050 (defun gdb-breakpoints-buffer-name ()
2051 (with-current-buffer gud-comint-buffer
2052 (concat "*breakpoints of " (gdb-get-target-string) "*")))
2053
2054 (defun gdb-display-breakpoints-buffer ()
2055 "Display status of user-settable breakpoints."
2056 (interactive)
2057 (gdb-display-buffer
2058 (gdb-get-buffer-create 'gdb-breakpoints-buffer) t))
2059
2060 (defun gdb-frame-breakpoints-buffer ()
2061 "Display status of user-settable breakpoints in a new frame."
2062 (interactive)
2063 (let ((special-display-regexps (append special-display-regexps '(".*")))
2064 (special-display-frame-alist gdb-frame-parameters))
2065 (display-buffer (gdb-get-buffer-create 'gdb-breakpoints-buffer))))
2066
2067 (defvar gdb-breakpoints-mode-map
2068 (let ((map (make-sparse-keymap))
2069 (menu (make-sparse-keymap "Breakpoints")))
2070 (define-key menu [quit] '("Quit" . gdb-delete-frame-or-window))
2071 (define-key menu [goto] '("Goto" . gdb-goto-breakpoint))
2072 (define-key menu [delete] '("Delete" . gdb-delete-breakpoint))
2073 (define-key menu [toggle] '("Toggle" . gdb-toggle-breakpoint))
2074 (suppress-keymap map)
2075 (define-key map [menu-bar breakpoints] (cons "Breakpoints" menu))
2076 (define-key map " " 'gdb-toggle-breakpoint)
2077 (define-key map "D" 'gdb-delete-breakpoint)
2078 ;; Don't bind "q" to kill-this-buffer as we need it for breakpoint icons.
2079 (define-key map "q" 'gdb-delete-frame-or-window)
2080 (define-key map "\r" 'gdb-goto-breakpoint)
2081 (define-key map [mouse-2] 'gdb-goto-breakpoint)
2082 (define-key map [follow-link] 'mouse-face)
2083 map))
2084
2085 (defun gdb-delete-frame-or-window ()
2086 "Delete frame if there is only one window. Otherwise delete the window."
2087 (interactive)
2088 (if (one-window-p) (delete-frame)
2089 (delete-window)))
2090
2091 (defun gdb-breakpoints-mode ()
2092 "Major mode for gdb breakpoints.
2093
2094 \\{gdb-breakpoints-mode-map}"
2095 (kill-all-local-variables)
2096 (setq major-mode 'gdb-breakpoints-mode)
2097 (setq mode-name "Breakpoints")
2098 (use-local-map gdb-breakpoints-mode-map)
2099 (setq buffer-read-only t)
2100 (run-mode-hooks 'gdb-breakpoints-mode-hook)
2101 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
2102 'gdb-invalidate-breakpoints
2103 'gdbmi-invalidate-breakpoints))
2104
2105 (defun gdb-toggle-breakpoint ()
2106 "Enable/disable breakpoint at current line."
2107 (interactive)
2108 (save-excursion
2109 (beginning-of-line 1)
2110 (if (looking-at gdb-breakpoint-regexp)
2111 (gdb-enqueue-input
2112 (list
2113 (concat gdb-server-prefix
2114 (if (eq ?y (char-after (match-beginning 3)))
2115 "disable "
2116 "enable ")
2117 (or (match-string 1) (match-string 2)) "\n") 'ignore))
2118 (error "Not recognized as break/watchpoint line"))))
2119
2120 (defun gdb-delete-breakpoint ()
2121 "Delete the breakpoint at current line."
2122 (interactive)
2123 (save-excursion
2124 (beginning-of-line 1)
2125 (if (looking-at gdb-breakpoint-regexp)
2126 (if (match-string 1)
2127 (gdb-enqueue-input
2128 (list
2129 (concat gdb-server-prefix "delete " (match-string 1) "\n")
2130 'ignore))
2131 (message-box "This breakpoint cannot be deleted on its own."))
2132 (error "Not recognized as break/watchpoint line"))))
2133
2134 (defun gdb-goto-breakpoint (&optional event)
2135 "Display the breakpoint location specified at current line."
2136 (interactive (list last-input-event))
2137 (if event (posn-set-point (event-end event)))
2138 (save-excursion
2139 (beginning-of-line 1)
2140 (if (looking-at "\\([0-9]+\\.?[0-9]*\\) .+ in .+ at\\s-+\\(\\S-+\\):\\([0-9]+\\)")
2141 (let ((bptno (match-string 1))
2142 (file (match-string 2))
2143 (line (match-string 3)))
2144 (save-selected-window
2145 (let* ((buffer (find-file-noselect
2146 (if (file-exists-p file) file
2147 (cdr (assoc bptno gdb-location-alist)))))
2148 (window (or (gdb-display-source-buffer buffer)
2149 (display-buffer buffer))))
2150 (setq gdb-source-window window)
2151 (with-current-buffer buffer
2152 (goto-line (string-to-number line))
2153 (set-window-point window (point))))))
2154 (error "No location specified."))))
2155 \f
2156
2157 ;; Frames buffer. This displays a perpetually correct bactracktrace
2158 ;; (from the command `where').
2159 ;;
2160 ;; Alas, if your stack is deep, it is costly.
2161 ;;
2162 (defcustom gdb-max-frames 40
2163 "Maximum number of frames displayed in call stack."
2164 :type 'integer
2165 :group 'gud
2166 :version "22.1")
2167
2168 (gdb-set-buffer-rules 'gdb-stack-buffer
2169 'gdb-stack-buffer-name
2170 'gdb-frames-mode)
2171
2172 (def-gdb-auto-updated-buffer gdb-stack-buffer
2173 gdb-invalidate-frames
2174 (concat "server info stack " (number-to-string gdb-max-frames) "\n")
2175 gdb-info-stack-handler
2176 gdb-info-stack-custom)
2177
2178 (defun gdb-info-stack-custom ()
2179 (with-current-buffer (gdb-get-buffer 'gdb-stack-buffer)
2180 (let (move-to)
2181 (save-excursion
2182 (unless (eq gdb-look-up-stack 'delete)
2183 (let ((buffer-read-only nil)
2184 bl el)
2185 (goto-char (point-min))
2186 (while (< (point) (point-max))
2187 (setq bl (line-beginning-position)
2188 el (line-end-position))
2189 (when (looking-at "#")
2190 (add-text-properties bl el
2191 '(mouse-face highlight
2192 help-echo "mouse-2, RET: Select frame")))
2193 (goto-char bl)
2194 (when (looking-at "^#\\([0-9]+\\)")
2195 (when (string-equal (match-string 1) gdb-frame-number)
2196 (if (> (car (window-fringes)) 0)
2197 (progn
2198 (or gdb-stack-position
2199 (setq gdb-stack-position (make-marker)))
2200 (set-marker gdb-stack-position (point))
2201 (setq move-to gdb-stack-position))
2202 (put-text-property bl (+ bl 4)
2203 'face '(:inverse-video t))
2204 (setq move-to bl)))
2205 (when (re-search-forward
2206 (concat
2207 (if (string-equal (match-string 1) "0") "" " in ")
2208 "\\([^ ]+\\) (") el t)
2209 (put-text-property (match-beginning 1) (match-end 1)
2210 'face font-lock-function-name-face)
2211 (setq bl (match-end 0))
2212 (while (re-search-forward "<\\([^>]+\\)>" el t)
2213 (put-text-property (match-beginning 1) (match-end 1)
2214 'face font-lock-function-name-face))
2215 (goto-char bl)
2216 (while (re-search-forward "\\(\\(\\sw\\|[_.]\\)+\\)=" el t)
2217 (put-text-property (match-beginning 1) (match-end 1)
2218 'face font-lock-variable-name-face))))
2219 (forward-line 1))
2220 (forward-line -1)
2221 (when (looking-at "(More stack frames follow...)")
2222 (add-text-properties (match-beginning 0) (match-end 0)
2223 '(mouse-face highlight
2224 gdb-max-frames t
2225 help-echo
2226 "mouse-2, RET: customize gdb-max-frames to see more frames")))))
2227 (when gdb-look-up-stack
2228 (goto-char (point-min))
2229 (when (re-search-forward "\\(\\S-+?\\):\\([0-9]+\\)" nil t)
2230 (let ((start (line-beginning-position))
2231 (file (match-string 1))
2232 (line (match-string 2)))
2233 (re-search-backward "^#*\\([0-9]+\\)" start t)
2234 (gdb-enqueue-input
2235 (list (concat gdb-server-prefix "frame "
2236 (match-string 1) "\n") 'gdb-set-hollow))
2237 (gdb-enqueue-input
2238 (list (concat gdb-server-prefix "frame 0\n") 'ignore))))))
2239 (when move-to
2240 (let ((window (get-buffer-window (current-buffer) 0)))
2241 (when window
2242 (with-selected-window window
2243 (goto-char move-to)
2244 (unless (pos-visible-in-window-p)
2245 (recenter '(center)))))))))
2246 (if (eq gdb-look-up-stack 'delete)
2247 (kill-buffer (gdb-get-buffer 'gdb-stack-buffer)))
2248 (setq gdb-look-up-stack nil))
2249
2250 (defun gdb-set-hollow ()
2251 (if gud-last-last-frame
2252 (with-current-buffer (gud-find-file (car gud-last-last-frame))
2253 (setq fringe-indicator-alist
2254 '((overlay-arrow . hollow-right-triangle))))))
2255
2256 (defun gdb-stack-buffer-name ()
2257 (with-current-buffer gud-comint-buffer
2258 (concat "*stack frames of " (gdb-get-target-string) "*")))
2259
2260 (defun gdb-display-stack-buffer ()
2261 "Display backtrace of current stack."
2262 (interactive)
2263 (gdb-display-buffer
2264 (gdb-get-buffer-create 'gdb-stack-buffer) t))
2265
2266 (defun gdb-frame-stack-buffer ()
2267 "Display backtrace of current stack in a new frame."
2268 (interactive)
2269 (let ((special-display-regexps (append special-display-regexps '(".*")))
2270 (special-display-frame-alist gdb-frame-parameters))
2271 (display-buffer (gdb-get-buffer-create 'gdb-stack-buffer))))
2272
2273 (defvar gdb-frames-mode-map
2274 (let ((map (make-sparse-keymap)))
2275 (suppress-keymap map)
2276 (define-key map "q" 'kill-this-buffer)
2277 (define-key map "\r" 'gdb-frames-select)
2278 (define-key map [mouse-2] 'gdb-frames-select)
2279 (define-key map [follow-link] 'mouse-face)
2280 map))
2281
2282 (defun gdb-frames-mode ()
2283 "Major mode for gdb call stack.
2284
2285 \\{gdb-frames-mode-map}"
2286 (kill-all-local-variables)
2287 (setq major-mode 'gdb-frames-mode)
2288 (setq mode-name "Frames")
2289 (setq gdb-stack-position nil)
2290 (add-to-list 'overlay-arrow-variable-list 'gdb-stack-position)
2291 (setq truncate-lines t) ;; Make it easier to see overlay arrow.
2292 (setq buffer-read-only t)
2293 (use-local-map gdb-frames-mode-map)
2294 (run-mode-hooks 'gdb-frames-mode-hook)
2295 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
2296 'gdb-invalidate-frames
2297 'gdbmi-invalidate-frames))
2298
2299 (defun gdb-get-frame-number ()
2300 (save-excursion
2301 (end-of-line)
2302 (let* ((start (line-beginning-position))
2303 (pos (re-search-backward "^#*\\([0-9]+\\)" start t))
2304 (n (or (and pos (match-string 1)) "0")))
2305 n)))
2306
2307 (defun gdb-frames-select (&optional event)
2308 "Select the frame and display the relevant source."
2309 (interactive (list last-input-event))
2310 (if event (posn-set-point (event-end event)))
2311 (if (get-text-property (point) 'gdb-max-frames)
2312 (progn
2313 (message-box "After setting gdb-max-frames, you need to enter\n\
2314 another GDB command e.g pwd, to see new frames")
2315 (customize-variable-other-window 'gdb-max-frames))
2316 (gdb-enqueue-input
2317 (list (concat gdb-server-prefix "frame "
2318 (gdb-get-frame-number) "\n") 'ignore))))
2319 \f
2320
2321 ;; Threads buffer. This displays a selectable thread list.
2322 ;;
2323 (gdb-set-buffer-rules 'gdb-threads-buffer
2324 'gdb-threads-buffer-name
2325 'gdb-threads-mode)
2326
2327 (def-gdb-auto-updated-buffer gdb-threads-buffer
2328 gdb-invalidate-threads
2329 (concat gdb-server-prefix "info threads\n")
2330 gdb-info-threads-handler
2331 gdb-info-threads-custom)
2332
2333 (defun gdb-info-threads-custom ()
2334 (with-current-buffer (gdb-get-buffer 'gdb-threads-buffer)
2335 (let ((buffer-read-only nil))
2336 (save-excursion
2337 (goto-char (point-min))
2338 (while (< (point) (point-max))
2339 (unless (looking-at "No ")
2340 (add-text-properties (line-beginning-position) (line-end-position)
2341 '(mouse-face highlight
2342 help-echo "mouse-2, RET: select thread")))
2343 (forward-line 1))))))
2344
2345 (defun gdb-threads-buffer-name ()
2346 (with-current-buffer gud-comint-buffer
2347 (concat "*threads of " (gdb-get-target-string) "*")))
2348
2349 (defun gdb-display-threads-buffer ()
2350 "Display IDs of currently known threads."
2351 (interactive)
2352 (gdb-display-buffer
2353 (gdb-get-buffer-create 'gdb-threads-buffer) t))
2354
2355 (defun gdb-frame-threads-buffer ()
2356 "Display IDs of currently known threads in a new frame."
2357 (interactive)
2358 (let ((special-display-regexps (append special-display-regexps '(".*")))
2359 (special-display-frame-alist gdb-frame-parameters))
2360 (display-buffer (gdb-get-buffer-create 'gdb-threads-buffer))))
2361
2362 (defvar gdb-threads-mode-map
2363 (let ((map (make-sparse-keymap)))
2364 (suppress-keymap map)
2365 (define-key map "q" 'kill-this-buffer)
2366 (define-key map "\r" 'gdb-threads-select)
2367 (define-key map [mouse-2] 'gdb-threads-select)
2368 (define-key map [follow-link] 'mouse-face)
2369 map))
2370
2371 (defvar gdb-threads-font-lock-keywords
2372 '((") +\\([^ ]+\\) (" (1 font-lock-function-name-face))
2373 ("in \\([^ ]+\\) (" (1 font-lock-function-name-face))
2374 ("\\(\\(\\sw\\|[_.]\\)+\\)=" (1 font-lock-variable-name-face)))
2375 "Font lock keywords used in `gdb-threads-mode'.")
2376
2377 (defun gdb-threads-mode ()
2378 "Major mode for gdb threads.
2379
2380 \\{gdb-threads-mode-map}"
2381 (kill-all-local-variables)
2382 (setq major-mode 'gdb-threads-mode)
2383 (setq mode-name "Threads")
2384 (setq buffer-read-only t)
2385 (use-local-map gdb-threads-mode-map)
2386 (set (make-local-variable 'font-lock-defaults)
2387 '(gdb-threads-font-lock-keywords))
2388 (run-mode-hooks 'gdb-threads-mode-hook)
2389 'gdb-invalidate-threads)
2390
2391 (defun gdb-get-thread-number ()
2392 (save-excursion
2393 (re-search-backward "^\\s-*\\([0-9]*\\)" nil t)
2394 (match-string-no-properties 1)))
2395
2396 (defun gdb-threads-select (&optional event)
2397 "Select the thread and display the relevant source."
2398 (interactive (list last-input-event))
2399 (if event (posn-set-point (event-end event)))
2400 (gdb-enqueue-input
2401 (list (concat gdb-server-prefix "thread "
2402 (gdb-get-thread-number) "\n") 'ignore))
2403 (gud-display-frame))
2404 \f
2405
2406 ;; Registers buffer.
2407 ;;
2408 (defcustom gdb-all-registers nil
2409 "Non-nil means include floating-point registers."
2410 :type 'boolean
2411 :group 'gud
2412 :version "22.1")
2413
2414 (gdb-set-buffer-rules 'gdb-registers-buffer
2415 'gdb-registers-buffer-name
2416 'gdb-registers-mode)
2417
2418 (def-gdb-auto-updated-buffer gdb-registers-buffer
2419 gdb-invalidate-registers
2420 (concat
2421 gdb-server-prefix "info " (if gdb-all-registers "all-") "registers\n")
2422 gdb-info-registers-handler
2423 gdb-info-registers-custom)
2424
2425 (defun gdb-info-registers-custom ()
2426 (with-current-buffer (gdb-get-buffer 'gdb-registers-buffer)
2427 (save-excursion
2428 (let ((buffer-read-only nil)
2429 start end)
2430 (goto-char (point-min))
2431 (while (< (point) (point-max))
2432 (setq start (line-beginning-position))
2433 (setq end (line-end-position))
2434 (when (looking-at "^[^ ]+")
2435 (unless (string-equal (match-string 0) "The")
2436 (put-text-property start (match-end 0)
2437 'face font-lock-variable-name-face)
2438 (add-text-properties start end
2439 '(help-echo "mouse-2: edit value"
2440 mouse-face highlight))))
2441 (forward-line 1))))))
2442
2443 (defun gdb-edit-register-value (&optional event)
2444 (interactive (list last-input-event))
2445 (save-excursion
2446 (if event (posn-set-point (event-end event)))
2447 (beginning-of-line)
2448 (let* ((register (current-word))
2449 (value (read-string (format "New value (%s): " register))))
2450 (gdb-enqueue-input
2451 (list (concat gdb-server-prefix "set $" register "=" value "\n")
2452 'ignore)))))
2453
2454 (defvar gdb-registers-mode-map
2455 (let ((map (make-sparse-keymap)))
2456 (suppress-keymap map)
2457 (define-key map "\r" 'gdb-edit-register-value)
2458 (define-key map [mouse-2] 'gdb-edit-register-value)
2459 (define-key map " " 'gdb-all-registers)
2460 (define-key map "q" 'kill-this-buffer)
2461 map))
2462
2463 (defun gdb-registers-mode ()
2464 "Major mode for gdb registers.
2465
2466 \\{gdb-registers-mode-map}"
2467 (kill-all-local-variables)
2468 (setq major-mode 'gdb-registers-mode)
2469 (setq mode-name "Registers")
2470 (setq buffer-read-only t)
2471 (use-local-map gdb-registers-mode-map)
2472 (run-mode-hooks 'gdb-registers-mode-hook)
2473 (if (string-equal gdb-version "pre-6.4")
2474 (progn
2475 (if gdb-all-registers (setq mode-name "Registers:All"))
2476 'gdb-invalidate-registers)
2477 'gdb-invalidate-registers-1))
2478
2479 (defun gdb-registers-buffer-name ()
2480 (with-current-buffer gud-comint-buffer
2481 (concat "*registers of " (gdb-get-target-string) "*")))
2482
2483 (defun gdb-display-registers-buffer ()
2484 "Display integer register contents."
2485 (interactive)
2486 (gdb-display-buffer
2487 (gdb-get-buffer-create 'gdb-registers-buffer) t))
2488
2489 (defun gdb-frame-registers-buffer ()
2490 "Display integer register contents in a new frame."
2491 (interactive)
2492 (let ((special-display-regexps (append special-display-regexps '(".*")))
2493 (special-display-frame-alist gdb-frame-parameters))
2494 (display-buffer (gdb-get-buffer-create 'gdb-registers-buffer))))
2495
2496 (defun gdb-all-registers ()
2497 "Toggle the display of floating-point registers (pre GDB 6.4 only)."
2498 (interactive)
2499 (when (string-equal gdb-version "pre-6.4")
2500 (if gdb-all-registers
2501 (progn
2502 (setq gdb-all-registers nil)
2503 (with-current-buffer (gdb-get-buffer-create 'gdb-registers-buffer)
2504 (setq mode-name "Registers")))
2505 (setq gdb-all-registers t)
2506 (with-current-buffer (gdb-get-buffer-create 'gdb-registers-buffer)
2507 (setq mode-name "Registers:All")))
2508 (message (format "Display of floating-point registers %sabled"
2509 (if gdb-all-registers "en" "dis")))
2510 (gdb-invalidate-registers)))
2511 \f
2512
2513 ;; Memory buffer.
2514 ;;
2515 (defcustom gdb-memory-repeat-count 32
2516 "Number of data items in memory window."
2517 :type 'integer
2518 :group 'gud
2519 :version "22.1")
2520
2521 (defcustom gdb-memory-format "x"
2522 "Display format of data items in memory window."
2523 :type '(choice (const :tag "Hexadecimal" "x")
2524 (const :tag "Signed decimal" "d")
2525 (const :tag "Unsigned decimal" "u")
2526 (const :tag "Octal" "o")
2527 (const :tag "Binary" "t"))
2528 :group 'gud
2529 :version "22.1")
2530
2531 (defcustom gdb-memory-unit "w"
2532 "Unit size of data items in memory window."
2533 :type '(choice (const :tag "Byte" "b")
2534 (const :tag "Halfword" "h")
2535 (const :tag "Word" "w")
2536 (const :tag "Giant word" "g"))
2537 :group 'gud
2538 :version "22.1")
2539
2540 (gdb-set-buffer-rules 'gdb-memory-buffer
2541 'gdb-memory-buffer-name
2542 'gdb-memory-mode)
2543
2544 (def-gdb-auto-updated-buffer gdb-memory-buffer
2545 gdb-invalidate-memory
2546 (concat gdb-server-prefix "x/" (number-to-string gdb-memory-repeat-count)
2547 gdb-memory-format gdb-memory-unit " " gdb-memory-address "\n")
2548 gdb-read-memory-handler
2549 gdb-read-memory-custom)
2550
2551 (defun gdb-read-memory-custom ()
2552 (save-excursion
2553 (goto-char (point-min))
2554 (if (looking-at "0x[[:xdigit:]]+")
2555 (setq gdb-memory-address (match-string 0)))))
2556
2557 (defvar gdb-memory-mode-map
2558 (let ((map (make-sparse-keymap)))
2559 (suppress-keymap map)
2560 (define-key map "q" 'kill-this-buffer)
2561 map))
2562
2563 (defun gdb-memory-set-address (event)
2564 "Set the start memory address."
2565 (interactive "e")
2566 (save-selected-window
2567 (select-window (posn-window (event-start event)))
2568 (let ((arg (read-from-minibuffer "Memory address: ")))
2569 (setq gdb-memory-address arg))
2570 (gdb-invalidate-memory)))
2571
2572 (defun gdb-memory-set-repeat-count (event)
2573 "Set the number of data items in memory window."
2574 (interactive "e")
2575 (save-selected-window
2576 (select-window (posn-window (event-start event)))
2577 (let* ((arg (read-from-minibuffer "Repeat count: "))
2578 (count (string-to-number arg)))
2579 (if (<= count 0)
2580 (error "Positive numbers only")
2581 (customize-set-variable 'gdb-memory-repeat-count count)
2582 (gdb-invalidate-memory)))))
2583
2584 (defun gdb-memory-format-binary ()
2585 "Set the display format to binary."
2586 (interactive)
2587 (customize-set-variable 'gdb-memory-format "t")
2588 (gdb-invalidate-memory))
2589
2590 (defun gdb-memory-format-octal ()
2591 "Set the display format to octal."
2592 (interactive)
2593 (customize-set-variable 'gdb-memory-format "o")
2594 (gdb-invalidate-memory))
2595
2596 (defun gdb-memory-format-unsigned ()
2597 "Set the display format to unsigned decimal."
2598 (interactive)
2599 (customize-set-variable 'gdb-memory-format "u")
2600 (gdb-invalidate-memory))
2601
2602 (defun gdb-memory-format-signed ()
2603 "Set the display format to decimal."
2604 (interactive)
2605 (customize-set-variable 'gdb-memory-format "d")
2606 (gdb-invalidate-memory))
2607
2608 (defun gdb-memory-format-hexadecimal ()
2609 "Set the display format to hexadecimal."
2610 (interactive)
2611 (customize-set-variable 'gdb-memory-format "x")
2612 (gdb-invalidate-memory))
2613
2614 (defvar gdb-memory-format-map
2615 (let ((map (make-sparse-keymap)))
2616 (define-key map [header-line down-mouse-3] 'gdb-memory-format-menu-1)
2617 map)
2618 "Keymap to select format in the header line.")
2619
2620 (defvar gdb-memory-format-menu (make-sparse-keymap "Format")
2621 "Menu of display formats in the header line.")
2622
2623 (define-key gdb-memory-format-menu [binary]
2624 '(menu-item "Binary" gdb-memory-format-binary
2625 :button (:radio . (equal gdb-memory-format "t"))))
2626 (define-key gdb-memory-format-menu [octal]
2627 '(menu-item "Octal" gdb-memory-format-octal
2628 :button (:radio . (equal gdb-memory-format "o"))))
2629 (define-key gdb-memory-format-menu [unsigned]
2630 '(menu-item "Unsigned Decimal" gdb-memory-format-unsigned
2631 :button (:radio . (equal gdb-memory-format "u"))))
2632 (define-key gdb-memory-format-menu [signed]
2633 '(menu-item "Signed Decimal" gdb-memory-format-signed
2634 :button (:radio . (equal gdb-memory-format "d"))))
2635 (define-key gdb-memory-format-menu [hexadecimal]
2636 '(menu-item "Hexadecimal" gdb-memory-format-hexadecimal
2637 :button (:radio . (equal gdb-memory-format "x"))))
2638
2639 (defun gdb-memory-format-menu (event)
2640 (interactive "@e")
2641 (x-popup-menu event gdb-memory-format-menu))
2642
2643 (defun gdb-memory-format-menu-1 (event)
2644 (interactive "e")
2645 (save-selected-window
2646 (select-window (posn-window (event-start event)))
2647 (let* ((selection (gdb-memory-format-menu event))
2648 (binding (and selection (lookup-key gdb-memory-format-menu
2649 (vector (car selection))))))
2650 (if binding (call-interactively binding)))))
2651
2652 (defun gdb-memory-unit-giant ()
2653 "Set the unit size to giant words (eight bytes)."
2654 (interactive)
2655 (customize-set-variable 'gdb-memory-unit "g")
2656 (gdb-invalidate-memory))
2657
2658 (defun gdb-memory-unit-word ()
2659 "Set the unit size to words (four bytes)."
2660 (interactive)
2661 (customize-set-variable 'gdb-memory-unit "w")
2662 (gdb-invalidate-memory))
2663
2664 (defun gdb-memory-unit-halfword ()
2665 "Set the unit size to halfwords (two bytes)."
2666 (interactive)
2667 (customize-set-variable 'gdb-memory-unit "h")
2668 (gdb-invalidate-memory))
2669
2670 (defun gdb-memory-unit-byte ()
2671 "Set the unit size to bytes."
2672 (interactive)
2673 (customize-set-variable 'gdb-memory-unit "b")
2674 (gdb-invalidate-memory))
2675
2676 (defvar gdb-memory-unit-map
2677 (let ((map (make-sparse-keymap)))
2678 (define-key map [header-line down-mouse-3] 'gdb-memory-unit-menu-1)
2679 map)
2680 "Keymap to select units in the header line.")
2681
2682 (defvar gdb-memory-unit-menu (make-sparse-keymap "Unit")
2683 "Menu of units in the header line.")
2684
2685 (define-key gdb-memory-unit-menu [giantwords]
2686 '(menu-item "Giant words" gdb-memory-unit-giant
2687 :button (:radio . (equal gdb-memory-unit "g"))))
2688 (define-key gdb-memory-unit-menu [words]
2689 '(menu-item "Words" gdb-memory-unit-word
2690 :button (:radio . (equal gdb-memory-unit "w"))))
2691 (define-key gdb-memory-unit-menu [halfwords]
2692 '(menu-item "Halfwords" gdb-memory-unit-halfword
2693 :button (:radio . (equal gdb-memory-unit "h"))))
2694 (define-key gdb-memory-unit-menu [bytes]
2695 '(menu-item "Bytes" gdb-memory-unit-byte
2696 :button (:radio . (equal gdb-memory-unit "b"))))
2697
2698 (defun gdb-memory-unit-menu (event)
2699 (interactive "@e")
2700 (x-popup-menu event gdb-memory-unit-menu))
2701
2702 (defun gdb-memory-unit-menu-1 (event)
2703 (interactive "e")
2704 (save-selected-window
2705 (select-window (posn-window (event-start event)))
2706 (let* ((selection (gdb-memory-unit-menu event))
2707 (binding (and selection (lookup-key gdb-memory-unit-menu
2708 (vector (car selection))))))
2709 (if binding (call-interactively binding)))))
2710
2711 ;;from make-mode-line-mouse-map
2712 (defun gdb-make-header-line-mouse-map (mouse function) "\
2713 Return a keymap with single entry for mouse key MOUSE on the header line.
2714 MOUSE is defined to run function FUNCTION with no args in the buffer
2715 corresponding to the mode line clicked."
2716 (let ((map (make-sparse-keymap)))
2717 (define-key map (vector 'header-line mouse) function)
2718 (define-key map (vector 'header-line 'down-mouse-1) 'ignore)
2719 map))
2720
2721 (defvar gdb-memory-font-lock-keywords
2722 '(;; <__function.name+n>
2723 ("<\\(\\(\\sw\\|[_.]\\)+\\)\\(\\+[0-9]+\\)?>" (1 font-lock-function-name-face))
2724 )
2725 "Font lock keywords used in `gdb-memory-mode'.")
2726
2727 (defun gdb-memory-mode ()
2728 "Major mode for examining memory.
2729
2730 \\{gdb-memory-mode-map}"
2731 (kill-all-local-variables)
2732 (setq major-mode 'gdb-memory-mode)
2733 (setq mode-name "Memory")
2734 (setq buffer-read-only t)
2735 (use-local-map gdb-memory-mode-map)
2736 (setq header-line-format
2737 '(:eval
2738 (concat
2739 "Read address["
2740 (propertize
2741 "-"
2742 'face font-lock-warning-face
2743 'help-echo "mouse-1: decrement address"
2744 'mouse-face 'mode-line-highlight
2745 'local-map
2746 (gdb-make-header-line-mouse-map
2747 'mouse-1
2748 (lambda () (interactive)
2749 (let ((gdb-memory-address
2750 ;; Let GDB do the arithmetic.
2751 (concat
2752 gdb-memory-address " - "
2753 (number-to-string
2754 (* gdb-memory-repeat-count
2755 (cond ((string= gdb-memory-unit "b") 1)
2756 ((string= gdb-memory-unit "h") 2)
2757 ((string= gdb-memory-unit "w") 4)
2758 ((string= gdb-memory-unit "g") 8)))))))
2759 (gdb-invalidate-memory)))))
2760 "|"
2761 (propertize "+"
2762 'face font-lock-warning-face
2763 'help-echo "mouse-1: increment address"
2764 'mouse-face 'mode-line-highlight
2765 'local-map (gdb-make-header-line-mouse-map
2766 'mouse-1
2767 (lambda () (interactive)
2768 (let ((gdb-memory-address nil))
2769 (gdb-invalidate-memory)))))
2770 "]: "
2771 (propertize gdb-memory-address
2772 'face font-lock-warning-face
2773 'help-echo "mouse-1: set memory address"
2774 'mouse-face 'mode-line-highlight
2775 'local-map (gdb-make-header-line-mouse-map
2776 'mouse-1
2777 #'gdb-memory-set-address))
2778 " Repeat Count: "
2779 (propertize (number-to-string gdb-memory-repeat-count)
2780 'face font-lock-warning-face
2781 'help-echo "mouse-1: set repeat count"
2782 'mouse-face 'mode-line-highlight
2783 'local-map (gdb-make-header-line-mouse-map
2784 'mouse-1
2785 #'gdb-memory-set-repeat-count))
2786 " Display Format: "
2787 (propertize gdb-memory-format
2788 'face font-lock-warning-face
2789 'help-echo "mouse-3: select display format"
2790 'mouse-face 'mode-line-highlight
2791 'local-map gdb-memory-format-map)
2792 " Unit Size: "
2793 (propertize gdb-memory-unit
2794 'face font-lock-warning-face
2795 'help-echo "mouse-3: select unit size"
2796 'mouse-face 'mode-line-highlight
2797 'local-map gdb-memory-unit-map))))
2798 (set (make-local-variable 'font-lock-defaults)
2799 '(gdb-memory-font-lock-keywords))
2800 (run-mode-hooks 'gdb-memory-mode-hook)
2801 'gdb-invalidate-memory)
2802
2803 (defun gdb-memory-buffer-name ()
2804 (with-current-buffer gud-comint-buffer
2805 (concat "*memory of " (gdb-get-target-string) "*")))
2806
2807 (defun gdb-display-memory-buffer ()
2808 "Display memory contents."
2809 (interactive)
2810 (gdb-display-buffer
2811 (gdb-get-buffer-create 'gdb-memory-buffer) t))
2812
2813 (defun gdb-frame-memory-buffer ()
2814 "Display memory contents in a new frame."
2815 (interactive)
2816 (let* ((special-display-regexps (append special-display-regexps '(".*")))
2817 (special-display-frame-alist
2818 (cons '(left-fringe . 0)
2819 (cons '(right-fringe . 0)
2820 (cons '(width . 83) gdb-frame-parameters)))))
2821 (display-buffer (gdb-get-buffer-create 'gdb-memory-buffer))))
2822 \f
2823
2824 ;; Locals buffer.
2825 ;;
2826 (gdb-set-buffer-rules 'gdb-locals-buffer
2827 'gdb-locals-buffer-name
2828 'gdb-locals-mode)
2829
2830 (def-gdb-auto-update-trigger gdb-invalidate-locals
2831 (gdb-get-buffer 'gdb-locals-buffer)
2832 "server info locals\n"
2833 gdb-info-locals-handler)
2834
2835 (defvar gdb-locals-watch-map
2836 (let ((map (make-sparse-keymap)))
2837 (suppress-keymap map)
2838 (define-key map "\r" (lambda () (interactive)
2839 (beginning-of-line)
2840 (gud-watch)))
2841 (define-key map [mouse-2] (lambda (event) (interactive "e")
2842 (mouse-set-point event)
2843 (beginning-of-line)
2844 (gud-watch)))
2845 map)
2846 "Keymap to create watch expression of a complex data type local variable.")
2847
2848 (defconst gdb-struct-string
2849 (concat (propertize "[struct/union]"
2850 'mouse-face 'highlight
2851 'help-echo "mouse-2: create watch expression"
2852 'local-map gdb-locals-watch-map) "\n"))
2853
2854 (defconst gdb-array-string
2855 (concat " " (propertize "[array]"
2856 'mouse-face 'highlight
2857 'help-echo "mouse-2: create watch expression"
2858 'local-map gdb-locals-watch-map) "\n"))
2859
2860 ;; Abbreviate for arrays and structures.
2861 ;; These can be expanded using gud-display.
2862 (defun gdb-info-locals-handler ()
2863 (setq gdb-pending-triggers (delq 'gdb-invalidate-locals
2864 gdb-pending-triggers))
2865 (let ((buf (gdb-get-buffer 'gdb-partial-output-buffer)))
2866 (with-current-buffer buf
2867 (goto-char (point-min))
2868 (while (re-search-forward "^[ }].*\n" nil t)
2869 (replace-match "" nil nil))
2870 (goto-char (point-min))
2871 (while (re-search-forward "{\\(.*=.*\n\\|\n\\)" nil t)
2872 (replace-match gdb-struct-string nil nil))
2873 (goto-char (point-min))
2874 (while (re-search-forward "\\s-*{.*\n" nil t)
2875 (replace-match gdb-array-string nil nil))))
2876 (let ((buf (gdb-get-buffer 'gdb-locals-buffer)))
2877 (and buf
2878 (with-current-buffer buf
2879 (let* ((window (get-buffer-window buf 0))
2880 (start (window-start window))
2881 (p (window-point window))
2882 (buffer-read-only nil))
2883 (erase-buffer)
2884 (insert-buffer-substring (gdb-get-buffer-create
2885 'gdb-partial-output-buffer))
2886 (set-window-start window start)
2887 (set-window-point window p))
2888 )))
2889 (run-hooks 'gdb-info-locals-hook))
2890
2891 (defvar gdb-locals-mode-map
2892 (let ((map (make-sparse-keymap)))
2893 (suppress-keymap map)
2894 (define-key map "q" 'kill-this-buffer)
2895 map))
2896
2897 (defun gdb-locals-mode ()
2898 "Major mode for gdb locals.
2899
2900 \\{gdb-locals-mode-map}"
2901 (kill-all-local-variables)
2902 (setq major-mode 'gdb-locals-mode)
2903 (setq mode-name (concat "Locals:" gdb-selected-frame))
2904 (setq buffer-read-only t)
2905 (use-local-map gdb-locals-mode-map)
2906 (set (make-local-variable 'font-lock-defaults)
2907 '(gdb-locals-font-lock-keywords))
2908 (run-mode-hooks 'gdb-locals-mode-hook)
2909 (if (and (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
2910 (string-equal gdb-version "pre-6.4"))
2911 'gdb-invalidate-locals
2912 'gdb-invalidate-locals-1))
2913
2914 (defun gdb-locals-buffer-name ()
2915 (with-current-buffer gud-comint-buffer
2916 (concat "*locals of " (gdb-get-target-string) "*")))
2917
2918 (defun gdb-display-locals-buffer ()
2919 "Display local variables of current stack and their values."
2920 (interactive)
2921 (gdb-display-buffer
2922 (gdb-get-buffer-create 'gdb-locals-buffer) t))
2923
2924 (defun gdb-frame-locals-buffer ()
2925 "Display local variables of current stack and their values in a new frame."
2926 (interactive)
2927 (let ((special-display-regexps (append special-display-regexps '(".*")))
2928 (special-display-frame-alist gdb-frame-parameters))
2929 (display-buffer (gdb-get-buffer-create 'gdb-locals-buffer))))
2930 \f
2931
2932 ;;;; Window management
2933 (defun gdb-display-buffer (buf dedicated &optional size)
2934 (let ((answer (get-buffer-window buf 0))
2935 (must-split nil))
2936 (if answer
2937 (display-buffer buf nil 0) ;Deiconify the frame if necessary.
2938 ;; The buffer is not yet displayed.
2939 (pop-to-buffer gud-comint-buffer) ;Select the right frame.
2940 (let ((window (get-lru-window)))
2941 (if (and window
2942 (not (memq window `(,(get-buffer-window gud-comint-buffer)
2943 ,gdb-source-window))))
2944 (progn
2945 (set-window-buffer window buf)
2946 (setq answer window))
2947 (setq must-split t)))
2948 (if must-split
2949 (let* ((largest (get-largest-window))
2950 (cur-size (window-height largest))
2951 (new-size (and size (< size cur-size) (- cur-size size))))
2952 (setq answer (split-window largest new-size))
2953 (set-window-buffer answer buf)
2954 (set-window-dedicated-p answer dedicated)))
2955 answer)))
2956
2957 \f
2958 ;;; Shared keymap initialization:
2959
2960 (let ((menu (make-sparse-keymap "GDB-Windows")))
2961 (define-key gud-menu-map [displays]
2962 `(menu-item "GDB-Windows" ,menu
2963 :visible (memq gud-minor-mode '(gdbmi gdba))))
2964 (define-key menu [gdb] '("Gdb" . gdb-display-gdb-buffer))
2965 (define-key menu [threads] '("Threads" . gdb-display-threads-buffer))
2966 (define-key menu [inferior]
2967 '(menu-item "Separate IO" gdb-display-separate-io-buffer
2968 :enable gdb-use-separate-io-buffer))
2969 (define-key menu [memory] '("Memory" . gdb-display-memory-buffer))
2970 (define-key menu [registers] '("Registers" . gdb-display-registers-buffer))
2971 (define-key menu [disassembly]
2972 '("Disassembly" . gdb-display-assembler-buffer))
2973 (define-key menu [breakpoints]
2974 '("Breakpoints" . gdb-display-breakpoints-buffer))
2975 (define-key menu [locals] '("Locals" . gdb-display-locals-buffer))
2976 (define-key menu [frames] '("Stack" . gdb-display-stack-buffer)))
2977
2978 (let ((menu (make-sparse-keymap "GDB-Frames")))
2979 (define-key gud-menu-map [frames]
2980 `(menu-item "GDB-Frames" ,menu
2981 :visible (memq gud-minor-mode '(gdbmi gdba))))
2982 (define-key menu [gdb] '("Gdb" . gdb-frame-gdb-buffer))
2983 (define-key menu [threads] '("Threads" . gdb-frame-threads-buffer))
2984 (define-key menu [memory] '("Memory" . gdb-frame-memory-buffer))
2985 (define-key menu [inferior]
2986 '(menu-item "Separate IO" gdb-frame-separate-io-buffer
2987 :enable gdb-use-separate-io-buffer))
2988 (define-key menu [registers] '("Registers" . gdb-frame-registers-buffer))
2989 (define-key menu [disassembly] '("Disassembly" . gdb-frame-assembler-buffer))
2990 (define-key menu [breakpoints]
2991 '("Breakpoints" . gdb-frame-breakpoints-buffer))
2992 (define-key menu [locals] '("Locals" . gdb-frame-locals-buffer))
2993 (define-key menu [frames] '("Stack" . gdb-frame-stack-buffer)))
2994
2995 (let ((menu (make-sparse-keymap "GDB-UI/MI")))
2996 (define-key gud-menu-map [ui]
2997 `(menu-item (if (eq gud-minor-mode 'gdba) "GDB-UI" "GDB-MI")
2998 ,menu :visible (memq gud-minor-mode '(gdbmi gdba))))
2999 (define-key menu [gdb-find-source-frame]
3000 '(menu-item "Look For Source Frame" gdb-find-source-frame
3001 :visible (eq gud-minor-mode 'gdba)
3002 :help "Toggle look for source frame."
3003 :button (:toggle . gdb-find-source-frame)))
3004 (define-key menu [gdb-use-separate-io]
3005 '(menu-item "Separate IO" gdb-use-separate-io-buffer
3006 :visible (eq gud-minor-mode 'gdba)
3007 :help "Toggle separate IO for debugged program."
3008 :button (:toggle . gdb-use-separate-io-buffer)))
3009 (define-key menu [gdb-many-windows]
3010 '(menu-item "Display Other Windows" gdb-many-windows
3011 :help "Toggle display of locals, stack and breakpoint information"
3012 :button (:toggle . gdb-many-windows)))
3013 (define-key menu [gdb-restore-windows]
3014 '(menu-item "Restore Window Layout" gdb-restore-windows
3015 :help "Restore standard layout for debug session.")))
3016
3017 (defun gdb-frame-gdb-buffer ()
3018 "Display GUD buffer in a new frame."
3019 (interactive)
3020 (let ((special-display-regexps (append special-display-regexps '(".*")))
3021 (special-display-frame-alist
3022 (remove '(menu-bar-lines) (remove '(tool-bar-lines)
3023 gdb-frame-parameters)))
3024 (same-window-regexps nil))
3025 (display-buffer gud-comint-buffer)))
3026
3027 (defun gdb-display-gdb-buffer ()
3028 "Display GUD buffer."
3029 (interactive)
3030 (let ((same-window-regexps nil))
3031 (pop-to-buffer gud-comint-buffer)))
3032
3033 (defun gdb-set-window-buffer (name)
3034 (set-window-buffer (selected-window) (get-buffer name))
3035 (set-window-dedicated-p (selected-window) t))
3036
3037 (defun gdb-setup-windows ()
3038 "Layout the window pattern for `gdb-many-windows'."
3039 (gdb-display-locals-buffer)
3040 (gdb-display-stack-buffer)
3041 (delete-other-windows)
3042 (gdb-display-breakpoints-buffer)
3043 (delete-other-windows)
3044 ; Don't dedicate.
3045 (pop-to-buffer gud-comint-buffer)
3046 (split-window nil ( / ( * (window-height) 3) 4))
3047 (split-window nil ( / (window-height) 3))
3048 (split-window-horizontally)
3049 (other-window 1)
3050 (gdb-set-window-buffer (gdb-locals-buffer-name))
3051 (other-window 1)
3052 (switch-to-buffer
3053 (if gud-last-last-frame
3054 (gud-find-file (car gud-last-last-frame))
3055 (if gdb-main-file
3056 (gud-find-file gdb-main-file)
3057 ;; Put buffer list in window if we
3058 ;; can't find a source file.
3059 (list-buffers-noselect))))
3060 (setq gdb-source-window (selected-window))
3061 (when gdb-use-separate-io-buffer
3062 (split-window-horizontally)
3063 (other-window 1)
3064 (gdb-set-window-buffer
3065 (gdb-get-buffer-create 'gdb-inferior-io)))
3066 (other-window 1)
3067 (gdb-set-window-buffer (gdb-stack-buffer-name))
3068 (split-window-horizontally)
3069 (other-window 1)
3070 (gdb-set-window-buffer (gdb-breakpoints-buffer-name))
3071 (other-window 1))
3072
3073 (defun gdb-restore-windows ()
3074 "Restore the basic arrangement of windows used by gdba.
3075 This arrangement depends on the value of `gdb-many-windows'."
3076 (interactive)
3077 (pop-to-buffer gud-comint-buffer) ;Select the right window and frame.
3078 (delete-other-windows)
3079 (if gdb-many-windows
3080 (gdb-setup-windows)
3081 (when (or gud-last-last-frame gdb-show-main)
3082 (split-window)
3083 (other-window 1)
3084 (switch-to-buffer
3085 (if gud-last-last-frame
3086 (gud-find-file (car gud-last-last-frame))
3087 (gud-find-file gdb-main-file)))
3088 (setq gdb-source-window (selected-window))
3089 (other-window 1))))
3090
3091 (defun gdb-reset ()
3092 "Exit a debugging session cleanly.
3093 Kills the gdb buffers, and resets variables and the source buffers."
3094 (dolist (buffer (buffer-list))
3095 (unless (eq buffer gud-comint-buffer)
3096 (with-current-buffer buffer
3097 (if (memq gud-minor-mode '(gdbmi gdba))
3098 (if (string-match "\\` ?\\*.+\\*\\'" (buffer-name))
3099 (kill-buffer nil)
3100 (gdb-remove-breakpoint-icons (point-min) (point-max) t)
3101 (setq gud-minor-mode nil)
3102 (kill-local-variable 'tool-bar-map)
3103 (kill-local-variable 'gdb-define-alist))))))
3104 (setq gdb-overlay-arrow-position nil)
3105 (setq overlay-arrow-variable-list
3106 (delq 'gdb-overlay-arrow-position overlay-arrow-variable-list))
3107 (setq fringe-indicator-alist '((overlay-arrow . right-triangle)))
3108 (setq gdb-stack-position nil)
3109 (setq overlay-arrow-variable-list
3110 (delq 'gdb-stack-position overlay-arrow-variable-list))
3111 (if (boundp 'speedbar-frame) (speedbar-timer-fn))
3112 (setq gud-running nil)
3113 (setq gdb-active-process nil)
3114 (setq gdb-var-list nil)
3115 (remove-hook 'after-save-hook 'gdb-create-define-alist t))
3116
3117 (defun gdb-source-info ()
3118 "Find the source file where the program starts and displays it with related
3119 buffers."
3120 (goto-char (point-min))
3121 (if (and (search-forward "Located in " nil t)
3122 (looking-at "\\S-+"))
3123 (setq gdb-main-file (match-string 0)))
3124 (goto-char (point-min))
3125 (if (search-forward "Includes preprocessor macro info." nil t)
3126 (setq gdb-macro-info t))
3127 (if gdb-many-windows
3128 (gdb-setup-windows)
3129 (gdb-get-buffer-create 'gdb-breakpoints-buffer)
3130 (if gdb-show-main
3131 (let ((pop-up-windows t))
3132 (display-buffer (gud-find-file gdb-main-file)))))
3133 (setq gdb-ready t))
3134
3135 (defun gdb-get-location (bptno line flag)
3136 "Find the directory containing the relevant source file.
3137 Put in buffer and place breakpoint icon."
3138 (goto-char (point-min))
3139 (catch 'file-not-found
3140 (if (search-forward "Located in " nil t)
3141 (when (looking-at "\\S-+")
3142 (delete (cons bptno "File not found") gdb-location-alist)
3143 (push (cons bptno (match-string 0)) gdb-location-alist))
3144 (gdb-resync)
3145 (unless (assoc bptno gdb-location-alist)
3146 (push (cons bptno "File not found") gdb-location-alist)
3147 (message-box "Cannot find source file for breakpoint location.\n\
3148 Add directory to search path for source files using the GDB command, dir."))
3149 (throw 'file-not-found nil))
3150 (with-current-buffer
3151 (find-file-noselect (match-string 0))
3152 (save-current-buffer
3153 (set (make-local-variable 'gud-minor-mode) 'gdba)
3154 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map))
3155 ;; only want one breakpoint icon at each location
3156 (save-excursion
3157 (goto-line (string-to-number line))
3158 (gdb-put-breakpoint-icon (eq flag ?y) bptno)))))
3159
3160 (add-hook 'find-file-hook 'gdb-find-file-hook)
3161
3162 (defun gdb-find-file-hook ()
3163 "Set up buffer for debugging if file is part of the source code
3164 of the current session."
3165 (if (and (buffer-name gud-comint-buffer)
3166 ;; in case gud or gdb-ui is just loaded
3167 gud-comint-buffer
3168 (memq (buffer-local-value 'gud-minor-mode gud-comint-buffer)
3169 '(gdba gdbmi)))
3170 ;;Pre GDB 6.3 "info sources" doesn't give absolute file name.
3171 (if (member (if (string-equal gdb-version "pre-6.4")
3172 (file-name-nondirectory buffer-file-name)
3173 buffer-file-name)
3174 gdb-source-file-list)
3175 (with-current-buffer (find-buffer-visiting buffer-file-name)
3176 (set (make-local-variable 'gud-minor-mode)
3177 (buffer-local-value 'gud-minor-mode gud-comint-buffer))
3178 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)))))
3179
3180 ;;from put-image
3181 (defun gdb-put-string (putstring pos &optional dprop &rest sprops)
3182 "Put string PUTSTRING in front of POS in the current buffer.
3183 PUTSTRING is displayed by putting an overlay into the current buffer with a
3184 `before-string' string that has a `display' property whose value is
3185 PUTSTRING."
3186 (let ((string (make-string 1 ?x))
3187 (buffer (current-buffer)))
3188 (setq putstring (copy-sequence putstring))
3189 (let ((overlay (make-overlay pos pos buffer))
3190 (prop (or dprop
3191 (list (list 'margin 'left-margin) putstring))))
3192 (put-text-property 0 1 'display prop string)
3193 (if sprops
3194 (add-text-properties 0 1 sprops string))
3195 (overlay-put overlay 'put-break t)
3196 (overlay-put overlay 'before-string string))))
3197
3198 ;;from remove-images
3199 (defun gdb-remove-strings (start end &optional buffer)
3200 "Remove strings between START and END in BUFFER.
3201 Remove only strings that were put in BUFFER with calls to `gdb-put-string'.
3202 BUFFER nil or omitted means use the current buffer."
3203 (unless buffer
3204 (setq buffer (current-buffer)))
3205 (dolist (overlay (overlays-in start end))
3206 (when (overlay-get overlay 'put-break)
3207 (delete-overlay overlay))))
3208
3209 (defun gdb-put-breakpoint-icon (enabled bptno)
3210 (if (string-match "[0-9+]+\\." bptno)
3211 (setq enabled gdb-parent-bptno-enabled))
3212 (let ((start (- (line-beginning-position) 1))
3213 (end (+ (line-end-position) 1))
3214 (putstring (if enabled "B" "b"))
3215 (source-window (get-buffer-window (current-buffer) 0)))
3216 (add-text-properties
3217 0 1 '(help-echo "mouse-1: clear bkpt, mouse-3: enable/disable bkpt")
3218 putstring)
3219 (if enabled
3220 (add-text-properties
3221 0 1 `(gdb-bptno ,bptno gdb-enabled t) putstring)
3222 (add-text-properties
3223 0 1 `(gdb-bptno ,bptno gdb-enabled nil) putstring))
3224 (gdb-remove-breakpoint-icons start end)
3225 (if (display-images-p)
3226 (if (>= (or left-fringe-width
3227 (if source-window (car (window-fringes source-window)))
3228 gdb-buffer-fringe-width) 8)
3229 (gdb-put-string
3230 nil (1+ start)
3231 `(left-fringe breakpoint
3232 ,(if enabled
3233 'breakpoint-enabled
3234 'breakpoint-disabled))
3235 'gdb-bptno bptno
3236 'gdb-enabled enabled)
3237 (when (< left-margin-width 2)
3238 (save-current-buffer
3239 (setq left-margin-width 2)
3240 (if source-window
3241 (set-window-margins
3242 source-window
3243 left-margin-width right-margin-width))))
3244 (put-image
3245 (if enabled
3246 (or breakpoint-enabled-icon
3247 (setq breakpoint-enabled-icon
3248 (find-image `((:type xpm :data
3249 ,breakpoint-xpm-data
3250 :ascent 100 :pointer hand)
3251 (:type pbm :data
3252 ,breakpoint-enabled-pbm-data
3253 :ascent 100 :pointer hand)))))
3254 (or breakpoint-disabled-icon
3255 (setq breakpoint-disabled-icon
3256 (find-image `((:type xpm :data
3257 ,breakpoint-xpm-data
3258 :conversion disabled
3259 :ascent 100 :pointer hand)
3260 (:type pbm :data
3261 ,breakpoint-disabled-pbm-data
3262 :ascent 100 :pointer hand))))))
3263 (+ start 1)
3264 putstring
3265 'left-margin))
3266 (when (< left-margin-width 2)
3267 (save-current-buffer
3268 (setq left-margin-width 2)
3269 (let ((window (get-buffer-window (current-buffer) 0)))
3270 (if window
3271 (set-window-margins
3272 window left-margin-width right-margin-width)))))
3273 (gdb-put-string
3274 (propertize putstring
3275 'face (if enabled 'breakpoint-enabled 'breakpoint-disabled))
3276 (1+ start)))))
3277
3278 (defun gdb-remove-breakpoint-icons (start end &optional remove-margin)
3279 (gdb-remove-strings start end)
3280 (if (display-images-p)
3281 (remove-images start end))
3282 (when remove-margin
3283 (setq left-margin-width 0)
3284 (let ((window (get-buffer-window (current-buffer) 0)))
3285 (if window
3286 (set-window-margins
3287 window left-margin-width right-margin-width)))))
3288
3289 \f
3290 ;;
3291 ;; Assembler buffer.
3292 ;;
3293 (gdb-set-buffer-rules 'gdb-assembler-buffer
3294 'gdb-assembler-buffer-name
3295 'gdb-assembler-mode)
3296
3297 ;; We can't use def-gdb-auto-update-handler because we don't want to use
3298 ;; window-start but keep the overlay arrow/current line visible.
3299 (defun gdb-assembler-handler ()
3300 (setq gdb-pending-triggers
3301 (delq 'gdb-invalidate-assembler
3302 gdb-pending-triggers))
3303 (let ((buf (gdb-get-buffer 'gdb-assembler-buffer)))
3304 (and buf
3305 (with-current-buffer buf
3306 (let* ((window (get-buffer-window buf 0))
3307 (p (window-point window))
3308 (buffer-read-only nil))
3309 (erase-buffer)
3310 (insert-buffer-substring (gdb-get-buffer-create
3311 'gdb-partial-output-buffer))
3312 (set-window-point window p)))))
3313 ;; put customisation here
3314 (gdb-assembler-custom))
3315
3316 (defun gdb-assembler-custom ()
3317 (let ((buffer (gdb-get-buffer 'gdb-assembler-buffer))
3318 (pos 1) (address) (flag) (bptno))
3319 (with-current-buffer buffer
3320 (save-excursion
3321 (if (not (equal gdb-pc-address "main"))
3322 (progn
3323 (goto-char (point-min))
3324 (if (and gdb-pc-address
3325 (search-forward gdb-pc-address nil t))
3326 (progn
3327 (setq pos (point))
3328 (beginning-of-line)
3329 (setq fringe-indicator-alist
3330 (if (string-equal gdb-frame-number "0")
3331 nil
3332 '((overlay-arrow . hollow-right-triangle))))
3333 (or gdb-overlay-arrow-position
3334 (setq gdb-overlay-arrow-position (make-marker)))
3335 (set-marker gdb-overlay-arrow-position (point))))))
3336 ;; remove all breakpoint-icons in assembler buffer before updating.
3337 (gdb-remove-breakpoint-icons (point-min) (point-max))))
3338 (with-current-buffer (gdb-get-buffer 'gdb-breakpoints-buffer)
3339 (goto-char (point-min))
3340 (while (< (point) (- (point-max) 1))
3341 (forward-line 1)
3342 (when (looking-at
3343 "\\([0-9]+\\.?[0-9]*\\).*?\\s-+\\(.\\)\\s-+0x0*\\(\\S-+\\)")
3344 (setq bptno (match-string 1))
3345 (setq flag (char-after (match-beginning 2)))
3346 (setq address (match-string 3))
3347 (with-current-buffer buffer
3348 (save-excursion
3349 (goto-char (point-min))
3350 (if (search-forward address nil t)
3351 (gdb-put-breakpoint-icon (eq flag ?y) bptno)))))))
3352 (if (not (equal gdb-pc-address "main"))
3353 (with-current-buffer buffer
3354 (set-window-point (get-buffer-window buffer 0) pos)))))
3355
3356 (defvar gdb-assembler-mode-map
3357 (let ((map (make-sparse-keymap)))
3358 (suppress-keymap map)
3359 (define-key map "q" 'kill-this-buffer)
3360 map))
3361
3362 (defvar gdb-assembler-font-lock-keywords
3363 '(;; <__function.name+n>
3364 ("<\\(\\(\\sw\\|[_.]\\)+\\)\\(\\+[0-9]+\\)?>"
3365 (1 font-lock-function-name-face))
3366 ;; 0xNNNNNNNN <__function.name+n>: opcode
3367 ("^0x[0-9a-f]+ \\(<\\(\\(\\sw\\|[_.]\\)+\\)\\+[0-9]+>\\)?:[ \t]+\\(\\sw+\\)"
3368 (4 font-lock-keyword-face))
3369 ;; %register(at least i386)
3370 ("%\\sw+" . font-lock-variable-name-face)
3371 ("^\\(Dump of assembler code for function\\) \\(.+\\):"
3372 (1 font-lock-comment-face)
3373 (2 font-lock-function-name-face))
3374 ("^\\(End of assembler dump\\.\\)" . font-lock-comment-face))
3375 "Font lock keywords used in `gdb-assembler-mode'.")
3376
3377 (defun gdb-assembler-mode ()
3378 "Major mode for viewing code assembler.
3379
3380 \\{gdb-assembler-mode-map}"
3381 (kill-all-local-variables)
3382 (setq major-mode 'gdb-assembler-mode)
3383 (setq mode-name (concat "Machine:" gdb-selected-frame))
3384 (setq gdb-overlay-arrow-position nil)
3385 (add-to-list 'overlay-arrow-variable-list 'gdb-overlay-arrow-position)
3386 (setq fringes-outside-margins t)
3387 (setq buffer-read-only t)
3388 (use-local-map gdb-assembler-mode-map)
3389 (gdb-invalidate-assembler)
3390 (set (make-local-variable 'font-lock-defaults)
3391 '(gdb-assembler-font-lock-keywords))
3392 (run-mode-hooks 'gdb-assembler-mode-hook)
3393 'gdb-invalidate-assembler)
3394
3395 (defun gdb-assembler-buffer-name ()
3396 (with-current-buffer gud-comint-buffer
3397 (concat "*disassembly of " (gdb-get-target-string) "*")))
3398
3399 (defun gdb-display-assembler-buffer ()
3400 "Display disassembly view."
3401 (interactive)
3402 (setq gdb-previous-frame nil)
3403 (gdb-display-buffer
3404 (gdb-get-buffer-create 'gdb-assembler-buffer) t))
3405
3406 (defun gdb-frame-assembler-buffer ()
3407 "Display disassembly view in a new frame."
3408 (interactive)
3409 (setq gdb-previous-frame nil)
3410 (let ((special-display-regexps (append special-display-regexps '(".*")))
3411 (special-display-frame-alist gdb-frame-parameters))
3412 (display-buffer (gdb-get-buffer-create 'gdb-assembler-buffer))))
3413
3414 ;; modified because if gdb-pc-address has changed value a new command
3415 ;; must be enqueued to update the buffer with the new output
3416 (defun gdb-invalidate-assembler (&optional ignored)
3417 (if (gdb-get-buffer 'gdb-assembler-buffer)
3418 (progn
3419 (unless (and gdb-selected-frame
3420 (string-equal gdb-selected-frame gdb-previous-frame))
3421 (if (or (not (member 'gdb-invalidate-assembler
3422 gdb-pending-triggers))
3423 (not (string-equal gdb-pc-address
3424 gdb-previous-frame-address)))
3425 (progn
3426 ;; take previous disassemble command, if any, off the queue
3427 (with-current-buffer gud-comint-buffer
3428 (let ((queue gdb-input-queue))
3429 (dolist (item queue)
3430 (if (equal (cdr item) '(gdb-assembler-handler))
3431 (setq gdb-input-queue
3432 (delete item gdb-input-queue))))))
3433 (gdb-enqueue-input
3434 (list
3435 (concat gdb-server-prefix "disassemble "
3436 (if (member gdb-pc-address '(nil "main")) nil "0x")
3437 gdb-pc-address "\n")
3438 'gdb-assembler-handler))
3439 (push 'gdb-invalidate-assembler gdb-pending-triggers)
3440 (setq gdb-previous-frame-address gdb-pc-address)
3441 (setq gdb-previous-frame gdb-selected-frame)))))))
3442
3443 (defun gdb-get-selected-frame ()
3444 (if (not (member 'gdb-get-selected-frame gdb-pending-triggers))
3445 (progn
3446 (gdb-enqueue-input
3447 (list (concat gdb-server-prefix "info frame\n") 'gdb-frame-handler))
3448 (push 'gdb-get-selected-frame
3449 gdb-pending-triggers))))
3450
3451 (defun gdb-frame-handler ()
3452 (setq gdb-pending-triggers
3453 (delq 'gdb-get-selected-frame gdb-pending-triggers))
3454 (goto-char (point-min))
3455 (when (re-search-forward
3456 "Stack level \\([0-9]+\\), frame at \\(0x[[:xdigit:]]+\\)" nil t)
3457 (setq gdb-frame-number (match-string 1))
3458 (setq gdb-frame-address (match-string 2)))
3459 (goto-char (point-min))
3460 (when (re-search-forward ".*=\\s-+0x0*\\(\\S-*\\)\\s-+in\\s-+\\(.*?\\)\
3461 \\(?: (\\(\\S-+?\\):[0-9]+?)\\)*; "
3462 nil t)
3463 (setq gdb-selected-frame (match-string 2))
3464 (if (gdb-get-buffer 'gdb-locals-buffer)
3465 (with-current-buffer (gdb-get-buffer 'gdb-locals-buffer)
3466 (setq mode-name (concat "Locals:" gdb-selected-frame))))
3467 (if (gdb-get-buffer 'gdb-assembler-buffer)
3468 (with-current-buffer (gdb-get-buffer 'gdb-assembler-buffer)
3469 (setq mode-name (concat "Machine:" gdb-selected-frame))))
3470 (setq gdb-pc-address (match-string 1))
3471 (if (and (match-string 3) gud-overlay-arrow-position)
3472 (let ((buffer (marker-buffer gud-overlay-arrow-position))
3473 (position (marker-position gud-overlay-arrow-position)))
3474 (when (and buffer
3475 (string-equal (file-name-nondirectory
3476 (buffer-file-name buffer))
3477 (file-name-nondirectory (match-string 3))))
3478 (with-current-buffer buffer
3479 (setq fringe-indicator-alist
3480 (if (string-equal gdb-frame-number "0")
3481 nil
3482 '((overlay-arrow . hollow-right-triangle))))
3483 (set-marker gud-overlay-arrow-position position))))))
3484 (goto-char (point-min))
3485 (if (re-search-forward " source language \\(\\S-+\\)\." nil t)
3486 (setq gdb-current-language (match-string 1)))
3487 (gdb-invalidate-assembler))
3488
3489 \f
3490 ;; Code specific to GDB 6.4
3491 (defconst gdb-source-file-regexp-1 "fullname=\"\\(.*?\\)\"")
3492
3493 (defun gdb-set-gud-minor-mode-existing-buffers-1 ()
3494 "Create list of source files for current GDB session.
3495 If buffers already exist for any of these files, gud-minor-mode
3496 is set in them."
3497 (goto-char (point-min))
3498 (while (re-search-forward gdb-source-file-regexp-1 nil t)
3499 (push (match-string 1) gdb-source-file-list))
3500 (dolist (buffer (buffer-list))
3501 (with-current-buffer buffer
3502 (when (member buffer-file-name gdb-source-file-list)
3503 (set (make-local-variable 'gud-minor-mode)
3504 (buffer-local-value 'gud-minor-mode gud-comint-buffer))
3505 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
3506 (when gud-tooltip-mode
3507 (make-local-variable 'gdb-define-alist)
3508 (gdb-create-define-alist)
3509 (add-hook 'after-save-hook 'gdb-create-define-alist nil t)))))
3510 (gdb-force-mode-line-update
3511 (propertize "ready" 'face font-lock-variable-name-face)))
3512
3513 ; Uses "-var-list-children --all-values". Needs GDB 6.4 onwards.
3514 (defun gdb-var-list-children-1 (varnum)
3515 (gdb-enqueue-input
3516 (list
3517 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
3518 (concat "server interpreter mi \"-var-list-children --all-values \\\""
3519 varnum "\\\"\"\n")
3520 (concat "-var-list-children --all-values \"" varnum "\"\n"))
3521 `(lambda () (gdb-var-list-children-handler-1 ,varnum)))))
3522
3523 (defconst gdb-var-list-children-regexp-1
3524 "child={.*?name=\"\\(.+?\\)\",.*?exp=\"\\(.+?\\)\",.*?\
3525 numchild=\"\\(.+?\\)\",.*?value=\\(\".*?\"\\)\
3526 \\(}\\|,.*?\\(type=\"\\(.+?\\)\"\\)?.*?}\\)")
3527
3528 (defun gdb-var-list-children-handler-1 (varnum)
3529 (goto-char (point-min))
3530 (let ((var-list nil))
3531 (catch 'child-already-watched
3532 (dolist (var gdb-var-list)
3533 (if (string-equal varnum (car var))
3534 (progn
3535 (push var var-list)
3536 (while (re-search-forward gdb-var-list-children-regexp-1 nil t)
3537 (let ((varchild (list (match-string 1)
3538 (match-string 2)
3539 (match-string 3)
3540 (match-string 7)
3541 (read (match-string 4))
3542 nil)))
3543 (if (assoc (car varchild) gdb-var-list)
3544 (throw 'child-already-watched nil))
3545 (push varchild var-list))))
3546 (push var var-list)))
3547 (setq gdb-var-list (nreverse var-list))))
3548 (gdb-speedbar-update))
3549
3550 ; Uses "-var-update --all-values". Needs GDB 6.4 onwards.
3551 (defun gdb-var-update-1 ()
3552 (if (not (member 'gdb-var-update gdb-pending-triggers))
3553 (progn
3554 (gdb-enqueue-input
3555 (list
3556 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
3557 "server interpreter mi \"-var-update --all-values *\"\n"
3558 "-var-update --all-values *\n")
3559 'gdb-var-update-handler-1))
3560 (push 'gdb-var-update gdb-pending-triggers))))
3561
3562 (defconst gdb-var-update-regexp-1
3563 "{.*?name=\"\\(.*?\\)\",.*?\\(?:value=\\(\".*?\"\\),\\)?.*?\
3564 in_scope=\"\\(.*?\\)\".*?}")
3565
3566 (defun gdb-var-update-handler-1 ()
3567 (dolist (var gdb-var-list)
3568 (setcar (nthcdr 5 var) nil))
3569 (goto-char (point-min))
3570 (while (re-search-forward gdb-var-update-regexp-1 nil t)
3571 (let* ((varnum (match-string 1))
3572 (var (assoc varnum gdb-var-list)))
3573 (when var
3574 (let ((match (match-string 3)))
3575 (cond ((string-equal match "false")
3576 (if gdb-delete-out-of-scope
3577 (gdb-var-delete-1 varnum)
3578 (setcar (nthcdr 5 var) 'out-of-scope)))
3579 ((string-equal match "true")
3580 (setcar (nthcdr 5 var) 'changed)
3581 (setcar (nthcdr 4 var)
3582 (read (match-string 2))))
3583 ((string-equal match "invalid")
3584 (gdb-var-delete-1 varnum)))))))
3585 (setq gdb-pending-triggers
3586 (delq 'gdb-var-update gdb-pending-triggers))
3587 (gdb-speedbar-update))
3588
3589 ;; Registers buffer.
3590 ;;
3591 (gdb-set-buffer-rules 'gdb-registers-buffer
3592 'gdb-registers-buffer-name
3593 'gdb-registers-mode)
3594
3595 (def-gdb-auto-update-trigger gdb-invalidate-registers-1
3596 (gdb-get-buffer 'gdb-registers-buffer)
3597 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
3598 "server interpreter mi \"-data-list-register-values x\"\n"
3599 "-data-list-register-values x\n")
3600 gdb-data-list-register-values-handler)
3601
3602 (defconst gdb-data-list-register-values-regexp
3603 "{.*?number=\"\\(.*?\\)\",.*?value=\"\\(.*?\\)\".*?}")
3604
3605 (defun gdb-data-list-register-values-handler ()
3606 (setq gdb-pending-triggers (delq 'gdb-invalidate-registers-1
3607 gdb-pending-triggers))
3608 (goto-char (point-min))
3609 (if (re-search-forward gdb-error-regexp nil t)
3610 (let ((err (match-string 1)))
3611 (with-current-buffer (gdb-get-buffer 'gdb-registers-buffer)
3612 (let ((buffer-read-only nil))
3613 (erase-buffer)
3614 (put-text-property 0 (length err) 'face font-lock-warning-face err)
3615 (insert err)
3616 (goto-char (point-min)))))
3617 (let ((register-list (reverse gdb-register-names))
3618 (register nil) (register-string nil) (register-values nil))
3619 (goto-char (point-min))
3620 (while (re-search-forward gdb-data-list-register-values-regexp nil t)
3621 (setq register (pop register-list))
3622 (setq register-string (concat register "\t" (match-string 2) "\n"))
3623 (if (member (match-string 1) gdb-changed-registers)
3624 (put-text-property 0 (length register-string)
3625 'face 'font-lock-warning-face
3626 register-string))
3627 (setq register-values
3628 (concat register-values register-string)))
3629 (let ((buf (gdb-get-buffer 'gdb-registers-buffer)))
3630 (with-current-buffer buf
3631 (let* ((window (get-buffer-window buf 0))
3632 (start (window-start window))
3633 (p (window-point window))
3634 (buffer-read-only nil))
3635 (erase-buffer)
3636 (insert register-values)
3637 (set-window-start window start)
3638 (set-window-point window p))))))
3639 (gdb-data-list-register-values-custom))
3640
3641 (defun gdb-data-list-register-values-custom ()
3642 (with-current-buffer (gdb-get-buffer 'gdb-registers-buffer)
3643 (save-excursion
3644 (let ((buffer-read-only nil)
3645 start end)
3646 (goto-char (point-min))
3647 (while (< (point) (point-max))
3648 (setq start (line-beginning-position))
3649 (setq end (line-end-position))
3650 (when (looking-at "^[^\t]+")
3651 (unless (string-equal (match-string 0) "No registers.")
3652 (put-text-property start (match-end 0)
3653 'face font-lock-variable-name-face)
3654 (add-text-properties start end
3655 '(help-echo "mouse-2: edit value"
3656 mouse-face highlight))))
3657 (forward-line 1))))))
3658
3659 ;; Needs GDB 6.4 onwards (used to fail with no stack).
3660 (defun gdb-get-changed-registers ()
3661 (if (and (gdb-get-buffer 'gdb-registers-buffer)
3662 (not (member 'gdb-get-changed-registers gdb-pending-triggers)))
3663 (progn
3664 (gdb-enqueue-input
3665 (list
3666 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
3667 "server interpreter mi -data-list-changed-registers\n"
3668 "-data-list-changed-registers\n")
3669 'gdb-get-changed-registers-handler))
3670 (push 'gdb-get-changed-registers gdb-pending-triggers))))
3671
3672 (defconst gdb-data-list-register-names-regexp "\"\\(.*?\\)\"")
3673
3674 (defun gdb-get-changed-registers-handler ()
3675 (setq gdb-pending-triggers
3676 (delq 'gdb-get-changed-registers gdb-pending-triggers))
3677 (setq gdb-changed-registers nil)
3678 (goto-char (point-min))
3679 (while (re-search-forward gdb-data-list-register-names-regexp nil t)
3680 (push (match-string 1) gdb-changed-registers)))
3681 \f
3682
3683 ;; Locals buffer.
3684 ;;
3685 ;; uses "-stack-list-locals --simple-values". Needs GDB 6.1 onwards.
3686 (gdb-set-buffer-rules 'gdb-locals-buffer
3687 'gdb-locals-buffer-name
3688 'gdb-locals-mode)
3689
3690 (def-gdb-auto-update-trigger gdb-invalidate-locals-1
3691 (gdb-get-buffer 'gdb-locals-buffer)
3692 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba)
3693 "server interpreter mi -\"stack-list-locals --simple-values\"\n"
3694 "-stack-list-locals --simple-values\n")
3695 gdb-stack-list-locals-handler)
3696
3697 (defconst gdb-stack-list-locals-regexp
3698 "{.*?name=\"\\(.*?\\)\",.*?type=\"\\(.*?\\)\"")
3699
3700 (defvar gdb-locals-watch-map-1
3701 (let ((map (make-sparse-keymap)))
3702 (suppress-keymap map)
3703 (define-key map "\r" 'gud-watch)
3704 (define-key map [mouse-2] 'gud-watch)
3705 map)
3706 "Keymap to create watch expression of a complex data type local variable.")
3707
3708 (defvar gdb-edit-locals-map-1
3709 (let ((map (make-sparse-keymap)))
3710 (suppress-keymap map)
3711 (define-key map "\r" 'gdb-edit-locals-value)
3712 (define-key map [mouse-2] 'gdb-edit-locals-value)
3713 map)
3714 "Keymap to edit value of a simple data type local variable.")
3715
3716 (defun gdb-edit-locals-value (&optional event)
3717 "Assign a value to a variable displayed in the locals buffer."
3718 (interactive (list last-input-event))
3719 (save-excursion
3720 (if event (posn-set-point (event-end event)))
3721 (beginning-of-line)
3722 (let* ((var (current-word))
3723 (value (read-string (format "New value (%s): " var))))
3724 (gdb-enqueue-input
3725 (list (concat gdb-server-prefix"set variable " var " = " value "\n")
3726 'ignore)))))
3727
3728 ;; Dont display values of arrays or structures.
3729 ;; These can be expanded using gud-watch.
3730 (defun gdb-stack-list-locals-handler ()
3731 (setq gdb-pending-triggers (delq 'gdb-invalidate-locals-1
3732 gdb-pending-triggers))
3733 (goto-char (point-min))
3734 (if (re-search-forward gdb-error-regexp nil t)
3735 (let ((err (match-string 1)))
3736 (with-current-buffer (gdb-get-buffer 'gdb-locals-buffer)
3737 (let ((buffer-read-only nil))
3738 (erase-buffer)
3739 (insert err)
3740 (goto-char (point-min)))))
3741 (let (local locals-list)
3742 (goto-char (point-min))
3743 (while (re-search-forward gdb-stack-list-locals-regexp nil t)
3744 (let ((local (list (match-string 1)
3745 (match-string 2)
3746 nil)))
3747 (if (looking-at ",value=\\(\".*\"\\).*?}")
3748 (setcar (nthcdr 2 local) (read (match-string 1))))
3749 (push local locals-list)))
3750 (let ((buf (gdb-get-buffer 'gdb-locals-buffer)))
3751 (and buf (with-current-buffer buf
3752 (let* ((window (get-buffer-window buf 0))
3753 (start (window-start window))
3754 (p (window-point window))
3755 (buffer-read-only nil) (name) (value))
3756 (erase-buffer)
3757 (dolist (local locals-list)
3758 (setq name (car local))
3759 (setq value (nth 2 local))
3760 (if (or (not value)
3761 (string-match "^\\0x" value))
3762 (add-text-properties 0 (length name)
3763 `(mouse-face highlight
3764 help-echo "mouse-2: create watch expression"
3765 local-map ,gdb-locals-watch-map-1)
3766 name)
3767 (add-text-properties 0 (length value)
3768 `(mouse-face highlight
3769 help-echo "mouse-2: edit value"
3770 local-map ,gdb-edit-locals-map-1)
3771 value))
3772 (insert
3773 (concat name "\t" (nth 1 local)
3774 "\t" value "\n")))
3775 (set-window-start window start)
3776 (set-window-point window p))))))))
3777
3778 (defun gdb-get-register-names ()
3779 "Create a list of register names."
3780 (goto-char (point-min))
3781 (setq gdb-register-names nil)
3782 (while (re-search-forward gdb-data-list-register-names-regexp nil t)
3783 (push (match-string 1) gdb-register-names)))
3784
3785 (provide 'gdb-ui)
3786
3787 ;; arch-tag: e9fb00c5-74ef-469f-a088-37384caae352
3788 ;;; gdb-ui.el ends here