[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Multi-return value functions and with-input-stream-do



Oliver Andrich writes:
 > Hello everybody!
 > 
 > ...
 > and I also managed to send all information for displaying the main
 > window. But then my problems started, I wanted to read something from
 > the in-stream and parse it, but I got really messed up with all these
 > input functions provided by LISP. Then I discovered this nice macro
 > with-open-stream and thought that this macro would solve my problems.
 > But I doesn't solve anything, cause make-pipe-io-stream returns a
 > multi-returnvalue. How do I use with-open-stream with make-pipe-io-stream?
 > 
 > Or how do I solve the following task? I want to constantly read from a
 > pipe similar to read-char-no-hang, but I want to read a whole line and
 > reading stops when an EOF is received, then all pipes produced by
 > make-pipe-io-stream should be closed.

I used the following code in the Plopp! planning system to solve the problem 
you described:

(defvar *WISH-PROG* 	  "wish")
(defvar *WISH-ARGS* 	  (list "-name" "Plopp"))
(defvar *WISH-EXIT-MSG*   "after 500 exit")
(defvar *WISH*            NIL  "The two-way-stream to the wish process")

;;; --------------------------------------------------------------------------
;;; WITH-WISH (macro)
;;; --------------------------------------------------------------------------

(defmacro WITH-WISH (&body body)
  `(let ((*wish* (run-program *wish-prog* 
                              :arguments *wish-args*
			      :input     :stream
			      :output    :stream)))
     (unwind-protect
	 (progn (read-until *wish*)
		,@body)
       (when *wish*
	 (format *wish* "~A~%" *wish-exit-msg*)
	 (force-output *wish*)
	 (setq *wish* NIL)))))

;;; --------------------------------------------------------------------------
;;; READ-UNTIL (function)
;;; --------------------------------------------------------------------------

(defun READ-UNTIL (stream &optional (prompt ""))
  (flet ((read-to-end ()
           (do ((s nil (cons (read-char-no-hang stream NIL NIL) s)))
               ((and (consp s) (null (car s)))
                (coerce (nreverse (cdr s)) 'string)))))
    (do* ((lp  (length prompt))
          (str (read-to-end) (concatenate 'string str (read-to-end)))
          (ls  (length str)  (length str)))
        ((or (zerop lp)
             (and (>= ls lp) (string= prompt (subseq str (- ls lp)))))
         (subseq str 0 (- ls lp))))))

Within the body of WITH-WISH you can communicate with the tcl/tk process
writing to *wish* and reading from it. READ-UNTIL reads from a stream 
as much as possible or until a prompt is found. (the implementation is weird 
and could be much simpler, as wishes do not send prompts to pipes - anyway it
works ... at least for me ;) )
Remember to call "(force-output *wish*)" on the CLisp side and "flush stdout"
on the wish side after each output operation.

 > 
 > I hope, that some could help me.
 > 

Hope it helped.

--Matthias

------------------------------------------------------------------------------
Matthias Lindner
FG Intellektik, FB Informatik
Technische Hochschule Darmstadt
Alexanderstr.10, D-64283 Darmstadt
TEL: +49 6151 166651
FAX: +49 6151 165326
NET: matthias@intellektik.informatik.th-darmstadt.de
WWW: http://aida.intellektik.informatik.th-darmstadt.de/~matthias/
------------------------------------------------------------------------------