home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / modes / dbx+.el < prev    next >
Encoding:
Text File  |  1990-03-21  |  21.2 KB  |  540 lines

  1. ;From: lupton@uhccux.uhcc.hawaii.edu (Robert Lupton)
  2. ;Newsgroups: comp.emacs,gnu.emacs
  3. ;Subject: dbx.el
  4. ;Message-ID: <4432@uhccux.uhcc.hawaii.edu>
  5. ;Date: 26 Jul 89 20:51:27 GMT
  6. ;Organization: University of Hawaii
  7. ;Lines: 530
  8. ;Keywords: dbx gnuemacs
  9. ;
  10. ;
  11. ;Here's (yet another) repost of dbx.el. I've been doing some debugging
  12. ;(of C that is, not lisp) and improved it somewhat. The diffs are
  13. ;bigger than the patches, so it's all here. Thanks to Brian for alpha
  14. ;testing some of it.
  15. ;
  16. ;The main changes are:
  17. ;        (In my previous posting)
  18.  
  19. ;   Added dbx-use to follow `use' commands.
  20. ;   If tracing is enabled, it now understands up/down/where and
  21. ; bus errors, segmentation violations, etc. (providing that no-one has
  22. ; messed with dbx-error messages. E.g. Sun).
  23. ;   Added dbx-command which can be bound to keys, to allow stepping
  24. ; through source without having a *dbx* window
  25. ;   Now runs dbx in current directory, but adds source directory to default
  26. ; dbx-dir-list. This allows post-mortem debugging.
  27. ;   dbx-command takes an optional repeat-count; this may be provided as
  28. ; a prefix argument to dbx-step etc.
  29.  
  30. ;        (new in this posting)
  31.  
  32. ;   dbx-print will pass a string or the region to dbx's `print' command,
  33. ; and provide the answer in the minibuffer; dbx-print-word will print the
  34. ; value of the word under the cursor
  35. ;   Only one dbx process is now permitted
  36. ;   A prefix argument to dbx-where will try to show the stack frame under the
  37. ; cursor (good for going through `where' commands)
  38. ;   Added dbx-compile which is the same as compile (q.v.), except that
  39. ; it first saves dbx's status (break etc.), then runs compile, and then
  40. ; restarts dbx
  41.  
  42. ;   Plus sundry other changes (some to the documentation).
  43.  
  44. ;Bug fixes/Flames (surely not!)/Improvements to lupton@uhccux.uhcc.hawaii.edu
  45.  
  46.  
  47. ;                Robert
  48. ;
  49. ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  50. ;; Run dbx under Emacs
  51. ;; Copyright (C) 1988 Free Software Foundation, Inc.
  52. ;; Main author Masanobu UMEDA (umerin@flab.fujitsu.junet)
  53. ;; Secondary Author Robert Lupton (lupton@uhifa.ifa.hawaii.edu)
  54.  
  55. ;; This file is part of GNU Emacs.
  56.  
  57. ;; GNU Emacs is distributed in the hope that it will be useful,
  58. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  59. ;; accepts responsibility to anyone for the consequences of using it
  60. ;; or for whether it serves any particular purpose or works at all,
  61. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  62. ;; License for full details.
  63.  
  64. ;; Everyone is granted permission to copy, modify and redistribute
  65. ;; GNU Emacs, but only under the conditions described in the
  66. ;; GNU Emacs General Public License.   A copy of this license is
  67. ;; supposed to have been given to you along with GNU Emacs so you
  68. ;; can know your rights and responsibilities.  It should be in a
  69. ;; file named COPYING.  Among other things, the copyright notice
  70. ;; and this notice must be preserved on all copies.
  71. ;
  72. ;   Added dbx-use to follow `use' commands.
  73. ;      RHL March 1989
  74. ;   If tracing is enabled, it now understands up/down/where and
  75. ; bus errors, segmentation violations, etc. (providing that no-one has
  76. ; messed with dbx-error messages. E.g. Sun).
  77. ;   Added dbx-command which can be bound to keys, to allow stepping
  78. ; through source without having a *dbx* window
  79. ;      RHL April 1989
  80. ;   Now runs dbx in current directory, but adds source directory to default
  81. ; dbx-dir-list. This allows post-mortem debugging.
  82. ;   dbx-command takes an optional repeat-count; this may be provided as
  83. ; a prefix argument to dbx-step etc.
  84. ;   dbx-print will pass a string or the region to dbx's `print' command,
  85. ; and provide the answer in the minibuffer; dbx-print-word will print the
  86. ; value of the word under the cursor
  87. ;   Only one dbx process is now permitted
  88. ;      RHL June 1989
  89. ;   A prefix argument to dbx-where will try to show the stack frame under the
  90. ; cursor (good for going through `where' commands)
  91. ;   Added dbx-compile which is the same as compile (q.v.), except that
  92. ; it first saves dbx's status (break etc.), then runs compile, and then
  93. ; restarts dbx
  94. ;
  95. (require 'shell)
  96.  
  97. (defvar dbx-trace-flag nil
  98.   "Dbx trace switch.")
  99.  
  100. (defvar dbx-process nil
  101.   "Dbx process name.")
  102.  
  103. (defvar dbx-dir-list nil
  104.   "List of directories searched by dbx-where, set by dbx-use")
  105.  
  106. (defvar dbx-break-point
  107.   "\\( in .* at\\|),\\) line \\([0-9]*\\)[^\"]*\"?\\([^\"]*\\)?\"?"
  108.   "Regexp of pattern that dbx writes at break points, etc.
  109. the second regular expression in \\\\(\\\\) should give the line number,
  110. the third the file name")
  111.  
  112. (defvar dbx-last-output
  113.   "The last output from dbx that was suppressed by setting dbx-no-output")
  114.  
  115. (defvar dbx-downcase-for-print nil
  116.   "*If set, convert strings to lowercase before submitting to dbx's `print'")
  117.  
  118. (defvar inferior-dbx-mode-map nil)
  119. (if inferior-dbx-mode-map
  120.     nil
  121.   (setq inferior-dbx-mode-map (copy-keymap shell-mode-map))
  122.   (define-key inferior-dbx-mode-map "\C-cu" 'dbx-use)
  123.   (define-key inferior-dbx-mode-map "\C-cw" 'dbx-where)
  124.   (define-key inferior-dbx-mode-map "\C-c\C-t" 'dbx-trace-mode)
  125.   (define-key ctl-x-map "\C-@" 'dbx-stop-at))
  126.  
  127. (defun inferior-dbx-mode ()
  128.   "Major mode for interacting with an inferior Dbx process.
  129. (Note that dbx is an alias for run-dbx)
  130.  
  131. The following commands are available:
  132. \\{inferior-dbx-mode-map}
  133.  
  134. You can display the debugging program in other window and point out
  135. where you are looking at using the command \\[dbx-where]. With a
  136. prefix argument, it'll try to display the position described by the
  137. text under the cursor (this is meant to be used to examine a stack
  138. trace produced by the `where' command; put the cursor on the level you
  139. want to see, and type ^U\\[dbx-where]).
  140.  
  141. \\[dbx-trace-mode] toggles dbx-trace mode. In dbx-trace mode, the
  142. debugging program is automatically traced using output from dbx.  The
  143. dbx commands `down', `up' and `where' are also traced (If no-one has
  144. messed with error formats, e.g. Sun)
  145.  
  146. Using the command dbx-command (e.g. M-x dbx-command \"step\") allows
  147. you to step through the source without using the *dbx* buffer.
  148. The commands dbx-cont, dbx-next, and dbx-step use this. They take an
  149. optional prefix argument to indicate how many steps to take. If no
  150. dbx-prompt is emitted (e.g. control is returned to your code) these
  151. may appear to hang: either concatenate your prompt onto the
  152. shell-prompt-pattern string, or hit ^G.
  153.  
  154. The command dbx-print passes a string to dbx's print command, and
  155. displays the answer in the mini-buffer. If the string is either nil or
  156. empty the current region will be used (i.e. from dot to mark).
  157. dbx-print-word uses this command to print the value of the word under
  158. the cursor. If the variable dbx-downcase-for-print is set then the
  159. string will be converted to lowercase before use.
  160.  
  161. All of the commands based on dbx-command assume that you have a dbx prompt
  162. in the *dbx* buffer, as they use the dbx process to do their work.
  163.  
  164. The command \\[dbx-stop-at] sets a break point at the current line of
  165. the program in the buffer. Major mode name of the buffer must be in
  166. dbx-language-mode-list.
  167.  
  168. You should use the command `dbx-use' (in the mini-buffer, or \\[dbx-use])
  169. rather than `use' so dbx-mode can find your source directories. (Using
  170. use, then dbx-use with no directories specified also works).
  171.  
  172. If you need to recompile, dbx-compile will first save dbx's environment
  173. (using the status command), then run compile (q.v.), then restart dbx
  174. restoring breakpoints, tracing, etc.
  175.  
  176. Commands:
  177.  
  178. Return at end of buffer sends line as input.
  179. Return not at end copies rest of line to end and sends it.
  180. \\[shell-send-eof] sends end-of-file as input.
  181. \\[kill-shell-input] and \\[backward-kill-word] are kill commands, imitating normal Unix input editing.
  182. \\[interrupt-shell-subjob] interrupts the shell or its current subjob if any.
  183. \\[stop-shell-subjob] stops, likewise. \\[quit-shell-subjob] sends quit signal, likewise.
  184. \\[dbx-use] tells dbx mode about any use commands you have issued
  185. \\[dbx-where] displays debugging program in other window and
  186.  points out where you are looking at.
  187. \\[dbx-trace-mode] toggles dbx-trace mode.
  188. \\[dbx-stop-at] sets break point at current line."
  189.   (interactive)
  190.   (kill-all-local-variables)
  191.   (setq major-mode 'inferior-dbx-mode)
  192.   (setq mode-name "Dbx")
  193.   (setq mode-line-process '(": %s"))
  194.   (use-local-map inferior-dbx-mode-map)
  195.   (make-local-variable 'last-input-start)
  196.   (setq last-input-start (make-marker))
  197.   (make-local-variable 'last-input-end)
  198.   (setq last-input-end (make-marker))
  199.   (setq dbx-trace-flag nil)
  200.   (make-variable-buffer-local 'shell-prompt-pattern)
  201.   (setq dbx-prompt ".*(dbx) *")
  202.   (setq shell-prompt-pattern dbx-prompt) ;Set dbx prompt pattern
  203.   (or (assq 'dbx-trace-flag minor-mode-alist)
  204.       (setq minor-mode-alist
  205.         (cons '(dbx-trace-flag " Trace") minor-mode-alist))))
  206.  
  207. (defun dbx () "An alias for run-dbx"
  208.   (interactive)
  209.   (call-interactively 'run-dbx))
  210.  
  211. (defun run-dbx (path)
  212.   "Run inferior Dbx process on PROGRAM, with I/O via buffer *dbx*.
  213.  
  214.    Running this function calls the value of dbx-mode-hook with no
  215. arguments, if that value is non-nil. Likewise with the value of
  216. shell-mode-hook. dbx-mode-hook is called after shell-mode-hook.  When
  217. the hooks are called, the variable path contains the full path name of
  218. the programme being debugged."
  219.  
  220.   (interactive "fProgram to debug: ")
  221.   (if (and dbx-process
  222.        (let ( (status (process-status dbx-process)) )
  223.          (not (or (equal status 'exit) (equal status 'signal)))))
  224.       (progn
  225.     (let ( (pbuff (process-buffer dbx-process)) pwind )
  226.       (if (setq pwind (get-buffer-window pbuff))
  227.           (select-window pwind)
  228.         (switch-to-buffer pbuff)))
  229.     (if (yes-or-no-p "You already running dbx: kill it? ")
  230.         (progn
  231.           (delete-region (point-min) (point-max))
  232.           (delete-process dbx-process))
  233.       (error ""))))
  234.   (setq path (expand-file-name path))
  235.   (switch-to-buffer "*dbx*")
  236.   (switch-to-buffer (make-shell "dbx" "dbx" nil path))
  237.   (setq dbx-process (get-buffer-process (current-buffer)))
  238.   (set-process-filter dbx-process 'dbx-filter)
  239.   (set-process-sentinel dbx-process 'dbx-sentinel)
  240.   (inferior-dbx-mode)
  241.   (let ( (dbx-wait t) )
  242.     (while dbx-wait
  243.       (accept-process-output dbx-process)))
  244.   (goto-char (point-max))
  245.   (dbx-use (concat ". " (file-name-directory path)))
  246.   (let ( ( tracing dbx-trace-flag) )
  247.     (dbx-trace-mode 1)
  248.     (if (and (boundp 'dbx-restart-file) (file-readable-p dbx-restart-file))
  249.     (dbx-command (concat "source " dbx-restart-file) 1 t))
  250.     (if (not tracing)
  251.     (dbx-trace-mode -1)))
  252.   (run-hooks 'shell-mode-hook 'dbx-mode-hook))
  253.  
  254. (defun dbx-trace-mode (arg)
  255.   "Toggle dbx-trace mode.
  256. With arg, turn dbx-trace mode on iff arg is positive.
  257. In dbx-trace mode, user program is automatically traced."
  258.   (interactive "P")
  259.   (setq dbx-trace-flag
  260.     (if (null arg)
  261.         (not dbx-trace-flag)
  262.       (> (prefix-numeric-value arg) 0)))
  263.   (if (and (not dbx-trace-flag) overlay-arrow-position)
  264.       (set-marker overlay-arrow-position nil))
  265.   ;; Force mode line redisplay
  266.   (set-buffer-modified-p (buffer-modified-p)))
  267.  
  268. (defun dbx-filter (process string)
  269.   "Trace debugging program automatically if dbx-trace-flag is not nil.
  270. Checks two flags: dbx-no-output suppresses output to buffer *dbx* if it exists
  271. and is non-nil, and dbx-wait is set to nil (if it exists) when the dbx prompt
  272. is received. If your programme has some prompt of its own then you should
  273. concatenate it with dbx-prompt, i.e.
  274.  (setq shell-prompt-pattern (concat dbx-prompt \"\\\\|my_prompt\")
  275. if you don't want dbx-no-output to throw away all output until the next
  276. dbx-prompt appears."
  277.   (save-excursion
  278.     (set-buffer (process-buffer process))
  279.     (goto-char (point-max))
  280.     (insert string)
  281.     (if (process-mark process)
  282.     (set-marker (process-mark process) (point-max)))
  283.     (goto-char (point-max))
  284.     (if (string-match shell-prompt-pattern string)    ; the next prompt
  285.     (progn
  286.       (if (and (boundp 'dbx-no-output)
  287.            (not (string-match dbx-prompt string)))
  288.           (setq dbx-no-output nil))    ; we do want output at programme prompt
  289.       (if (boundp 'dbx-wait) (setq dbx-wait nil))
  290.       (let ((end (point))
  291.         (beg)
  292.         (search-start (save-excursion (forward-line -20) (point)))
  293.         (str))
  294.         (re-search-backward shell-prompt-pattern search-start t)
  295.         (if (re-search-backward shell-prompt-pattern search-start t)
  296.         (setq beg (match-end 0))
  297.           (setq beg search-start))
  298.         (setq str (buffer-substring beg end))
  299.         (if (and (boundp 'dbx-no-output) dbx-no-output)
  300.         (progn
  301.           (setq dbx-last-output str)
  302.           (delete-region beg end)
  303.           (goto-char (point-max))))
  304.         (if dbx-trace-flag (dbx-show-where str))))))
  305.   (if (eq (process-buffer process) (current-buffer))
  306.       (goto-char (point-max))))
  307.   
  308. (defun dbx-sentinel (process string)
  309.   "Catch dbx exiting and clean up"
  310.   (if (equal string "finished\n")
  311.       (progn
  312.     (insert "\nProcess has finished\n")
  313.     (dbx-trace-mode -1)
  314.     (if overlay-arrow-position
  315.         (set-marker overlay-arrow-position nil))
  316.     (if (and (boundp 'dbx-restart-file)
  317.          (file-readable-p dbx-restart-file))
  318.         (delete-file dbx-restart-file)))))
  319.  
  320. (defun dbx-where (arg)
  321.   "Display dbx'ed program in other window and point out what you are
  322. looking at.  With a prefix argument, try to interpret the line under
  323. the cursor as part of a stack trace as produced by the `where'
  324. command) and display it."
  325.   (interactive "p")
  326.   (if (= arg 1)                ; just run where
  327.       (dbx-command "where" 1 t)
  328.     (let ( (beg (save-excursion (beginning-of-line) (point))) )
  329.       (dbx-show-where (buffer-substring beg (point-max))))))
  330.  
  331. (defun dbx-show-where (string)
  332.   "Display dbx'ed program in other window and point out what you are
  333. looking at.  STRING contains dbx's output."
  334. ;
  335. ; This function can be recursive via dbx-filter, hence dbx-file is not 
  336. ; inside a (let ...)
  337. ;
  338.   (let (file line)
  339.     (if (string-match dbx-break-point string)
  340.     (progn
  341.       (setq line (substring string (match-beginning 2) (match-end 2)))
  342.       (setq file (substring string (match-beginning 3) (match-end 3)))
  343.       (if (equal file "")        ; don't know where we are
  344.           (if (boundp 'dbx-loop)
  345.           (error "Sorry, I can't figure out which file you are in")
  346.         (let ((dbx-loop nil))    ; no file name: try a `where'
  347.           (dbx-command "where" 1 t)
  348.           (string-match dbx-break-point dbx-last-output)))
  349.         (if (string-match "/[^/]*$" file)
  350.         (setq file (substring file (+ 1 (match-beginning 0)) nil)))
  351.         (setq dbx-file file))
  352.       (if (and dbx-file line)            ;Found break point?
  353.           (progn
  354.         ;; Look for the file in each of the dbx-dir-list directories
  355.         (let ((dir dbx-dir-list))
  356.           (while (and dir (not (file-readable-p
  357.               (expand-file-name (concat (car dir) "/" dbx-file) nil))))
  358.             (setq dir (cdr dir)))
  359.           (if (not dir)
  360.               (error (format "Can't find file %s" dbx-file)))
  361.           (setq dbx-file
  362.                (expand-file-name (concat (car dir) "/" dbx-file) nil)))
  363.         (set-buffer (window-buffer))
  364.         (let ( (looking-at-file
  365.             (and (buffer-file-name)
  366.                  (equal (buffer-file-name) dbx-file))) )
  367.           (if (not looking-at-file)
  368.               (find-file-other-window dbx-file))
  369.           (goto-line (string-to-int line))
  370.           (beginning-of-line)
  371.           (setq overlay-arrow-string "=>")
  372.           (or overlay-arrow-position 
  373.               (setq overlay-arrow-position (make-marker)))
  374.           (set-marker overlay-arrow-position (point) (current-buffer))
  375.           (if (not looking-at-file) (other-window 1)))))))))
  376.  
  377. (defun dbx-stop-at ()
  378.   "Set break point at current line."
  379.   (interactive)
  380.   (let ((file-name (file-name-nondirectory buffer-file-name))
  381.     (line (save-restriction
  382.         (widen)
  383.         (1+ (count-lines
  384.              1 (save-excursion (beginning-of-line) (point)))))))
  385.     (send-string dbx-process
  386.          (concat "stop at \"" file-name "\":" line "\n")))
  387.     (accept-process-output dbx-process)
  388.     ; now move point to end of buffer:
  389.     (set-buffer (get-buffer (process-buffer dbx-process)))
  390.     (save-window-excursion
  391.       (switch-to-buffer-other-window (current-buffer))
  392.       (goto-char (point-max)))
  393.     (if (process-mark dbx-process)
  394.     (set-marker (process-mark dbx-process) (point-max))))
  395.  
  396. (defun dbx-use (dirs)
  397.   "Run dbx's `use' command and parse the output to make a list of
  398. directories for the use of dbx-where. If no directories are specified,
  399. get the current list and parse that"
  400.   (interactive "suse: ")
  401.   (setq dbx-dir-list nil)
  402.   (save-window-excursion
  403.     (let ( (dbx-wait t) )        ; set to nil when next prompt is ready
  404.       (if (string-match "[^ \t]" dirs)
  405.       (let ( (dbx-no-output t) )    ; used by dbx-filter to kill output
  406.         (send-string dbx-process (concat "use " dirs "\n"))
  407.         (while dbx-wait (accept-process-output dbx-process))))
  408.       (setq dbx-wait t)
  409.       (send-string dbx-process "use\n")
  410.       (while dbx-wait (accept-process-output dbx-process)))
  411.     (switch-to-buffer (process-buffer dbx-process))
  412.     (end-of-buffer)
  413.     (previous-line 1)
  414.     (beginning-of-line)
  415.     (while (looking-at shell-prompt-pattern)
  416.     (goto-char (match-end 0)))
  417.     (while (looking-at "[ \t]*[^ \t\n]+")
  418.       (progn 
  419.     (goto-char (match-end 0))
  420.     (skip-chars-forward " \t")
  421.     (setq dbx-dir-list
  422.           (append dbx-dir-list
  423.               (list
  424.                (let ((dir (buffer-substring
  425.                    (match-beginning 0) (match-end 0))))
  426.              (if (string-match "/$" dir)
  427.                  (setq dir (substring dir 0 -1))
  428.                dir))))))))
  429.   (end-of-buffer)
  430.   (kill-region (progn (previous-line 1) (dot)) (point-max)))
  431.  
  432. (defun dbx-command (command &optional num no-trace)
  433.   "Run a dbx COMMAND from the current buffer, suppressing output to *dbx*.
  434. If you have enabled tracing this enables you to step through the source.
  435. This is probably most useful for `next', `step', and `cont'.
  436. Optionally, provide a repeat count NUM. If NO-TRACE is t, don't trace
  437. position in source"
  438.   (interactive "sCommand: ")
  439.   (if (not dbx-trace-flag)
  440.       (error "This command only works if tracing is turned on"))
  441.   (if (not num) (setq num 1))
  442.   (while (>= (setq num (- num 1)) 0)
  443.     (let ( (dbx-no-output t)        ; used by dbx-filter to kill output
  444.        (dbx-wait t))        ; set to nil when next prompt is ready
  445.       (send-string dbx-process (concat command "\n"))
  446.       (while dbx-wait
  447.     (accept-process-output dbx-process))
  448.       )
  449.     (if (not no-trace)
  450.     (let ( (mark-buffer) (bw) )
  451.       (if (and overlay-arrow-position
  452.            (setq mark-buffer (marker-buffer overlay-arrow-position)))
  453.       (progn
  454.         (setq bw (get-buffer-window mark-buffer))
  455.         (if bw (select-window bw)
  456.           (switch-to-buffer mark-buffer))
  457.         (goto-char (marker-position overlay-arrow-position))))))))
  458.  
  459. (defun dbx-cont (num)
  460.   "Key-bindable interface to dbx-command, for `cont' command"
  461.   (interactive "p")
  462.   (dbx-command "cont" num))
  463.  
  464. (defun dbx-next (num)
  465.   "Key-bindable interface to dbx-command, for `next' command"
  466.   (interactive "p")
  467.   (dbx-command "next" num))
  468.  
  469. (defun dbx-step (num)
  470.   "Key-bindable interface to dbx-command, for `step' command"
  471.   (interactive "p")
  472.   (dbx-command "step" num))
  473.  
  474. (defun dbx-print ( &optional expr)
  475.   "Feed an expression to dbx as the subject of a `print' command, and
  476. output the answer in the minibuffer. If the expression is nil or empty
  477. print the region in the current buffer. If the variable dbx-downcase-for-print
  478. is set, convert the expression to lowercase before using it (this may
  479. be useful for languages like fortran). See dbx-print-word for printing
  480. the word under the cursor."
  481.   (interactive "sExpression: ")
  482.   (if (or (not expr) (equal expr ""))
  483.       (setq expr (buffer-substring (region-beginning) (region-end))))
  484.   (if dbx-downcase-for-print
  485.       (setq expr (downcase expr)))
  486.   (dbx-command (concat "print " expr) 1 t)
  487.   (string-match dbx-prompt dbx-last-output)
  488.   (let ( (val (substring dbx-last-output 0 (- (match-beginning 0) 1))) )
  489.     (if (string-match "= *" val)
  490.     (setq val (substring val (match-end 0) nil)))
  491.     (message (format "%s : %s" expr val))))
  492.  
  493. (defun dbx-print-word (num)
  494.   "print the value of the word under the cursor in the mini-buffer,
  495. with a prefix-argument simply call dbx-print"
  496.   (interactive "p")
  497.   (if (not (= num 1))            ; there's a prefix argument
  498.       (call-interactively 'dbx-print)
  499.     (save-excursion
  500.       (let ( (beg (progn (forward-word 1) (dot)))
  501.          (end (progn (forward-word -1) (dot))) )
  502.     (dbx-print (buffer-substring beg end))))))
  503.  
  504. (defun dbx-compile ()
  505.   "Compile a programme. Just like compile, except that it first saves
  506. the state of the current dbx session, then compiles, then restarts
  507. dbx. If the compilation fails the status should be recovered when a
  508. dbx-compile finally succeeds. If you exit dbx (`quit'), then the
  509. status information is lost, but dbx-compile will still attempt to
  510. restart the same programme."
  511.   (interactive)
  512.   (if (and (boundp 'dbx-process) (equal (process-status dbx-process) 'run))
  513.       (progn
  514.     (if (and (boundp 'dbx-restart-file)
  515.          (file-readable-p dbx-restart-file))
  516.         (delete-file dbx-restart-file))
  517.     (setq dbx-restart-file (make-temp-name "/tmp/dbx_"))
  518.     (let ( (dbx-wait t)
  519.            (pt (point)))
  520.       (send-string dbx-process (concat "status > " dbx-restart-file "\n"))
  521.       (while dbx-wait
  522.         (accept-process-output dbx-process))
  523.       (set-process-sentinel dbx-process nil) ; don't delete restart file
  524.       (kill-process dbx-process)
  525.       (delete-region (point) pt))))
  526.   (call-interactively 'compile)
  527.   (set-process-sentinel compilation-process 'compilation-sentinel2))
  528. ;
  529. ; Replace the compilation sentinel by one that restarts dbx
  530. ;
  531. (defun compilation-sentinel2 (proc msg)
  532.   (compilation-sentinel proc msg)
  533.   (if (or (equal msg "exit\n") (equal msg "finished\n"))
  534.       (if (y-or-n-p "restart dbx? ")
  535.       (let ( (pgm (car (reverse (process-command dbx-process)))))
  536.         (set-buffer (process-buffer dbx-process))
  537.         (goto-char (point-max))
  538.         (insert "\nIf line numbers have changed, break points may be wrong\n")
  539.         (run-dbx pgm)))))
  540.