[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] GNU Guile branch, master, updated. release_1-9-2-119-g63

From: Neil Jerram
Subject: [Guile-commits] GNU Guile branch, master, updated. release_1-9-2-119-g639bf3e
Date: Thu, 27 Aug 2009 21:53:13 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Guile".

The branch, master has been updated
       via  639bf3e507959ca53fef713306eb33f1074f1588 (commit)
       via  8a40db3714628f88b138017835d448231257d13b (commit)
       via  57692c07427cb2b3f193df2e998e30cf7616e567 (commit)
       via  c0c8dc84eacc41cc81d43b24d8caf7e927b09150 (commit)
       via  72553cb0ce71d38c46c336ce48c151919a83ba60 (commit)
       via  a9408365f9e34cdedef0cbaa6af1124a1e978ee9 (commit)
       via  2cbe132f07aebf1a4db8227670d871e4da3f9202 (commit)
       via  1a2285752e1c16c167d84b23f9e8fe86319c51e2 (commit)
       via  8b0872202395e5f35064eaf6ac6b56977de6dff2 (commit)
      from  cdc4f3db09727cc1613f7a2fd2335efa10a9d53f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 639bf3e507959ca53fef713306eb33f1074f1588
Merge: cdc4f3db09727cc1613f7a2fd2335efa10a9d53f 
Author: Neil Jerram <address@hidden>
Date:   Thu Aug 27 22:52:20 2009 +0100

    Merge branch 'ossau-gds-dev'


Summary of changes:
 .gitignore                  |    2 +
 AUTHORS                     |   29 ++++++-
 THANKS                      |    3 +
 emacs/gds-faq.txt           |  225 +++++++++++++++++++++++++++++++++++++++++++
 emacs/gds-server.el         |   19 ++--
 emacs/gds-test.el           |  166 +++++++++++++++++++++++++++++++
 emacs/           |    2 +
 emacs/gds-test.stdin        |    1 +
 emacs/gds-tutorial.txt      |  223 ++++++++++++++++++++++++++++++++++++++++++
 emacs/gds.el                |   27 ++++--
 module/ice-9/gds-client.scm |   29 +++---
 module/ice-9/gds-server.scm |   53 +++++------
 12 files changed, 715 insertions(+), 64 deletions(-)
 create mode 100755 emacs/gds-faq.txt
 create mode 100644 emacs/gds-test.el
 create mode 100755 emacs/
 create mode 100644 emacs/gds-test.stdin
 create mode 100755 emacs/gds-tutorial.txt

diff --git a/.gitignore b/.gitignore
index 9d507e1..8754b48 100644
--- a/.gitignore
+++ b/.gitignore
@@ -72,6 +72,8 @@ gdb-pre-inst-guile
diff --git a/AUTHORS b/AUTHORS
index ed2adba..b8f605e 100644
@@ -206,8 +206,34 @@ In the subdirectory doc, changes to:
 Many changes throughout.
 Neil Jerram:
+In the subdirectory emacs, wrote:
+    gds.el              gds-scheme.el           gds-server.el
+    gds-test.el            gds-test.stdin
+    gds-tutorial.txt   gds-faq.txt
 In the subdirectory ice-9, wrote:
-    buffered-input.scm
+    buffered-input.scm gds-client.scm      gds-server.scm
+In the subdirectory ice-9/debugging, wrote:
+    example-fns.scm     ice-9-debugger-extensions.scm
+    steps.scm          trace.scm           traps.scm
+    trc.scm
+In the subdirectory lang/elisp, wrote:
+    base.scm           example.el          interface.scm
+    transform.scm      variables.scm
+In the subdirectory lang/elisp/internals, wrote:
+    evaluation.scm      format.scm         fset.scm
+    lambda.scm         load.scm            null.scm
+    set.scm            signal.scm          time.scm
+    trace.scm
+In the subdirectory lang/elisp/primitives, wrote:
+    buffers.scm                char-table.scm      features.scm
+    fns.scm            format.scm          guile.scm
+    keymaps.scm                lists.scm           load.scm
+    match.scm          numbers.scm         pure.scm
+    read.scm           signal.scm          strings.scm
+    symprop.scm                syntax.scm          system.scm
+    time.scm
+In the subdirectory srfi, wrote:
+    srfi-34.scm
 In the subdirectory doc, wrote:
     deprecated.texi   goops.texi    scheme-ideas.texi
@@ -227,6 +253,7 @@ In the subdirectory doc, changes to:
     scm.texi        scripts.texi    script-getopt.texi
 In the subdirectory doc/maint, wrote:
+Many other changes throughout.
 Thien-Thi Nguyen:
 In the top-level directory, wrote:
