]> code.delx.au - gnu-emacs/blob - lisp/progmodes/gdb-ui.el
2005-05-23 Martin Stjernholm <bug-cc-mode@gnu.org>
[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 Free Software Foundation, Inc.
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
25
26 ;;; Commentary:
27
28 ;; This mode acts as a graphical user interface to GDB. You can interact with
29 ;; GDB through the GUD buffer in the usual way, but there are also further
30 ;; buffers which control the execution and describe the state of your program.
31 ;; It separates the input/output of your program from that of GDB, if
32 ;; required, and watches expressions in the speedbar. It also uses features of
33 ;; Emacs 21 such as the fringe/display margin for breakpoints, and the toolbar
34 ;; (see the GDB Graphical Interface section in the Emacs info manual).
35
36 ;; By default, M-x gdb will start the debugger. However, if you have customised
37 ;; gud-gdb-command-name, then start it with M-x gdba.
38
39 ;; This file has evolved from gdba.el that was included with GDB 5.0 and
40 ;; written by Tom Lord and Jim Kingdon. It uses GDB's annotation interface.
41 ;; You don't need to know about annotations to use this mode as a debugger,
42 ;; but if you are interested developing the mode itself, then see the
43 ;; Annotations section in the GDB info manual.
44 ;;
45 ;; GDB developers plan to make the annotation interface obsolete. A new
46 ;; interface called GDB/MI (machine interface) has been designed to replace
47 ;; it. Some GDB/MI commands are used in this file through the CLI command
48 ;; 'interpreter mi <mi-command>'. A file called gdb-mi.el is included with
49 ;; GDB (6.2 onwards) that uses GDB/MI as the primary interface to GDB. It is
50 ;; still under development and is part of a process to migrate Emacs from
51 ;; annotations to GDB/MI.
52 ;;
53 ;; Known Bugs:
54 ;;
55 ;; TODO:
56 ;; 1) Use MI command -data-read-memory for memory window.
57 ;; 2) Highlight changed register values (use MI commands
58 ;; -data-list-register-values and -data-list-changed-registers instead
59 ;; of 'info registers'.
60 ;; 3) Use tree-widget.el instead of the speedbar for watch-expressions?
61 ;; 4) Mark breakpoint locations on scroll-bar of source buffer?
62 ;; 5) After release of 22.1 use '-var-list-children --all-values'
63 ;; and '-stack-list-locals 2' which need GDB 6.1 onwards.
64
65 ;;; Code:
66
67 (require 'gud)
68
69 (defvar gdb-current-address "main" "Initialisation for Assembler buffer.")
70 (defvar gdb-previous-address nil)
71 (defvar gdb-memory-address "main")
72 (defvar gdb-previous-frame nil)
73 (defvar gdb-current-frame nil)
74 (defvar gdb-current-stack-level nil)
75 (defvar gdb-current-language nil)
76 (defvar gdb-var-list nil "List of variables in watch window.")
77 (defvar gdb-var-changed nil "Non-nil means that gdb-var-list has changed.")
78 (defvar gdb-buffer-type nil)
79 (defvar gdb-overlay-arrow-position nil)
80 (defvar gdb-server-prefix nil)
81 (defvar gdb-flush-pending-output nil)
82 (defvar gdb-location-alist nil
83 "Alist of breakpoint numbers and full filenames.")
84 (defvar gdb-find-file-unhook nil)
85 (defvar gdb-active-process nil "GUD tooltips display variable values when t, \
86 and #define directives otherwise.")
87 (defvar gdb-macro-info nil
88 "Non-nil if GDB knows that the inferior includes preprocessor macro info.")
89
90 (defvar gdb-buffer-type nil
91 "One of the symbols bound in `gdb-buffer-rules'.")
92
93 (defvar gdb-input-queue ()
94 "A list of gdb command objects.")
95
96 (defvar gdb-prompting nil
97 "True when gdb is idle with no pending input.")
98
99 (defvar gdb-output-sink 'user
100 "The disposition of the output of the current gdb command.
101 Possible values are these symbols:
102
103 `user' -- gdb output should be copied to the GUD buffer
104 for the user to see.
105
106 `inferior' -- gdb output should be copied to the inferior-io buffer
107
108 `pre-emacs' -- output should be ignored util the post-prompt
109 annotation is received. Then the output-sink
110 becomes:...
111 `emacs' -- output should be collected in the partial-output-buffer
112 for subsequent processing by a command. This is the
113 disposition of output generated by commands that
114 gdb mode sends to gdb on its own behalf.
115 `post-emacs' -- ignore output until the prompt annotation is
116 received, then go to USER disposition.
117
118 gdba (gdb-ui.el) uses all five values, gdbmi (gdb-mi.el) only two
119 \(`user' and `emacs').")
120
121 (defvar gdb-current-item nil
122 "The most recent command item sent to gdb.")
123
124 (defvar gdb-pending-triggers '()
125 "A list of trigger functions that have run later than their output
126 handlers.")
127
128 ;; end of gdb variables
129
130 ;;;###autoload
131 (defun gdba (command-line)
132 "Run gdb on program FILE in buffer *gud-FILE*.
133 The directory containing FILE becomes the initial working directory
134 and source-file directory for your debugger.
135
136 If `gdb-many-windows' is nil (the default value) then gdb just
137 pops up the GUD buffer unless `gdb-show-main' is t. In this case
138 it starts with two windows: one displaying the GUD buffer and the
139 other with the source file with the main routine of the inferior.
140
141 If `gdb-many-windows' is t, regardless of the value of
142 `gdb-show-main', the layout below will appear unless
143 `gdb-use-inferior-io-buffer' is nil when the source buffer
144 occupies the full width of the frame. Keybindings are given in
145 relevant buffer.
146
147 Watch expressions appear in the speedbar/slowbar.
148
149 The following commands help control operation :
150
151 `gdb-many-windows' - Toggle the number of windows gdb uses.
152 `gdb-restore-windows' - To restore the window layout.
153
154 See Info node `(emacs)GDB Graphical Interface' for a more
155 detailed description of this mode.
156
157
158 ---------------------------------------------------------------------
159 GDB Toolbar
160 ---------------------------------------------------------------------
161 GUD buffer (I/O of GDB) | Locals buffer
162 |
163 |
164 |
165 ---------------------------------------------------------------------
166 Source buffer | Input/Output (of inferior) buffer
167 | (comint-mode)
168 |
169 |
170 |
171 |
172 |
173 |
174 ---------------------------------------------------------------------
175 Stack buffer | Breakpoints buffer
176 RET gdb-frames-select | SPC gdb-toggle-breakpoint
177 | RET gdb-goto-breakpoint
178 | d gdb-delete-breakpoint
179 ---------------------------------------------------------------------"
180 ;;
181 (interactive (list (gud-query-cmdline 'gdba)))
182 ;;
183 ;; Let's start with a basic gud-gdb buffer and then modify it a bit.
184 (gdb command-line)
185 (gdb-ann3))
186
187 (defvar gdb-debug-log nil)
188
189 (defcustom gdb-enable-debug-log nil
190 "Non-nil means record the process input and output in `gdb-debug-log'."
191 :type 'boolean
192 :group 'gud
193 :version "22.1")
194
195 (defcustom gdb-use-inferior-io-buffer nil
196 "Non-nil means display output from the inferior in a separate buffer."
197 :type 'boolean
198 :group 'gud
199 :version "22.1")
200
201 (defcustom gdb-cpp-define-alist-program "gcc -E -dM -"
202 "Shell command for generating a list of defined macros in a source file.
203 This list is used to display the #define directive associated
204 with an identifier as a tooltip. It works in a debug session with
205 GDB, when gud-tooltip-mode is t.
206
207 Set `gdb-cpp-define-alist-flags' for any include paths or
208 predefined macros."
209 :type 'string
210 :group 'gud
211 :version "22.1")
212
213 (defcustom gdb-cpp-define-alist-flags ""
214 "*Preprocessor flags for `gdb-cpp-define-alist-program'."
215 :type 'string
216 :group 'gud
217 :version "22.1")
218
219 (defvar gdb-define-alist nil "Alist of #define directives for GUD tooltips.")
220
221 (defun gdb-create-define-alist ()
222 "Create an alist of #define directives for GUD tooltips."
223 (let* ((file (buffer-file-name))
224 (output
225 (with-output-to-string
226 (with-current-buffer standard-output
227 (call-process shell-file-name
228 (if (file-exists-p file) file nil)
229 (list t nil) nil "-c"
230 (concat gdb-cpp-define-alist-program " "
231 gdb-cpp-define-alist-flags)))))
232 (define-list (split-string output "\n" t))
233 (name))
234 (setq gdb-define-alist nil)
235 (dolist (define define-list)
236 (setq name (nth 1 (split-string define "[( ]")))
237 (push (cons name define) gdb-define-alist))))
238
239 (defun gdb-tooltip-print ()
240 (tooltip-show
241 (with-current-buffer (gdb-get-buffer 'gdb-partial-output-buffer)
242 (let ((string (buffer-string)))
243 ;; remove newline for gud-tooltip-echo-area
244 (substring string 0 (- (length string) 1))))
245 gud-tooltip-echo-area))
246
247 ;; If expr is a macro for a function don't print because of possible dangerous
248 ;; side-effects. Also printing a function within a tooltip generates an
249 ;; unexpected starting annotation (phase error).
250 (defun gdb-tooltip-print-1 (expr)
251 (with-current-buffer (gdb-get-buffer 'gdb-partial-output-buffer)
252 (goto-char (point-min))
253 (if (search-forward "expands to: " nil t)
254 (unless (looking-at "\\S+.*(.*).*")
255 (gdb-enqueue-input
256 (list (concat gdb-server-prefix "print " expr "\n")
257 'gdb-tooltip-print))))))
258
259 (defun gdb-set-gud-minor-mode (buffer)
260 "Set gud-minor-mode from find-file if appropriate."
261 (goto-char (point-min))
262 (unless (search-forward "No source file named " nil t)
263 (condition-case nil
264 (gdb-enqueue-input
265 (list (concat gdb-server-prefix "info source\n")
266 `(lambda () (gdb-set-gud-minor-mode-1 ,buffer))))
267 (error (setq gdb-find-file-unhook t)))))
268
269 (defun gdb-set-gud-minor-mode-1 (buffer)
270 (goto-char (point-min))
271 (when (and (search-forward "Located in " nil t)
272 (looking-at "\\S-*")
273 (string-equal (buffer-file-name buffer)
274 (match-string 0)))
275 (with-current-buffer buffer
276 (set (make-local-variable 'gud-minor-mode) 'gdba)
277 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
278 (when gud-tooltip-mode
279 (make-local-variable 'gdb-define-alist)
280 (gdb-create-define-alist)
281 (add-hook 'after-save-hook 'gdb-create-define-alist nil t)))))
282
283 (defun gdb-set-gud-minor-mode-existing-buffers ()
284 (dolist (buffer (buffer-list))
285 (let ((file (buffer-file-name buffer)))
286 (if file
287 (progn
288 (gdb-enqueue-input
289 (list (concat gdb-server-prefix "list "
290 (file-name-nondirectory file) ":1\n")
291 `(lambda () (gdb-set-gud-minor-mode ,buffer)))))))))
292
293 (defun gdb-ann3 ()
294 (setq gdb-debug-log nil)
295 (set (make-local-variable 'gud-minor-mode) 'gdba)
296 (set (make-local-variable 'gud-marker-filter) 'gud-gdba-marker-filter)
297 ;;
298 (gud-def gud-break (if (not (string-equal mode-name "Machine"))
299 (gud-call "break %f:%l" arg)
300 (save-excursion
301 (beginning-of-line)
302 (forward-char 2)
303 (gud-call "break *%a" arg)))
304 "\C-b" "Set breakpoint at current line or address.")
305 ;;
306 (gud-def gud-remove (if (not (string-equal mode-name "Machine"))
307 (gud-call "clear %f:%l" arg)
308 (save-excursion
309 (beginning-of-line)
310 (forward-char 2)
311 (gud-call "clear *%a" arg)))
312 "\C-d" "Remove breakpoint at current line or address.")
313 ;;
314 (gud-def gud-until (if (not (string-equal mode-name "Machine"))
315 (gud-call "until %f:%l" arg)
316 (save-excursion
317 (beginning-of-line)
318 (forward-char 2)
319 (gud-call "until *%a" arg)))
320 "\C-u" "Continue to current line or address.")
321
322 (define-key gud-minor-mode-map [left-margin mouse-1]
323 'gdb-mouse-set-clear-breakpoint)
324 (define-key gud-minor-mode-map [left-fringe mouse-1]
325 'gdb-mouse-set-clear-breakpoint)
326 (define-key gud-minor-mode-map [left-margin mouse-3]
327 'gdb-mouse-toggle-breakpoint)
328 ; Currently only works in margin.
329 ; (define-key gud-minor-mode-map [left-fringe mouse-3]
330 ; 'gdb-mouse-toggle-breakpoint)
331
332 (setq comint-input-sender 'gdb-send)
333 ;;
334 ;; (re-)initialize
335 (setq gdb-current-address "main")
336 (setq gdb-previous-address nil)
337 (setq gdb-memory-address "main")
338 (setq gdb-previous-frame nil)
339 (setq gdb-current-frame nil)
340 (setq gdb-current-stack-level nil)
341 (setq gdb-var-list nil)
342 (setq gdb-var-changed nil)
343 (setq gdb-first-prompt nil)
344 (setq gdb-prompting nil)
345 (setq gdb-input-queue nil)
346 (setq gdb-current-item nil)
347 (setq gdb-pending-triggers nil)
348 (setq gdb-output-sink 'user)
349 (setq gdb-server-prefix "server ")
350 (setq gdb-flush-pending-output nil)
351 (setq gdb-location-alist nil)
352 (setq gdb-find-file-unhook nil)
353 (setq gdb-macro-info nil)
354 ;;
355 (setq gdb-buffer-type 'gdba)
356 ;;
357 (if gdb-use-inferior-io-buffer (gdb-clear-inferior-io))
358 ;;
359 (if (eq window-system 'w32)
360 (gdb-enqueue-input (list "set new-console off\n" 'ignore)))
361 (gdb-enqueue-input (list "set height 0\n" 'ignore))
362 (gdb-enqueue-input (list "set width 0\n" 'ignore))
363 ;; find source file and compilation directory here
364 (gdb-enqueue-input (list "server list main\n" 'ignore)) ; C program
365 (gdb-enqueue-input (list "server list MAIN__\n" 'ignore)) ; Fortran program
366 (gdb-enqueue-input (list "server info source\n" 'gdb-source-info))
367 ;;
368 (gdb-set-gud-minor-mode-existing-buffers)
369 (run-hooks 'gdba-mode-hook))
370
371 (defcustom gdb-use-colon-colon-notation nil
372 "If non-nil use FUN::VAR format to display variables in the speedbar."
373 :type 'boolean
374 :group 'gud
375 :version "22.1")
376
377 (defun gud-watch ()
378 "Watch expression at point."
379 (interactive)
380 (require 'tooltip)
381 (let ((expr (tooltip-identifier-from-point (point))))
382 (if (and (string-equal gdb-current-language "c")
383 gdb-use-colon-colon-notation gdb-current-frame)
384 (setq expr (concat gdb-current-frame "::" expr)))
385 (catch 'already-watched
386 (dolist (var gdb-var-list)
387 (if (string-equal expr (car var)) (throw 'already-watched nil)))
388 (set-text-properties 0 (length expr) nil expr)
389 (gdb-enqueue-input
390 (list
391 (if (eq gud-minor-mode 'gdba)
392 (concat "server interpreter mi \"-var-create - * " expr "\"\n")
393 (concat"-var-create - * " expr "\n"))
394 `(lambda () (gdb-var-create-handler ,expr))))))
395 (select-window (get-buffer-window gud-comint-buffer 0)))
396
397 (defconst gdb-var-create-regexp
398 "name=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\",type=\"\\(.*?\\)\"")
399
400 (defun gdb-var-create-handler (expr)
401 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
402 (goto-char (point-min))
403 (if (re-search-forward gdb-var-create-regexp nil t)
404 (let ((var (list expr
405 (match-string 1)
406 (match-string 2)
407 (match-string 3)
408 nil nil)))
409 (push var gdb-var-list)
410 (speedbar 1)
411 (if (equal (nth 2 var) "0")
412 (gdb-enqueue-input
413 (list
414 (if (with-current-buffer
415 gud-comint-buffer (eq gud-minor-mode 'gdba))
416 (concat "server interpreter mi \"-var-evaluate-expression "
417 (nth 1 var) "\"\n")
418 (concat "-var-evaluate-expression " (nth 1 var) "\n"))
419 `(lambda () (gdb-var-evaluate-expression-handler
420 ,(nth 1 var) nil))))
421 (setq gdb-var-changed t)))
422 (if (re-search-forward "Undefined command" nil t)
423 (message-box "Watching expressions requires gdb 6.0 onwards")
424 (message "No symbol %s in current context." expr)))))
425
426 (defun gdb-var-evaluate-expression-handler (varnum changed)
427 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
428 (goto-char (point-min))
429 (re-search-forward ".*value=\"\\(.*?\\)\"" nil t)
430 (catch 'var-found
431 (let ((num 0))
432 (dolist (var gdb-var-list)
433 (if (string-equal varnum (cadr var))
434 (progn
435 (if changed (setcar (nthcdr 5 var) t))
436 (setcar (nthcdr 4 var) (match-string 1))
437 (setcar (nthcdr num gdb-var-list) var)
438 (throw 'var-found nil)))
439 (setq num (+ num 1))))))
440 (setq gdb-var-changed t))
441
442 (defun gdb-var-list-children (varnum)
443 (gdb-enqueue-input
444 (list (concat "server interpreter mi \"-var-list-children " varnum "\"\n")
445 `(lambda () (gdb-var-list-children-handler ,varnum)))))
446
447 (defconst gdb-var-list-children-regexp
448 "name=\"\\(.*?\\)\",exp=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\"")
449
450 (defun gdb-var-list-children-handler (varnum)
451 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
452 (goto-char (point-min))
453 (let ((var-list nil))
454 (catch 'child-already-watched
455 (dolist (var gdb-var-list)
456 (if (string-equal varnum (cadr var))
457 (progn
458 (push var var-list)
459 (while (re-search-forward gdb-var-list-children-regexp nil t)
460 (let ((varchild (list (match-string 2)
461 (match-string 1)
462 (match-string 3)
463 nil nil nil)))
464 (if (looking-at ",type=\"\\(.*?\\)\"")
465 (setcar (nthcdr 3 varchild) (match-string 1)))
466 (dolist (var1 gdb-var-list)
467 (if (string-equal (cadr var1) (cadr varchild))
468 (throw 'child-already-watched nil)))
469 (push varchild var-list)
470 (if (equal (nth 2 varchild) "0")
471 (gdb-enqueue-input
472 (list
473 (concat
474 "server interpreter mi \"-var-evaluate-expression "
475 (nth 1 varchild) "\"\n")
476 `(lambda () (gdb-var-evaluate-expression-handler
477 ,(nth 1 varchild) nil))))))))
478 (push var var-list)))
479 (setq gdb-var-list (nreverse var-list))))))
480
481 (defun gdb-var-update ()
482 (if (not (member 'gdb-var-update gdb-pending-triggers))
483 (progn
484 (gdb-enqueue-input
485 (list
486 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
487 "server interpreter mi \"-var-update *\"\n"
488 "-var-update *\n")
489 'gdb-var-update-handler))
490 (push 'gdb-var-update gdb-pending-triggers))))
491
492 (defconst gdb-var-update-regexp "name=\"\\(.*?\\)\"")
493
494 (defun gdb-var-update-handler ()
495 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
496 (goto-char (point-min))
497 (while (re-search-forward gdb-var-update-regexp nil t)
498 (let ((varnum (match-string 1)))
499 (gdb-enqueue-input
500 (list
501 (if (with-current-buffer gud-comint-buffer
502 (eq gud-minor-mode 'gdba))
503 (concat "server interpreter mi \"-var-evaluate-expression "
504 varnum "\"\n")
505 (concat "-var-evaluate-expression " varnum "\n"))
506 `(lambda () (gdb-var-evaluate-expression-handler
507 ,varnum t)))))))
508 (setq gdb-pending-triggers
509 (delq 'gdb-var-update gdb-pending-triggers))
510 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame))
511 ;; dummy command to update speedbar at right time
512 (gdb-enqueue-input (list "server pwd\n" 'gdb-speedbar-timer-fn))
513 ;; keep gdb-pending-triggers non-nil till end
514 (push 'gdb-speedbar-timer gdb-pending-triggers)))
515
516 (defun gdb-speedbar-timer-fn ()
517 (setq gdb-pending-triggers
518 (delq 'gdb-speedbar-timer gdb-pending-triggers))
519 (with-current-buffer gud-comint-buffer
520 (speedbar-timer-fn)))
521
522 (defun gdb-var-delete ()
523 "Delete watched expression from the speedbar."
524 (interactive)
525 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
526 (let ((text (speedbar-line-text)))
527 (string-match "\\(\\S-+\\)" text)
528 (let* ((expr (match-string 1 text))
529 (var (assoc expr gdb-var-list))
530 (varnum (cadr var)))
531 (unless (string-match "\\." varnum)
532 (gdb-enqueue-input
533 (list
534 (if (with-current-buffer gud-comint-buffer
535 (eq gud-minor-mode 'gdba))
536 (concat "server interpreter mi \"-var-delete " varnum "\"\n")
537 (concat "-var-delete " varnum "\n"))
538 'ignore))
539 (setq gdb-var-list (delq var gdb-var-list))
540 (dolist (varchild gdb-var-list)
541 (if (string-match (concat (nth 1 var) "\\.") (nth 1 varchild))
542 (setq gdb-var-list (delq varchild gdb-var-list))))
543 (setq gdb-var-changed t))))))
544
545 (defun gdb-edit-value (text token indent)
546 "Assign a value to a variable displayed in the speedbar."
547 (let* ((var (nth (- (count-lines (point-min) (point)) 2) gdb-var-list))
548 (varnum (cadr var)) (value))
549 (setq value (read-string "New value: "))
550 (gdb-enqueue-input
551 (list
552 (if (with-current-buffer gud-comint-buffer
553 (eq gud-minor-mode 'gdba))
554 (concat "server interpreter mi \"-var-assign "
555 varnum " " value "\"\n")
556 (concat "-var-assign " varnum " " value "\n"))
557 'ignore))))
558
559 (defcustom gdb-show-changed-values t
560 "If non-nil highlight values that have recently changed in the speedbar.
561 The highlighting is done with `font-lock-warning-face'."
562 :type 'boolean
563 :group 'gud
564 :version "22.1")
565
566 (defun gdb-speedbar-expand-node (text token indent)
567 "Expand the node the user clicked on.
568 TEXT is the text of the button we clicked on, a + or - item.
569 TOKEN is data related to this node.
570 INDENT is the current indentation depth."
571 (cond ((string-match "+" text) ;expand this node
572 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
573 (gdb-var-list-children token)
574 (gdbmi-var-list-children token)))
575 ((string-match "-" text) ;contract this node
576 (dolist (var gdb-var-list)
577 (if (string-match (concat token "\\.") (nth 1 var))
578 (setq gdb-var-list (delq var gdb-var-list))))
579 (setq gdb-var-changed t))))
580
581 (defun gdb-get-target-string ()
582 (with-current-buffer gud-comint-buffer
583 gud-target-name))
584 \f
585
586 ;;
587 ;; gdb buffers.
588 ;;
589 ;; Each buffer has a TYPE -- a symbol that identifies the function
590 ;; of that particular buffer.
591 ;;
592 ;; The usual gdb interaction buffer is given the type `gdba' and
593 ;; is constructed specially.
594 ;;
595 ;; Others are constructed by gdb-get-create-buffer and
596 ;; named according to the rules set forth in the gdb-buffer-rules-assoc
597
598 (defvar gdb-buffer-rules-assoc '())
599
600 (defun gdb-get-buffer (key)
601 "Return the gdb buffer tagged with type KEY.
602 The key should be one of the cars in `gdb-buffer-rules-assoc'."
603 (save-excursion
604 (gdb-look-for-tagged-buffer key (buffer-list))))
605
606 (defun gdb-get-create-buffer (key)
607 "Create a new gdb buffer of the type specified by KEY.
608 The key should be one of the cars in `gdb-buffer-rules-assoc'."
609 (or (gdb-get-buffer key)
610 (let* ((rules (assoc key gdb-buffer-rules-assoc))
611 (name (funcall (gdb-rules-name-maker rules)))
612 (new (get-buffer-create name)))
613 (with-current-buffer new
614 (let ((trigger))
615 (if (cdr (cdr rules))
616 (setq trigger (funcall (car (cdr (cdr rules))))))
617 (set (make-local-variable 'gdb-buffer-type) key)
618 (set (make-local-variable 'gud-minor-mode)
619 (with-current-buffer gud-comint-buffer gud-minor-mode))
620 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
621 (if trigger (funcall trigger)))
622 new))))
623
624 (defun gdb-rules-name-maker (rules) (car (cdr rules)))
625
626 (defun gdb-look-for-tagged-buffer (key bufs)
627 (let ((retval nil))
628 (while (and (not retval) bufs)
629 (set-buffer (car bufs))
630 (if (eq gdb-buffer-type key)
631 (setq retval (car bufs)))
632 (setq bufs (cdr bufs)))
633 retval))
634
635 ;;
636 ;; This assoc maps buffer type symbols to rules. Each rule is a list of
637 ;; at least one and possible more functions. The functions have these
638 ;; roles in defining a buffer type:
639 ;;
640 ;; NAME - Return a name for this buffer type.
641 ;;
642 ;; The remaining function(s) are optional:
643 ;;
644 ;; MODE - called in a new buffer with no arguments, should establish
645 ;; the proper mode for the buffer.
646 ;;
647
648 (defun gdb-set-buffer-rules (buffer-type &rest rules)
649 (let ((binding (assoc buffer-type gdb-buffer-rules-assoc)))
650 (if binding
651 (setcdr binding rules)
652 (push (cons buffer-type rules)
653 gdb-buffer-rules-assoc))))
654
655 ;; GUD buffers are an exception to the rules
656 (gdb-set-buffer-rules 'gdba 'error)
657
658 ;;
659 ;; Partial-output buffer : This accumulates output from a command executed on
660 ;; behalf of emacs (rather than the user).
661 ;;
662 (gdb-set-buffer-rules 'gdb-partial-output-buffer
663 'gdb-partial-output-name)
664
665 (defun gdb-partial-output-name ()
666 (concat "*partial-output-"
667 (gdb-get-target-string)
668 "*"))
669
670 \f
671 (gdb-set-buffer-rules 'gdb-inferior-io
672 'gdb-inferior-io-name
673 'gdb-inferior-io-mode)
674
675 (defun gdb-inferior-io-name ()
676 (concat "*input/output of "
677 (gdb-get-target-string)
678 "*"))
679
680 (defun gdb-display-inferior-io-buffer ()
681 "Display IO of inferior in a separate window."
682 (interactive)
683 (if gdb-use-inferior-io-buffer
684 (gdb-display-buffer
685 (gdb-get-create-buffer 'gdb-inferior-io))))
686
687 (defun gdb-frame-inferior-io-buffer ()
688 "Display IO of inferior in a new frame."
689 (interactive)
690 (if gdb-use-inferior-io-buffer
691 (let ((special-display-regexps (append special-display-regexps '(".*")))
692 (special-display-frame-alist gdb-frame-parameters))
693 (display-buffer (gdb-get-create-buffer 'gdb-inferior-io)))))
694
695 (defvar gdb-inferior-io-mode-map
696 (let ((map (make-sparse-keymap)))
697 (define-key map "\C-c\C-c" 'gdb-inferior-io-interrupt)
698 (define-key map "\C-c\C-z" 'gdb-inferior-io-stop)
699 (define-key map "\C-c\C-\\" 'gdb-inferior-io-quit)
700 (define-key map "\C-c\C-d" 'gdb-inferior-io-eof)
701 map))
702
703 (define-derived-mode gdb-inferior-io-mode comint-mode "Inferior I/O"
704 "Major mode for gdb inferior-io."
705 :syntax-table nil :abbrev-table nil
706 ;; We want to use comint because it has various nifty and familiar
707 ;; features. We don't need a process, but comint wants one, so create
708 ;; a dummy one.
709 (make-comint-in-buffer
710 (substring (buffer-name) 1 (- (length (buffer-name)) 1))
711 (current-buffer) "hexl")
712 (setq comint-input-sender 'gdb-inferior-io-sender))
713
714 (defun gdb-inferior-io-sender (proc string)
715 ;; PROC is the pseudo-process created to satisfy comint.
716 (with-current-buffer (process-buffer proc)
717 (setq proc (get-buffer-process gud-comint-buffer))
718 (process-send-string proc string)
719 (process-send-string proc "\n")))
720
721 (defun gdb-inferior-io-interrupt ()
722 "Interrupt the program being debugged."
723 (interactive)
724 (interrupt-process
725 (get-buffer-process gud-comint-buffer) comint-ptyp))
726
727 (defun gdb-inferior-io-quit ()
728 "Send quit signal to the program being debugged."
729 (interactive)
730 (quit-process
731 (get-buffer-process gud-comint-buffer) comint-ptyp))
732
733 (defun gdb-inferior-io-stop ()
734 "Stop the program being debugged."
735 (interactive)
736 (stop-process
737 (get-buffer-process gud-comint-buffer) comint-ptyp))
738
739 (defun gdb-inferior-io-eof ()
740 "Send end-of-file to the program being debugged."
741 (interactive)
742 (process-send-eof
743 (get-buffer-process gud-comint-buffer)))
744 \f
745
746 ;;
747 ;; gdb communications
748 ;;
749
750 ;; INPUT: things sent to gdb
751 ;;
752 ;; The queues are lists. Each element is either a string (indicating user or
753 ;; user-like input) or a list of the form:
754 ;;
755 ;; (INPUT-STRING HANDLER-FN)
756 ;;
757 ;; The handler function will be called from the partial-output buffer when the
758 ;; command completes. This is the way to write commands which invoke gdb
759 ;; commands autonomously.
760 ;;
761 ;; These lists are consumed tail first.
762 ;;
763
764 (defun gdb-send (proc string)
765 "A comint send filter for gdb.
766 This filter may simply queue input for a later time."
767 (let ((item (concat string "\n")))
768 (if gud-running
769 (progn
770 (if gdb-enable-debug-log (push (cons 'send item) gdb-debug-log))
771 (process-send-string proc item))
772 (gdb-enqueue-input item))))
773
774 ;; Note: Stuff enqueued here will be sent to the next prompt, even if it
775 ;; is a query, or other non-top-level prompt.
776
777 (defun gdb-enqueue-input (item)
778 (if gdb-prompting
779 (progn
780 (gdb-send-item item)
781 (setq gdb-prompting nil))
782 (push item gdb-input-queue)))
783
784 (defun gdb-dequeue-input ()
785 (let ((queue gdb-input-queue))
786 (and queue
787 (let ((last (car (last queue))))
788 (unless (nbutlast queue) (setq gdb-input-queue '()))
789 last))))
790
791 (defun gdb-send-item (item)
792 (setq gdb-flush-pending-output nil)
793 (if gdb-enable-debug-log (push (cons 'send-item item) gdb-debug-log))
794 (setq gdb-current-item item)
795 (with-current-buffer gud-comint-buffer
796 (if (eq gud-minor-mode 'gdba)
797 (if (stringp item)
798 (progn
799 (setq gdb-output-sink 'user)
800 (process-send-string (get-buffer-process gud-comint-buffer) item))
801 (progn
802 (gdb-clear-partial-output)
803 (setq gdb-output-sink 'pre-emacs)
804 (process-send-string (get-buffer-process gud-comint-buffer)
805 (car item))))
806 ;; case: eq gud-minor-mode 'gdbmi
807 (gdb-clear-partial-output)
808 (setq gdb-output-sink 'emacs)
809 (process-send-string (get-buffer-process gud-comint-buffer)
810 (car item)))))
811 \f
812 ;;
813 ;; output -- things gdb prints to emacs
814 ;;
815 ;; GDB output is a stream interrupted by annotations.
816 ;; Annotations can be recognized by their beginning
817 ;; with \C-j\C-z\C-z<tag><opt>\C-j
818 ;;
819 ;; The tag is a string obeying symbol syntax.
820 ;;
821 ;; The optional part `<opt>' can be either the empty string
822 ;; or a space followed by more data relating to the annotation.
823 ;; For example, the SOURCE annotation is followed by a filename,
824 ;; line number and various useless goo. This data must not include
825 ;; any newlines.
826 ;;
827
828 (defcustom gud-gdba-command-name "gdb -annotate=3"
829 "Default command to execute an executable under the GDB-UI debugger."
830 :type 'string
831 :group 'gud
832 :version "22.1")
833
834 (defvar gdb-annotation-rules
835 '(("pre-prompt" gdb-pre-prompt)
836 ("prompt" gdb-prompt)
837 ("commands" gdb-subprompt)
838 ("overload-choice" gdb-subprompt)
839 ("query" gdb-subprompt)
840 ;; Need this prompt for GDB 6.1
841 ("nquery" gdb-subprompt)
842 ("prompt-for-continue" gdb-subprompt)
843 ("post-prompt" gdb-post-prompt)
844 ("source" gdb-source)
845 ("starting" gdb-starting)
846 ("exited" gdb-exited)
847 ("signalled" gdb-exited)
848 ("signal" gdb-stopping)
849 ("breakpoint" gdb-stopping)
850 ("watchpoint" gdb-stopping)
851 ("frame-begin" gdb-frame-begin)
852 ("stopped" gdb-stopped)
853 ) "An assoc mapping annotation tags to functions which process them.")
854
855 (defun gdb-resync()
856 (setq gdb-flush-pending-output t)
857 (setq gud-running nil)
858 (setq gdb-output-sink 'user)
859 (setq gdb-input-queue nil)
860 (setq gdb-pending-triggers nil)
861 (setq gdb-prompting t))
862
863 (defconst gdb-source-spec-regexp
864 "\\(.*\\):\\([0-9]*\\):[0-9]*:[a-z]*:\\(0x[a-f0-9]*\\)")
865
866 ;; Do not use this except as an annotation handler.
867 (defun gdb-source (args)
868 (string-match gdb-source-spec-regexp args)
869 ;; Extract the frame position from the marker.
870 (setq gud-last-frame
871 (cons
872 (match-string 1 args)
873 (string-to-number (match-string 2 args))))
874 (setq gdb-current-address (match-string 3 args))
875 ;; cover for auto-display output which comes *before*
876 ;; stopped annotation
877 (if (eq gdb-output-sink 'inferior) (setq gdb-output-sink 'user)))
878
879 (defun gdb-pre-prompt (ignored)
880 "An annotation handler for `pre-prompt'.
881 This terminates the collection of output from a previous command if that
882 happens to be in effect."
883 (let ((sink gdb-output-sink))
884 (cond
885 ((eq sink 'user) t)
886 ((eq sink 'emacs)
887 (setq gdb-output-sink 'post-emacs))
888 (t
889 (gdb-resync)
890 (error "Phase error in gdb-pre-prompt (got %s)" sink)))))
891
892 (defun gdb-prompt (ignored)
893 "An annotation handler for `prompt'.
894 This sends the next command (if any) to gdb."
895 (when gdb-first-prompt (gdb-ann3))
896 (let ((sink gdb-output-sink))
897 (cond
898 ((eq sink 'user) t)
899 ((eq sink 'post-emacs)
900 (setq gdb-output-sink 'user)
901 (let ((handler
902 (car (cdr gdb-current-item))))
903 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
904 (funcall handler))))
905 (t
906 (gdb-resync)
907 (error "Phase error in gdb-prompt (got %s)" sink))))
908 (let ((input (gdb-dequeue-input)))
909 (if input
910 (gdb-send-item input)
911 (progn
912 (setq gdb-prompting t)
913 (gud-display-frame)))))
914
915 (defun gdb-subprompt (ignored)
916 "An annotation handler for non-top-level prompts."
917 (setq gdb-prompting t))
918
919 (defun gdb-starting (ignored)
920 "An annotation handler for `starting'.
921 This says that I/O for the subprocess is now the program being debugged,
922 not GDB."
923 (setq gdb-active-process t)
924 (let ((sink gdb-output-sink))
925 (cond
926 ((eq sink 'user)
927 (progn
928 (setq gud-running t)
929 (if gdb-use-inferior-io-buffer
930 (setq gdb-output-sink 'inferior))))
931 (t
932 (gdb-resync)
933 (error "Unexpected `starting' annotation")))))
934
935 (defun gdb-stopping (ignored)
936 "An annotation handler for `breakpoint' and other annotations.
937 They say that I/O for the subprocess is now GDB, not the program
938 being debugged."
939 (if gdb-use-inferior-io-buffer
940 (let ((sink gdb-output-sink))
941 (cond
942 ((eq sink 'inferior)
943 (setq gdb-output-sink 'user))
944 (t
945 (gdb-resync)
946 (error "Unexpected stopping annotation"))))))
947
948 (defun gdb-exited (ignored)
949 "An annotation handler for `exited' and `signalled'.
950 They say that I/O for the subprocess is now GDB, not the program
951 being debugged and that the program is no longer running. This
952 function is used to change the focus of GUD tooltips to #define
953 directives."
954 (setq gdb-active-process nil)
955 (gdb-stopping ignored))
956
957 (defun gdb-frame-begin (ignored)
958 (let ((sink gdb-output-sink))
959 (cond
960 ((eq sink 'inferior)
961 (setq gdb-output-sink 'user))
962 ((eq sink 'user) t)
963 ((eq sink 'emacs) t)
964 (t
965 (gdb-resync)
966 (error "Unexpected frame-begin annotation (%S)" sink)))))
967
968 (defun gdb-stopped (ignored)
969 "An annotation handler for `stopped'.
970 It is just like `gdb-stopping', except that if we already set the output
971 sink to `user' in `gdb-stopping', that is fine."
972 (setq gud-running nil)
973 (let ((sink gdb-output-sink))
974 (cond
975 ((eq sink 'inferior)
976 (setq gdb-output-sink 'user))
977 ((eq sink 'user) t)
978 (t
979 (gdb-resync)
980 (error "Unexpected stopped annotation")))))
981
982 (defun gdb-post-prompt (ignored)
983 "An annotation handler for `post-prompt'.
984 This begins the collection of output from the current command if that
985 happens to be appropriate."
986 (unless gdb-pending-triggers
987 (gdb-get-current-frame)
988 (gdb-invalidate-frames)
989 (gdb-invalidate-breakpoints)
990 (gdb-invalidate-assembler)
991 (gdb-invalidate-registers)
992 (gdb-invalidate-memory)
993 (gdb-invalidate-locals)
994 (gdb-invalidate-threads)
995 (unless (eq system-type 'darwin) ;Breaks on Darwin's GDB-5.3.
996 ;; FIXME: with GDB-6 on Darwin, this might very well work.
997 ;; only needed/used with speedbar/watch expressions
998 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame))
999 (setq gdb-var-changed t) ; force update
1000 (dolist (var gdb-var-list)
1001 (setcar (nthcdr 5 var) nil))
1002 (gdb-var-update))))
1003 (let ((sink gdb-output-sink))
1004 (cond
1005 ((eq sink 'user) t)
1006 ((eq sink 'pre-emacs)
1007 (setq gdb-output-sink 'emacs))
1008 (t
1009 (gdb-resync)
1010 (error "Phase error in gdb-post-prompt (got %s)" sink)))))
1011
1012 (defun gud-gdba-marker-filter (string)
1013 "A gud marker filter for gdb. Handle a burst of output from GDB."
1014 (if gdb-flush-pending-output
1015 nil
1016 (if gdb-enable-debug-log (push (cons 'recv string) gdb-debug-log))
1017 ;; Recall the left over gud-marker-acc from last time
1018 (setq gud-marker-acc (concat gud-marker-acc string))
1019 ;; Start accumulating output for the GUD buffer
1020 (let ((output ""))
1021 ;;
1022 ;; Process all the complete markers in this chunk.
1023 (while (string-match "\n\032\032\\(.*\\)\n" gud-marker-acc)
1024 (let ((annotation (match-string 1 gud-marker-acc)))
1025 ;;
1026 ;; Stuff prior to the match is just ordinary output.
1027 ;; It is either concatenated to OUTPUT or directed
1028 ;; elsewhere.
1029 (setq output
1030 (gdb-concat-output
1031 output
1032 (substring gud-marker-acc 0 (match-beginning 0))))
1033 ;;
1034 ;; Take that stuff off the gud-marker-acc.
1035 (setq gud-marker-acc (substring gud-marker-acc (match-end 0)))
1036 ;;
1037 ;; Parse the tag from the annotation, and maybe its arguments.
1038 (string-match "\\(\\S-*\\) ?\\(.*\\)" annotation)
1039 (let* ((annotation-type (match-string 1 annotation))
1040 (annotation-arguments (match-string 2 annotation))
1041 (annotation-rule (assoc annotation-type
1042 gdb-annotation-rules)))
1043 ;; Call the handler for this annotation.
1044 (if annotation-rule
1045 (funcall (car (cdr annotation-rule))
1046 annotation-arguments)
1047 ;; Else the annotation is not recognized. Ignore it silently,
1048 ;; so that GDB can add new annotations without causing
1049 ;; us to blow up.
1050 ))))
1051 ;;
1052 ;; Does the remaining text end in a partial line?
1053 ;; If it does, then keep part of the gud-marker-acc until we get more.
1054 (if (string-match "\n\\'\\|\n\032\\'\\|\n\032\032.*\\'"
1055 gud-marker-acc)
1056 (progn
1057 ;; Everything before the potential marker start can be output.
1058 (setq output
1059 (gdb-concat-output output
1060 (substring gud-marker-acc 0
1061 (match-beginning 0))))
1062 ;;
1063 ;; Everything after, we save, to combine with later input.
1064 (setq gud-marker-acc (substring gud-marker-acc
1065 (match-beginning 0))))
1066 ;;
1067 ;; In case we know the gud-marker-acc contains no partial annotations:
1068 (progn
1069 (setq output (gdb-concat-output output gud-marker-acc))
1070 (setq gud-marker-acc "")))
1071 output)))
1072
1073 (defun gdb-concat-output (so-far new)
1074 (let ((sink gdb-output-sink))
1075 (cond
1076 ((eq sink 'user) (concat so-far new))
1077 ((or (eq sink 'pre-emacs) (eq sink 'post-emacs)) so-far)
1078 ((eq sink 'emacs)
1079 (gdb-append-to-partial-output new)
1080 so-far)
1081 ((eq sink 'inferior)
1082 (gdb-append-to-inferior-io new)
1083 so-far)
1084 (t
1085 (gdb-resync)
1086 (error "Bogon output sink %S" sink)))))
1087
1088 (defun gdb-append-to-partial-output (string)
1089 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
1090 (goto-char (point-max))
1091 (insert string)))
1092
1093 (defun gdb-clear-partial-output ()
1094 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
1095 (erase-buffer)))
1096
1097 (defun gdb-append-to-inferior-io (string)
1098 (with-current-buffer (gdb-get-create-buffer 'gdb-inferior-io)
1099 (goto-char (point-max))
1100 (insert-before-markers string))
1101 (if (not (string-equal string ""))
1102 (gdb-display-buffer (gdb-get-create-buffer 'gdb-inferior-io))))
1103
1104 (defun gdb-clear-inferior-io ()
1105 (with-current-buffer (gdb-get-create-buffer 'gdb-inferior-io)
1106 (erase-buffer)))
1107 \f
1108
1109 ;; One trick is to have a command who's output is always available in a buffer
1110 ;; of it's own, and is always up to date. We build several buffers of this
1111 ;; type.
1112 ;;
1113 ;; There are two aspects to this: gdb has to tell us when the output for that
1114 ;; command might have changed, and we have to be able to run the command
1115 ;; behind the user's back.
1116 ;;
1117 ;; The output phasing associated with the variable gdb-output-sink
1118 ;; help us to run commands behind the user's back.
1119 ;;
1120 ;; Below is the code for specificly managing buffers of output from one
1121 ;; command.
1122 ;;
1123
1124 ;; The trigger function is suitable for use in the assoc GDB-ANNOTATION-RULES
1125 ;; It adds an input for the command we are tracking. It should be the
1126 ;; annotation rule binding of whatever gdb sends to tell us this command
1127 ;; might have changed it's output.
1128 ;;
1129 ;; NAME is the function name. DEMAND-PREDICATE tests if output is really needed.
1130 ;; GDB-COMMAND is a string of such. OUTPUT-HANDLER is the function bound to the
1131 ;; input in the input queue (see comment about ``gdb communications'' above).
1132
1133 (defmacro def-gdb-auto-update-trigger (name demand-predicate gdb-command
1134 output-handler)
1135 `(defun ,name (&optional ignored)
1136 (if (and (,demand-predicate)
1137 (not (member ',name
1138 gdb-pending-triggers)))
1139 (progn
1140 (gdb-enqueue-input
1141 (list ,gdb-command ',output-handler))
1142 (push ',name gdb-pending-triggers)))))
1143
1144 (defmacro def-gdb-auto-update-handler (name trigger buf-key custom-defun)
1145 `(defun ,name ()
1146 (setq gdb-pending-triggers
1147 (delq ',trigger
1148 gdb-pending-triggers))
1149 (let ((buf (gdb-get-buffer ',buf-key)))
1150 (and buf
1151 (with-current-buffer buf
1152 (let ((p (point))
1153 (buffer-read-only nil))
1154 (erase-buffer)
1155 (insert-buffer-substring (gdb-get-create-buffer
1156 'gdb-partial-output-buffer))
1157 (goto-char p)))))
1158 ;; put customisation here
1159 (,custom-defun)))
1160
1161 (defmacro def-gdb-auto-updated-buffer (buffer-key
1162 trigger-name gdb-command
1163 output-handler-name custom-defun)
1164 `(progn
1165 (def-gdb-auto-update-trigger ,trigger-name
1166 ;; The demand predicate:
1167 (lambda () (gdb-get-buffer ',buffer-key))
1168 ,gdb-command
1169 ,output-handler-name)
1170 (def-gdb-auto-update-handler ,output-handler-name
1171 ,trigger-name ,buffer-key ,custom-defun)))
1172
1173 \f
1174 ;;
1175 ;; Breakpoint buffer : This displays the output of `info breakpoints'.
1176 ;;
1177 (gdb-set-buffer-rules 'gdb-breakpoints-buffer
1178 'gdb-breakpoints-buffer-name
1179 'gdb-breakpoints-mode)
1180
1181 (def-gdb-auto-updated-buffer gdb-breakpoints-buffer
1182 ;; This defines the auto update rule for buffers of type
1183 ;; `gdb-breakpoints-buffer'.
1184 ;;
1185 ;; It defines a function to serve as the annotation handler that
1186 ;; handles the `foo-invalidated' message. That function is called:
1187 gdb-invalidate-breakpoints
1188 ;;
1189 ;; To update the buffer, this command is sent to gdb.
1190 "server info breakpoints\n"
1191 ;;
1192 ;; This also defines a function to be the handler for the output
1193 ;; from the command above. That function will copy the output into
1194 ;; the appropriately typed buffer. That function will be called:
1195 gdb-info-breakpoints-handler
1196 ;; buffer specific functions
1197 gdb-info-breakpoints-custom)
1198
1199 (defconst breakpoint-xpm-data
1200 "/* XPM */
1201 static char *magick[] = {
1202 /* columns rows colors chars-per-pixel */
1203 \"10 10 2 1\",
1204 \" c red\",
1205 \"+ c None\",
1206 /* pixels */
1207 \"+++ +++\",
1208 \"++ ++\",
1209 \"+ +\",
1210 \" \",
1211 \" \",
1212 \" \",
1213 \" \",
1214 \"+ +\",
1215 \"++ ++\",
1216 \"+++ +++\",
1217 };"
1218 "XPM data used for breakpoint icon.")
1219
1220 (defconst breakpoint-enabled-pbm-data
1221 "P1
1222 10 10\",
1223 0 0 0 0 1 1 1 1 0 0 0 0
1224 0 0 0 1 1 1 1 1 1 0 0 0
1225 0 0 1 1 1 1 1 1 1 1 0 0
1226 0 1 1 1 1 1 1 1 1 1 1 0
1227 0 1 1 1 1 1 1 1 1 1 1 0
1228 0 1 1 1 1 1 1 1 1 1 1 0
1229 0 1 1 1 1 1 1 1 1 1 1 0
1230 0 0 1 1 1 1 1 1 1 1 0 0
1231 0 0 0 1 1 1 1 1 1 0 0 0
1232 0 0 0 0 1 1 1 1 0 0 0 0"
1233 "PBM data used for enabled breakpoint icon.")
1234
1235 (defconst breakpoint-disabled-pbm-data
1236 "P1
1237 10 10\",
1238 0 0 1 0 1 0 1 0 0 0
1239 0 1 0 1 0 1 0 1 0 0
1240 1 0 1 0 1 0 1 0 1 0
1241 0 1 0 1 0 1 0 1 0 1
1242 1 0 1 0 1 0 1 0 1 0
1243 0 1 0 1 0 1 0 1 0 1
1244 1 0 1 0 1 0 1 0 1 0
1245 0 1 0 1 0 1 0 1 0 1
1246 0 0 1 0 1 0 1 0 1 0
1247 0 0 0 1 0 1 0 1 0 0"
1248 "PBM data used for disabled breakpoint icon.")
1249
1250 (defvar breakpoint-enabled-icon nil
1251 "Icon for enabled breakpoint in display margin.")
1252
1253 (defvar breakpoint-disabled-icon nil
1254 "Icon for disabled breakpoint in display margin.")
1255
1256 ;; Bitmap for breakpoint in fringe
1257 (and (display-images-p)
1258 (define-fringe-bitmap 'breakpoint
1259 "\x3c\x7e\xff\xff\xff\xff\x7e\x3c"))
1260
1261 (defface breakpoint-enabled
1262 '((t
1263 :foreground "red"
1264 :weight bold))
1265 "Face for enabled breakpoint icon in fringe."
1266 :group 'gud)
1267 ;; compatibility alias for old name
1268 (put 'breakpoint-enabled-bitmap-face 'face-alias 'breakpoint-enabled)
1269
1270 (defface breakpoint-disabled
1271 ;; We use different values of grey for different background types,
1272 ;; so that on low-color displays it will end up as something visible
1273 ;; if it has to be approximated.
1274 '((((background dark)) :foreground "grey60")
1275 (((background light)) :foreground "grey40"))
1276 "Face for disabled breakpoint icon in fringe."
1277 :group 'gud)
1278 ;; compatibility alias for old name
1279 (put 'breakpoint-disabled-bitmap-face 'face-alias 'breakpoint-disabled)
1280
1281 ;;-put breakpoint icons in relevant margins (even those set in the GUD buffer)
1282 (defun gdb-info-breakpoints-custom ()
1283 (let ((flag) (bptno))
1284 ;; remove all breakpoint-icons in source buffers but not assembler buffer
1285 (dolist (buffer (buffer-list))
1286 (with-current-buffer buffer
1287 (if (and (eq gud-minor-mode 'gdba)
1288 (not (string-match "\\`\\*.+\\*\\'" (buffer-name))))
1289 (gdb-remove-breakpoint-icons (point-min) (point-max)))))
1290 (with-current-buffer (gdb-get-buffer 'gdb-breakpoints-buffer)
1291 (save-excursion
1292 (goto-char (point-min))
1293 (while (< (point) (- (point-max) 1))
1294 (forward-line 1)
1295 (if (looking-at "[^\t].*breakpoint")
1296 (progn
1297 (looking-at "\\([0-9]+\\)\\s-+\\S-+\\s-+\\S-+\\s-+\\(.\\)")
1298 (setq bptno (match-string 1))
1299 (setq flag (char-after (match-beginning 2)))
1300 (beginning-of-line)
1301 (if (re-search-forward " in .* at\\s-+" nil t)
1302 (progn
1303 (looking-at "\\(\\S-+\\):\\([0-9]+\\)")
1304 (let ((line (match-string 2)) (buffer-read-only nil)
1305 (file (match-string 1)))
1306 (add-text-properties (line-beginning-position)
1307 (line-end-position)
1308 '(mouse-face highlight
1309 help-echo "mouse-2, RET: visit breakpoint"))
1310 (unless (file-exists-p file)
1311 (setq file (cdr (assoc bptno gdb-location-alist))))
1312 (if (and file
1313 (not (string-equal file "File not found")))
1314 (with-current-buffer (find-file-noselect file)
1315 (set (make-local-variable 'gud-minor-mode)
1316 'gdba)
1317 (set (make-local-variable 'tool-bar-map)
1318 gud-tool-bar-map)
1319 ;; only want one breakpoint icon at each
1320 ;; location
1321 (save-excursion
1322 (goto-line (string-to-number line))
1323 (gdb-put-breakpoint-icon (eq flag ?y) bptno)))
1324 (gdb-enqueue-input
1325 (list
1326 (concat "list "
1327 (match-string-no-properties 1) ":1\n")
1328 'ignore))
1329 (gdb-enqueue-input
1330 (list "info source\n"
1331 `(lambda () (gdb-get-location
1332 ,bptno ,line ,flag))))))))))
1333 (end-of-line)))))
1334 (if (gdb-get-buffer 'gdb-assembler-buffer) (gdb-assembler-custom)))
1335
1336 (defun gdb-mouse-set-clear-breakpoint (event)
1337 "Set/clear breakpoint in left fringe/margin with mouse click."
1338 (interactive "e")
1339 (mouse-minibuffer-check event)
1340 (let ((posn (event-end event)))
1341 (if (numberp (posn-point posn))
1342 (with-selected-window (posn-window posn)
1343 (save-excursion
1344 (goto-char (posn-point posn))
1345 (if (or (posn-object posn)
1346 (eq (car (fringe-bitmaps-at-pos (posn-point posn)))
1347 'breakpoint))
1348 (gud-remove nil)
1349 (gud-break nil)))))))
1350
1351 (defun gdb-mouse-toggle-breakpoint (event)
1352 "Enable/disable breakpoint in left fringe/margin with mouse click."
1353 (interactive "e")
1354 (mouse-minibuffer-check event)
1355 (let ((posn (event-end event)))
1356 (if (numberp (posn-point posn))
1357 (with-selected-window (posn-window posn)
1358 (save-excursion
1359 (goto-char (posn-point posn))
1360 (if
1361 ; (or
1362 (posn-object posn)
1363 ; (eq (car (fringe-bitmaps-at-pos (posn-point posn)))
1364 ; 'breakpoint))
1365 (gdb-enqueue-input
1366 (list
1367 (let ((bptno (get-text-property
1368 0 'gdb-bptno (car (posn-string posn)))))
1369 (concat
1370 (if (get-text-property
1371 0 'gdb-enabled (car (posn-string posn)))
1372 "disable "
1373 "enable ")
1374 bptno "\n")) 'ignore))))))))
1375
1376 (defun gdb-breakpoints-buffer-name ()
1377 (with-current-buffer gud-comint-buffer
1378 (concat "*breakpoints of " (gdb-get-target-string) "*")))
1379
1380 (defun gdb-display-breakpoints-buffer ()
1381 "Display status of user-settable breakpoints."
1382 (interactive)
1383 (gdb-display-buffer
1384 (gdb-get-create-buffer 'gdb-breakpoints-buffer)))
1385
1386 (defconst gdb-frame-parameters
1387 '((height . 14) (width . 80)
1388 (unsplittable . t)
1389 (tool-bar-lines . nil)
1390 (menu-bar-lines . nil)
1391 (minibuffer . nil)))
1392
1393 (defun gdb-frame-breakpoints-buffer ()
1394 "Display status of user-settable breakpoints in a new frame."
1395 (interactive)
1396 (let ((special-display-regexps (append special-display-regexps '(".*")))
1397 (special-display-frame-alist gdb-frame-parameters))
1398 (display-buffer (gdb-get-create-buffer 'gdb-breakpoints-buffer))))
1399
1400 (defvar gdb-breakpoints-mode-map
1401 (let ((map (make-sparse-keymap))
1402 (menu (make-sparse-keymap "Breakpoints")))
1403 (define-key menu [quit] '("Quit" . kill-this-buffer))
1404 (define-key menu [goto] '("Goto" . gdb-goto-breakpoint))
1405 (define-key menu [delete] '("Delete" . gdb-delete-breakpoint))
1406 (define-key menu [toggle] '("Toggle" . gdb-toggle-breakpoint))
1407 (suppress-keymap map)
1408 (define-key map [menu-bar breakpoints] (cons "Breakpoints" menu))
1409 (define-key map " " 'gdb-toggle-breakpoint)
1410 (define-key map "d" 'gdb-delete-breakpoint)
1411 (define-key map "q" 'kill-this-buffer)
1412 (define-key map "\r" 'gdb-goto-breakpoint)
1413 (define-key map [mouse-2] 'gdb-goto-breakpoint)
1414 (define-key map [follow-link] 'mouse-face)
1415 map))
1416
1417 (defun gdb-breakpoints-mode ()
1418 "Major mode for gdb breakpoints.
1419
1420 \\{gdb-breakpoints-mode-map}"
1421 (kill-all-local-variables)
1422 (setq major-mode 'gdb-breakpoints-mode)
1423 (setq mode-name "Breakpoints")
1424 (use-local-map gdb-breakpoints-mode-map)
1425 (setq buffer-read-only t)
1426 (run-mode-hooks 'gdb-breakpoints-mode-hook)
1427 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
1428 'gdb-invalidate-breakpoints
1429 'gdbmi-invalidate-breakpoints))
1430
1431 (defun gdb-toggle-breakpoint ()
1432 "Enable/disable breakpoint at current line."
1433 (interactive)
1434 (save-excursion
1435 (beginning-of-line 1)
1436 (if (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
1437 (looking-at "\\([0-9]+\\).*point\\s-*\\S-*\\s-*\\(.\\)")
1438 (looking-at
1439 "\\([0-9]+\\)\\s-*\\S-*\\s-*\\S-*\\s-*\\(.\\)\\s-*\\S-*\\s-*\\S-*:[0-9]+"))
1440 (gdb-enqueue-input
1441 (list
1442 (concat gdb-server-prefix
1443 (if (eq ?y (char-after (match-beginning 2)))
1444 "disable "
1445 "enable ")
1446 (match-string 1) "\n") 'ignore))
1447 (error "Not recognized as break/watchpoint line"))))
1448
1449 (defun gdb-delete-breakpoint ()
1450 "Delete the breakpoint at current line."
1451 (interactive)
1452 (beginning-of-line 1)
1453 (if (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
1454 (looking-at "\\([0-9]+\\).*point\\s-*\\S-*\\s-*\\(.\\)")
1455 (looking-at
1456 "\\([0-9]+\\)\\s-*\\S-*\\s-*\\S-*\\s-*.\\s-*\\S-*\\s-*\\S-*:[0-9]+"))
1457 (gdb-enqueue-input
1458 (list
1459 (concat gdb-server-prefix "delete " (match-string 1) "\n") 'ignore))
1460 (error "Not recognized as break/watchpoint line")))
1461
1462 (defun gdb-goto-breakpoint (&optional event)
1463 "Display the breakpoint location specified at current line."
1464 (interactive (list last-input-event))
1465 (if event (mouse-set-point event))
1466 (save-excursion
1467 (beginning-of-line 1)
1468 (if (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
1469 (looking-at "\\([0-9]+\\) .* in .* at\\s-+\\(\\S-*\\):\\([0-9]+\\)")
1470 (looking-at
1471 "\\([0-9]+\\)\\s-*\\S-*\\s-*\\S-*\\s-*.\\s-*\\S-*\\s-*\
1472 \\(\\S-*\\):\\([0-9]+\\)"))
1473 (let ((bptno (match-string 1))
1474 (file (match-string 2))
1475 (line (match-string 3)))
1476 (save-selected-window
1477 (let* ((buf (find-file-noselect
1478 (if (file-exists-p file) file
1479 (cdr (assoc bptno gdb-location-alist)))))
1480 (window (display-buffer buf)))
1481 (with-current-buffer buf
1482 (goto-line (string-to-number line))
1483 (set-window-point window (point))))))
1484 (error "Not recognized as break/watchpoint line"))))
1485 \f
1486
1487 ;; Frames buffer. This displays a perpetually correct bactracktrace
1488 ;; (from the command `where').
1489 ;;
1490 ;; Alas, if your stack is deep, it is costly.
1491 ;;
1492 (gdb-set-buffer-rules 'gdb-stack-buffer
1493 'gdb-stack-buffer-name
1494 'gdb-frames-mode)
1495
1496 (def-gdb-auto-updated-buffer gdb-stack-buffer
1497 gdb-invalidate-frames
1498 "server where\n"
1499 gdb-info-frames-handler
1500 gdb-info-frames-custom)
1501
1502 (defun gdb-info-frames-custom ()
1503 (with-current-buffer (gdb-get-buffer 'gdb-stack-buffer)
1504 (save-excursion
1505 (let ((buffer-read-only nil))
1506 (goto-char (point-min))
1507 (while (< (point) (point-max))
1508 (add-text-properties (line-beginning-position) (line-end-position)
1509 '(mouse-face highlight
1510 help-echo "mouse-2, RET: Select frame"))
1511 (beginning-of-line)
1512 (when (and (looking-at "^#\\([0-9]+\\)")
1513 (equal (match-string 1) gdb-current-stack-level))
1514 (put-text-property (line-beginning-position) (line-end-position)
1515 'face '(:inverse-video t)))
1516 (forward-line 1))))))
1517
1518 (defun gdb-stack-buffer-name ()
1519 (with-current-buffer gud-comint-buffer
1520 (concat "*stack frames of " (gdb-get-target-string) "*")))
1521
1522 (defun gdb-display-stack-buffer ()
1523 "Display backtrace of current stack."
1524 (interactive)
1525 (gdb-display-buffer
1526 (gdb-get-create-buffer 'gdb-stack-buffer)))
1527
1528 (defun gdb-frame-stack-buffer ()
1529 "Display backtrace of current stack in a new frame."
1530 (interactive)
1531 (let ((special-display-regexps (append special-display-regexps '(".*")))
1532 (special-display-frame-alist gdb-frame-parameters))
1533 (display-buffer (gdb-get-create-buffer 'gdb-stack-buffer))))
1534
1535 (defvar gdb-frames-mode-map
1536 (let ((map (make-sparse-keymap)))
1537 (suppress-keymap map)
1538 (define-key map "q" 'kill-this-buffer)
1539 (define-key map "\r" 'gdb-frames-select)
1540 (define-key map [mouse-2] 'gdb-frames-select)
1541 (define-key map [follow-link] 'mouse-face)
1542 map))
1543
1544 (defun gdb-frames-mode ()
1545 "Major mode for gdb frames.
1546
1547 \\{gdb-frames-mode-map}"
1548 (kill-all-local-variables)
1549 (setq major-mode 'gdb-frames-mode)
1550 (setq mode-name "Frames")
1551 (setq buffer-read-only t)
1552 (use-local-map gdb-frames-mode-map)
1553 (font-lock-mode -1)
1554 (run-mode-hooks 'gdb-frames-mode-hook)
1555 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
1556 'gdb-invalidate-frames
1557 'gdbmi-invalidate-frames))
1558
1559 (defun gdb-get-frame-number ()
1560 (save-excursion
1561 (let* ((pos (re-search-backward "^#*\\([0-9]*\\)" nil t))
1562 (n (or (and pos (match-string-no-properties 1)) "0")))
1563 n)))
1564
1565 (defun gdb-frames-select (&optional event)
1566 "Select the frame and display the relevant source."
1567 (interactive (list last-input-event))
1568 (if event (mouse-set-point event))
1569 (gdb-enqueue-input
1570 (list (concat gdb-server-prefix "frame "
1571 (gdb-get-frame-number) "\n") 'ignore))
1572 (gud-display-frame))
1573 \f
1574
1575 ;; Threads buffer. This displays a selectable thread list.
1576 ;;
1577 (gdb-set-buffer-rules 'gdb-threads-buffer
1578 'gdb-threads-buffer-name
1579 'gdb-threads-mode)
1580
1581 (def-gdb-auto-updated-buffer gdb-threads-buffer
1582 gdb-invalidate-threads
1583 (concat gdb-server-prefix "info threads\n")
1584 gdb-info-threads-handler
1585 gdb-info-threads-custom)
1586
1587 (defun gdb-info-threads-custom ()
1588 (with-current-buffer (gdb-get-buffer 'gdb-threads-buffer)
1589 (let ((buffer-read-only nil))
1590 (goto-char (point-min))
1591 (while (< (point) (point-max))
1592 (add-text-properties (line-beginning-position) (line-end-position)
1593 '(mouse-face highlight
1594 help-echo "mouse-2, RET: select thread"))
1595 (forward-line 1)))))
1596
1597 (defun gdb-threads-buffer-name ()
1598 (with-current-buffer gud-comint-buffer
1599 (concat "*threads of " (gdb-get-target-string) "*")))
1600
1601 (defun gdb-display-threads-buffer ()
1602 "Display IDs of currently known threads."
1603 (interactive)
1604 (gdb-display-buffer
1605 (gdb-get-create-buffer 'gdb-threads-buffer)))
1606
1607 (defun gdb-frame-threads-buffer ()
1608 "Display IDs of currently known threads in a new frame."
1609 (interactive)
1610 (let ((special-display-regexps (append special-display-regexps '(".*")))
1611 (special-display-frame-alist gdb-frame-parameters))
1612 (display-buffer (gdb-get-create-buffer 'gdb-threads-buffer))))
1613
1614 (defvar gdb-threads-mode-map
1615 (let ((map (make-sparse-keymap)))
1616 (suppress-keymap map)
1617 (define-key map "q" 'kill-this-buffer)
1618 (define-key map "\r" 'gdb-threads-select)
1619 (define-key map [mouse-2] 'gdb-threads-select)
1620 map))
1621
1622 (defun gdb-threads-mode ()
1623 "Major mode for gdb frames.
1624
1625 \\{gdb-threads-mode-map}"
1626 (kill-all-local-variables)
1627 (setq major-mode 'gdb-threads-mode)
1628 (setq mode-name "Threads")
1629 (setq buffer-read-only t)
1630 (use-local-map gdb-threads-mode-map)
1631 (run-mode-hooks 'gdb-threads-mode-hook)
1632 'gdb-invalidate-threads)
1633
1634 (defun gdb-get-thread-number ()
1635 (save-excursion
1636 (re-search-backward "^\\s-*\\([0-9]*\\)" nil t)
1637 (match-string-no-properties 1)))
1638
1639 (defun gdb-threads-select (&optional event)
1640 "Select the thread and display the relevant source."
1641 (interactive (list last-input-event))
1642 (if event (mouse-set-point event))
1643 (gdb-enqueue-input
1644 (list (concat "thread " (gdb-get-thread-number) "\n") 'ignore))
1645 (gud-display-frame))
1646 \f
1647
1648 ;; Registers buffer.
1649 ;;
1650 (gdb-set-buffer-rules 'gdb-registers-buffer
1651 'gdb-registers-buffer-name
1652 'gdb-registers-mode)
1653
1654 (def-gdb-auto-updated-buffer gdb-registers-buffer
1655 gdb-invalidate-registers
1656 (concat gdb-server-prefix "info registers\n")
1657 gdb-info-registers-handler
1658 gdb-info-registers-custom)
1659
1660 (defun gdb-info-registers-custom ())
1661
1662 (defvar gdb-registers-mode-map
1663 (let ((map (make-sparse-keymap)))
1664 (suppress-keymap map)
1665 (define-key map "q" 'kill-this-buffer)
1666 map))
1667
1668 (defun gdb-registers-mode ()
1669 "Major mode for gdb registers.
1670
1671 \\{gdb-registers-mode-map}"
1672 (kill-all-local-variables)
1673 (setq major-mode 'gdb-registers-mode)
1674 (setq mode-name "Registers")
1675 (setq buffer-read-only t)
1676 (use-local-map gdb-registers-mode-map)
1677 (run-mode-hooks 'gdb-registers-mode-hook)
1678 'gdb-invalidate-registers)
1679
1680 (defun gdb-registers-buffer-name ()
1681 (with-current-buffer gud-comint-buffer
1682 (concat "*registers of " (gdb-get-target-string) "*")))
1683
1684 (defun gdb-display-registers-buffer ()
1685 "Display integer register contents."
1686 (interactive)
1687 (gdb-display-buffer
1688 (gdb-get-create-buffer 'gdb-registers-buffer)))
1689
1690 (defun gdb-frame-registers-buffer ()
1691 "Display integer register contents in a new frame."
1692 (interactive)
1693 (let ((special-display-regexps (append special-display-regexps '(".*")))
1694 (special-display-frame-alist gdb-frame-parameters))
1695 (display-buffer (gdb-get-create-buffer 'gdb-registers-buffer))))
1696
1697 ;; Memory buffer.
1698 ;;
1699 (defcustom gdb-memory-repeat-count 32
1700 "Number of data items in memory window."
1701 :type 'integer
1702 :group 'gud
1703 :version "22.1")
1704
1705 (defcustom gdb-memory-format "x"
1706 "Display format of data items in memory window."
1707 :type '(choice (const :tag "Hexadecimal" "x")
1708 (const :tag "Signed decimal" "d")
1709 (const :tag "Unsigned decimal" "u")
1710 (const :tag "Octal" "o")
1711 (const :tag "Binary" "t"))
1712 :group 'gud
1713 :version "22.1")
1714
1715 (defcustom gdb-memory-unit "w"
1716 "Unit size of data items in memory window."
1717 :type '(choice (const :tag "Byte" "b")
1718 (const :tag "Halfword" "h")
1719 (const :tag "Word" "w")
1720 (const :tag "Giant word" "g"))
1721 :group 'gud
1722 :version "22.1")
1723
1724 (gdb-set-buffer-rules 'gdb-memory-buffer
1725 'gdb-memory-buffer-name
1726 'gdb-memory-mode)
1727
1728 (def-gdb-auto-updated-buffer gdb-memory-buffer
1729 gdb-invalidate-memory
1730 (concat gdb-server-prefix "x/" (number-to-string gdb-memory-repeat-count)
1731 gdb-memory-format gdb-memory-unit " " gdb-memory-address "\n")
1732 gdb-read-memory-handler
1733 gdb-read-memory-custom)
1734
1735 (defun gdb-read-memory-custom ())
1736
1737 (defvar gdb-memory-mode-map
1738 (let ((map (make-sparse-keymap)))
1739 (suppress-keymap map)
1740 (define-key map "q" 'kill-this-buffer)
1741 map))
1742
1743 (defun gdb-memory-set-address (event)
1744 "Set the start memory address."
1745 (interactive "e")
1746 (save-selected-window
1747 (select-window (posn-window (event-start event)))
1748 (let ((arg (read-from-minibuffer "Memory address: ")))
1749 (setq gdb-memory-address arg))
1750 (gdb-invalidate-memory)))
1751
1752 (defun gdb-memory-set-repeat-count (event)
1753 "Set the number of data items in memory window."
1754 (interactive "e")
1755 (save-selected-window
1756 (select-window (posn-window (event-start event)))
1757 (let* ((arg (read-from-minibuffer "Repeat count: "))
1758 (count (string-to-number arg)))
1759 (if (< count 0)
1760 (error "Non-negative numbers only")
1761 (customize-set-variable 'gdb-memory-repeat-count count)
1762 (gdb-invalidate-memory)))))
1763
1764 (defun gdb-memory-format-binary ()
1765 "Set the display format to binary."
1766 (interactive)
1767 (customize-set-variable 'gdb-memory-format "t")
1768 (gdb-invalidate-memory))
1769
1770 (defun gdb-memory-format-octal ()
1771 "Set the display format to octal."
1772 (interactive)
1773 (customize-set-variable 'gdb-memory-format "o")
1774 (gdb-invalidate-memory))
1775
1776 (defun gdb-memory-format-unsigned ()
1777 "Set the display format to unsigned decimal."
1778 (interactive)
1779 (customize-set-variable 'gdb-memory-format "u")
1780 (gdb-invalidate-memory))
1781
1782 (defun gdb-memory-format-signed ()
1783 "Set the display format to decimal."
1784 (interactive)
1785 (customize-set-variable 'gdb-memory-format "d")
1786 (gdb-invalidate-memory))
1787
1788 (defun gdb-memory-format-hexadecimal ()
1789 "Set the display format to hexadecimal."
1790 (interactive)
1791 (customize-set-variable 'gdb-memory-format "x")
1792 (gdb-invalidate-memory))
1793
1794 (defvar gdb-memory-format-keymap
1795 (let ((map (make-sparse-keymap)))
1796 (define-key map [header-line down-mouse-3] 'gdb-memory-format-menu-1)
1797 map)
1798 "Keymap to select format in the header line.")
1799
1800 (defvar gdb-memory-format-menu (make-sparse-keymap "Format")
1801 "Menu of display formats in the header line.")
1802
1803 (define-key gdb-memory-format-menu [binary]
1804 '(menu-item "Binary" gdb-memory-format-binary
1805 :button (:radio . (equal gdb-memory-format "t"))))
1806 (define-key gdb-memory-format-menu [octal]
1807 '(menu-item "Octal" gdb-memory-format-octal
1808 :button (:radio . (equal gdb-memory-format "o"))))
1809 (define-key gdb-memory-format-menu [unsigned]
1810 '(menu-item "Unsigned Decimal" gdb-memory-format-unsigned
1811 :button (:radio . (equal gdb-memory-format "u"))))
1812 (define-key gdb-memory-format-menu [signed]
1813 '(menu-item "Signed Decimal" gdb-memory-format-signed
1814 :button (:radio . (equal gdb-memory-format "d"))))
1815 (define-key gdb-memory-format-menu [hexadecimal]
1816 '(menu-item "Hexadecimal" gdb-memory-format-hexadecimal
1817 :button (:radio . (equal gdb-memory-format "x"))))
1818
1819 (defun gdb-memory-format-menu (event)
1820 (interactive "@e")
1821 (x-popup-menu event gdb-memory-format-menu))
1822
1823 (defun gdb-memory-format-menu-1 (event)
1824 (interactive "e")
1825 (save-selected-window
1826 (select-window (posn-window (event-start event)))
1827 (let* ((selection (gdb-memory-format-menu event))
1828 (binding (and selection (lookup-key gdb-memory-format-menu
1829 (vector (car selection))))))
1830 (if binding (call-interactively binding)))))
1831
1832 (defun gdb-memory-unit-giant ()
1833 "Set the unit size to giant words (eight bytes)."
1834 (interactive)
1835 (customize-set-variable 'gdb-memory-unit "g")
1836 (gdb-invalidate-memory))
1837
1838 (defun gdb-memory-unit-word ()
1839 "Set the unit size to words (four bytes)."
1840 (interactive)
1841 (customize-set-variable 'gdb-memory-unit "w")
1842 (gdb-invalidate-memory))
1843
1844 (defun gdb-memory-unit-halfword ()
1845 "Set the unit size to halfwords (two bytes)."
1846 (interactive)
1847 (customize-set-variable 'gdb-memory-unit "h")
1848 (gdb-invalidate-memory))
1849
1850 (defun gdb-memory-unit-byte ()
1851 "Set the unit size to bytes."
1852 (interactive)
1853 (customize-set-variable 'gdb-memory-unit "b")
1854 (gdb-invalidate-memory))
1855
1856 (defvar gdb-memory-unit-keymap
1857 (let ((map (make-sparse-keymap)))
1858 (define-key map [header-line down-mouse-3] 'gdb-memory-unit-menu-1)
1859 map)
1860 "Keymap to select units in the header line.")
1861
1862 (defvar gdb-memory-unit-menu (make-sparse-keymap "Unit")
1863 "Menu of units in the header line.")
1864
1865 (define-key gdb-memory-unit-menu [giantwords]
1866 '(menu-item "Giant words" gdb-memory-unit-giant
1867 :button (:radio . (equal gdb-memory-unit "g"))))
1868 (define-key gdb-memory-unit-menu [words]
1869 '(menu-item "Words" gdb-memory-unit-word
1870 :button (:radio . (equal gdb-memory-unit "w"))))
1871 (define-key gdb-memory-unit-menu [halfwords]
1872 '(menu-item "Halfwords" gdb-memory-unit-halfword
1873 :button (:radio . (equal gdb-memory-unit "h"))))
1874 (define-key gdb-memory-unit-menu [bytes]
1875 '(menu-item "Bytes" gdb-memory-unit-byte
1876 :button (:radio . (equal gdb-memory-unit "b"))))
1877
1878 (defun gdb-memory-unit-menu (event)
1879 (interactive "@e")
1880 (x-popup-menu event gdb-memory-unit-menu))
1881
1882 (defun gdb-memory-unit-menu-1 (event)
1883 (interactive "e")
1884 (save-selected-window
1885 (select-window (posn-window (event-start event)))
1886 (let* ((selection (gdb-memory-unit-menu event))
1887 (binding (and selection (lookup-key gdb-memory-unit-menu
1888 (vector (car selection))))))
1889 (if binding (call-interactively binding)))))
1890
1891 ;;from make-mode-line-mouse-map
1892 (defun gdb-make-header-line-mouse-map (mouse function) "\
1893 Return a keymap with single entry for mouse key MOUSE on the header line.
1894 MOUSE is defined to run function FUNCTION with no args in the buffer
1895 corresponding to the mode line clicked."
1896 (let ((map (make-sparse-keymap)))
1897 (define-key map (vector 'header-line mouse) function)
1898 (define-key map (vector 'header-line 'down-mouse-1) 'ignore)
1899 map))
1900
1901 (defun gdb-memory-mode ()
1902 "Major mode for examining memory.
1903
1904 \\{gdb-memory-mode-map}"
1905 (kill-all-local-variables)
1906 (setq major-mode 'gdb-memory-mode)
1907 (setq mode-name "Memory")
1908 (setq buffer-read-only t)
1909 (use-local-map gdb-memory-mode-map)
1910 (setq header-line-format
1911 '(:eval
1912 (concat
1913 "Read address: "
1914 (propertize gdb-memory-address
1915 'face font-lock-warning-face
1916 'help-echo "mouse-1: Set memory address"
1917 'local-map (gdb-make-header-line-mouse-map
1918 'mouse-1
1919 #'gdb-memory-set-address))
1920 " Repeat Count: "
1921 (propertize (number-to-string gdb-memory-repeat-count)
1922 'face font-lock-warning-face
1923 'help-echo "mouse-1: Set repeat count"
1924 'local-map (gdb-make-header-line-mouse-map
1925 'mouse-1
1926 #'gdb-memory-set-repeat-count))
1927 " Display Format: "
1928 (propertize gdb-memory-format
1929 'face font-lock-warning-face
1930 'help-echo "mouse-3: Select display format"
1931 'local-map gdb-memory-format-keymap)
1932 " Unit Size: "
1933 (propertize gdb-memory-unit
1934 'face font-lock-warning-face
1935 'help-echo "mouse-3: Select unit size"
1936 'local-map gdb-memory-unit-keymap))))
1937 (run-mode-hooks 'gdb-memory-mode-hook)
1938 'gdb-invalidate-memory)
1939
1940 (defun gdb-memory-buffer-name ()
1941 (with-current-buffer gud-comint-buffer
1942 (concat "*memory of " (gdb-get-target-string) "*")))
1943
1944 (defun gdb-display-memory-buffer ()
1945 "Display memory contents."
1946 (interactive)
1947 (gdb-display-buffer
1948 (gdb-get-create-buffer 'gdb-memory-buffer)))
1949
1950 (defun gdb-frame-memory-buffer ()
1951 "Display memory contents in a new frame."
1952 (interactive)
1953 (let ((special-display-regexps (append special-display-regexps '(".*")))
1954 (special-display-frame-alist gdb-frame-parameters))
1955 (display-buffer (gdb-get-create-buffer 'gdb-memory-buffer))))
1956 \f
1957
1958 ;; Locals buffer.
1959 ;;
1960 (gdb-set-buffer-rules 'gdb-locals-buffer
1961 'gdb-locals-buffer-name
1962 'gdb-locals-mode)
1963
1964 (def-gdb-auto-updated-buffer gdb-locals-buffer
1965 gdb-invalidate-locals
1966 "server info locals\n"
1967 gdb-info-locals-handler
1968 gdb-info-locals-custom)
1969
1970 ;; Abbreviate for arrays and structures.
1971 ;; These can be expanded using gud-display.
1972 (defun gdb-info-locals-handler nil
1973 (setq gdb-pending-triggers (delq 'gdb-invalidate-locals
1974 gdb-pending-triggers))
1975 (let ((buf (gdb-get-buffer 'gdb-partial-output-buffer)))
1976 (with-current-buffer buf
1977 (goto-char (point-min))
1978 (while (re-search-forward "^[ }].*\n" nil t)
1979 (replace-match "" nil nil))
1980 (goto-char (point-min))
1981 (while (re-search-forward "{\\(.*=.*\n\\|\n\\)" nil t)
1982 (replace-match "(structure);\n" nil nil))
1983 (goto-char (point-min))
1984 (while (re-search-forward "\\s-*{.*\n" nil t)
1985 (replace-match " (array);\n" nil nil))))
1986 (let ((buf (gdb-get-buffer 'gdb-locals-buffer)))
1987 (and buf (with-current-buffer buf
1988 (let ((p (point))
1989 (buffer-read-only nil))
1990 (delete-region (point-min) (point-max))
1991 (insert-buffer-substring (gdb-get-create-buffer
1992 'gdb-partial-output-buffer))
1993 (goto-char p)))))
1994 (run-hooks 'gdb-info-locals-hook))
1995
1996 (defun gdb-info-locals-custom ()
1997 nil)
1998
1999 (defvar gdb-locals-mode-map
2000 (let ((map (make-sparse-keymap)))
2001 (suppress-keymap map)
2002 (define-key map "q" 'kill-this-buffer)
2003 map))
2004
2005 (defun gdb-locals-mode ()
2006 "Major mode for gdb locals.
2007
2008 \\{gdb-locals-mode-map}"
2009 (kill-all-local-variables)
2010 (setq major-mode 'gdb-locals-mode)
2011 (setq mode-name (concat "Locals:" gdb-current-frame))
2012 (setq buffer-read-only t)
2013 (use-local-map gdb-locals-mode-map)
2014 (run-mode-hooks 'gdb-locals-mode-hook)
2015 (if (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gdba))
2016 'gdb-invalidate-locals
2017 'gdbmi-invalidate-locals))
2018
2019 (defun gdb-locals-buffer-name ()
2020 (with-current-buffer gud-comint-buffer
2021 (concat "*locals of " (gdb-get-target-string) "*")))
2022
2023 (defun gdb-display-locals-buffer ()
2024 "Display local variables of current stack and their values."
2025 (interactive)
2026 (gdb-display-buffer
2027 (gdb-get-create-buffer 'gdb-locals-buffer)))
2028
2029 (defun gdb-frame-locals-buffer ()
2030 "Display local variables of current stack and their values in a new frame."
2031 (interactive)
2032 (let ((special-display-regexps (append special-display-regexps '(".*")))
2033 (special-display-frame-alist gdb-frame-parameters))
2034 (display-buffer (gdb-get-create-buffer 'gdb-locals-buffer))))
2035 \f
2036
2037 ;;;; Window management
2038 (defun gdb-display-buffer (buf &optional size)
2039 (let ((answer (get-buffer-window buf 0))
2040 (must-split nil))
2041 (if answer
2042 (display-buffer buf nil 0) ;Raise the frame if necessary.
2043 ;; The buffer is not yet displayed.
2044 (pop-to-buffer gud-comint-buffer) ;Select the right frame.
2045 (let ((window (get-lru-window)))
2046 (if (and window
2047 (not (eq window (get-buffer-window gud-comint-buffer))))
2048 (progn
2049 (set-window-buffer window buf)
2050 (setq answer window))
2051 (setq must-split t)))
2052 (if must-split
2053 (let* ((largest (get-largest-window))
2054 (cur-size (window-height largest))
2055 (new-size (and size (< size cur-size) (- cur-size size))))
2056 (setq answer (split-window largest new-size))
2057 (set-window-buffer answer buf)
2058 (set-window-dedicated-p answer t)))
2059 answer)))
2060
2061 \f
2062 ;;; Shared keymap initialization:
2063
2064 (let ((menu (make-sparse-keymap "GDB-Windows")))
2065 (define-key gud-menu-map [displays]
2066 `(menu-item "GDB-Windows" ,menu
2067 :visible (memq gud-minor-mode '(gdbmi gdba))))
2068 (define-key menu [gdb] '("Gdb" . gdb-display-gdb-buffer))
2069 (define-key menu [threads] '("Threads" . gdb-display-threads-buffer))
2070 (define-key menu [memory] '("Memory" . gdb-display-memory-buffer))
2071 (define-key menu [assembler] '("Machine" . gdb-display-assembler-buffer))
2072 (define-key menu [registers] '("Registers" . gdb-display-registers-buffer))
2073 (define-key menu [inferior]
2074 '(menu-item "Inferior IO" gdb-display-inferior-io-buffer
2075 :enable gdb-use-inferior-io-buffer))
2076 (define-key menu [locals] '("Locals" . gdb-display-locals-buffer))
2077 (define-key menu [frames] '("Stack" . gdb-display-stack-buffer))
2078 (define-key menu [breakpoints]
2079 '("Breakpoints" . gdb-display-breakpoints-buffer)))
2080
2081 (let ((menu (make-sparse-keymap "GDB-Frames")))
2082 (define-key gud-menu-map [frames]
2083 `(menu-item "GDB-Frames" ,menu
2084 :visible (memq gud-minor-mode '(gdbmi gdba))))
2085 (define-key menu [gdb] '("Gdb" . gdb-frame-gdb-buffer))
2086 (define-key menu [threads] '("Threads" . gdb-frame-threads-buffer))
2087 (define-key menu [memory] '("Memory" . gdb-frame-memory-buffer))
2088 (define-key menu [assembler] '("Machine" . gdb-frame-assembler-buffer))
2089 (define-key menu [registers] '("Registers" . gdb-frame-registers-buffer))
2090 (define-key menu [inferior]
2091 '(menu-item "Inferior IO" gdb-frame-inferior-io-buffer
2092 :enable gdb-use-inferior-io-buffer))
2093 (define-key menu [locals] '("Locals" . gdb-frame-locals-buffer))
2094 (define-key menu [frames] '("Stack" . gdb-frame-stack-buffer))
2095 (define-key menu [breakpoints]
2096 '("Breakpoints" . gdb-frame-breakpoints-buffer)))
2097
2098 (let ((menu (make-sparse-keymap "GDB-UI")))
2099 (define-key gud-menu-map [ui]
2100 `(menu-item "GDB-UI" ,menu :visible (eq gud-minor-mode 'gdba)))
2101 (define-key menu [gdb-restore-windows]
2102 '(menu-item "Restore Window Layout" gdb-restore-windows
2103 :help "Restore standard layout for debug session."))
2104 (define-key menu [gdb-many-windows]
2105 '(menu-item "Display Other Windows" gdb-many-windows
2106 :help "Toggle display of locals, stack and breakpoint information"
2107 :button (:toggle . gdb-many-windows)))
2108 (define-key menu [gdb-use-inferior-io]
2109 (menu-bar-make-toggle toggle-gdb-use-inferior-io-buffer
2110 gdb-use-inferior-io-buffer
2111 "Separate inferior IO" "Use separate IO %s"
2112 "Toggle separate IO for inferior.")))
2113
2114 (defadvice toggle-gdb-use-inferior-io-buffer (after gdb-kill-io-buffer activate)
2115 (unless gdb-use-inferior-io-buffer
2116 (kill-buffer (gdb-inferior-io-name))))
2117
2118 (defun gdb-frame-gdb-buffer ()
2119 "Display GUD buffer in a new frame."
2120 (interactive)
2121 (select-frame (make-frame gdb-frame-parameters))
2122 (switch-to-buffer (gdb-get-create-buffer 'gdba))
2123 (set-window-dedicated-p (selected-window) t))
2124
2125 (defun gdb-display-gdb-buffer ()
2126 "Display GUD buffer."
2127 (interactive)
2128 (gdb-display-buffer
2129 (gdb-get-create-buffer 'gdba)))
2130
2131 (defvar gdb-main-file nil "Source file from which program execution begins.")
2132
2133 (defcustom gdb-show-main nil
2134 "Nil means don't display source file containing the main routine."
2135 :type 'boolean
2136 :group 'gud
2137 :version "22.1")
2138
2139 (defun gdb-set-window-buffer (name)
2140 (set-window-buffer (selected-window) (get-buffer name))
2141 (set-window-dedicated-p (selected-window) t))
2142
2143 (defun gdb-setup-windows ()
2144 "Layout the window pattern for gdb-many-windows."
2145 (gdb-display-locals-buffer)
2146 (gdb-display-stack-buffer)
2147 (delete-other-windows)
2148 (gdb-display-breakpoints-buffer)
2149 (delete-other-windows)
2150 ; Don't dedicate.
2151 (pop-to-buffer gud-comint-buffer)
2152 (split-window nil ( / ( * (window-height) 3) 4))
2153 (split-window nil ( / (window-height) 3))
2154 (split-window-horizontally)
2155 (other-window 1)
2156 (gdb-set-window-buffer (gdb-locals-buffer-name))
2157 (other-window 1)
2158 (switch-to-buffer
2159 (if gud-last-last-frame
2160 (gud-find-file (car gud-last-last-frame))
2161 (gud-find-file gdb-main-file)))
2162 (when gdb-use-inferior-io-buffer
2163 (split-window-horizontally)
2164 (other-window 1)
2165 (gdb-set-window-buffer
2166 (gdb-get-create-buffer 'gdb-inferior-io)))
2167 (other-window 1)
2168 (gdb-set-window-buffer (gdb-stack-buffer-name))
2169 (split-window-horizontally)
2170 (other-window 1)
2171 (gdb-set-window-buffer (gdb-breakpoints-buffer-name))
2172 (other-window 1))
2173
2174 (defcustom gdb-many-windows nil
2175 "Nil means just pop up the GUD buffer unless `gdb-show-main' is t.
2176 In this case it starts with two windows: one displaying the GUD
2177 buffer and the other with the source file with the main routine
2178 of the inferior. Non-nil means display the layout shown for
2179 `gdba'."
2180 :type 'boolean
2181 :group 'gud
2182 :version "22.1")
2183
2184 (defun gdb-many-windows (arg)
2185 "Toggle the number of windows in the basic arrangement."
2186 (interactive "P")
2187 (setq gdb-many-windows
2188 (if (null arg)
2189 (not gdb-many-windows)
2190 (> (prefix-numeric-value arg) 0)))
2191 (condition-case nil
2192 (gdb-restore-windows)
2193 (error nil)))
2194
2195 (defun gdb-restore-windows ()
2196 "Restore the basic arrangement of windows used by gdba.
2197 This arrangement depends on the value of `gdb-many-windows'."
2198 (interactive)
2199 (pop-to-buffer gud-comint-buffer) ;Select the right window and frame.
2200 (delete-other-windows)
2201 (if gdb-many-windows
2202 (gdb-setup-windows)
2203 (split-window)
2204 (other-window 1)
2205 (switch-to-buffer
2206 (if gud-last-last-frame
2207 (gud-find-file (car gud-last-last-frame))
2208 (gud-find-file gdb-main-file)))
2209 (other-window 1)))
2210
2211 (defun gdb-reset ()
2212 "Exit a debugging session cleanly.
2213 Kills the gdb buffers and resets the source buffers."
2214 (dolist (buffer (buffer-list))
2215 (unless (eq buffer gud-comint-buffer)
2216 (with-current-buffer buffer
2217 (if (memq gud-minor-mode '(gdbmi gdba))
2218 (if (string-match "\\`\\*.+\\*\\'" (buffer-name))
2219 (kill-buffer nil)
2220 (gdb-remove-breakpoint-icons (point-min) (point-max) t)
2221 (setq gud-minor-mode nil)
2222 (kill-local-variable 'tool-bar-map)
2223 (kill-local-variable 'gdb-define-alist))))))
2224 (when (markerp gdb-overlay-arrow-position)
2225 (move-marker gdb-overlay-arrow-position nil)
2226 (setq gdb-overlay-arrow-position nil))
2227 (setq overlay-arrow-variable-list
2228 (delq 'gdb-overlay-arrow-position overlay-arrow-variable-list))
2229 (setq gud-running nil)
2230 (setq gdb-active-process nil)
2231 (remove-hook 'after-save-hook 'gdb-create-define-alist t))
2232
2233 (defun gdb-source-info ()
2234 "Find the source file where the program starts and displays it with related
2235 buffers."
2236 (goto-char (point-min))
2237 (if (and (search-forward "Located in " nil t)
2238 (looking-at "\\S-*"))
2239 (setq gdb-main-file (match-string 0)))
2240 (goto-char (point-min))
2241 (if (search-forward "Includes preprocessor macro info." nil t)
2242 (setq gdb-macro-info t))
2243 (if gdb-many-windows
2244 (gdb-setup-windows)
2245 (gdb-get-create-buffer 'gdb-breakpoints-buffer)
2246 (if gdb-show-main
2247 (let ((pop-up-windows t))
2248 (display-buffer (gud-find-file gdb-main-file))))))
2249
2250 (defun gdb-get-location (bptno line flag)
2251 "Find the directory containing the relevant source file.
2252 Put in buffer and place breakpoint icon."
2253 (goto-char (point-min))
2254 (catch 'file-not-found
2255 (if (search-forward "Located in " nil t)
2256 (when (looking-at "\\S-*")
2257 (delete (cons bptno "File not found") gdb-location-alist)
2258 (push (cons bptno (match-string 0)) gdb-location-alist))
2259 (gdb-resync)
2260 (unless (assoc bptno gdb-location-alist)
2261 (push (cons bptno "File not found") gdb-location-alist)
2262 (message-box "Cannot find source file for breakpoint location.\n\
2263 Add directory to search path for source files using the GDB command, dir."))
2264 (throw 'file-not-found nil))
2265 (with-current-buffer
2266 (find-file-noselect (match-string 0))
2267 (save-current-buffer
2268 (set (make-local-variable 'gud-minor-mode) 'gdba)
2269 (set (make-local-variable 'tool-bar-map) gud-tool-bar-map))
2270 ;; only want one breakpoint icon at each location
2271 (save-excursion
2272 (goto-line (string-to-number line))
2273 (gdb-put-breakpoint-icon (eq flag ?y) bptno)))))
2274
2275 (add-hook 'find-file-hook 'gdb-find-file-hook)
2276
2277 (defun gdb-find-file-hook ()
2278 (if (and (not gdb-find-file-unhook)
2279 ;; in case gud or gdb-ui is just loaded
2280 gud-comint-buffer
2281 (buffer-name gud-comint-buffer)
2282 (with-current-buffer gud-comint-buffer
2283 (eq gud-minor-mode 'gdba)))
2284 (condition-case nil
2285 (gdb-enqueue-input
2286 (list (concat gdb-server-prefix "list "
2287 (file-name-nondirectory buffer-file-name)
2288 ":1\n")
2289 `(lambda () (gdb-set-gud-minor-mode ,(current-buffer)))))
2290 (error (setq gdb-find-file-unhook t)))))
2291
2292 ;;from put-image
2293 (defun gdb-put-string (putstring pos &optional dprop)
2294 "Put string PUTSTRING in front of POS in the current buffer.
2295 PUTSTRING is displayed by putting an overlay into the current buffer with a
2296 `before-string' STRING that has a `display' property whose value is
2297 PUTSTRING."
2298 (let ((string (make-string 1 ?x))
2299 (buffer (current-buffer)))
2300 (setq putstring (copy-sequence putstring))
2301 (let ((overlay (make-overlay pos pos buffer))
2302 (prop (or dprop
2303 (list (list 'margin 'left-margin) putstring))))
2304 (put-text-property 0 (length string) 'display prop string)
2305 (overlay-put overlay 'put-break t)
2306 (overlay-put overlay 'before-string string))))
2307
2308 ;;from remove-images
2309 (defun gdb-remove-strings (start end &optional buffer)
2310 "Remove strings between START and END in BUFFER.
2311 Remove only strings that were put in BUFFER with calls to `gdb-put-string'.
2312 BUFFER nil or omitted means use the current buffer."
2313 (unless buffer
2314 (setq buffer (current-buffer)))
2315 (dolist (overlay (overlays-in start end))
2316 (when (overlay-get overlay 'put-break)
2317 (delete-overlay overlay))))
2318
2319 (defun gdb-put-breakpoint-icon (enabled bptno)
2320 (let ((start (- (line-beginning-position) 1))
2321 (end (+ (line-end-position) 1))
2322 (putstring (if enabled "B" "b")))
2323 (add-text-properties
2324 0 1 '(help-echo "mouse-1: set/clear bkpt, mouse-3: enable/disable bkpt")
2325 putstring)
2326 (if enabled (add-text-properties
2327 0 1 `(gdb-bptno ,bptno gdb-enabled t) putstring)
2328 (add-text-properties
2329 0 1 `(gdb-bptno ,bptno gdb-enabled nil) putstring))
2330 (gdb-remove-breakpoint-icons start end)
2331 (if (display-images-p)
2332 (if (>= (car (window-fringes)) 8)
2333 (gdb-put-string
2334 nil (1+ start)
2335 `(left-fringe breakpoint
2336 ,(if enabled
2337 'breakpoint-enabled
2338 'breakpoint-disabled)))
2339 (when (< left-margin-width 2)
2340 (save-current-buffer
2341 (setq left-margin-width 2)
2342 (if (get-buffer-window (current-buffer) 0)
2343 (set-window-margins
2344 (get-buffer-window (current-buffer) 0)
2345 left-margin-width right-margin-width))))
2346 (put-image
2347 (if enabled
2348 (or breakpoint-enabled-icon
2349 (setq breakpoint-enabled-icon
2350 (find-image `((:type xpm :data
2351 ,breakpoint-xpm-data
2352 :ascent 100 :pointer hand)
2353 (:type pbm :data
2354 ,breakpoint-enabled-pbm-data
2355 :ascent 100 :pointer hand)))))
2356 (or breakpoint-disabled-icon
2357 (setq breakpoint-disabled-icon
2358 (find-image `((:type xpm :data
2359 ,breakpoint-xpm-data
2360 :conversion disabled
2361 :ascent 100)
2362 (:type pbm :data
2363 ,breakpoint-disabled-pbm-data
2364 :ascent 100))))))
2365 (+ start 1)
2366 putstring
2367 'left-margin))
2368 (when (< left-margin-width 2)
2369 (save-current-buffer
2370 (setq left-margin-width 2)
2371 (if (get-buffer-window (current-buffer) 0)
2372 (set-window-margins
2373 (get-buffer-window (current-buffer) 0)
2374 left-margin-width right-margin-width))))
2375 (gdb-put-string
2376 (propertize putstring
2377 'face (if enabled 'breakpoint-enabled 'breakpoint-disabled))
2378 (1+ start)))))
2379
2380 (defun gdb-remove-breakpoint-icons (start end &optional remove-margin)
2381 (gdb-remove-strings start end)
2382 (if (display-images-p)
2383 (remove-images start end))
2384 (when remove-margin
2385 (setq left-margin-width 0)
2386 (if (get-buffer-window (current-buffer) 0)
2387 (set-window-margins
2388 (get-buffer-window (current-buffer) 0)
2389 left-margin-width right-margin-width))))
2390
2391 \f
2392 ;;
2393 ;; Assembler buffer.
2394 ;;
2395 (gdb-set-buffer-rules 'gdb-assembler-buffer
2396 'gdb-assembler-buffer-name
2397 'gdb-assembler-mode)
2398
2399 (def-gdb-auto-updated-buffer gdb-assembler-buffer
2400 gdb-invalidate-assembler
2401 (concat gdb-server-prefix "disassemble " gdb-current-address "\n")
2402 gdb-assembler-handler
2403 gdb-assembler-custom)
2404
2405 (defun gdb-assembler-custom ()
2406 (let ((buffer (gdb-get-buffer 'gdb-assembler-buffer))
2407 (pos 1) (address) (flag) (bptno))
2408 (with-current-buffer buffer
2409 (if (not (equal gdb-current-address "main"))
2410 (progn
2411 (goto-char (point-min))
2412 (if (re-search-forward gdb-current-address nil t)
2413 (progn
2414 (setq pos (point))
2415 (beginning-of-line)
2416 (or gdb-overlay-arrow-position
2417 (setq gdb-overlay-arrow-position (make-marker)))
2418 (set-marker gdb-overlay-arrow-position
2419 (point) (current-buffer))))))
2420 ;; remove all breakpoint-icons in assembler buffer before updating.
2421 (gdb-remove-breakpoint-icons (point-min) (point-max)))
2422 (with-current-buffer (gdb-get-buffer 'gdb-breakpoints-buffer)
2423 (goto-char (point-min))
2424 (while (< (point) (- (point-max) 1))
2425 (forward-line 1)
2426 (if (looking-at "[^\t].*breakpoint")
2427 (progn
2428 (looking-at
2429 "\\([0-9]+\\)\\s-+\\S-+\\s-+\\S-+\\s-+\\(.\\)\\s-+0x\\(\\S-+\\)")
2430 (setq bptno (match-string 1))
2431 (setq flag (char-after (match-beginning 2)))
2432 (setq address (match-string 3))
2433 ;; remove leading 0s from output of info break.
2434 (if (string-match "^0+\\(.*\\)" address)
2435 (setq address (match-string 1 address)))
2436 (with-current-buffer buffer
2437 (goto-char (point-min))
2438 (if (re-search-forward address nil t)
2439 (gdb-put-breakpoint-icon (eq flag ?y) bptno)))))))
2440 (if (not (equal gdb-current-address "main"))
2441 (set-window-point (get-buffer-window buffer 0) pos))))
2442
2443 (defvar gdb-assembler-mode-map
2444 (let ((map (make-sparse-keymap)))
2445 (suppress-keymap map)
2446 (define-key map "q" 'kill-this-buffer)
2447 map))
2448
2449 (defvar gdb-assembler-font-lock-keywords
2450 '(;; <__function.name+n>
2451 ("<\\(\\(\\sw\\|[_.]\\)+\\)\\(\\+[0-9]+\\)?>"
2452 (1 font-lock-function-name-face))
2453 ;; 0xNNNNNNNN <__function.name+n>: opcode
2454 ("^0x[0-9a-f]+ \\(<\\(\\(\\sw\\|[_.]\\)+\\)\\+[0-9]+>\\)?:[ \t]+\\(\\sw+\\)"
2455 (4 font-lock-keyword-face))
2456 ;; %register(at least i386)
2457 ("%\\sw+" . font-lock-variable-name-face)
2458 ("^\\(Dump of assembler code for function\\) \\(.+\\):"
2459 (1 font-lock-comment-face)
2460 (2 font-lock-function-name-face))
2461 ("^\\(End of assembler dump\\.\\)" . font-lock-comment-face))
2462 "Font lock keywords used in `gdb-assembler-mode'.")
2463
2464 (defun gdb-assembler-mode ()
2465 "Major mode for viewing code assembler.
2466
2467 \\{gdb-assembler-mode-map}"
2468 (kill-all-local-variables)
2469 (setq major-mode 'gdb-assembler-mode)
2470 (setq mode-name "Machine")
2471 (setq gdb-overlay-arrow-position nil)
2472 (add-to-list 'overlay-arrow-variable-list 'gdb-overlay-arrow-position)
2473 (setq fringes-outside-margins t)
2474 (setq buffer-read-only t)
2475 (use-local-map gdb-assembler-mode-map)
2476 (gdb-invalidate-assembler)
2477 (set (make-local-variable 'font-lock-defaults)
2478 '(gdb-assembler-font-lock-keywords))
2479 (run-mode-hooks 'gdb-assembler-mode-hook)
2480 'gdb-invalidate-assembler)
2481
2482 (defun gdb-assembler-buffer-name ()
2483 (with-current-buffer gud-comint-buffer
2484 (concat "*Machine Code " (gdb-get-target-string) "*")))
2485
2486 (defun gdb-display-assembler-buffer ()
2487 "Display disassembly view."
2488 (interactive)
2489 (gdb-display-buffer
2490 (gdb-get-create-buffer 'gdb-assembler-buffer)))
2491
2492 (defun gdb-frame-assembler-buffer ()
2493 "Display disassembly view in a new frame."
2494 (interactive)
2495 (let ((special-display-regexps (append special-display-regexps '(".*")))
2496 (special-display-frame-alist gdb-frame-parameters))
2497 (display-buffer (gdb-get-create-buffer 'gdb-assembler-buffer))))
2498
2499 ;; modified because if gdb-current-address has changed value a new command
2500 ;; must be enqueued to update the buffer with the new output
2501 (defun gdb-invalidate-assembler (&optional ignored)
2502 (if (gdb-get-buffer 'gdb-assembler-buffer)
2503 (progn
2504 (unless (string-equal gdb-current-frame gdb-previous-frame)
2505 (if (or (not (member 'gdb-invalidate-assembler
2506 gdb-pending-triggers))
2507 (not (string-equal gdb-current-address
2508 gdb-previous-address)))
2509 (progn
2510 ;; take previous disassemble command off the queue
2511 (with-current-buffer gud-comint-buffer
2512 (let ((queue gdb-input-queue))
2513 (dolist (item queue)
2514 (if (equal (cdr item) '(gdb-assembler-handler))
2515 (setq gdb-input-queue
2516 (delete item gdb-input-queue))))))
2517 (gdb-enqueue-input
2518 (list (concat gdb-server-prefix "disassemble "
2519 gdb-current-address "\n")
2520 'gdb-assembler-handler))
2521 (push 'gdb-invalidate-assembler gdb-pending-triggers)
2522 (setq gdb-previous-address gdb-current-address)
2523 (setq gdb-previous-frame gdb-current-frame)))))))
2524
2525 (defun gdb-get-current-frame ()
2526 (if (not (member 'gdb-get-current-frame gdb-pending-triggers))
2527 (progn
2528 (gdb-enqueue-input
2529 (list (concat gdb-server-prefix "info frame\n") 'gdb-frame-handler))
2530 (push 'gdb-get-current-frame
2531 gdb-pending-triggers))))
2532
2533 (defun gdb-frame-handler ()
2534 (setq gdb-pending-triggers
2535 (delq 'gdb-get-current-frame gdb-pending-triggers))
2536 (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer)
2537 (goto-char (point-min))
2538 (if (looking-at "Stack level \\([0-9]+\\)")
2539 (setq gdb-current-stack-level (match-string 1)))
2540 (forward-line)
2541 (if (looking-at ".*=\\s-+0x\\(\\S-*\\)\\s-+in\\s-+\\(\\S-*?\\);? ")
2542 (progn
2543 (setq gdb-current-frame (match-string 2))
2544 (if (gdb-get-buffer 'gdb-locals-buffer)
2545 (with-current-buffer (gdb-get-buffer 'gdb-locals-buffer)
2546 (setq mode-name (concat "Locals:" gdb-current-frame))))
2547 (let ((address (match-string 1)))
2548 ;; remove leading 0s from output of info frame command.
2549 (if (string-match "^0+\\(.*\\)" address)
2550 (setq gdb-current-address
2551 (concat "0x" (match-string 1 address)))
2552 (setq gdb-current-address (concat "0x" address))))
2553 (if (not (re-search-forward "(\\S-*:[0-9]*);" nil t))
2554 ;;update with new frame for machine code if necessary
2555 (gdb-invalidate-assembler)))))
2556 (if (re-search-forward " source language \\(\\S-*\\)\." nil t)
2557 (setq gdb-current-language (match-string 1))))
2558
2559 (provide 'gdb-ui)
2560
2561 ;; arch-tag: e9fb00c5-74ef-469f-a088-37384caae352
2562 ;;; gdb-ui.el ends here