home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD1.bin
/
new
/
util
/
edit
/
jade
/
lisp
/
gdb.jl
< prev
next >
Wrap
Lisp/Scheme
|
1994-10-03
|
8KB
|
207 lines
;;;; gdb.jl -- run gdb in a buffer
;;; Copyright (C) 1994 John Harper <jsh@ukc.ac.uk>
;;; This file is part of Jade.
;;; Jade is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 2, or (at your option)
;;; any later version.
;;; Jade is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;; You should have received a copy of the GNU General Public License
;;; along with Jade; see the file COPYING. If not, write to
;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
(require 'shell)
(provide 'gdb)
(defvar gdb-file-name "gdb"
"The file name of the gdb program to run.")
(defvar gdb-auto-centre nil
"When non-nil the current line in the source window is automatically
centred each time it changes.")
(defvar gdb-last-frame nil
"(FILE . LINE-NUMBER) representing the last frame we displayed.")
(make-variable-buffer-local 'gdb-last-frame)
(defvar gdb-last-buffer nil
"This is the last *gdb* buffer which was used.")
(defvar gdb-buffer-p nil
"Flag that says this buffer is for running a gdb process.")
(make-variable-buffer-local 'gdb-buffer-p)
(defvar gdb-spare-output nil)
(make-variable-buffer-local 'gdb-spare-output)
(defvar gdb-delete-prompt nil)
(make-variable-buffer-local 'gdb-delete-prompt)
(defvar gdb-ctrl-c-keymap (copy-sequence shell-ctrl-c-keymap))
(bind-keys gdb-ctrl-c-keymap
"Ctrl-n" '(gdb-command "next %d\n" (prefix-numeric-argument current-prefix-arg))
"Ctrl-s" '(gdb-command "step %d\n" (prefix-numeric-argument current-prefix-arg))
"Ctrl-i" '(gdb-command "stepi %d\n" (prefix-numeric-argument current-prefix-arg))
"Ctrl-I" '(gdb-command "nexti %d\n" (prefix-numeric-argument current-prefix-arg))
"Ctrl-f" '(gdb-command "finish\n")
"Ctrl-r" '(gdb-command "cont\n")
"Ctrl-<" '(gdb-command "up %d\n" (prefix-numeric-argument current-prefix-arg))
"Ctrl->" '(gdb-command "down %d\n" (prefix-numeric-argument current-prefix-arg))
"Ctrl-b" '(gdb-command "break %s:%d\n" (gdb-current-file) (gdb-current-line))
"Ctrl-t" '(gdb-command "tbreak %s:%d\n" (gdb-current-file) (gdb-current-line))
"Ctrl-d" '(gdb-command "clear %d\n" (gdb-current-line))
"Ctrl-l" 'gdb-redisplay-frame)
(bind-keys ctrl-x-keymap
"Ctrl-a" '(setq next-keymap-path '(gdb-ctrl-c-keymap)))
;;;###autoload
(defun gdb (prog)
"Run the gdb debugger in an editor buffer (called `*gdb*'). PROG is the
program which is to be debugged.
See the `gdb-mode' documentation for details of the available commands.
There is no limit to the number of gdb processes you may run at once."
(interactive "fProgram to debug:")
(let*
((buffer (get-buffer "*gdb*")))
(if (or (not buffer) (with-buffer buffer shell-process))
(progn
(setq buffer (make-buffer "*gdb*"))
(set-buffer-special buffer t))
(clear-buffer buffer))
(goto-buffer buffer)
(kill-all-buffer-variables)
(set-buffer-file-name buffer prog)
(setq shell-program gdb-file-name
shell-program-args (list "-fullname" (file-name-nondirectory prog))
shell-prompt-regexp "^(.*\\(.+\\) *|.+---)"
shell-output-stream (list 'lambda '(x)
(list 'gdb-output-filter
(current-buffer)
'x)))
(shell-mode)
(setq mode-name (concat "GDB:" (file-name-nondirectory prog))
major-mode 'gdb-mode
ctrl-c-keymap gdb-ctrl-c-keymap
gdb-last-buffer buffer
gdb-buffer-p t
mildly-special-buffer t)
(eval-hook 'gdb-hook)))
(defun gdb-mode ()
"Gdb Mode:\n
This major-mode is used to run the GDB debugger in an editor buffer. To
start a gdb subprocess use the `ESC x gdb' command.\n
Each time the target process stops executing the source line of the
current frame is highlighted in a separate window.\n
The following commands are available in the `*gdb*' buffer,\n
`Ctrl-c Ctrl-n' Next line
`Ctrl-c Ctrl-s' Step
`Ctrl-c Ctrl-i' Step the next instruction
`Ctrl-c Ctrl-I' Next instruction
`Ctrl-c Ctrl-f' Finish this frame
`Ctrl-c Ctrl-r' Continue execution
`Ctrl-c Ctrl-<' Move up one frame
`Ctrl-c Ctrl->' Move down one frame
`Ctrl-c Ctrl-b' Set a breakpoint at the current line
`Ctrl-c Ctrl-t' Set a temporary breakpoint
`Ctrl-c Ctrl-d' Delete the breakpoint at the current line
`Ctrl-c Ctrl-l' Redisplay the current frame\n
They are also accessible in any buffer by replacing the `Ctrl-c' prefix
with `Ctrl-x Ctrl-a'.\n
Since this command is built on top of the shell-mode all commands from
that mode are available as well.")
;; Digs the variable VAR out of the gdb-last-buffer
(defmacro gdb-get-buffer-var (var)
(list 'with-buffer 'gdb-last-buffer var))
;; Gets the name of the current file
(defun gdb-current-file ()
(file-name-nondirectory (if gdb-buffer-p
(car gdb-last-frame)
(buffer-file-name))))
;; Gets the current line number, it increments it as well
(defun gdb-current-line ()
(1+ (if gdb-buffer-p
(cdr gdb-last-frame)
(pos-line (cursor-pos)))))
;; Send a command to the correct gdb process
(defun gdb-command (format-spec &rest format-args)
(when gdb-buffer-p
(setq gdb-last-buffer (current-buffer)))
(apply 'format
(gdb-get-buffer-var shell-process)
format-spec format-args)
(with-buffer gdb-last-buffer
(when (regexp-match-line "^\\(.*gdb.*\\) *" (buffer-end))
(setq gdb-delete-prompt t))))
;; Receives all output from the gdb subprocess, it acts upon and removes
;; any frame markers
(defun gdb-output-filter (buffer data)
(let
(new-frame)
(with-buffer buffer
(when gdb-spare-output
(setq data (concat gdb-spare-output data)))
(goto-buffer-end)
(when (and gdb-delete-prompt
(regexp-match-line shell-prompt-regexp))
(delete-area (match-start) (match-end))
(setq gdb-delete-prompt nil))
(while (regexp-match "\032\032([^:\n]+):([0-9]+):([0-9]+):.*\n" data)
;; A whole marker to process
(insert (substring data 0 (match-start 0)))
(setq
gdb-last-frame (cons (substring data (match-start 1) (match-end 1))
(1- (read (cons 0 (substring data
(match-start 2)
(match-end 2))))))
new-frame t
data (substring data (match-end 0))))
(if (regexp-match "\032" data)
;; Start of an incomplete marker; save it for later
(progn
(insert (substring data 0 (match-start 0)))
(setq gdb-spare-output (substring data (match-start 0))))
(insert data)
(setq gdb-spare-output nil)))
(when new-frame
(setq gdb-last-buffer buffer)
;; Now redisplay the frame and its highlight
(let*
((frame (with-buffer buffer gdb-last-frame))
(window (if gdb-buffer-p (other-window) (current-window)))
(line-pos (pos 0 (cdr frame)))
old-buf)
(with-window window
(setq old-buf (current-buffer))
(goto-buffer (open-file (car frame)))
(mark-block line-pos (line-end line-pos))
(goto-char (line-end line-pos))
(when (or gdb-auto-centre (not (eq old-buf (current-buffer))))
(centre-display)))))))
(defun gdb-redisplay-frame ()
(interactive)
(when gdb-buffer-p
(setq gdb-last-buffer (current-buffer)))
(let*
((frame (gdb-get-buffer-var gdb-last-frame))
(line-pos (pos 0 (cdr frame))))
(goto-buffer (open-file (car frame)))
(mark-block line-pos (line-end line-pos))
(goto-char (line-end line-pos))
(centre-display)))