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