|
|
- ;; swank-larceny.scm --- Swank server for Larceny
- ;;
- ;; License: Public Domain
- ;; Author: Helmut Eller
- ;;
- ;; In a shell execute:
- ;; larceny -r6rs -program swank-larceny.scm
- ;; and then `M-x slime-connect' in Emacs.
-
- (library (swank os)
- (export getpid make-server-socket accept local-port close-socket)
- (import (rnrs)
- (primitives foreign-procedure
- ffi/handle->address
- ffi/string->asciiz
- sizeof:pointer
- sizeof:int
- %set-pointer
- %get-int))
-
- (define getpid (foreign-procedure "getpid" '() 'int))
- (define fork (foreign-procedure "fork" '() 'int))
- (define close (foreign-procedure "close" '(int) 'int))
- (define dup2 (foreign-procedure "dup2" '(int int) 'int))
-
- (define bytevector-content-offset$ sizeof:pointer)
-
- (define execvp% (foreign-procedure "execvp" '(string boxed) 'int))
- (define (execvp file . args)
- (let* ((nargs (length args))
- (argv (make-bytevector (* (+ nargs 1)
- sizeof:pointer))))
- (do ((offset 0 (+ offset sizeof:pointer))
- (as args (cdr as)))
- ((null? as))
- (%set-pointer argv
- offset
- (+ (ffi/handle->address (ffi/string->asciiz (car as)))
- bytevector-content-offset$)))
- (%set-pointer argv (* nargs sizeof:pointer) 0)
- (execvp% file argv)))
-
- (define pipe% (foreign-procedure "pipe" '(boxed) 'int))
- (define (pipe)
- (let ((array (make-bytevector (* sizeof:int 2))))
- (let ((r (pipe% array)))
- (values r (%get-int array 0) (%get-int array sizeof:int)))))
-
- (define (fork/exec file . args)
- (let ((pid (fork)))
- (cond ((= pid 0)
- (apply execvp file args))
- (#t pid))))
-
- (define (start-process file . args)
- (let-values (((r1 down-out down-in) (pipe))
- ((r2 up-out up-in) (pipe))
- ((r3 err-out err-in) (pipe)))
- (assert (= 0 r1))
- (assert (= 0 r2))
- (assert (= 0 r3))
- (let ((pid (fork)))
- (case pid
- ((-1)
- (error "Failed to fork a subprocess."))
- ((0)
- (close up-out)
- (close err-out)
- (close down-in)
- (dup2 down-out 0)
- (dup2 up-in 1)
- (dup2 err-in 2)
- (apply execvp file args)
- (exit 1))
- (else
- (close down-out)
- (close up-in)
- (close err-in)
- (list pid
- (make-fd-io-stream up-out down-in)
- (make-fd-io-stream err-out err-out)))))))
-
- (define (make-fd-io-stream in out)
- (let ((write (lambda (bv start count) (fd-write out bv start count)))
- (read (lambda (bv start count) (fd-read in bv start count)))
- (closeit (lambda () (close in) (close out))))
- (make-custom-binary-input/output-port
- "fd-stream" read write #f #f closeit)))
-
- (define write% (foreign-procedure "write" '(int ulong int) 'int))
- (define (fd-write fd bytevector start count)
- (write% fd
- (+ (ffi/handle->address bytevector)
- bytevector-content-offset$
- start)
- count))
-
- (define read% (foreign-procedure "read" '(int ulong int) 'int))
- (define (fd-read fd bytevector start count)
- ;;(printf "fd-read: ~a ~s ~a ~a\n" fd bytevector start count)
- (read% fd
- (+ (ffi/handle->address bytevector)
- bytevector-content-offset$
- start)
- count))
-
- (define (make-server-socket port)
- (let* ((args `("/bin/bash" "bash"
- "-c"
- ,(string-append
- "netcat -s 127.0.0.1 -q 0 -l -v "
- (if port
- (string-append "-p " (number->string port))
- ""))))
- (nc (apply start-process args))
- (err (transcoded-port (list-ref nc 2)
- (make-transcoder (latin-1-codec))))
- (line (get-line err))
- (pos (last-index-of line '#\])))
- (cond (pos
- (let* ((tail (substring line (+ pos 1) (string-length line)))
- (port (get-datum (open-string-input-port tail))))
- (list (car nc) (cadr nc) err port)))
- (#t (error "netcat failed: " line)))))
-
- (define (accept socket codec)
- (let* ((line (get-line (caddr socket)))
- (pos (last-index-of line #\])))
- (cond (pos
- (close-port (caddr socket))
- (let ((stream (cadr socket)))
- (let ((io (transcoded-port stream (make-transcoder codec))))
- (values io io))))
- (else (error "accept failed: " line)))))
-
- (define (local-port socket)
- (list-ref socket 3))
-
- (define (last-index-of str chr)
- (let loop ((i (string-length str)))
- (cond ((<= i 0) #f)
- (#t (let ((i (- i 1)))
- (cond ((char=? (string-ref str i) chr)
- i)
- (#t
- (loop i))))))))
-
- (define (close-socket socket)
- ;;(close-port (cadr socket))
- #f
- )
-
- )
-
- (library (swank sys)
- (export implementation-name eval-in-interaction-environment)
- (import (rnrs)
- (primitives system-features
- aeryn-evaluator))
-
- (define (implementation-name) "larceny")
-
- ;; see $LARCENY/r6rsmode.sch:
- ;; Larceny's ERR5RS and R6RS modes.
- ;; Code names:
- ;; Aeryn ERR5RS
- ;; D'Argo R6RS-compatible
- ;; Spanky R6RS-conforming (not yet implemented)
- (define (eval-in-interaction-environment form)
- (aeryn-evaluator form))
-
- )
-
- (import (rnrs) (rnrs eval) (larceny load))
- (load "swank-r6rs.scm")
- (eval '(start-server #f) (environment '(swank)))
|