home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / modes / mipsdbx.el.el < prev    next >
Encoding:
Text File  |  1992-11-25  |  15.3 KB  |  431 lines

  1. ; Newsgroups: gnu.emacs.help,gnu.emacs.sources
  2. ; Path: hal.com!decwrl!uunet!mcsun!sunic!aun.uninett.no!nuug!nntp.uio.no!egilp
  3. ; From: egilp@ulrik.uio.no (Egil Pedersen)
  4. ; Subject: Re: Is there a dbx-mode for DEC's Ultrix dbx?
  5. ; In-Reply-To: whaley@kpc.com's message of Mon, 16 Nov 1992 03:20:27 GMT
  6. ; Organization: University of Oslo, Norway
  7. ; Date: Mon, 16 Nov 1992 10:28:14 GMT
  8. ; In article <whaley.721884027@kpc.com> whaley@kpc.com (Kenneth Whaley) writes:
  9. ;  Unfortunately, DEC's Ultrix dbx outputs different strings  for breakpoints,
  10. ;  etc. than the dbx that all the "dbx.el"s I've found on the net are
  11. ;  written to work with.  If it were simply a matter of changing the 
  12. ;  regexp of breakpoints, then I could get this to work, but
  13. ;  unfortunately the DEC dbx does not print out the file name at every
  14. ;  breakpoint, only the line number (and the breakpoint number, the function
  15. ;  name, and the PC).
  16. ; You may try this one. It works with 18.58. I do not remember where I got it.
  17. ;
  18.  
  19.  
  20. ;; Run MIPS dbx under Emacs
  21. ;; Author: W. Schelter, University of Texas
  22. ;;     wfs@rascal.ics.utexas.edu
  23. ;; Rewritten by rms.
  24. ;; Some ideas are due to Masanobu.
  25. ;; Converted from gdb.el to mipsdbx.el by Kung and Killian.
  26.  
  27. ;; LCD Archive Entry:
  28. ;; mipsdbx.el|Egil Pedersen|egilp@ulrik.uio.no|
  29. ;; Run MIPS dbx under Emacs.|
  30. ;; 92-11-16||~/modes/mipsdbx.el.el.Z|
  31.  
  32. ;; This file is part of GNU Emacs.
  33. ;; Copyright (C) 1988 Free Software Foundation, Inc.
  34.  
  35. ;; GNU Emacs is distributed in the hope that it will be useful, but
  36. ;; WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  37. ;; to anyone for the consequences of using it or for whether it serves
  38. ;; any particular purpose or works at all, unless he says so in writing.
  39. ;; Refer to the GNU Emacs General Public License for full details.
  40.  
  41. ;; Everyone is granted permission to copy, modify and redistribute GNU
  42. ;; Emacs, but only under the conditions described in the GNU Emacs
  43. ;; General Public License.  A copy of this license is supposed to have
  44. ;; been given to you along with GNU Emacs so you can know your rights and
  45. ;; responsibilities.  It should be in a file named COPYING.  Among other
  46. ;; things, the copyright notice and this notice must be preserved on all
  47. ;; copies.
  48.  
  49. ;; Description of DBX interface:
  50.  
  51. ;; A facility is provided for the simultaneous display of the source code
  52. ;; in one window, while using dbx to step through a function in the
  53. ;; other.  A small arrow in the source window, indicates the current
  54. ;; line.
  55.  
  56. ;; Starting up:
  57.  
  58. ;; In order to use this facility, invoke the command DBX to obtain a
  59. ;; shell window with the appropriate command bindings.  You will be asked
  60. ;; for the name of a file to run.  Dbx will be invoked on this file, in a
  61. ;; window named *dbx-foo* if the file is foo.
  62.  
  63. ;; M-s steps by one line, and redisplays the source file and line.
  64.  
  65. ;; You may easily create additional commands and bindings to interact
  66. ;; with the display.  For example to put the dbx command next on \M-n
  67. ;; (def-dbx next "\M-n")
  68.  
  69. ;; This causes the emacs command dbx-next to be defined, and runs
  70. ;; dbx-display-frame after the command.
  71.  
  72. ;; dbx-display-frame is the basic display function.  It tries to display
  73. ;; in the other window, the file and line corresponding to the current
  74. ;; position in the dbx window.  For example after a dbx-step, it would
  75. ;; display the line corresponding to the position for the last step.  Or
  76. ;; if you have done a backtrace in the dbx buffer, and move the cursor
  77. ;; into one of the frames, it would display the position corresponding to
  78. ;; that frame.
  79.  
  80. ;; dbx-display-frame is invoked automatically when a filename-and-line-number
  81. ;; appears in the output.
  82.  
  83.  
  84. (require 'shell)
  85.  
  86. (defvar dbx-prompt-pattern "^(.*dbx[+]?) *"
  87.   "A regexp to recognize the prompt for dbx or dbx+.")
  88.  
  89. (defvar dbx-mode-map nil
  90.   "Keymap for dbx-mode.")
  91.  
  92. (if dbx-mode-map
  93.    nil
  94.   (setq dbx-mode-map (copy-keymap shell-mode-map))
  95.   (define-key dbx-mode-map "\C-l" 'dbx-refresh))
  96.  
  97. (define-key ctl-x-map " " 'dbx-break)
  98. (define-key ctl-x-map "&" 'send-dbx-command)
  99.  
  100. ;;Of course you may use `def-dbx' with any other dbx command, including
  101. ;;user defined ones.
  102.  
  103. (defmacro def-dbx (name key &optional doc)
  104.   (let* ((fun (intern (format "dbx-%s" name)))
  105.      (cstr (list 'if '(not (= 1 arg))
  106.              (list 'format "%s %s" name 'arg)
  107.              name)))
  108.     (list 'progn
  109.        (list 'defun fun '(arg)
  110.         (or doc "")
  111.         '(interactive "p")
  112.         (list 'dbx-call cstr))
  113.       (list 'define-key 'dbx-mode-map key  (list 'quote fun)))))
  114.  
  115. (def-dbx "step"   "\M-s" "Step one source line with display")
  116. (def-dbx "stepi"  "\M-i" "Step one instruction with display")
  117. (def-dbx "next"   "\M-n" "Step one source line (skip functions)")
  118. (def-dbx "cont"   "\M-c" "Continue with display")
  119.  
  120. (def-dbx "quit!" "\C-c\C-f" "Finish executing current function")
  121. (def-dbx "up"     "\M-u"   "Go up N stack frames (numeric arg) with display")
  122. (def-dbx "down"   "\M-d"   "Go down N stack frames (numeric arg) with display")
  123.  
  124. (defun dbx-mode ()
  125.   "Major mode for interacting with an child Dbx process.
  126. The following commands are available:
  127.  
  128. \\{dbx-mode-map}
  129.  
  130. \\[dbx-display-frame] displays in the other window
  131. the last line referred to in the dbx buffer.
  132.  
  133. \\[dbx-step],\\[dbx-next], and \\[dbx-nexti] in the dbx window,
  134. call dbx to step,next or nexti and then update the other window
  135. with the current file and position.
  136.  
  137. If you are in a source file, you may select a point to break
  138. at, by doing \\[dbx-break].
  139.  
  140. Commands:
  141. Many commands are inherited from shell mode.
  142. Additionally we have:
  143.  
  144. \\[dbx-display-frame] display frames file in other window
  145. \\[dbx-step] advance one line in program
  146. \\[dbx-next] advance one line in program (skip over calls).
  147. \\[send-dbx-command] used for special printing of an arg at the current point.
  148. C-x SPACE sets break point at current line."
  149.   (interactive)
  150.   (kill-all-local-variables)
  151.   (setq major-mode 'dbx-mode)
  152.   (setq mode-name "Child Dbx")
  153.   (setq mode-line-process '(": %s"))
  154.   (use-local-map dbx-mode-map)
  155.   (make-local-variable 'last-input-start)
  156.   (setq last-input-start (make-marker))
  157.   (make-local-variable 'last-input-end)
  158.   (setq last-input-end (make-marker))
  159.   (make-local-variable 'dbx-last-frame)
  160.   (setq dbx-last-frame nil)
  161.   (make-local-variable 'dbx-last-frame-displayed-p)
  162.   (setq dbx-last-frame-displayed-p t)
  163.   (make-local-variable 'dbx-delete-prompt-marker)
  164.   (setq dbx-delete-prompt-marker nil)
  165.   (make-local-variable 'dbx-filter-accumulator)
  166.   (setq dbx-filter-accumulator nil)
  167.   (make-local-variable 'shell-prompt-pattern)
  168.   (setq shell-prompt-pattern dbx-prompt-pattern)
  169.   (run-hooks 'shell-mode-hook 'dbx-mode-hook))
  170.  
  171. (defvar current-dbx-buffer nil)
  172.  
  173. (defvar dbx-command-name "dbx"
  174.   "Pathname for executing dbx.")
  175.  
  176. (defun dbx (path &optional dbxargs)
  177.   "Run dbx on program FILE in buffer *dbx-FILE*.
  178. The directory containing FILE becomes the initial working directory
  179. and source-file directory for DBX.  If you wish to change this, use
  180. the DBX commands `cd DIR' and `directory'."
  181.   (interactive "FRun dbx on file: ")
  182.   (setq path (expand-file-name path))
  183.   (let ((file (file-name-nondirectory path)))
  184.     (switch-to-buffer (concat "*dbx-" file "*"))
  185.     (setq default-directory (file-name-directory path))
  186.     (or (bolp) (newline))
  187.     (insert "Current directory is " default-directory "\n")
  188.     (if dbxargs
  189.     (make-shell (concat "dbx-" file) dbx-command-name nil "-emacs" dbxargs file)
  190.       (make-shell (concat "dbx-" file) dbx-command-name nil "-emacs" file))
  191.     (dbx-mode)
  192.     (set-process-filter (get-buffer-process (current-buffer)) 'dbx-filter)
  193.     (set-process-sentinel (get-buffer-process (current-buffer)) 'dbx-sentinel)
  194.     (dbx-set-buffer)))
  195.  
  196. (defun dbx-set-buffer ()
  197.   (cond ((eq major-mode 'dbx-mode)
  198.     (setq current-dbx-buffer (current-buffer)))))
  199.  
  200. ;; This function is responsible for inserting output from DBX
  201. ;; into the buffer.
  202. ;; Aside from inserting the text, it notices and deletes
  203. ;; each filename-and-line-number;
  204. ;; that DBX prints to identify the selected frame.
  205. ;; It records the filename and line number, and maybe displays that file.
  206. (defun dbx-filter (proc string)
  207.   (let ((inhibit-quit t))
  208.     (if dbx-filter-accumulator
  209.     (dbx-filter-accumulate-marker proc
  210.                       (concat dbx-filter-accumulator string))
  211.     (dbx-filter-scan-input proc string))))
  212.  
  213. (defun dbx-filter-accumulate-marker (proc string)
  214.   (setq dbx-filter-accumulator nil)
  215.   (if (> (length string) 1)
  216.       (if (= (aref string 1) ?\032)
  217.       (let ((end (string-match "\n" string)))
  218.         (if end
  219.         (progn
  220.           (let* ((first-colon (string-match ":" string 2))
  221.              (second-colon
  222.               (string-match ":" string (1+ first-colon))))
  223.             (setq dbx-last-frame
  224.               (cons (substring string 2 first-colon)
  225.                 (cons (string-to-int
  226.                      (substring string (1+ first-colon)
  227.                         second-colon))
  228.                       (string-to-int
  229.                      (substring string (1+ second-colon)
  230.                         end))))))
  231.           (setq dbx-last-frame-displayed-p nil)
  232.           (dbx-filter-scan-input proc
  233.                      (substring string (1+ end))))
  234.           (setq dbx-filter-accumulator string)))
  235.     (dbx-filter-insert proc "\032")
  236.     (dbx-filter-scan-input proc (substring string 1)))
  237.     (setq dbx-filter-accumulator string)))
  238.  
  239. (defun dbx-filter-scan-input (proc string)
  240.   (if (equal string "")
  241.       (setq dbx-filter-accumulator nil)
  242.       (let ((start (string-match "\032" string)))
  243.     (if start
  244.         (progn (dbx-filter-insert proc (substring string 0 start))
  245.            (dbx-filter-accumulate-marker proc
  246.                          (substring string start)))
  247.         (dbx-filter-insert proc string)))))
  248.  
  249. (defun dbx-filter-insert (proc string)
  250.   (let ((moving (= (point) (process-mark proc)))
  251.     (output-after-point (< (point) (process-mark proc)))
  252.     (old-buffer (current-buffer))
  253.     start)
  254.     (set-buffer (process-buffer proc))
  255.     (unwind-protect
  256.     (save-excursion
  257.       ;; Insert the text, moving the process-marker.
  258.       (goto-char (process-mark proc))
  259.       (setq start (point))
  260.       (insert string)
  261.       (set-marker (process-mark proc) (point))
  262.       (dbx-maybe-delete-prompt)
  263.       ;; Check for a filename-and-line number.
  264.       (dbx-display-frame
  265.        ;; Don't display the specified file
  266.        ;; unless (1) point is at or after the position where output appears
  267.        ;; and (2) this buffer is on the screen.
  268.        (or output-after-point
  269.            (not (get-buffer-window (current-buffer))))
  270.        ;; Display a file only when a new filename-and-line-number appears.
  271.        t))
  272.       (set-buffer old-buffer))
  273.     (if moving (goto-char (process-mark proc)))))
  274.  
  275. (defun dbx-sentinel (proc msg)
  276.   (cond ((null (buffer-name (process-buffer proc)))
  277.      ;; buffer killed
  278.      ;; Stop displaying an arrow in a source file.
  279.      (setq overlay-arrow-position nil)
  280.      (set-process-buffer proc nil))
  281.     ((memq (process-status proc) '(signal exit))
  282.      ;; Stop displaying an arrow in a source file.
  283.      (setq overlay-arrow-position nil)
  284.      ;; Fix the mode line.
  285.      (setq mode-line-process
  286.            (concat ": "
  287.                (symbol-name (process-status proc))))
  288.      (let* ((obuf (current-buffer)))
  289.        ;; save-excursion isn't the right thing if
  290.        ;;  process-buffer is current-buffer
  291.        (unwind-protect
  292.            (progn
  293.          ;; Write something in *compilation* and hack its mode line,
  294.          (set-buffer (process-buffer proc))
  295.          ;; Force mode line redisplay soon
  296.          (set-buffer-modified-p (buffer-modified-p))
  297.          (if (eobp)
  298.              (insert ?\n mode-name " " msg)
  299.            (save-excursion
  300.              (goto-char (point-max))
  301.              (insert ?\n mode-name " " msg)))
  302.          ;; If buffer and mode line will show that the process
  303.          ;; is dead, we can delete it now.  Otherwise it
  304.          ;; will stay around until M-x list-processes.
  305.          (delete-process proc))
  306.          ;; Restore old buffer, but don't restore old point
  307.          ;; if obuf is the dbx buffer.
  308.          (set-buffer obuf))))))
  309.  
  310.  
  311. (defun dbx-refresh ()
  312.   "Fix up a possibly garbled display, and redraw the arrow."
  313.   (interactive)
  314.   (redraw-display)
  315.   (dbx-display-frame))
  316.  
  317. (defun dbx-display-frame (&optional nodisplay noauto)
  318.   "Find, obey and delete the last filename-and-line marker from DBX.
  319. The marker looks like \\032\\032FILENAME:LINE:CHARPOS\\n.
  320. Obeying it means displaying in another window the specified file and line."
  321.   (interactive)
  322.   (dbx-set-buffer)
  323.   (and dbx-last-frame (not nodisplay)
  324.        (or (not dbx-last-frame-displayed-p) (not noauto))
  325.        (progn (dbx-display-line (car dbx-last-frame)
  326.                        (car (cdr dbx-last-frame))
  327.                 (cdr (cdr dbx-last-frame)))
  328.           (setq dbx-last-frame-displayed-p t))))
  329.  
  330. ;; Make sure the file named TRUE-FILE is in a buffer that appears on the screen
  331. ;; and that its line LINE is visible.
  332. ;; Put the overlay-arrow on the line LINE in that buffer.
  333.  
  334. (defun dbx-display-line (true-file line chpos)
  335.   (let* ((buffer (find-file-noselect true-file))
  336.      (window (display-buffer buffer t))
  337.      (pos))
  338.     (save-excursion
  339.       (set-buffer buffer)
  340.       (save-restriction
  341.     (widen)
  342.     (goto-line line)
  343.     (setq pos (point))
  344.     (cond ((not (= chpos 0)) (setq overlay-arrow-string "=>"))
  345.           (t (setq overlay-arrow-string "")))
  346.     (or overlay-arrow-position
  347.         (setq overlay-arrow-position (make-marker)))
  348.     (set-marker overlay-arrow-position (point) (current-buffer)))
  349.       (cond ((or (< pos (point-min)) (> pos (point-max)))
  350.          (widen)
  351.          (goto-char pos))))
  352.     (set-window-point window overlay-arrow-position)))
  353.  
  354. (defun dbx-call (command)
  355.   "Invoke dbx COMMAND displaying source in other window."
  356.   (interactive)
  357.   (goto-char (point-max))
  358.   (setq dbx-delete-prompt-marker (point-marker))
  359.   (dbx-set-buffer)
  360.   (send-string (get-buffer-process current-dbx-buffer)
  361.            (concat command "\n")))
  362.  
  363. (defun dbx-maybe-delete-prompt ()
  364.   (if (and dbx-delete-prompt-marker
  365.        (> (point-max) (marker-position dbx-delete-prompt-marker)))
  366.       (let (start)
  367.     (goto-char dbx-delete-prompt-marker)
  368.     (setq start (point))
  369.     (beginning-of-line)
  370.     (delete-region (point) start)
  371.     (setq dbx-delete-prompt-marker nil))))
  372.  
  373. (defun dbx-break ()
  374.   "Set DBX breakpoint at this source line."
  375.   (interactive)
  376.   (let ((file-name (file-name-nondirectory buffer-file-name))
  377.     (line (save-restriction
  378.         (widen)
  379.         (1+ (count-lines 1 (point))))))
  380.     (send-string (get-buffer-process current-dbx-buffer)
  381.          (concat "stop at \"" file-name "\":" line "\n"))))
  382.  
  383. (defun dbx-read-address()
  384.   "Return a string containing the core-address found in the buffer at point."
  385.   (save-excursion
  386.    (let ((pt (dot)) found begin)
  387.      (setq found (if (search-backward "0x" (- pt 7) t)(dot)))
  388.      (cond (found (forward-char 2)(setq result
  389.             (buffer-substring found
  390.                  (progn (re-search-forward "[^0-9a-f]")
  391.                     (forward-char -1)
  392.                     (dot)))))
  393.        (t (setq begin (progn (re-search-backward "[^0-9]") (forward-char 1)
  394.                  (dot)))
  395.           (forward-char 1)
  396.           (re-search-forward "[^0-9]")
  397.           (forward-char -1)
  398.           (buffer-substring begin (dot)))))))
  399.  
  400.  
  401. (defvar dbx-commands nil
  402.   "List of strings or functions used by send-dbx-command.
  403. It is for customization by you.")
  404.  
  405. (defun send-dbx-command (arg)
  406.  
  407.   "This command reads the number where the cursor is positioned.  It
  408.  then inserts this ADDR at the end of the dbx buffer.  A numeric arg
  409.  selects the ARG'th member COMMAND of the list dbx-print-command.  If
  410.  COMMAND is a string, (format COMMAND ADDR) is inserted, otherwise
  411.  (funcall COMMAND ADDR) is inserted.  eg. \"p (rtx)%s->fld[0].rtint\"
  412.  is a possible string to be a member of dbx-commands.  "
  413.  
  414.  
  415.   (interactive "P")
  416.   (let (comm addr)
  417.     (if arg (setq comm (nth arg dbx-commands)))
  418.     (setq addr (dbx-read-address))
  419.     (if (eq (current-buffer) current-dbx-buffer)
  420.     (set-mark (point)))
  421.     (cond (comm
  422.        (setq comm
  423.          (if (stringp comm) (format comm addr) (funcall comm addr))))
  424.       (t (setq comm addr)))
  425.     (switch-to-buffer current-dbx-buffer)
  426.     (goto-char (dot-max))
  427.     (insert-string comm)))
  428.