diff --git a/THANKS b/THANKS
index 17816c5..9012109 100644
--- a/THANKS
+++ b/THANKS
@@ -30,6 +30,7 @@ For fixes or providing information which led to a fix:
             Rob Browning
          Adrian Bunk
         Michael Carmack
+              R Clayton
         Stephen Compall
           Brian Crowder
     Christopher Cramer
@@ -95,6 +96,7 @@ For fixes or providing information which led to a fix:
          Werner Scheinast
           Bill Schottstaedt
          Frank Schwidom
+    John Steele Scott
          Thiemo Seufer
           Scott Shedden
            Alex Shinn
@@ -115,6 +117,7 @@ For fixes or providing information which led to a fix:
        Andreas Vögele
         Michael Talbot-Wilson
         Michael Tuexen
+         Thomas Wawrzinek
         Mark H. Weaver
             Jon Wilson
            Andy Wingo
diff --git a/emacs/gds-faq.txt b/emacs/gds-faq.txt
new file mode 100755
index 0000000..b60a2c9
--- /dev/null
+++ b/emacs/gds-faq.txt
@@ -0,0 +1,225 @@
+* Installation
+** How do I install guile-debugging?
+After unpacking the .tar.gz file, run the usual sequence of commands:
+$ ./configure
+$ make
+$ sudo make install
+Then you need to make sure that the directory where guile-debugging's
+Scheme files were installed is included in your Guile's load path.
+(The sequence above will usually install guile-debugging under
+/usr/local, and /usr/local is not in Guile's load path by default,
+unless Guile itself was installed under /usr/local.)  You can discover
+your Guile's default load path by typing
+$ guile -q -c '(begin (write %load-path) (newline))'
+There are two ways to add guile-debugging's installation directory to
+Guile's load path, if it isn't already there.
+1. Edit or create the `init.scm' file, which Guile reads on startup,
+   so that it includes a line like this:
+   (set! %load-path (cons "/usr/local/share/guile" %load-path))
+   but with "/usr/local" replaced by the prefix that you installed
+   guile-debugging under, if not /usr/local.
+   The init.scm file must be installed (if it does not already exist
+   there) in one of the directories in Guile's default load-path.
+2. Add this line to your .emacs file:
+   (setq gds-scheme-directory "/usr/local/share/guile")
+   before the `require' or `load' line that loads GDS, but with
+   "/usr/local" replaced by the prefix that you installed
+   guile-debugging under, if not /usr/local.
+Finally, if you want guile-debugging's GDS interface to be loaded
+automatically whenever you run Emacs, add this line to your .emacs:
+(require 'gds)
+* Troubleshooting
+** "error in process filter" when starting Emacs (or loading GDS)
+This is caused by an internal error in GDS's Scheme code, for which a
+backtrace will have appeared in the gds-debug buffer, so please switch
+to the gds-debug buffer and see what it says there.
+The most common cause is a load path problem: Guile cannot find GDS's
+Scheme code because it is not in the known load path.  In this case
+you should see the error message "no code for module" somewhere in the
+backtrace.  If you see this, please try the remedies described in `How
+do I install guile-debugging?' above, then restart Emacs and see if
+the problem has been cured.
+If you don't see "no code for module", or if the described remedies
+don't fix the problem, please send the contents of the gds-debug
+buffer to me at <address@hidden>, so I can debug the problem.
+If you don't see a backtrace at all in the gds-debug buffer, try the
+next item ...
+** "error in process filter" at some other time
+This is caused by an internal error somewhere in GDS's Emacs Lisp
+code.  If possible, please
+- switch on the `debug-on-error' option (M-x set-variable RET
+  debug-on-error RET t RET)
+- do whatever you were doing so that the same error happens again
+- send the Emacs Lisp stack trace which pops up to me at
+  <address@hidden>.
+If that doesn't work, please just mail me with as much detail as
+possible of what you were doing when the error occurred.
+* GDS Features
+** How do I inspect variable values?
+Type `e' followed by the name of the variable, then <RET>.  This
+works whenever GDS is displaying a stack for an error at at a
+breakpoint.  (You can actually `e' to evaluate any expression in the
+local environment of the selected stack frame; inspecting variables is
+the special case of this where the expression is only a variable name.)
+If GDS is displaying the associated source code in the window above or
+below the stack, you can see the values of any variables in the
+highlighted code just by hovering your mouse over them.
+** How do I change a variable's value?
+Type `e' and then `(set! VARNAME NEWVAL)', where VARNAME is the name
+of the variable you want to set and NEWVAL is an expression which
+Guile can evaluate to get the new value.  This works whenever GDS is
+displaying a stack for an error at at a breakpoint.  The setting will
+take effect in the local environment of the selected stack frame.
+** How do I change the expression that Guile is about to evaluate?
+Type `t' followed by the expression that you want Guile to evaluate
+instead, then <RET>.
+Then type one of the commands that tells Guile to continue execution.
+(Tweaking expressions, as described here, is only supported by the
+latest CVS version of Guile.  The GDS stack display tells you when
+tweaking is possible by adding "(tweakable)" to the first line of the
+stack window.)
+** How do I return a value from the current stack frame different to what the 
evaluator has calculated?
+You have to be at the normal exit of the relevant frame first, so if
+GDS is not already showing you the normally calculated return value,
+type `o' to finish the evaluation of the selected frame.
+Then type `t' followed by the value you want to return, and <RET>.
+The value that you type can be any expression, but note that it will
+not be evaluated before being returned; for example if you type `(+ 2
+3)', the return value will be a three-element list, not 5.
+Finally type one of the commands that tells Guile to continue
+(Tweaking return values, as described here, is only supported by the
+latest CVS version of Guile.  The GDS stack display tells you when
+tweaking is possible by adding "(tweakable)" to the first line of the
+stack window.)
+** How do I step over a line of code?
+Scheme isn't organized by lines, so it doesn't really make sense to
+think of stepping over lines.  Instead please see the next entry on
+stepping over expressions.
+** How do I step over an expression?
+It depends what you mean by "step over".  If you mean that you want
+Guile to evaluate that expression normally, but then show you its
+return value, type `o', which does exactly that.
+If you mean that you want to skip the evaluation of that expression
+(for example because it has side effects that you don't want to
+happen), use `t' to change the expression to something else which
+Guile will evaluate instead.
+There has to be a substitute expression so Guile can calculate a value
+to return to the calling frame.  If you know at a particular point
+that the return value is not important, you can type `t #f <RET>' or
+`t 0 <RET>'.
+See `How do I change the expression that Guile is about to evaluate?'
+above for more on using `t'.
+** How do I move up and down the call stack?
+Type `u' to move up and `d' to move down.  "Up" in GDS means to a more
+"inner" frame, and "down" means to a more "outer" frame.
+** How do I run until the next breakpoint?
+Type `g' (for "go").
+** How do I run until the end of the selected stack frame?
+Type `o'.
+** How do I set a breakpoint?
+First identify the code that you want to set the breakpoint in, and
+what kind of breakpoint you want.  To set a breakpoint on entry to a
+top level procedure, move the cursor to anywhere in the procedure
+definition, and make sure that the region/mark is inactive.  To set a
+breakpoint on a particular expression (or sequence of expressions) set
+point and mark so that the region covers the opening parentheses of
+all the target expressions.
+Then type ...
+  `C-c C-b d' for a `debug' breakpoint, which means that GDS will
+  display the stack when the breakpoint is hit
+  `C-c C-b t' for a `trace' breakpoint, which means that the start and
+  end of the relevant procedure or expression(s) will be traced to the
+  *GDS Trace* buffer
+  `C-c C-b T' for a `trace-subtree' breakpoint, which means that every
+  evaluation step involved in the evaluation of the relevant procedure
+  or expression(s) will be traced to the *GDS Trace* buffer.
+You can also type `C-x <SPC>', which does the same as one of the
+above, depending on the value of `gds-default-breakpoint-type'.
+** How do I clear a breakpoint?
+Select a region containing the breakpoints that you want to clear, and
+type `C-c C-b <DEL>'.
+** How do I trace calls to a particular procedure or evaluations of a 
particular expression?
+In GDS this means setting a breakpoint whose type is `trace' or
+`trace-subtree'.  See `How do I set a breakpoint?' above.
+* Development
+** How can I follow or contribute to guile-debugging's development?
+guile-debugging is hosted at, so please see the project
+page there.  Feel free to raise bugs, tasks containing patches or
+feature requests, and so on.  You can also write directly to me by
+email: <address@hidden>.
+Local Variables:
+mode: outline
diff --git a/emacs/gds-server.el b/emacs/gds-server.el
index d4fe997..9cfcd3a 100644
--- a/emacs/gds-server.el
+++ b/emacs/gds-server.el
@@ -43,25 +43,24 @@
   :group 'gds
   :type '(choice (const :tag "nil" nil) directory))
