Klimi's new dotfiles with stow.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

176 rader
4.8 KiB

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