Add recommended targets to debian/rules
[kmrcl.git] / repl.lisp
1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
4 ;;;;
5 ;;;; Name:          repl.lisp
6 ;;;; Purpose:       A repl server
7 ;;;; Programmer:    Kevin M. Rosenberg
8 ;;;; Date Started:  Apr 2000
9 ;;;;
10 ;;;; This file, part of KMRCL, is Copyright (c) 2002 by Kevin M. Rosenberg
11 ;;;;
12 ;;;; KMRCL users are granted the rights to distribute and use this software
13 ;;;; as governed by the terms of the Lisp Lesser GNU Public License
14 ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
15 ;;;; *************************************************************************
16
17 (in-package #:kmrcl)
18
19 (defconstant +default-repl-server-port+ 4000)
20
21 (defclass repl ()
22   ((listener :initarg :listener :accessor listener
23              :initform nil)))
24
25 (defun make-repl (&key (port +default-repl-server-port+)
26                        announce user-checker remote-host-checker)
27   (make-instance 'listener
28     :port port
29     :base-name "repl"
30     :function 'repl-worker
31     :function-args (list user-checker announce)
32     :format :text
33     :wait nil
34     :remote-host-checker remote-host-checker
35     :catch-errors nil))
36
37 (defun init/repl (repl state)
38   (init/listener repl state))
39
40
41 (defun repl-worker (conn user-checker announce)
42   (when announce
43     (format conn "~A~%" announce)
44     (force-output conn))
45   (when user-checker
46     (let (login password)
47       (format conn "login: ")
48       (finish-output conn)
49       (setq login (read-socket-line conn))
50       (format conn "password: ")
51       (finish-output conn)
52       (setq password (read-socket-line conn))
53       (unless (funcall user-checker login password)
54         (format conn "Invalid login~%")
55         (finish-output conn)
56         (return-from repl-worker))))
57   #+allegro
58   (tpl::start-interactive-top-level
59    conn
60    #'tpl::top-level-read-eval-print-loop
61    nil)
62   #-allegro
63   (repl-on-stream conn)
64   )
65
66 (defun read-socket-line (stream)
67   (string-right-trim-one-char #\return
68                               (read-line stream nil nil)))
69
70 (defun print-prompt (stream)
71   (format stream "~&~A> " (package-name *package*))
72   (force-output stream))
73
74 (defun repl-on-stream (stream)
75   (let ((*standard-input* stream)
76         (*standard-output* stream)
77         (*terminal-io* stream)
78         (*debug-io* stream))
79     #|
80     #+sbcl
81     (if (and (find-package 'sb-aclrepl)
82              (fboundp (intern "REPL-FUN" "SB-ACLREPL")))
83         (sb-aclrepl::repl-fun)
84         (%repl))
85     #-sbcl
86     |#
87     (%repl)))
88
89 (defun %repl ()
90   (loop
91     (print-prompt *standard-output*)
92     (let ((form (read *standard-input*)))
93       (format *standard-output* "~&~S~%" (eval form)))))
94