;;-*- Mode:LISP; Package:VERIFICATION-INTERNALS; Base:8 -*- ;; (C) Copyright 1983 LispMachineInc. ;; 11/08/83 11:13:01 -George Carrette ;; Copyright LISP Machine, Inc. 1984 ;; See filename "Copyright" for ;; licensing and release information. ;; A kind of BATCH processing of a file of lisp expressions, with "log output" ;; to file and terminal. (defvar *showtime? nil) (defvar *comment* nil) (defvar *verify-file-comment* nil) (defun (:property :verify-file fs:file-attribute-bindings) (ignore ignore value) (values (list '*verify-file-comment*) (list value))) (defun verify-file (&optional (input-filename "") &key (output-filename "") (terminal-stream terminal-io) (comment nil) (showtime? nil) (driver 'verify-stream)) "Reads expressions from the , evaluates them in the usual load environment, and prints the results as in a read-eval-print loop. Input and output is echoed to the and//or the . Example: (verify-file /"ED:TEST.LISP/" :Output-filename /"ED-BUFFER:TEST.OUT/"." (or (get driver 'verify-pathname-defaults) (setf (get driver 'verify-pathname-defaults) (fs:make-pathname-defaults))) (if terminal-stream (send terminal-stream ':fresh-line)) (let ((input-filename (fs:merge-pathname-defaults input-filename (get driver 'verify-pathname-defaults))) (*showtime? showtime?) (*comment* comment)) (with-open-stream (input-stream (file-retry-new-pathname (input-filename fs:file-error) (send input-filename ':open-canonical-default-type ':LISP))) (setq input-filename (or (send input-stream ':pathname) (fs:parse-pathname input-filename))) (fs:set-default-pathname input-filename (get driver 'verify-pathname-defaults)) (let ((GENERIC-PATHNAME (SEND INPUT-FILENAME ':GENERIC-PATHNAME))) (FS:READ-ATTRIBUTE-LIST GENERIC-PATHNAME INPUT-STREAM) (MULTIPLE-VALUE-BIND (VARS VALS) (FS:FILE-ATTRIBUTE-BINDINGS GENERIC-PATHNAME) (PROGV VARS VALS (if output-filename (with-open-file (output-stream (send (fs:merge-pathname-defaults output-filename input-filename) ':new-type "OUT") ':OUT) (funcall driver input-stream output-stream terminal-stream)) (funcall driver input-stream () terminal-stream)))))))) (defun verify-stream (input-stream &rest output-streams) (let ((output-stream (apply #'make-broadcast-stream (delq () (copylist output-streams))))) (format output-stream "; Verification of ~A by ~A using ~A~%;" (send input-stream ':truename) user-id si:local-host-name) (time:print-current-date output-stream) (terpri output-stream) (when *comment* (princ *comment* output-stream) (terpri output-stream)) (when *verify-file-comment* (format output-stream "~&Extra-Filename-Information ~A~%" *verify-file-comment*)) (si:describe-system-versions output-stream) (terpri output-stream) (verify-repl (make-verify-stream input-stream output-stream) output-stream))) (defconst *other-output-streams* '(error-output trace-output)) (defun verify-repl (standard-input standard-output) (progv *other-output-streams* (circular-list standard-output) (let ((time-before-everything (time)) (time-eval-total 0)) (do ((form)(eofp (list ()))(eval-time-inc)) ((eq (setq form (read standard-input eofp)) eofp)) (unwind-protect ;; maybe add some condition handling here. handle sys:abort etc ;; like in a lisp listener. (let ((time-before-eval (time))) (setq * (eval form)) (let ((time-after-eval (time))) (setq eval-time-inc (time-difference time-after-eval time-before-eval)) (setq time-eval-total (+ time-eval-total eval-time-inc)))) (setq + form)) (if *showtime? (format standard-output "~&; Evaluation took ~S seconds." (// eval-time-inc 60.0))) (print * standard-output)) (let ((time-after-everything (time))) (let ((time-total-total (time-difference time-after-everything time-before-everything))) (let ((tet (funcall (get ':realtime 'measure-convert) time-eval-total)) (ttt (funcall (get ':realtime 'measure-convert) time-total-total))) (format standard-output "~&; End of test.~%; ~S seconds realtime total, ~S during evaluation.~%" ttt tet) (list (send standard-input ':truename) ':total-realtime ttt ':eval-realtime tet))))))) ;; this bidirection broadcast-stream hack could go with other system I/O functions. ;; i guess i really should be using flavorized streams here, even if it is hairier ;; to do so. (defvar *verify-input-stream*) (defvar *verify-output-stream*) (defvar *verify-untyi-char*) (defun verify-stream-closure-function (operation &optional arg1 &Rest args) (selectq operation (:which-operations '(:tyi :untyi :tyipeek)) ((:tyi :tyipeek) (let (c) (if (null *verify-untyi-char*) (or (eq arg1 (setq c (send *verify-input-stream* ':tyi arg1))) (send *verify-output-stream* ':tyo c)) (setq c *verify-untyi-char*)) (setq *verify-untyi-char* (and (eq operation ':tyipeek) c)) c)) (:untyi (setq *verify-untyi-char* arg1)) (:truename (send *verify-input-stream* ':truename)) (:otherwise (stream-default-handler #'verify-stream-closure-function operation arg1 args)))) (defun make-verify-stream (input-from output-to) "Makes a kind of bi-directional broadcast stream" (let ((*verify-input-stream* input-from) (*verify-output-stream* output-to) (*verify-untyi-char* ())) (closure '(*verify-input-stream* *verify-output-stream* *verify-untyi-char*) #'verify-stream-closure-function)))