Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane
From: Eduardo Ochs <eduardoochs-Re5JQEeQqe8AvxtiuMwx3w <at> public.gmane.org>
Subject: eepitch and GUD
Newsgroups: gmane.emacs.eev.devel
Date: Sunday 8th July 2007 16:10:57 UTC (over 9 years ago)
Hey eepitch people (Rubikitch, and who else?),

what do you use to run GDB and other GUD-friendly debuggers using
eepitch? After a lot of refactoring I had transformed Rubikitch's
original code into this, that is at:

  (find-eevfile "eev-mini-steps.el" "defvar eepitch-code")
  http://angg.twu.net/eev-current/eev-mini-steps.el.html#eepitch-code

--snip--snip--

;;;                  _ _       _
;;;   ___  ___ _ __ (_) |_ ___| |__
;;;  / _ \/ _ \ '_ \| | __/ __| '_ \
;;; |  __/  __/ |_) | | || (__| | | |
;;;  \___|\___| .__/|_|\__\___|_| |_|
;;;           |_|

(defvar eepitch-code '(error "eepitch not set up"))
(defvar eepitch-target-buffer nil)

(defun eepitch-prepare-target-buffer ()
"Run `eepitch-code' and store the name of the resulting buffer in
`eepitch-target-buffer'."
  (save-window-excursion
    (eval eepitch-code)
    (setq eepitch-target-buffer (current-buffer))))

(defun eepitch-display-target-buffer ()
  "Display the buffer `eepitch-target-buffer' in another window."
  (if (not (get-buffer-window eepitch-target-buffer))
      (let ((pop-up-windows t)
	    (same-window-buffer-names nil))
	(display-buffer eepitch-target-buffer))))

(defun eepitch (code)
"Set the target buffer for pitching lines to; CODE is something like
`(shell)'.
To pitch lines to the target buffer, use `\\[eepitch-this-line]'.
As with `eechannel', lines starting with `' are executed as Lisp;
other lines are sent."
  (if (not (listp code))
      (error "eepitch is no longer a macro - quote the code!"))
  (setq eepitch-code code)
  (eepitch-prepare-target-buffer)
  (eepitch-display-target-buffer))

(defun eepitch-line (line)
  (save-selected-window
    (select-window (get-buffer-window eepitch-target-buffer))
    (insert line)                              ; "type" the line
    (call-interactively (key-binding "\r"))))  ; then do a RET

(defun eepitch-not-this-buffer ()
  (if (eq (current-buffer) eepitch-target-buffer)
      (error "Can't pitch to the current buffer")))

(defun eepitch-this-line ()
"Pitch this line to the target buffer, or eval it as lisp if it starts
with `'."
  (interactive)
  (let ((line (buffer-substring (ee-bol) (ee-eol)))) ; contents of this
line
    (if (string-match "^\\(.*\\)" line)             ; lines with a red
star
        (ee-eval-string (match-string 1 line))       ; are eval'ed -
      (eepitch-prepare-target-buffer)	 ; for other lines reconstruct the
      (eepitch-display-target-buffer)	 ; target buffer, display it, make
      (eepitch-not-this-buffer)		 ; sure it's a different buffer, and
      (eepitch-line line)))		 ; pitch the line to the target.
  (next-line 1))

(defun eepitch-kill ()
  (interactive)
  (eepitch-prepare-target-buffer)	 ; Prepare (maybe reconstruct) the
  (eepitch-display-target-buffer)	 ; target buffer, display it, make
  (eepitch-not-this-buffer)		 ; sure it's a different buffer...
  (save-selected-window			 ; Then temporarily switch to the
    (select-window (get-buffer-window eepitch-target-buffer)) ; right
window,
    (kill-this-buffer)))		 ; and kill the buffer that is there.

--snip--snip--

but I knew that this wouldn't work for GUD, as I would need a 3-window
setting for it - one window for the e-script, one for the "*gud-prog*"
window, and another one for the program being followed...

Yesterday I experimented with several 3-window configurations, and I
found that this one works (the ascii screenshot was made by hand using
"(format-mode-line mode-line-format 0)" and picture-more and is not
very realistic, but I'm attaching a real screenshot too):

 ______________________________________________________________________
|* (eepitch-gdb-lua-kill)           |#include               |
|* (eepitch-gdb-lua)                |#include                 |
|set args /tmp/loadso.lua           |static int my_foo(lua_State* L) { |
|# br main                          @  int n = lua_gettop(L);          |
|tbr ll_loadlib                     |  int isnum = lua_isnumber(L, 1); |
|run                                |  int m = lua_tonumber(L, 1);     |
|n                                  |  printf("Hi hi!\n");             |
|n                                  |  printf("%d %d %d!\n", n, isnum, |
|p path                             |  return 0;                       |
|p init                             |}                                 |
|n                                  |LUALIB_API int my_init(lua_State *+
|br my_foo                          |  lua_register(L, "foo", my_foo); |
|cont                               |  return 0;                       |
|                                   |}                                 |
|                                   |                                  |
|-:**  TODO  Bot L3255  (Fundamental|                                  |
|Current directory is /home/edrx/usr+                                  |
|GNU gdb 6.6-debian                 |                                  |
|Copyright (C) 2006 Free Software Fo+                                  |
|..blablabla..                      |                                  |
|(gdb) set args /tmp/loadso.lua     |                                  |
|(gdb) br ll_loadlib                |                                  |
|Breakpoint 1 at 0x806bcd8: file loa+                                  |
|(gdb) run                          |                                  |
|Starting program: /home/edrx/usrc/l+                                  |
|Breakpoint 1, ll_loadlib (L=0x80710+                                  |
|(gdb) n                            |                                  |
|(gdb) n                            |                                  |
|(gdb) p path                       |                                  |
|$1 = 0x8082310 "/tmp/so.so"        |                                  |
|(gdb) p init                       |                                  |
|$2 = 0x8081a68 "my_init"           |                                  |
|(gdb) n                            |                                  |
|(gdb) br my_foo                    |                                  |
|Breakpoint 2 at 0xb7ef4602: file so+                                  |
|(gdb) cont                         |                                  |
|Continuing.                        |                                  |
|Breakpoint 2, my_foo (L=0x8071008) |                                  |
|(gdb)                              |                                  |
|                                   |                                  |
|--:**  *gud-lua_O0*  All L33  (Debu|--:--  so.c  All L17  (C/l Abbrev)|
|______________________________________________________________________|


The code for eepitch-gdb-lua-kill and eepitch-gdb-lua is here:

    (defun eepitch-gdb (buffer-name gdb-prog-and-args)
      (delete-other-windows)
      (split-window-horizontally)
      (split-window-vertically)
      (other-window 1)
      (if (get-buffer buffer-name)
          (find-ebuffer buffer-name)
        (gdb gdb-prog-and-args)
        (eegud-keys-mode 1))
      (other-window 2)
      (setq eepitch-code `(find-ebuffer ,buffer-name)))

    (defun eepitch-gdb-kill (buffer-name)
      (if (get-buffer buffer-name) (kill-buffer buffer-name))
      (delete-other-windows))

    (defun eepitch-gdb-lua ()
      (eepitch-gdb "*gud-lua_O0*"
                   "gdb --annotate=3 ~/usrc/lua-5.1.2/src/lua_O0"))

    (defun eepitch-gdb-lua-kill ()
      (eepitch-gdb-kill "*gud-lua_O0*"))

I also changed one of the bindings in eegud-keys-mode:

    (define-key eegud-keys-mode-map "\M-k" 'eegud-kill-this-buffer)

    (defun eegud-kill-this-buffer ()
      (interactive)
      (delete-other-windows)
      (kill-this-buffer))

and the bizarre name of the GUD buffer - "*gud-lua_O0*" - is because
the binary that GDB is debugging is called "lua_O0". GDB (6.6, from
Debian unstable) was giving messages like "variable optimized away"
when I tried to examine the variables "path" and "init", so I changed
my build script for Lua to build two separate binaries, "lua_O0",
compiled with "-g -O0", and "lua", compiled with "-g -O2".

Any comments or suggestions? As I've said, the code for eepitch-gdb-*
is very fresh, from yesterday, and I haven't played with it enough...
one thing that I need to do now is a way to create breakpoints using
hyperlinks; for example,

#          (find-lua51file "src/lvm.c" "case OP_CLOSE:" 1)
* (ee-tbr '(find-lua51file "src/lvm.c" "case OP_CLOSE:" 1))

in an e-script for GDB the first line is a comment; it's a hyperlink.
The second line starts with a red star, and when we pitch it with F8
the ee-tbr follows the hyperlink - with save-excursion - and sets a
temporary breakpoint at that line. I haven't implemented this yet.

  Cheers,
    Eduardo Ochs
    http://angg.twu.net/
    [email protected]
 
CD: 4ms