Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
5.2 KiB

4 years ago
  1. ;;; -*- indent-tabs-mode: nil; coding: latin-1-unix -*-
  2. ;;;
  3. ;;; swank-rpc.lisp -- Pass remote calls and responses between lisp systems.
  4. ;;;
  5. ;;; Created 2010, Terje Norderhaug <terje@in-progress.com>
  6. ;;;
  7. ;;; This code has been placed in the Public Domain. All warranties
  8. ;;; are disclaimed.
  9. ;;;
  10. (in-package swank/rpc)
  11. ;;;;; Input
  12. (define-condition swank-reader-error (reader-error)
  13. ((packet :type string :initarg :packet
  14. :reader swank-reader-error.packet)
  15. (cause :type reader-error :initarg :cause
  16. :reader swank-reader-error.cause)))
  17. (defun read-message (stream package)
  18. (let ((packet (read-packet stream)))
  19. (handler-case (values (read-form packet package))
  20. (reader-error (c)
  21. (error 'swank-reader-error
  22. :packet packet :cause c)))))
  23. (defun read-packet (stream)
  24. (let* ((length (parse-header stream))
  25. (octets (read-chunk stream length)))
  26. (handler-case (swank/backend:utf8-to-string octets)
  27. (error (c)
  28. (error 'swank-reader-error
  29. :packet (asciify octets)
  30. :cause c)))))
  31. (defun asciify (packet)
  32. (with-output-to-string (*standard-output*)
  33. (loop for code across (etypecase packet
  34. (string (map 'vector #'char-code packet))
  35. (vector packet))
  36. do (cond ((<= code #x7f) (write-char (code-char code)))
  37. (t (format t "\\x~x" code))))))
  38. (defun parse-header (stream)
  39. (parse-integer (map 'string #'code-char (read-chunk stream 6))
  40. :radix 16))
  41. (defun read-chunk (stream length)
  42. (let* ((buffer (make-array length :element-type '(unsigned-byte 8)))
  43. (count (read-sequence buffer stream)))
  44. (cond ((= count length)
  45. buffer)
  46. ((zerop count)
  47. (error 'end-of-file :stream stream))
  48. (t
  49. (error "Short read: length=~D count=~D" length count)))))
  50. (defparameter *validate-input* nil
  51. "Set to true to require input that more strictly conforms to the protocol")
  52. (defun read-form (string package)
  53. (with-standard-io-syntax
  54. (let ((*package* package))
  55. (if *validate-input*
  56. (validating-read string)
  57. (read-from-string string)))))
  58. (defun validating-read (string)
  59. (with-input-from-string (*standard-input* string)
  60. (simple-read)))
  61. (defun simple-read ()
  62. "Read a form that conforms to the protocol, otherwise signal an error."
  63. (let ((c (read-char)))
  64. (case c
  65. (#\( (loop collect (simple-read)
  66. while (ecase (read-char)
  67. (#\) nil)
  68. (#\space t))))
  69. (#\' `(quote ,(simple-read)))
  70. (t
  71. (cond
  72. ((digit-char-p c)
  73. (parse-integer
  74. (map 'simple-string #'identity
  75. (loop for ch = c then (read-char nil nil)
  76. while (and ch (digit-char-p ch))
  77. collect ch
  78. finally (unread-char ch)))))
  79. ((or (member c '(#\: #\")) (alpha-char-p c))
  80. (unread-char c)
  81. (read-preserving-whitespace))
  82. (t (error "Invalid character ~:c" c)))))))
  83. ;;;;; Output
  84. (defun write-message (message package stream)
  85. (let* ((string (prin1-to-string-for-emacs message package))
  86. (octets (handler-case (swank/backend:string-to-utf8 string)
  87. (error (c) (encoding-error c string))))
  88. (length (length octets)))
  89. (write-header stream length)
  90. (write-sequence octets stream)
  91. (finish-output stream)))
  92. ;; FIXME: for now just tell emacs that we and an encoding problem.
  93. (defun encoding-error (condition string)
  94. (swank/backend:string-to-utf8
  95. (prin1-to-string-for-emacs
  96. `(:reader-error
  97. ,(asciify string)
  98. ,(format nil "Error during string-to-utf8: ~a"
  99. (or (ignore-errors (asciify (princ-to-string condition)))
  100. (asciify (princ-to-string (type-of condition))))))
  101. (find-package :cl))))
  102. (defun write-header (stream length)
  103. (declare (type (unsigned-byte 24) length))
  104. ;;(format *trace-output* "length: ~d (#x~x)~%" length length)
  105. (loop for c across (format nil "~6,'0x" length)
  106. do (write-byte (char-code c) stream)))
  107. (defun switch-to-double-floats (x)
  108. (typecase x
  109. (double-float x)
  110. (float (coerce x 'double-float))
  111. (null x)
  112. (list (loop for (x . cdr) on x
  113. collect (switch-to-double-floats x) into result
  114. until (atom cdr)
  115. finally (return (append result (switch-to-double-floats cdr)))))
  116. (t x)))
  117. (defun prin1-to-string-for-emacs (object package)
  118. (with-standard-io-syntax
  119. (let ((*print-case* :downcase)
  120. (*print-readably* nil)
  121. (*print-pretty* nil)
  122. (*package* package)
  123. ;; Emacs has only double floats.
  124. (*read-default-float-format* 'double-float))
  125. (prin1-to-string (switch-to-double-floats object)))))
  126. #| TEST/DEMO:
  127. (defparameter *transport*
  128. (with-output-to-string (out)
  129. (write-message '(:message (hello "world")) *package* out)
  130. (write-message '(:return 5) *package* out)
  131. (write-message '(:emacs-rex NIL) *package* out)))
  132. *transport*
  133. (with-input-from-string (in *transport*)
  134. (loop while (peek-char T in NIL)
  135. collect (read-message in *package*)))
  136. |#