pcs/newpcs/pio.s

499 lines
16 KiB
Common Lisp
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; -*- Mode: Lisp -*- Filename: pio.s
; Last Revision: 10-Feb-87 0800ct
;--------------------------------------------------------------------------;
; ;
; TI SCHEME -- PCS Compiler ;
; Copyright 1985 (c) Texas Instruments ;
; ;
; David Bartley ;
; ;
; Standard SCHEME Input/Output Routines ;
; ;
; READ modified for R^3 quasi-quote - TC ;
; READ-STRING removed and coded in asm 2/10/87 - TC ;
; Random I/O included from David Stevens 2/10/87 - TC ;
; Fixed input-port? and output-port? 3/13/87 - TC ;
; Open-binary-input-file,open-binary-output-file 3/13/87 - TC ;
; compile, etc. removed and placed in PCOMP.S ;
; for building of compiler-less system 6/02/87 - TC ;
; LOAD is just defined in terms of FAST-LOAD ;
; for compilerless systems. Its real definition ;
; is in PCOMP.S. 6/15/87 - TC ;
; Set line-length=0 for OPEN-BINARY-OUTPUT-FILE 1/21/88 - RB ;
; ;
;--------------------------------------------------------------------------;
; The following definitions are used only at compile time for readability
; and understanding. They will not be written out to the .so file.
; See pboot.s and compile.all.
(compile-time-alias %read-file-flag #b00000001) ; read flag
(compile-time-alias %write-file-flag #b00000011) ; write flag(s)
(compile-time-alias %window-flag #b00000100) ; window port
(compile-time-alias %open-file-flag #b00001000) ; open port
(compile-time-alias %binary-file-flag #b00100000) ; binary file
(compile-time-alias %string-flag #b01000000) ; string file
(define call-with-input-file ; CALL-WITH-INPUT-FILE
(lambda (filename proc)
(let* ((port (open-input-file filename))
(answer (proc port)))
(close-input-port port)
answer)))
(define call-with-output-file ; CALL-WITH-OUTPUT-FILE
(lambda (filename proc)
(let* ((port (open-output-file filename))
(answer (proc port)))
(close-output-port port)
answer)))
(define current-column ; CURRENT-COLUMN
(lambda args
(+ 1 (%reify-port (car args) 1))))
(define-integrable current-input-port ; CURRENT-INPUT-PORT
(lambda ()
(fluid input-port)))
(define-integrable current-output-port ; CURRENT-OUTPUT-PORT
(lambda ()
(fluid output-port)))
(define eof-object? ; EOF-OBJECT?
(lambda (obj)
(eqv? obj eof))) ; temporary ???
;;;
;;; Compile functions are now in PCOMP.S, ; COMPILE
;;; which reflects compiler-only functions
;;;
(define fast-load ; FAST-LOAD
(lambda (file)
(letrec ((fasl
(lambda (name)
(let ((pgm (%%fasl name)))
(when (not (eof-object? pgm))
(%execute pgm)
(fasl '() ))))))
(if (string? file)
(if (file-exists? file)
(begin
(fasl file)
'ok)
(error "FAST-LOAD file does not exist" file))
(%error-invalid-operand 'FAST-LOAD file)))))
(if (unbound? load)
(define load fast-load)) ; LOAD
(define file-exists? ; FILE-EXISTS?
(lambda (name)
(and (string? name)
(not (string-null? name))
(call/cc
(fluid-lambda (*file-exists-open*)
(let ((port (%open-port name 'read)))
(if (port? port)
(begin
(close-input-port port)
#!true)
;else
#!false)))))))
(define flush-input ; FLUSH-INPUT
(lambda args
(let ((x '())
(port (car args)))
(if (and (not (zero? (%logand (%reify-port port 11) %open-file-flag)))
(zero? (%logand (%reify-port port 11) %read-file-flag))
(char-ready? port))
(do ((x (read-char port) (read-char port)) )
((or (eq? x #\newline)
(eof-object? x)
(not (char-ready? port)))))))))
(define fresh-line ; FRESH-LINE
(lambda p
(when p (set! p (car p)))
(when (positive? (%reify-port p 1))
(newline p))))
(define input-port? ; INPUT-PORT?
(lambda (p)
(and (port? p)
(let ((pflags (%reify-port p 11)))
(and (not (zero? (%logand %open-file-flag pflags)))
(zero? (%logand %read-file-flag pflags)))))))
(define line-length ; LINE-LENGTH
(lambda args
(%reify-port (car args) 5)))
(define open-input-file ; OPEN-INPUT-FILE
(lambda (name) (%open-port name 'read)))
(define open-binary-input-file ; OPEN-BINARY-INPUT-FILE
(lambda (name)
(let ((port (%open-port name 'read)))
(%reify-port!
port
11
(%logior %binary-file-flag (%reify-port port 11)))
port)))
(define open-output-file ; OPEN-OUTPUT-FILE
(lambda (name) (%open-port name 'write)))
(define open-binary-output-file ; OPEN-BINARY-OUTPUT-FILE
(lambda (name)
(let ((port (%open-port name 'write)))
(%reify-port!
port
11
(%logior %binary-file-flag (%reify-port port 11)))
(set-line-length! 0 port)
port)))
(define open-extend-file ; OPEN-EXTEND-FILE
(lambda (name) (%open-port name 'append)))
(define close-input-port ; CLOSE-INPUT-PORT
(lambda (port) (%close-port port)))
(define close-output-port ; CLOSE-OUTPUT-PORT
(lambda (port) (%close-port port)))
(define (open-input-string str) ; OPEN-INPUT-STRING
(if (string? str)
(let ((p (%make-window '())))
(%reify! p 0 str)
(%reify-port! p 2 3)
(%reify-port! p 11 (%logior %string-flag (%reify-port p 11)))
p)
(%error-invalid-operand 'OPEN-INPUT-STRING str)))
(define output-port? ; OUTPUT-PORT?
(lambda (p)
(and (port? p)
(let ((pflags (%reify-port p 11)))
(and (not (zero? (%logand %open-file-flag pflags)))
(not (zero? (%logand %write-file-flag pflags))))))))
(define read ; READ
(letrec
((rd-object
(lambda (port qq?)
(let ((item (read-atom port)))
(cond ((eof-object? item) item)
((atom? item) item)
(else
(let ((item (car item)))
(case item
(|#(| (rd-vector-tail port qq?))
( |(| (rd-list-tail port qq?))
( |)| (error "Unexpected `)' encountered before `('"))
( |.| (dot-warning)(rd-object port qq?))
( |`| (rd-mac port #!true item #!false))
( |'| (rd-mac port qq? item #!false))
((|[| |]| |{| |}|)
item)
(else (rd-mac port qq? item #!true)))))))))
(rd-mac
(lambda (port qq? item qq-op?)
(if (and (not qq?) qq-op?)
(error "Invalid outside of QUASIQUOTE expression:" item)
(let ((obj (rd-object port qq?)))
(if (eof-object? obj)
(eof-warning)
(list (cdr (assq item qq-ops)) obj))))))
(rd-vector-tail
(lambda (port qq?)
(list->vector (rd-tail port qq? #!false '()))))
(rd-list-tail
(lambda (port qq?)
(rd-tail port qq? #!true '())))
(rd-tail
(lambda (port qq? dot-ok? result)
(let ((item (read-atom port)))
(cond ((eof-object? item)
(eof-warning)
(reverse! result))
((atom? item)
(if (eq? item 'quasiquote)
(rd-tail port #!true dot-ok? (cons item result))
;else
(rd-tail port qq? dot-ok? (cons item result))))
(else
(let ((item (car item)))
(case item
( |)| (reverse! result))
( |.| (if (and dot-ok? (not (null? result)))
(rd-dotted-tail port qq? result)
(begin
(dot-warning)
(rd-tail port qq? dot-ok? result))))
(else
(let ((obj (case item
(|#(| (rd-vector-tail port qq?))
( |(| (rd-list-tail port qq?))
( |`| (rd-mac port #!true item #!false))
( |'| (rd-mac port qq? item #!false))
((|[| |]| |{| |}|)
item)
(else (rd-mac port qq? item #!true)))))
(rd-tail port qq? dot-ok? (cons obj result)))))))))))
(rd-dotted-tail
(lambda (port qq? result)
(let ((tail (rd-tail port qq? #!false '())))
(append! (reverse! result)
(cond ((and (pair? tail)
(null? (cdr tail)))
(car tail))
(else
(dot-warning)
tail))))))
(dot-warning
(lambda ()
(newline)
(display "WARNING -- Invalid use of `.' encountered during READ")
(newline)))
(eof-warning
(lambda ()
(newline)
(display "WARNING -- EOF encountered during READ")
(newline)
eof))
(qq-ops
'((|'| . QUOTE)
(|`| . QUASIQUOTE)
(|,| . UNQUOTE)
(|,@| . UNQUOTE-SPLICING)
(|,.| . UNQUOTE-SPLICING!))))
(lambda args
(let ((port (car args)))
(rd-object port #!false)))))
;
; READ-LINE re-coded in assembly language on 2-10-86 by TC
;
;(define read-line ; READ-LINE
; (lambda args
; (define (readln-rec port n char char-list)
; (cond ((eof-object? char)
; (if (null? char-list)
; char
; (fill-string (trim char-list))))
; ((eqv? char #\return)
; (if (null? char-list)
; ""
; (fill-string (trim char-list))))
; ((eqv? char #\newline)
; (readln-rec port n (read-char port) char-list))
; (else
; (readln-rec port (+ n 1) (read-char port)
; (cons char char-list)))))
; (define (trim char-list)
; (cond ((null? char-list)
; '())
; ((eqv? (car char-list) #\space)
; (trim (cdr char-list)))
; (else
; char-list)))
; (define (fill-string char-list)
; (let ((size (length char-list)))
; (fill-rec char-list (- size 1) (make-string size '()))))
; (define (fill-rec char-list i string)
; (if (null? char-list)
; string
; (begin
; (string-set! string i (car char-list))
; (fill-rec (cdr char-list) (- i 1) string))))
; (let ((port (and args (car args))))
; (readln-rec port 0 (read-char port) '()))))
;
(define set-line-length! ; SET-LINE-LENGTH!
(lambda (value . rest)
(%reify-port! (car rest) 5 value)
'()))
(define transcript-on)
(define transcript-off)
(let ((port '()))
(set! transcript-on ; TRANSCRIPT-ON
(lambda (file)
(when (not (null? port))
(transcript-off))
(cond ((string? file)
(set! port (open-extend-file file))
(if (port? port)
(begin
(%transcript port)
'ok )
(begin
(set! port '())
(error "Unable to open transcript file" file))))
((window? file)
(set! port file)
(%transcript file)
'ok)
(else
(error "Invalid argument to transcript-on" file)))))
(set! transcript-off ; TRANSCRIPT-OFF
(lambda ()
(when (not (null? port))
(%transcript '())
(close-output-port port)
(set! port '()))
'ok)))
;;; WITH-INPUT-FROM-FILE and WITH-OUTPUT-TO-FILE need to be rewritten
;;; to use DYNAMIC-WIND, or its equivalent.
(define with-input-from-file ; WITH-INPUT-FROM-FILE
(lambda (filename thunk)
(let ((port (open-input-file filename)))
(if (port? port)
(let ((ans (fluid-let ((input-port port)) (thunk))))
(close-input-port port)
ans)
port))))
(define with-output-to-file ; WITH-OUTPUT-TO-FILE
(lambda (filename thunk)
(let ((port (open-output-file filename)))
(if (port? port)
(let ((ans (fluid-let ((output-port port)) (thunk))))
(close-output-port port)
ans)
port))))
(define window? ; WINDOW?
(lambda (obj)
(and (port? obj)
(positive? (%logand (%reify-port obj 11) %window-flag)))))
(define writeln ; WRITELN
(lambda args
(do ((args args (cdr args)))
((null? args)
(newline))
(display (car args)))))
;****************************************************************************
;* SET-FILE-POSITION will move the file pointer to a new position *
;* and update a pointer in the buffer to point to a new location. *
;* The offset variable can be: *
;* 0 for positioning from the start of the file *
;* 1 for positioning relative to the current position *
;* 2 for positioning from the end of the file *
;****************************************************************************
(define set-file-position! ; SET-FILE-POSITION!
(lambda (port #-of-bytes offset)
(let ((current-pos (%reify-port port 9))
(end-of-buffer (%reify-port port 10))
(new-pos '())
(current-chunk (max 0 (-1+ (%reify-port port 12))))
(new-chunk '())
(messages '())
(file-size (+ (* (%reify-port port 4) 65536) (%reify-port port 6)))
(port-flags (%reify-port port 11)))
(if (and (port? port)
(=? (%logand port-flags %window-flag) 0))
(case offset
((0) ; offset from the start of the file
(set! #-of-bytes (abs #-of-bytes))
(if (=? (%logand port-flags %write-file-flag) 0)
(set! #-of-bytes (min #-of-bytes file-size)))
(set! new-chunk (truncate (/ #-of-bytes 256)))
(set! new-pos (- #-of-bytes (* new-chunk 256)))
(if (and (<? new-pos end-of-buffer)
(>=? new-pos 0)
(=? (%logand port-flags %write-file-flag) 0) ; open for reading
(=? new-chunk current-chunk))
(%reify-port! port 9 new-pos)
(%sfpos port new-chunk new-pos)))
((1) ; offset from the current position
(set! new-pos (+ current-pos #-of-bytes))
(if (and (<? new-pos end-of-buffer)
(>=? new-pos 0)
(=? (%logand port-flags %write-file-flag) 0)) ; open for reading
(%reify-port! port 9 new-pos)
(begin
(set! new-pos (+ (+ current-pos (* 256 current-chunk))
#-of-bytes)) ; offset from the begining of the file
(if (and (>? new-pos file-size)
(=? (%logand port-flags %write-file-flag) 0))
(set! new-pos file-size))
(if (<? new-pos 0)
(set! new-pos 0))
(set! new-chunk (truncate (/ new-pos 256)))
(%sfpos port new-chunk (- new-pos (* new-chunk 256))))))
((2) ; offset from the end of the file
(set! #-of-bytes (min (abs #-of-bytes) file-size))
(set! new-pos (- file-size (abs #-of-bytes))) ; absolute position
(set! new-chunk (truncate (/ new-pos 256)))
(set! new-pos (- new-pos (* new-chunk 256))) ; buffer position
(if (=? (%logand port-flags %write-file-flag) 0)
(if (and (<? new-pos end-of-buffer)
(>=? new-pos 0)
(=? new-chunk current-chunk))
(%reify-port! port 9 new-pos)
(%sfpos port new-chunk new-pos))
(error
"SET-FILE-POSITION! - offset from EOF only valid for input files")
))
(else (%error-invalid-operand 'SET-FILE-POSITION! offset)))
(%error-invalid-operand 'SET-FILE-POSITION! port)))))
;******************************************************************
;* get-file-position will return the current file position in the *
;* number of bytes from the beginning of the file. *
;******************************************************************
;(define get-file-position
; (lambda (port)
; (let (( result '())
; (chunk (max 1 (%reify-port port 12))))
; (if (and (port? port)
; (=? (%logand (%reify-port port 11) %window-flag) 0))
; (set! result (+ (* 256 (-1+ chunk)) ; chunk#
; (%reify-port port 9))) ; current position
; (set! result "Needs to be a port/file object!"))
; result)))
(define get-file-position ; GET-FILE-POSITION
(lambda (port)
(if (and (port? port)
(=? (%logand (%reify-port port 11) %window-flag) 0))
(+ (* 256 (-1+ (max 1 (%reify-port port 12)))) ; chunk#
(%reify-port port 9)) ; offset within chunk
(error "Invalid argument to GET-FILE-POSITION. Port object must represent a file." port))))