summaryrefslogtreecommitdiffhomepage
path: root/misc/mixvm.el
blob: c437dfd665f269e7356c28900e759a366afa4066 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
;;; mixvm.el --- mdk's mixvm / Emacs gud interaction
;; Copyright (C) 2001 Free Software Foundation, Inc.
     
;; Author: Philip Ellis King <pking@pdq.net>
;; Maintainer: Philip Ellis King <pking@pdq.net>
;; Created: 12 Feb 2001
;; Version: 0.2
;; Keywords: tools
     

;;; Commentary:
;; mixvm.el provides an interface between mdk's mixvm and Emacs,
;; via gud.  Place this file in your load-path, optionally adding
;; the following line to your .emacs file:
;; (autoload 'mixvm "mixvm" "mixvm/gud interaction" t)
;; Initiate a mdk/gud session with the command mixvm, gud will
;; reflect the current line in the source file buffer.

;; (mixvm.el is based on a study of gdb, perldb, and pdb as found
;; in gud.el, and rubydb3x.el distributed with the source code to
;; the Ruby language.

;;; Change Log:
;; Version 0.2
;; Initial release


;;; Code:
(require 'gud)
(provide 'mixvm)

;;; History of argument lists passed to mixvm.
(defvar gud-mixvm-history nil)

;; rubydb3x provided good examples of xemacs/emacs
;; compatibility (not interested at the moment)
(defun gud-mixvm-massage-args (file args)
  (cons "--emacs" args))

;; There's no guarantee that Emacs will hand the filter the entire
;; marker at once; it could be broken up across several strings.  We
;; might even receive a big chunk with several markers in it.  If we
;; receive a chunk of text which looks like it might contain the
;; beginning of a marker, we save it here between calls to the
;; filter.
(defvar gud-mixvm-marker-acc "")
(make-variable-buffer-local 'gud-mixvm-marker-acc)

(defun gud-mixvm-marker-filter (string)
  (setq gud-mixvm-marker-acc (concat gud-mixvm-marker-acc string))
  (let ((output ""))

    ;; Process all the complete markers in this chunk.
    (while (string-match "\032\032mixvm:\\([^:]+\\):\\([0-9]+\\)"
                         gud-mixvm-marker-acc)
      (setq

       ;; Extract the frame position from the marker.
       gud-last-frame
       (cons (substring gud-mixvm-marker-acc (match-beginning 1) (match-end 1))
             (string-to-int (substring gud-mixvm-marker-acc
                                       (match-beginning 2)
                                       (match-end 2))))

       ;; Append any text before the marker to the output we're going
       ;; to return - we don't include the marker in this text.
       output (concat output
                      (substring gud-mixvm-marker-acc 0 (match-beginning 0)))

       ;; Set the accumulator to the remaining text.
       gud-mixvm-marker-acc (substring gud-mixvm-marker-acc (match-end 0))))

    ;; Does the remaining text look like it might end with the
    ;; beginning of another marker?  If it does, then keep it in
    ;; gud-mixvm-marker-acc until we receive the rest of it.  Since we
    ;; know the full marker regexp above failed, it's pretty simple to
    ;; test for marker starts.
    ;; (note: \\' matches the end of the string (Perl's '$'))
    (if (string-match "\032.*\\'" gud-mixvm-marker-acc)
        (progn
          ;; Everything before the potential marker start can be output.
          (setq output (concat output (substring gud-mixvm-marker-acc
                                                 0 (match-beginning 0))))

          ;; Everything after, we save, to combine with later input.
          (setq gud-mixvm-marker-acc
                (substring gud-mixvm-marker-acc (match-beginning 0))))

      (setq output (concat output gud-mixvm-marker-acc)
            gud-mixvm-marker-acc ""))

    output))

;; See gdb for more comprehensive example
;; pek: it bugs me that this is run for EVERY interactive
;; mixvm command, should we cache some info somewhere?
(defun gud-mixvm-find-file (file)
  (save-excursion
    (let* ((buf (find-file-noselect file)))
      (set-buffer buf)
      (when (boundp 'gud-make-debug-menu)
	(gud-make-debug-menu))
      buf)))


(defvar mixvm-minibuffer-local-map nil
  "Keymap for minibuffer prompting of mixvm startup command.")
(if mixvm-minibuffer-local-map
    ()
  (setq mixvm-minibuffer-local-map (copy-keymap minibuffer-local-map))
  (define-key
    mixvm-minibuffer-local-map "\C-i" 'comint-dynamic-complete-filename))


(defcustom gud-mixvm-command-name "mixvm"
  "File name for executing the mixvm debugger.
This should be an executable on your path, or an absolute file name."
  :type 'string
  :group 'gud)


;;;###autoload
(defun mixvm (command-line)
  "Run mixvm on program FILE in buffer `*gud-FILE*'.
The directory containing FILE becomes the initial working directory
and source-file directory for your debugger."
  (interactive
   (list (read-from-minibuffer "Run mixvm (like this): "
                               (if (consp gud-mixvm-history)
                                   (car gud-mixvm-history)
                                 (concat gud-mixvm-command-name " "))
                               mixvm-minibuffer-local-map nil
                               '(gud-mixvm-history . 1))))

  (gud-common-init command-line 'gud-mixvm-massage-args
                   'gud-mixvm-marker-filter 'gud-mixvm-find-file)

  (gud-def gud-break  "sbp %l"     "\C-b" "Set breakpoint at current line.")
  (gud-def gud-remove "cbp %l"     "\C-d" "Remove breakpoint at current line")
  (gud-def gud-step   "next"         "\C-s" "Step one source line with display.")
  (gud-def gud-next   "next"         "\C-n" "Step one line.")
  (gud-def gud-stepi   "next"         "\C-i" "Step one line.")
  (gud-def gud-cont   "run"     "\C-r" "Continue with display.")
  (gud-def gud-finish "run"       "\C-f" "Finish executing current function.")
  (gud-def gud-print  "weval %e"         "\C-p" "Evaluate expression at point.")
;   (gud-def gud-up     "up"           "<" "Up one stack frame.")
;   (gud-def gud-down   "down"         ">" "Down one stack frame.")
;   ;; Is this right?
;   (gud-def gud-statement "! %e"      "\C-e" "Execute Python statement at point.")

;   (local-set-key [menu-bar debug finish] '("Finish Function" . gud-finish))
;   (local-set-key [menu-bar debug up] '("Up Stack" . gud-up))
;   (local-set-key [menu-bar debug down] '("Down Stack" . gud-down))
  (setq comint-prompt-regexp "^MIX > ")
  (set (make-local-variable 'paragraph-start) comint-prompt-regexp)
  (run-hooks 'mixvm-mode-hook))

;;; mixvm.el ends here