-(defun gds-start-server (procname port-or-path protocol-handler &optional 
-  "Start a GDS server process called PROCNAME, listening on TCP port
-or Unix domain socket PORT-OR-PATH.  PROTOCOL-HANDLER should be a
-function that accepts and processes one protocol form.  Optional arg
-BUFNAME specifies the name of the buffer that is used for process
-output; if not specified the buffer name is the same as the process
-  (with-current-buffer (get-buffer-create (or bufname procname))
+(defun gds-start-server (procname unix-socket-name tcp-port protocol-handler)
+  "Start a GDS server process called PROCNAME, listening on Unix
+domain socket UNIX-SOCKET-NAME and TCP port number TCP-PORT.
+PROTOCOL-HANDLER should be a function that accepts and processes
+one protocol form."
+  (with-current-buffer (get-buffer-create procname)
     (let* ((code (format "(begin
                             (use-modules (ice-9 gds-server))
-                            (run-server %S))"
+                            (run-server %S %S))"
                         (if gds-scheme-directory
                             (concat "(set! %load-path (cons "
                                     (format "%S" gds-scheme-directory)
                                     " %load-path))")
-                         port-or-path))
+                         unix-socket-name
+                        tcp-port))
            (process-connection-type nil) ; use a pipe
            (proc (start-process procname
diff --git a/emacs/gds-test.el b/emacs/gds-test.el
new file mode 100644
index 0000000..dfd4f6c
--- /dev/null
+++ b/emacs/gds-test.el
@@ -0,0 +1,166 @@
+;; Test utility code.
+(defun gds-test-execute-keys (keys &optional keys2)
+  (execute-kbd-macro (apply 'vector (listify-key-sequence keys))))
+(defvar gds-test-expecting nil)
+(defun gds-test-protocol-hook (form)
+  (message "[protocol: %s]" (car form))
+  (if (eq (car form) gds-test-expecting)
+      (setq gds-test-expecting nil)))
+(defun gds-test-expect-protocol (proc &optional timeout)
+  (message "[expect: %s]" proc)
+  (setq gds-test-expecting proc)
+  (while gds-test-expecting
+    (or (accept-process-output gds-debug-server (or timeout 5))
+       (error "Timed out after %ds waiting for %s" (or timeout 5) proc))))
+(defun gds-test-check-buffer (name &rest strings)
+  (let ((buf (or (get-buffer name) (error "No %s buffer" name))))
+    (save-excursion
+      (set-buffer buf)
+      (goto-char (point-min))
+      (while strings
+       (search-forward (car strings))
+       (setq strings (cdr strings))))))
+(defun TEST (desc)
+  (message "TEST: %s" desc))
+;; Make sure we take GDS elisp code from this code tree.
+(setq load-path (cons (concat default-directory "emacs/") load-path))
+;; Protect the tests so we can do some cleanups in case of error.
+    (progn
+      ;; Visit the tutorial.
+      (find-file "gds-tutorial.txt")
+      (TEST "Load up GDS.")
+      (search-forward "(require 'gds)")
+      (setq load-path (cons (concat default-directory "emacs/") load-path))
+      (gds-test-execute-keys "\C-x\C-e")
+      ;; Install our testing hook.
+      (add-hook 'gds-protocol-hook 'gds-test-protocol-hook)
+      (TEST "Help.")
+      (search-forward "(list-ref")
+      (backward-char 2)
+      (gds-test-execute-keys "\C-hg\C-m")
+      (gds-test-expect-protocol 'eval-results 10)
+      (gds-test-check-buffer "*Guile Help*"
+                            "help list-ref"
+                            "is a primitive procedure in the (guile) module")
+      (TEST "Completion.")
+      (re-search-forward "^with-output-to-s")
+      (gds-test-execute-keys "\e\C-i")
+      (beginning-of-line)
+      (or (looking-at "with-output-to-string")
+         (error "Expected completion `with-output-to-string' failed"))
+      (TEST "Eval defun.")
+      (search-forward "(display z)")
+      (gds-test-execute-keys "\e\C-x")
+      (gds-test-expect-protocol 'eval-results)
+      (gds-test-check-buffer "*Guile Evaluation*"
+                            "(let ((x 1) (y 2))"
+                            "Arctangent is: 0.46"
+                            "=> 0.46")
+      (TEST "Multiple values.")
+      (search-forward "(values 'a ")
+      (gds-test-execute-keys "\e\C-x")
+      (gds-test-expect-protocol 'eval-results)
+      (gds-test-check-buffer "*Guile Evaluation*"
+                            "(values 'a"
+                            "hello world"
+                            "=> a"
+                            "=> b"
+                            "=> c")
+      (TEST "Eval region with multiple expressions.")
+      (search-forward "(display \"Arctangent is: \")")
+      (beginning-of-line)
+      (push-mark nil nil t)
+      (forward-line 3)
+      (gds-test-execute-keys "\C-c\C-r")
+      (gds-test-expect-protocol 'eval-results)
+      (gds-test-check-buffer "*Guile Evaluation*"
+                            "(display \"Arctangent is"
+                            "Arctangent is:"
+                            "=> no (or unspecified) value"
+                            "ERROR: Unbound variable: z"
+                            "=> error-in-evaluation"
+                            "Evaluating expression 3"
+                            "=> no (or unspecified) value")
+      (TEST "Eval syntactically unbalanced region.")
+      (search-forward "(let ((z (atan x y)))")
+      (beginning-of-line)
+      (push-mark nil nil t)
+      (forward-line 4)
+      (gds-test-execute-keys "\C-c\C-r")
+      (gds-test-expect-protocol 'eval-results)
+      (gds-test-check-buffer "*Guile Evaluation*"
+                            "(let ((z (atan"
+                            "Reading expressions to evaluate"
+                            "ERROR"
+                            "end of file"
+                            "=> error-in-read")
+      (TEST "Stepping through an evaluation.")
+      (search-forward "(for-each (lambda (x)")
+      (forward-line 1)
+      (push-mark nil nil t)
+      (forward-line 1)
+      (gds-test-execute-keys "\C-u\e\C-x")
+      (gds-test-expect-protocol 'stack)
+      (gds-test-execute-keys " ")
+      (gds-test-expect-protocol 'stack)
+      (gds-test-execute-keys "o")
+      (gds-test-expect-protocol 'stack)
+      (gds-test-execute-keys "o")
+      (gds-test-expect-protocol 'stack)
+      (gds-test-execute-keys "o")
+      (gds-test-expect-protocol 'stack)
+      (gds-test-execute-keys "o")
+      (gds-test-expect-protocol 'stack)
+      (gds-test-execute-keys "o")
+      (gds-test-expect-protocol 'stack)
+      (gds-test-execute-keys "o")
+      (gds-test-expect-protocol 'stack)
+      (gds-test-execute-keys "o")
+      (gds-test-expect-protocol 'stack)
+      (gds-test-execute-keys "o")
+      (gds-test-expect-protocol 'stack)
+      (gds-test-execute-keys "o")
+      (gds-test-expect-protocol 'stack)
+      (gds-test-execute-keys "o")
+      (gds-test-expect-protocol 'stack)
+      (gds-test-execute-keys "g")
+      (gds-test-expect-protocol 'eval-results)
+      (gds-test-check-buffer "*Guile Evaluation*"
+                            "(for-each (lambda"
+                            "Evaluating in current module"
+                            "3 cubed is 27"
+                            "=> no (or unspecified) value")
+      ;; Done.
+      (message "====================================")
+      (message "gds-test.el completed without errors")
+      (message "====================================")
+      )
+  (switch-to-buffer "gds-debug")
+  (write-region (point-min) (point-max) "gds-test.debug")
+  (switch-to-buffer "*GDS Transcript*")
+  (write-region (point-min) (point-max) "gds-test.transcript")
+  )
diff --git a/emacs/ b/emacs/
new file mode 100755
index 0000000..2f8ddff
--- /dev/null
+++ b/emacs/
@@ -0,0 +1,2 @@
+GUILE_LOAD_PATH=$(pwd) emacs --batch --no-site-file -q -l gds-test.el < 
diff --git a/emacs/gds-test.stdin b/emacs/gds-test.stdin
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/emacs/gds-test.stdin
@@ -0,0 +1 @@
diff --git a/emacs/gds-tutorial.txt b/emacs/gds-tutorial.txt
new file mode 100755
index 0000000..4254803
--- /dev/null
+++ b/emacs/gds-tutorial.txt
@@ -0,0 +1,223 @@
+;; Welcome to the GDS tutorial!
+;; This tutorial teaches the use of GDS by leading you through a set
+;; of examples where you actually use GDS, in Emacs, along the way.
+;; To get maximum benefit, therefore, you should be reading this
+;; tutorial in Emacs.
+;; ** GDS setup
+;; The first thing to do, if you haven't already, is to load the GDS
+;; library into Emacs.  The Emacs Lisp expression for this is:
+(require 'gds)
+;; So, if you don't already have this in your .emacs, either add it
+;; and then restart Emacs, or evaluate it just for this Emacs session
+;; by moving the cursor to just after the closing parenthesis and
+;; typing `C-x C-e'.
+;; (Note that if you _have_ already loaded GDS, and you type `C-x C-e'
+;; after this expression, you will see a *Guile Evaluation* window
+;; telling you that the evaluation failed because `require' is
+;; unbound.  Don't worry; this is not a problem, and the rest of the
+;; tutorial should still work just fine.)
+;; ** Help
+;; GDS makes it easy to access the Guile help system when working on a
+;; Scheme program in Emacs.  For example, suppose that you are writing
+;; code that uses list-ref, and need to remind yourself about
+;; list-ref's arguments ...
+(define (penultimate l)
+  (list-ref
+;; Just place the cursor on the word "list-ref" and type `C-h g RET'.
+;; Try it now!
+;; If GDS is working correctly, a window should have popped up above
+;; or below showing the Guile help for list-ref.
+;; You can also do an "apropos" search through Guile's help.  If you
+;; couldn't remember the name list-ref, for example, you could search
+;; for anything matching "list" by typing `C-h C-g' and entering
+;; "list" at the minibuffer prompt.  Try doing this now: you should
+;; see a longish list of Guile definitions whose names include "list".
+;; As usual in Emacs, you can use `M-PageUp' and `M-PageDown' to
+;; conveniently scroll the other window without having to select it.
+;; The functions called by `C-h g' and `C-h C-g' are gds-help-symbol
+;; and gds-apropos.  They both look up the symbol or word at point by
+;; default, but that default can be overidden by typing something else
+;; at the minibuffer prompt.
+;; ** Completion
+;; As you are typing Scheme code, you can ask GDS to complete the
+;; symbol before point for you, by typing `ESC TAB'.  GDS selects
+;; possible completions by matching the text so far against all
+;; definitions in the Guile environment.  (This may be contrasted with
+;; the "dabbrev" completion performed by `M-/', which selects possible
+;; completions from the contents of Emacs buffers.  So, if you are
+;; trying to complete "with-ou", to get "with-output-to-string", for
+;; example, `ESC TAB' will always work, because with-output-to-string
+;; is always defined in Guile's default environment, whereas `M-/'
+;; will only work if one of Emacs's buffers happens to contain the
+;; full name "with-output-to-string".)
+;; To illustrate the idea, here are some partial names that you can
+;; try completing.  For each one, move the cursor to the end of the
+;; line and type `ESC TAB' to try to complete it.
+;; (If you are not familiar with any of the completed definitions,
+;; feel free to use `C-h g' to find out about them!)
+;; ** Evaluation
+;; GDS provides several ways for you to evaluate Scheme code from
+;; within Emacs.
+;; Just like in Emacs Lisp, a single expression in a buffer can be
+;; evaluated using `C-x C-e' or `C-M-x'.  For `C-x C-e', the
+;; expression is that which ends immediately before point (so that it
+;; is useful for evaluating something just after you have typed it).
+;; For `C-M-x', the expression is the "top level defun" around point;
+;; this means the balanced chunk of code around point whose opening
+;; parenthesis is in column 0.
+;; Take this code fragment as an example:
+(let ((x 1) (y 2))
+  (let ((z (atan x y)))
+    (display "Arctangent is: ")
+    (display z)
+    (newline)
+    z))
+;; If you move the cursor to the end of the (display z) line and type
+;; `C-x C-e', the code evaluated is just "(display z)", which normally
+;; produces an error, because z is not defined in the usual Guile
+;; environment.  If, however, you type `C-M-x' with the cursor in the
+;; same place, the code evaluated is the whole "(let ((x 1) (y 2))
+;; ...)" kaboodle, because that is the most recent expression before
+;; point that starts in column 0.
+;; Try these now.  The Guile Evaluation window should pop up again,
+;; and show you:
+;; - the expression that was evaluated (probably abbreviated)
+;; - the module that it was evaluated in
+;; - anything that the code wrote to its standard output
+;; - the return value(s) of the evaluation.
+;; Following the convention of the Emacs Lisp and Guile manuals,
+;; return values are indicated by the symbol "=>".
+;; To see what happens when an expression has multiple return values,
+;; try evaluating this one:
+(values 'a (begin (display "hello world\n") 'b) 'c)
+;; You can also evaluate a region of a buffer using `C-c C-r'.  If the
+;; code in the region consists of multiple expressions, GDS evaluates
+;; them sequentially.  For example, try selecting the following three
+;; lines and typing `C-c C-r'.
+    (display "Arctangent is: ")
+    (display z)
+    (newline)
+;; If the code in the region evaluated isn't syntactically balanced,
+;; GDS will indicate a read error, for example for this code:
+  (let ((z (atan x y)))
+    (display "Arctangent is: ")
+    (display z)
+    (newline)
+;; Finally, if you want to evaluate something quickly that is not in a
+;; buffer, you can use `C-c C-e' and type the code to evaluate at the
+;; minibuffer prompt.  The results are popped up in the same way as
+;; for code from a buffer.
+;; ** Breakpoints
+;; Before evaluating Scheme code from an Emacs buffer, you may want to
+;; set some breakpoints in it.  With GDS you can set breakpoints in
+;; Scheme code by typing `C-x SPC'.
+;; To see how this works, select the second line of the following code
+;; (the `(format ...)' line) and type `C-x SPC'.
+(for-each (lambda (x)
+           (format #t "~A cubed is ~A\n" x (* x x x)))
+         (iota 6))
+;; The two opening parentheses in that line should now be highlighted
+;; in red, to show that breakpoints have been set at the start of the
+;; `(format ...)' and `(* x x x)' expressions.  Then evaluate the
+;; whole for-each expression by typing `C-M-x' ...
+;; In the upper half of your Emacs, a buffer appears showing you the
+;; Scheme stack.
+;; In the lower half, the `(format ...)' expression is highlighted.
+;; What has happened is that Guile started evaluating the for-each
+;; code, but then hit the breakpoint that you set on the start of the
+;; format expression.  Guile therefore pauses the evaluation at that
+;; point and passes the stack (which encapsulates everything that is
+;; interesting about the state of Guile at that point) to GDS.  You
+;; can then explore the stack and decide how to tell Guile to
+;; continue.
+;; - If you move your mouse over any of the identifiers in the
+;;   highlighted code, a help echo (or tooltip) will appear to tell
+;;   you that identifier's current value.  (Note though that this only
+;;   works when the stack buffer is selected.  So if you have switched
+;;   to this buffer in order to scroll down and read these lines, you
+;;   will need to switch back to the stack buffer before trying this
+;;   out.)
+;; - In the stack buffer, the "=>" on the left shows you that the top
+;;   frame is currently selected.  You can move up and down the stack
+;;   by pressing the up and down arrows (or `u' and `d').  As you do
+;;   this, GDS will change the highlight in the lower window to show
+;;   the code that corresponds to the selected stack frame.
+;; - You can evaluate an arbitrary expression in the local environment
+;;   of the selected stack frame by typing `e' followed by the
+;;   expression.
+;; - You can show various bits of information about the selected frame
+;;   by typing `I', `A' and `S'.  Feel free to try these now, to see
+;;   what they do.
+;; You also have control over the continuing evaluation of this code.
+;; Here are some of the things you can do - please try them as you
+;; read.
+;; - `g' tells Guile to continue execution normally.  In this case
+;;   that means that evaluation will continue until it hits the next
+;;   breakpoint, which is on the `(* x x x)' expression.
+;; - `SPC' tells Guile to continue until the next significant event in
+;;   the same source file as the selected frame.  A "significant
+;;   event" means either beginning to evaluate an expression in the
+;;   relevant file, or completing such an evaluation, in which case
+;;   GDS tells you the value that it is returning.  Pressing `SPC'
+;;   repeatedly is a nice way to step through all the details of the
+;;   code in a given file, but stepping over calls that involve code
+;;   from other files.
+;; - `o' tells Guile to continue execution until the selected stack
+;;   frame completes, and then to show its return value.
+;; Local Variables:
+;; mode: scheme
+;; End:
diff --git a/emacs/gds.el b/emacs/gds.el
index a9450d0..991ba75 100644
--- a/emacs/gds.el
+++ b/emacs/gds.el
@@ -36,10 +36,11 @@
 ;; The subprocess object for the debug server.
 (defvar gds-debug-server nil)
-(defvar gds-socket-type-alist '((tcp . 8333)
-                               (unix . "/tmp/.gds_socket"))
-  "Maps each of the possible socket types that the GDS server can
-listen on to the path that it should bind to for each one.")
+(defvar gds-unix-socket-name (format "/tmp/.gds-socket-%d" (emacs-pid))
+  "Name of the Unix domain socket that GDS will listen on.")
+(defvar gds-tcp-port 8333
+  "The TCP port number that GDS will listen on.")
 (defun gds-run-debug-server ()
   "Start (or restart, if already running) the GDS debug server process."
@@ -47,10 +48,14 @@ listen on to the path that it should bind to for each one.")
   (if gds-debug-server (gds-kill-debug-server))
   (setq gds-debug-server
         (gds-start-server "gds-debug"
-                         (cdr (assq gds-server-socket-type
-                                    gds-socket-type-alist))
+                         gds-unix-socket-name
+                         gds-tcp-port
-  (process-kill-without-query gds-debug-server))
+  (process-kill-without-query gds-debug-server)
+  ;; Add the Unix socket name to the environment, so that Guile
+  ;; clients started from within this Emacs will be able to use it,
+  ;; and thereby ensure that they connect to the GDS in this Emacs.
+  (setenv "GDS_UNIX_SOCKET_NAME" gds-unix-socket-name))
 (defun gds-kill-debug-server ()
   "Kill the GDS debug server process."
@@ -137,7 +142,13 @@ listen on to the path that it should bind to for each 
 ;;;; Debugger protocol
+(defcustom gds-protocol-hook nil
+  "Hook called on receipt of a protocol form from the GDS client."
+  :type 'hook
+  :group 'gds)
 (defun gds-debug-protocol (client form)
+  (run-hook-with-args 'gds-protocol-hook form)
   (or (eq client '*)
       (let ((proc (car form)))
         (cond ((eq proc 'name)
@@ -610,7 +621,7 @@ you would add an element to this alist to transform
   :group 'gds)
 (defcustom gds-server-socket-type 'tcp
-  "What kind of socket the GDS server should listen on."
+  "This option is now obsolete and has no effect."
   :group 'gds
   :type '(choice (const :tag "TCP" tcp)
                 (const :tag "Unix" unix)))
diff --git a/module/ice-9/gds-client.scm b/module/ice-9/gds-client.scm
index cdca7b6..03e2927 100755
--- a/module/ice-9/gds-client.scm
+++ b/module/ice-9/gds-client.scm
@@ -163,23 +163,20 @@
 (define (connect-to-gds . application-name)
   (or gds-port
-      (begin
+      (let ((gds-unix-socket-name (getenv "GDS_UNIX_SOCKET_NAME")))
         (set! gds-port
-             (or (let ((s (socket PF_INET SOCK_STREAM 0))
-                       (SOL_TCP 6)
-                       (TCP_NODELAY 1))
-                   (setsockopt s SOL_TCP TCP_NODELAY 1)
-                   (catch #t
-                          (lambda ()
-                            (connect s AF_INET (inet-aton "") 8333)
-                            s)
-                          (lambda _ #f)))
-                 (let ((s (socket PF_UNIX SOCK_STREAM 0)))
-                   (catch #t
-                          (lambda ()
-                            (connect s AF_UNIX "/tmp/.gds_socket")
-                            s)
-                          (lambda _ #f)))
+             (or (and gds-unix-socket-name
+                      (false-if-exception
+                       (let ((s (socket PF_UNIX SOCK_STREAM 0)))
+                         (connect s AF_UNIX gds-unix-socket-name)
+                         s)))
+                 (false-if-exception
+                  (let ((s (socket PF_INET SOCK_STREAM 0))
+                        (SOL_TCP 6)
+                        (TCP_NODELAY 1))
+                    (setsockopt s SOL_TCP TCP_NODELAY 1)
+                    (connect s AF_INET (inet-aton "") 8333)
+                    s))
                  (error "Couldn't connect to GDS by TCP or Unix domain 
         (write-form (list 'name (getpid) (apply client-name 
diff --git a/module/ice-9/gds-server.scm b/module/ice-9/gds-server.scm
index b64e411..5ec8675 100644
--- a/module/ice-9/gds-server.scm
+++ b/module/ice-9/gds-server.scm
@@ -36,38 +36,31 @@
 (define connection->id (make-object-property))
-(define (run-server port-or-path)
-  (or (integer? port-or-path)
-      (string? port-or-path)
-      (error "port-or-path should be an integer (port number) or a string 
(file name)"
-            port-or-path))
-  (let ((server (socket (if (integer? port-or-path) PF_INET PF_UNIX)
-                       SOCK_STREAM
-                       0)))
-    ;; Initialize server socket.
-    (if (integer? port-or-path)
-       (begin
-         (setsockopt server SOL_SOCKET SO_REUSEADDR 1)
-         (bind server AF_INET INADDR_ANY port-or-path))
-       (begin
-         (catch #t
-                (lambda () (delete-file port-or-path))
-                (lambda _ #f))
-         (bind server AF_UNIX port-or-path)))
-    ;; Start listening.
-    (listen server 5)
+(define (run-server unix-socket-name tcp-port)
+  (let ((unix-server (socket PF_UNIX SOCK_STREAM 0))
+       (tcp-server (socket PF_INET SOCK_STREAM 0)))
+    ;; Bind and start listening on the Unix domain socket.
+    (false-if-exception (delete-file unix-socket-name))
+    (bind unix-server AF_UNIX unix-socket-name)
+    (listen unix-server 5)
+    ;; Bind and start listening on the TCP socket.
+    (setsockopt tcp-server SOL_SOCKET SO_REUSEADDR 1)
+    (false-if-exception (bind tcp-server AF_INET INADDR_ANY tcp-port))
+    (listen tcp-server 5)
+    ;; Main loop.
     (let loop ((clients '()) (readable-sockets '()))
       (define (do-read port)
        (cond ((eq? port (current-input-port))
-             ((eq? port server)
-              (accept-new-client))
+             ((eq? port unix-server)
+              (accept-new-client unix-server))
+             ((eq? port tcp-server)
+              (accept-new-client tcp-server))
               (do-read-from-client port))))
@@ -86,7 +79,7 @@
              (trc "client not found")))        
-      (define (accept-new-client)
+      (define (accept-new-client server)
         (let ((new-port (car (accept server))))
          ;; Read the client's ID.
          (let ((name-form (read new-port)))
@@ -122,8 +115,10 @@
       ;;(trc 'readable-sockets readable-sockets)
       (if (null? readable-sockets)
-         (loop clients (car (select (cons (current-input-port)
-                                          (cons server clients))
+         (loop clients (car (select (cons* (current-input-port)
+                                           unix-server
+                                           tcp-server
+                                           clients)
          (loop (do-read (car readable-sockets)) (cdr readable-sockets))))))

GNU Guile

reply via email to

[Prev in Thread] Current Thread [Next in Thread]