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