Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
marvel
GitHub Repository: marvel/qnf
Path: blob/master/elisp/slime/contrib/swank-larceny.scm
990 views
1
;; swank-larceny.scm --- Swank server for Larceny
2
;;
3
;; License: Public Domain
4
;; Author: Helmut Eller
5
;;
6
;; In a shell execute:
7
;; larceny -r6rs -program swank-larceny.scm
8
;; and then `M-x slime-connect' in Emacs.
9
10
(library (swank os)
11
(export getpid make-server-socket accept local-port close-socket)
12
(import (rnrs)
13
(primitives foreign-procedure
14
ffi/handle->address
15
ffi/string->asciiz
16
sizeof:pointer
17
sizeof:int
18
%set-pointer
19
%get-int))
20
21
(define getpid (foreign-procedure "getpid" '() 'int))
22
(define fork (foreign-procedure "fork" '() 'int))
23
(define close (foreign-procedure "close" '(int) 'int))
24
(define dup2 (foreign-procedure "dup2" '(int int) 'int))
25
26
(define bytevector-content-offset$ sizeof:pointer)
27
28
(define execvp% (foreign-procedure "execvp" '(string boxed) 'int))
29
(define (execvp file . args)
30
(let* ((nargs (length args))
31
(argv (make-bytevector (* (+ nargs 1)
32
sizeof:pointer))))
33
(do ((offset 0 (+ offset sizeof:pointer))
34
(as args (cdr as)))
35
((null? as))
36
(%set-pointer argv
37
offset
38
(+ (ffi/handle->address (ffi/string->asciiz (car as)))
39
bytevector-content-offset$)))
40
(%set-pointer argv (* nargs sizeof:pointer) 0)
41
(execvp% file argv)))
42
43
(define pipe% (foreign-procedure "pipe" '(boxed) 'int))
44
(define (pipe)
45
(let ((array (make-bytevector (* sizeof:int 2))))
46
(let ((r (pipe% array)))
47
(values r (%get-int array 0) (%get-int array sizeof:int)))))
48
49
(define (fork/exec file . args)
50
(let ((pid (fork)))
51
(cond ((= pid 0)
52
(apply execvp file args))
53
(#t pid))))
54
55
(define (start-process file . args)
56
(let-values (((r1 down-out down-in) (pipe))
57
((r2 up-out up-in) (pipe))
58
((r3 err-out err-in) (pipe)))
59
(assert (= 0 r1))
60
(assert (= 0 r2))
61
(assert (= 0 r3))
62
(let ((pid (fork)))
63
(case pid
64
((-1)
65
(error "Failed to fork a subprocess."))
66
((0)
67
(close up-out)
68
(close err-out)
69
(close down-in)
70
(dup2 down-out 0)
71
(dup2 up-in 1)
72
(dup2 err-in 2)
73
(apply execvp file args)
74
(exit 1))
75
(else
76
(close down-out)
77
(close up-in)
78
(close err-in)
79
(list pid
80
(make-fd-io-stream up-out down-in)
81
(make-fd-io-stream err-out err-out)))))))
82
83
(define (make-fd-io-stream in out)
84
(let ((write (lambda (bv start count) (fd-write out bv start count)))
85
(read (lambda (bv start count) (fd-read in bv start count)))
86
(closeit (lambda () (close in) (close out))))
87
(make-custom-binary-input/output-port
88
"fd-stream" read write #f #f closeit)))
89
90
(define write% (foreign-procedure "write" '(int ulong int) 'int))
91
(define (fd-write fd bytevector start count)
92
(write% fd
93
(+ (ffi/handle->address bytevector)
94
bytevector-content-offset$
95
start)
96
count))
97
98
(define read% (foreign-procedure "read" '(int ulong int) 'int))
99
(define (fd-read fd bytevector start count)
100
;;(printf "fd-read: ~a ~s ~a ~a\n" fd bytevector start count)
101
(read% fd
102
(+ (ffi/handle->address bytevector)
103
bytevector-content-offset$
104
start)
105
count))
106
107
(define (make-server-socket port)
108
(let* ((args `("/bin/bash" "bash"
109
"-c"
110
,(string-append
111
"netcat -s 127.0.0.1 -q 0 -l -v "
112
(if port
113
(string-append "-p " (number->string port))
114
""))))
115
(nc (apply start-process args))
116
(err (transcoded-port (list-ref nc 2)
117
(make-transcoder (latin-1-codec))))
118
(line (get-line err))
119
(pos (last-index-of line '#\])))
120
(cond (pos
121
(let* ((tail (substring line (+ pos 1) (string-length line)))
122
(port (get-datum (open-string-input-port tail))))
123
(list (car nc) (cadr nc) err port)))
124
(#t (error "netcat failed: " line)))))
125
126
(define (accept socket codec)
127
(let* ((line (get-line (caddr socket)))
128
(pos (last-index-of line #\])))
129
(cond (pos
130
(close-port (caddr socket))
131
(let ((stream (cadr socket)))
132
(let ((io (transcoded-port stream (make-transcoder codec))))
133
(values io io))))
134
(else (error "accept failed: " line)))))
135
136
(define (local-port socket)
137
(list-ref socket 3))
138
139
(define (last-index-of str chr)
140
(let loop ((i (string-length str)))
141
(cond ((<= i 0) #f)
142
(#t (let ((i (- i 1)))
143
(cond ((char=? (string-ref str i) chr)
144
i)
145
(#t
146
(loop i))))))))
147
148
(define (close-socket socket)
149
;;(close-port (cadr socket))
150
#f
151
)
152
153
)
154
155
(library (swank sys)
156
(export implementation-name eval-in-interaction-environment)
157
(import (rnrs)
158
(primitives system-features
159
aeryn-evaluator))
160
161
(define (implementation-name) "larceny")
162
163
;; see $LARCENY/r6rsmode.sch:
164
;; Larceny's ERR5RS and R6RS modes.
165
;; Code names:
166
;; Aeryn ERR5RS
167
;; D'Argo R6RS-compatible
168
;; Spanky R6RS-conforming (not yet implemented)
169
(define (eval-in-interaction-environment form)
170
(aeryn-evaluator form))
171
172
)
173
174
(import (rnrs) (rnrs eval) (larceny load))
175
(load "swank-r6rs.scm")
176
(eval '(start-server #f) (environment '(swank)))
177
178