Shammer's Philosophy

My private adversaria

ソースコードを複数の処理系に対応させる

#+ccl とか #+clisp というのを使用すればできるようだ。以下のような感じ。

(defun open-socket-server ()
  (make-socket :connect :passive
	       :reuse-address t
	       :local-port 7001))

(defun open-echo-server ()
  #+CCL
  (let
      ((server (open-socket-server)))
    (unwind-protect
	 (let ((client-socket (accept-connection server)))
	   (format t "> Server received a message: ~%")
	   (do ((line (read-line client-socket nil nil)
		      (read-line client-socket nil nil)))
	       ((string-equal line (string '#\Newline)))
	     (format t "Echo::: ~A~%" line))
	   (format t "> Received Complete...~%")
	   (close client-socket))
      (close server)))
  #+CLISP
  (let ((server (socket:socket-server 7001)))
    (format t "~&Waiting for a connection on ~S:~D~%"
	    (socket:socket-server-host server)
	    (socket:socket-server-port server))
    (unwind-protect
	 ;; Infinite loop, terminate with Control+C
	 (loop (with-open-stream (client (socket:socket-accept server))
		 (multiple-value-bind (local-host local-port) (socket:socket-stream-local client)
		   (multiple-value-bind (remote-host remote-port) (socket:socket-stream-peer client)
		     (format t "~&Connection: ~S:~D -- ~S:~D~%"
			     remote-host remote-port local-host local-port)))
		 ;; loop is terminated when the remote host closes the connection or on EXT:EXIT
		 (loop (when (eq :eof (socket:socket-status (cons client :input))) (return))
		    (print (eval (read client)) client)
		    ;; fluch everything left in socket
		    (loop :for c = (read-char-no-hang client nil nil) :while c)
		    (terpri client))))
      ;; make sure server is closed
      (socket:socket-server-close server))))

Clozure CL と clisp ではソケット系の処理が異なるが、#+ を使用すればその処理系ごとのコードを書くことができる。