home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
vis-ftp.cs.umass.edu
/
vis-ftp.cs.umass.edu.tar
/
vis-ftp.cs.umass.edu
/
pub
/
Software
/
ASCENDER
/
ascendMar8.tar
/
UMass
/
ISR
/
isr2fileio.lisp
< prev
next >
Wrap
Lisp/Scheme
|
1995-04-11
|
85KB
|
2,354 lines
;; ; -*- Mode:Common-Lisp; Package:isr2; Base:10 -*-
;;;------------------------------------------------------------------------
;;; ISR2FileIo.LISP - Functions for saving and loading frames
;;; Created: Thu May 26 15:19:13 1988
;;; Author: Robert Heller
;;;------------------------------------------------------------------------
;;; Copyright (c) University of Massachusetts 1988
;;;------------------------------------------------------------------------
;;; modified 05/01/89 17:18:15 by Bob Collins
;;; added code for selecting files by menu, or interactively
;;; entering a new filename. The heart of this code is
;;; menu-choose-source-file. Function ask-user-for-source-files-to-load
;;; modified to call the choosing code when sub-frame-action is :ask-user.
;;; Also, read-frame modified to call choosing code on parent frame when
;;; frame-ask-user is non-nil. Global variable *global-directory-search-list*
;;; is a list of directories to look through to find file choices to
;;; display in the menu. Changes read-in-decendants to push the directory
;;; of the parent filename onto the directory search list temporarily, if
;;; sub-frame-action is :ask-user.
(in-package "ISR2")
(export '(store restore write-frame read-frame describe-file))
(defmacro with-open-isr2-frame-file ((stream-var fname direction) &body body)
"Helper macro..."
`(with-open-file (,stream-var ,fname :direction ,direction
:element-type '(unsigned-byte 8)
:if-exists :new-version
)
,@body))
(defmacro with-open-isr2-read-frame-file ((stream-var fname frame-path) &body body)
"Helper macro..."
`(let ((file-name (if (probe-file ,fname)
,fname
(menu-choose-source-file
,fname (format nil "Choose source file for frame path ~s" ,frame-path)))))
(with-open-file (,stream-var file-name :direction :input
:element-type '(unsigned-byte 8)
)
,@body)))
;; magic header hacking code
(defvar *file-version-number* 1 "File Version number")
(defconstant magic-8-byte-header-v0 "ISR2V000"
"This 8-byte sequence is written at the beginning of the file to indicate
that it is an ISR2 (V000) frame file.")
(defconstant magic-8-byte-header-v1 "ISR2V001"
"This 8-byte sequence is written at the beginning of the file to indicate
that it is an ISR2 (V001) frame file.")
(#-(or :allegro :lispworks) defsubst #+(or :allegro :lispworks) defun write-isr2-header (file)
(dotimes (i 8)
(write-byte (char-code (aref magic-8-byte-header-v1 i)) file)))
(defun read-and-check-isr2-header (file &aux (header-string (make-string 8)))
(dotimes (i 8)
(setf (aref header-string i) (code-char (read-byte file))))
(cond ((string= header-string magic-8-byte-header-v0)
(warn "~2&+++ Warning: file ~s is an old format file!~&"
(truename file))
0)
((string= header-string magic-8-byte-header-v1) 1)
(t nil)))
(DEFVAR *WORD* 0 "for byte depositing")
(DEFVAR *TEMP* 0 "for macros, to avoid annoying let gensym stuff")
(defvar *null-extents* nil)
(eval-when (compile load eval)
(setf *null-extents* (make-extents 0 0 0 0 0))) ;written out in place of undefined extents
;; byte fields in multi-byte objects -- NOTE Byte Sex - Low byte first. This works
;; for the VAX and the LISP Machine. Will also work on Intel-based cpus (i.e.
;; 80386-based SUN's and Sequents). Beware 68K systems (SUN workstations with
;; 68020's, Apple MAC's, Atari ST's, etc.)!
(defconstant byte0 (byte 8 0))
(defconstant byte1 (byte 8 8))
(defconstant byte2 (byte 8 16))
(defconstant byte3 (byte 8 24))
;;;;======================== LOW LEVEL INPUT =======================================
(#-(or :allegro :lispworks) defsubst #+(or :allegro :lispworks) defun read-ubyte8 (stream)
"Read in an unsigned 8-bit byte"
(read-byte stream))
(#-(or :allegro :lispworks) defsubst #+(or :allegro :lispworks) defun read-ubyte16 (stream)
"Read in an unsigned 16-bit byte"
(dpb (read-byte stream) byte0
(dpb (read-byte stream) byte1 0)))
(defconstant max-short-int #x08000)
(defconstant max-ushort-int #x10000)
(#-(or :allegro :lispworks) defsubst #+(or :allegro :lispworks) defun read-sbyte16 (stream)
"Read in a signed 16-bit byte (short int)"
(let ((temp (read-ubyte16 stream)))
(if (> temp max-short-int) (- temp max-ushort-int) temp)))
(#-(or :allegro :lispworks) defsubst #+(or :allegro :lispworks) defun read-ubyte32 (stream)
"Read in an unsigned 32-bit byte"
(dpb (read-byte stream) byte0
(dpb (read-byte stream) byte1
(dpb (read-byte stream) byte2
(dpb (read-byte stream) byte3 0)))))
(defconstant max-long-int #x080000000)
(defconstant max-ulong-int #x100000000)
(defconstant MAXINT32 #x0FFFFFFFF)
(#-(or :allegro :lispworks) defsubst #+(or :allegro :lispworks) defun read-sbyte32 (stream)
"Read in a signed 32-bit byte (long int)"
(let ((temp (read-ubyte32 stream)))
(if (> temp max-long-int) (- temp max-ulong-int) temp)))
#+:allegro
(ff:def-c-type fl-union :union (float :single-float) (ub32 :unsigned-long))
#+:lispworks
(foreign::define-foreign-function (float-from-ub32 "convert_float_long" :source)
((l :alien)) :result-type :single-float :language :c)
#+:lispworks
(foreign::define-foreign-function (ub32-from-float "convert_long_float" :source)
((l :single-float :reference-pass)) :result-type :uinteger :language :c)
#+:lispworks
(eval-when (load eval compile)
(foreign::define-foreign-type ulong-array (:array :unsigned-long 1) :language :c))
#+:lispworks
(defvar ulong-temp (make-ulong-array))
#+:allegro
(defvar fl-union-holder (make-fl-union))
#+:allegro
(defun read-float32 (stream)
(setf (fl-union-ub32 fl-union-holder) (read-ubyte32 stream))
(fl-union-float fl-union-holder)
)
#+:lispworks
(defun read-float32 (stream)
(setf (ulong-array[] ulong-temp 0) (read-ubyte32 stream))
(float-from-ub32 ulong-temp))
#-(or :allegro :lispworks)
(defvar fl-union-ub32 (make-array 1 :element-type '(unsigned-byte 32)))
#-(or :allegro :lispworks)
(defvar fl-union-fl32 (make-array 1 :element-type 'single-float
:displaced-to fl-union-ub32))
#-(or :allegro :lispworks)
(defun read-float32 (stream)
(setf (aref fl-union-ub32 0) (read-ubyte32 stream))
(aref fl-union-fl32 0))
(defun read-isr2-string (file &aux string ch length)
"Read in a counted string. The string's length is in a unsigned 16-bit
byte, followed by the ASCII chars of the string followed by a NUL byte
at the end (the NUL byte is counted by the string length byte). True ASCII
is used, with ASCII HT's for tabs and ASCII LF's for newline marks. The
rest of the text should be the normal printable ASCII characters (' ' to '~')."
(setf length (1- (read-ubyte16 file))
string (make-string length))
(dotimes (i length)
(setf ch (read-byte file))
;; force character to be a "standard" ASCII character
;; (newline using C convention, preserving TABs, trashing all other
;; "funny" characters to spaces)
(cond ((= ch 10) (setf ch #\NEWLINE)) ;; convert LF to #\NEWLINE
((= ch 9) (setf ch #\TAB)) ;; convert ASCII HT to #\TAB
((< ch 32) (setf ch #\SPACE)) ;; convert all other out-of-range chars
((> ch 126) (setf ch #\SPACE)) ;; to #\SPACE
(t (setf ch (code-char ch)))) ;; normal characters (ASCII ' ' to '~').
(setf (aref string i) ch))
;; gobble null byte at the end (C convention)
(read-byte file)
string)
(defun read-isr2-string-n (file len &aux string ch length)
"Read in a counted string. The string's length is len (already read in).
This function reads in the ASCII chars of the string and the NUL byte
at the end (the NUL byte is counted by the string length byte). True ASCII
is used, with ASCII HT's for tabs and ASCII LF's for newline marks. The
rest of the text should be the normal printable ASCII characters (' ' to '~')."
(setf length (1- len)
string (make-string length))
(dotimes (i length)
(setf ch (read-byte file))
;; force character to be a "standard" ASCII character
;; (newline using C convention, preserving TABs, trashing all other
;; "funny" characters to spaces)
(cond ((= ch 10) (setf ch #\NEWLINE)) ;; convert LF to #\NEWLINE
((= ch 9) (setf ch #\TAB)) ;; convert ASCII HT to #\TAB
((< ch 32) (setf ch #\SPACE)) ;; convert all other out-of-range chars
((> ch 126) (setf ch #\SPACE)) ;; to #\SPACE
(t (setf ch (code-char ch)))) ;; normal characters (ASCII ' ' to '~').
(setf (aref string i) ch))
;; gobble null byte at the end (C convention)
(read-byte file)
string)
;;;;======================= INTERMEDIATE LEVEL INPUT ==============================
(defun read-isr2-sexpr-pkg (file &optional (*package* *package*) &aux sexp)
(setf sexp (read-from-string (read-isr2-string file)))
(cond ((and (= *file-version-number* 0)
(eq sexp *old-ptr-undefined*))
*ptr-undefined*)
((and (= *file-version-number* 0)
(eq sexp *old-ptr-undefinable*))
*ptr-undefinable*)
(t sexp))
)
(defun read-isr2-sexpr-pkg-n (file len &optional (*package* *package*) &aux sexp)
(setf sexp (read-from-string (read-isr2-string-n file len)))
(cond ((and (= *file-version-number* 0)
(eq sexp *old-ptr-undefined*))
*ptr-undefined*)
((and (= *file-version-number* 0)
(eq sexp *old-ptr-undefinable*))
*ptr-undefinable*)
(t sexp))
)
(defvar *old-frame-path* nil "Holds frame path as read and parsed from file")
(defvar *new-frame-path* nil "Holds new frame path as specified in read-frame call")
(defun adjust-handle (raw-handle &aux in-frame-parsed-path)
(if (member raw-handle `(,*ptr-undefined* ,*ptr-undefinable*))
raw-handle
(progn
(setf in-frame-parsed-path
(adjust-path (parse-token-name raw-handle)))
(multiple-value-bind (handle more-path)
(make-handle-from-parsed-path in-frame-parsed-path)
(if more-path
(cons handle more-path)
handle))))
)
(defun adjust-path (in-parsed-path)
(do ((p1 in-parsed-path (rest p1))
(p2 *old-frame-path* (rest p2)))
((null p2) (append *new-frame-path* p1))
(unless (and (not (null p1))
(equalp (first p1) (first p2)))
(return in-parsed-path)))
)
(defun create-empty-frames-if-needed (handle-spec)
(do ()
((or (eq handle-spec *ptr-undefined*)
(eq handle-spec *ptr-undefinable*)
(handle-p handle-spec)
(or (and (integerp (second handle-spec)) (null (rest (rest handle-spec))))
(eq (second handle-spec) :?)
(and (stringp (second handle-spec))
(string= (subseq (second handle-spec) 0 2) "F_")))
)
handle-spec)
(cond ((null (rest handle-spec)) (setf handle-spec (first handle-spec)))
(t (setf handle-spec (cons (create-stub-frame (list (first handle-spec)
(second handle-spec)))
(rest (rest handle-spec))))))
)
)
(defun create-stub-frame (path &aux new-frame-handle new-frame)
(setf new-frame-handle (create path))
(when (and (handle-p new-frame-handle) (eq (handle-type new-frame-handle) :frame))
(setf new-frame (handle-frame new-frame-handle)
(frame-is-loaded-p new-frame) nil))
new-frame-handle)
(defun read-isr2-tss (file &optional skip &aux frame-path frame-handle flag evv)
(setf frame-path (read-isr2-string file)
frame-handle (create-empty-frames-if-needed
(adjust-handle frame-path)))
(unless (or skip (and frame-handle
(handle-p frame-handle)
(eq (handle-type frame-handle) :frame)))
(error "I/O Error: Illegal TSS stored in file ~S - frame path was: ~S"
(namestring (truename file)) frame-path))
(setf frame-handle (copy-handle frame-handle))
(setf flag (= (read-ubyte16 file) 0))
(if flag
(setf evv (read-isr2-token-list file))
(setf evv (read-isr2-2vv file skip)))
(setf (handle-type frame-handle) :token-subset
(handle-token-existence-array frame-handle) evv)
(if skip (make-null-tss! frame-handle) frame-handle)
)
(defvar *sort-fixup-list* nil "List of sort objects to be fixed up")
(defun read-isr2-tsort (file &optional skip &aux frame-path frame-handle flag
sort-order fname evv)
(setf frame-path (read-isr2-string file)
frame-handle (adjust-handle frame-path))
(unless (or skip (and frame-handle
(handle-p frame-handle)
(eq (handle-type frame-handle) :frame)))
(error "I/O Error: Illegal Sort stored in file ~S - frame path was: ~S"
(namestring (truename file)) frame-path))
(unless (handle-p frame-handle) (setf frame-handle (make-handle)))
(setf fname (read-isr2-string file))
(setf flag (= (read-ubyte16 file) 0))
(if flag
(setf sort-order :ascending)
(setf sort-order :descending))
(setf evv (read-isr2-token-list file))
(setf (handle-type frame-handle) :token-sort
(handle-token-existence-array frame-handle) evv
(handle-sort-order frame-handle) sort-order
(handle-feature frame-handle) fname)
(push frame-handle *sort-fixup-list*)
frame-handle
)
(defun fixup-sorts ()
(map nil #'(lambda (sort)
(setf (handle-fdescr sort)
(first (member (handle-feature sort)
(frame-token-set-feature-vector
(handle-frame sort))
:test #'equalp
:key #'fdescr-featurename))))
*sort-fixup-list*))
(defun read-isr2-token-list (file &aux len result)
(setf len (read-ubyte16 file)
result (make-list len))
(do ((p result (rest p)))
((null p))
(setf (first p) (read-ubyte32 file)))
result)
(defun read-isr2-2vv (file &optional skip &aux type-code result block-count
low val ovec ivec ov)
(setf type-code (read-ubyte16 file))
(setf result (make-2index-vector-vector type-code))
(setf block-count (read-ubyte16 file))
(setf ovec (2index-vector-vector-data result))
(dotimes (k block-count)
(setf low (read-ubyte32 file))
(add-2index-vector result (setf ov (truncate
low
*default-2index-vector-size*)))
(setf ivec (2index-vector-data-vector (aref ovec ov)))
(cond ((= type-code *boolean*)
(read-bits-into-bvec file ivec *default-2index-vector-size*))
(t (dotimes (iv *default-2index-vector-size*)
(setf val (case type-code
(#.*int* (read-sbyte32 file))
(#.*real* (read-float32 file))
(#.*handle* (read-isr2-handle file skip))
(#.*extents* (read-isr2-extents file))
(#.*bitplane* (read-isr2-bitplane file))
(#.*array* (read-isr2-array file))
(#.*string* (read-isr2-sexpr-pkg
file
(find-package (if (= *file-version-number* 0) 'user 'isr2))))
(#.*pointer* (read-isr2-sexpr-pkg
file
(find-package (if (= *file-version-number* 0) 'user 'isr2))))))
(setf (aref ivec iv) val))))
)
(if skip (progn (free-2vv result) nil) result))
#-(or :allegro :lispworks)
(defun read-bits-into-bvec (file vec size &aux byte-vec)
(setf byte-vec (make-array (ceiling size 8) :element-type '(unsigned-byte 8)
:displaced-to vec))
(dotimes (ib (ceiling size 8))
(setf (aref byte-vec ib) (read-ubyte8 file)))
vec)
#+(or :allegro :lispworks)
(defmacro getbit (thebyte ibit)
`(ldb (byte 1 ,ibit) ,thebyte))
#+(or :allegro :lispworks)
(defmacro setbit (thebyte ibit newbit)
`(setf ,thebyte (dpb ,newbit (byte 1 ,ibit) ,thebyte)))
#+(or :allegro :lispworks)
(defun read-bits-into-bvec (file vec size &aux flat-bits)
(setf flat-bits (make-array size :element-type 'bit :displaced-to vec))
(dotimes (ib (ceiling size 8))
(let ((abyte (read-ubyte8 file)))
(dotimes (ibit 8)
(setf (aref flat-bits (+ (* ib 8) ibit)) (getbit abyte ibit))
))
)
vec)
(defconstant tss-header-tag-as-16-bit-ubyte
(dpb (char-code #\#) byte0
(dpb (char-code #\T) byte1 0)))
(defconstant sort-header-tag-as-16-bit-ubyte
(dpb (char-code #\#) byte0
(dpb (char-code #\S) byte1 0)))
(defun read-isr2-handle (file &optional skip)
(let ((start-tag (read-ubyte16 file)))
(cond ((= start-tag tss-header-tag-as-16-bit-ubyte)
(read-isr2-tss file skip))
((= start-tag sort-header-tag-as-16-bit-ubyte)
(read-isr2-tsort file skip))
(t (create-empty-frames-if-needed
(adjust-handle
(read-isr2-sexpr-pkg-n
file start-tag (find-package (if (= *file-version-number* 0) 'user 'isr2)))))
)
)
)
)
(defun read-isr2-extents (file)
(let ((pixcount (read-ubyte32 file))) ; pixel-count
(if (= pixcount 0)
*ptr-undefined*
(if (= pixcount MAXINT32)
*ptr-undefinable*
(make-extents pixcount
(read-sbyte16 file) ; minx (mincol)
(read-sbyte16 file) ; miny (minrow)
(read-sbyte16 file) ; maxx (maxcol)
(read-sbyte16 file)))) ; maxy (maxrow)
)
)
(defun read-isr2-bitplane (file)
(let ((numbytes (read-ubyte32 file))) ; total byte count
(if (= numbytes 0)
*ptr-undefined*
(if (= numbytes MAXINT32)
*ptr-undefinable*
(let* ((bit-width (read-ubyte16 file)) ; total number of bit columns
(bit-height (read-ubyte16 file)) ; total number of bit rows
(byte-width (ceiling bit-width 8)) ; total number of byte columns
)
;; check for consistent data
(unless (= (* byte-width bit-height) numbytes)
(error "Number of bytes in bitplane is ~D, it should be ~D" numbytes
(* byte-width bit-height)))
;; read in bitplane, padding to longword boundary if needed
; compute next highest multiple of 32 bits
(let ((new-byte-width (* 4 (ceiling byte-width 4)))
#+:EXPLORER (default-cons-area *bitplane-area*))
#+:EXPLORER (declare (special default-cons-area))
#-(or :allegro :lispworks)
(let ((bitplane (make-array (list bit-height new-byte-width)
:element-type '(unsigned-byte 8))))
;read in bitplane, a byte at a time
(dotimes (y bit-height)
(dotimes (x byte-width)
(setf (aref bitplane y x)
(read-ubyte8 file))))
(make-array (list bit-height (* 8 new-byte-width))
:element-type 'bit
:displaced-to bitplane))
#+(or :allegro :lispworks)
(let ((bitplane (make-array (list bit-height
(* new-byte-width 8)
:element-type 'bit))))
;read in bitplane, a byte at a time
(dotimes (y bit-height)
(dotimes (x byte-width)
(let ((abyte (read-ubyte8 file)))
(dotimes (ibit 8)
(setf (aref bitplane
y (+ (* 8 x)
ibit))
(getbit abyte ibit))))
))
bitplane)
))
)
)
)
)
(defun read-isr2-array (file)
(let ((numdims (read-ubyte16 file)))
(if (= numdims #x0FFFF)
*ptr-undefined*
(if (= numdims #x0FFFE)
*ptr-undefinable*
(let ((dimlist (make-list numdims))
array flat-array)
(do ((p dimlist (rest p)))
((null p))
(setf (first p) (read-ubyte32 file)))
(case (read-ubyte16 file)
(#.*boolean*
(setf array (make-array dimlist :element-type 'bit))
(read-bits-into-bvec file array (length array)))
(#.*real*
(setf array (make-array dimlist :element-type 'single-float))
(setf flat-array (make-array (length array)
:element-type 'single-float
:displaced-to array))
(dotimes (i (length flat-array))
(setf (aref flat-array i) (read-float32 file)))
)
(#.*int*
(setf array (make-array dimlist :element-type 'fixnum))
(setf flat-array (make-array (length array)
:element-type 'fixnum
:displaced-to array))
(dotimes (i (length flat-array))
(setf (aref flat-array i) (read-sbyte32 file)))
)
(#.*pointer*
(setf array (make-array dimlist :element-type 't))
(setf flat-array (make-array (length array)
:element-type 't
:displaced-to array))
(dotimes (i (length flat-array))
(setf (aref flat-array i) (read-isr2-sexpr-pkg
file
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
)
)
array))
)
)
)
;;;;========================= LOW LEVEL OUTPUT ====================================
(#-(or :allegro :lispworks) defsubst #+(or :allegro :lispworks) defun write-byte8 (stream value)
"write a signed or unsigned 8 bit value to the stream."
(write-byte value stream))
(#-(or :allegro :lispworks) defsubst #+(or :allegro :lispworks) defun write-byte16 (stream value)
"write a signed or unsigned 16 bit value to the stream."
(write-byte (ldb byte0 value) stream)
(write-byte (ldb byte1 value) stream)
value)
(#-(or :allegro :lispworks) defsubst #+(or :allegro :lispworks) defun write-byte32 (stream val)
"write a signed or unsigned 32 bit value to the stream."
(write-byte (ldb byte0 val) stream)
(write-byte (ldb byte1 val) stream)
(write-byte (ldb byte2 val) stream)
(write-byte (ldb byte3 val) stream)
val)
(#-(or :allegro :lispworks) defsubst #+(or :allegro :lispworks) defun write-int32 (stream val)
"write 25-bit signed integer as a 32-bit signed integer"
(write-byte (ldb byte0 val) stream)
(write-byte (ldb byte1 val) stream)
(write-byte (ldb byte2 val) stream)
(if (evenp (ldb byte3 val))
(write-byte 0 stream) ;positive
(write-byte 255 stream)) ;negative
val)
#+:lispworks
(defun write-float32 (stream flonum)
(write-byte32 stream (ub32-from-float flonum)))
#+:allegro
(defun write-float32 (stream flonum)
(setf (fl-union-float fl-union-holder) flonum)
(write-byte32 stream (fl-union-ub32 fl-union-holder))
flonum)
#-(or :allegro :lispworks)
(defun write-float32 (stream flonum)
(setf (aref fl-union-fl32 0) flonum)
(write-byte32 stream (aref fl-union-ub32 0))
flonum)
(defun write-isr2-string (file string &aux ch)
"Write a string to an ISR2 data file. The string is written as a standard
ASCII string, using C conventions: #\NEWLINE becomes ASCII LF ('\n'), #\TAB
becomes ASCII HT. Any other characters outside of the normal printable ASCII
set become spaces. A NUL byte is written after the last character. The string
is preceded by its length (plus the NUL byte) as a unsigned 16-bit byte."
(write-byte16 file (1+ (length string)))
(dotimes (i (length string))
(setf ch (aref string i))
;; force character to be a string char
(unless (typep ch 'string-char)
(setf ch (make-char ch)))
;; force character to be a "standard" ASCII character
;; (newline using C convention, preserving TABs, trashing all other
;; "funny" characters to spaces)
(cond ((eql ch #\NEWLINE) (setf ch 10)) ;; convert #\NEWLINE to LF
((eql ch #\TAB) (setf ch 9)) ;; convert #\TAB to ASCII HT
((char< ch #\space) (setf ch 32)) ;; convert all other "strange"
((char> ch #\~) (setf ch 32)) ;; chars to #\SPACE
(t (setf ch (char-code ch)))) ;; Normal character
(write-byte ch file))
;; append a null byte to the end (C convention)
(write-byte 0 file)
string)
(defun write-isr2-sexpr-pkg (file sexpr &optional (*package* *package*))
(write-isr2-string
file
(write-to-string sexpr :escape t :radix nil :base 10 :circle nil
:pretty nil :level nil :length nil :case :upcase
:gensym t :array t)))
(defun write-isr2-tss (file tss &aux frame-path evv)
(setf frame-path (frame-path (handle-frame tss))
evv (handle-token-existence-array tss))
(write-byte16 file tss-header-tag-as-16-bit-ubyte)
(write-isr2-string file frame-path)
(if (typep evv '2index-vector-vector)
(progn
(write-byte16 file #x0ffff)
(write-isr2-2vv file evv))
(progn
(write-byte16 file 0)
(write-isr2-token-list file evv))
)
tss)
(defun write-isr2-tsort (file sort &aux frame-path evv)
(setf frame-path (frame-path (handle-frame sort))
evv (handle-token-existence-array sort))
(write-byte16 file sort-header-tag-as-16-bit-ubyte)
(write-isr2-string file frame-path)
(write-isr2-string file (handle-feature sort))
(write-byte16 file (if (eq (handle-sort-order sort) :ascending) 0 #xffff))
(write-isr2-token-list file evv)
sort)
(defun write-isr2-token-list (file list)
(write-byte16 file (length list))
(dolist (tok list)
(write-byte32 file tok))
list)
(defun write-isr2-2vv (file 2vv &aux type-code)
(setf type-code (case (2index-vector-vector-resource-type 2vv)
(2index-bin-vector *boolean*)
(2index-int-vector *int*)
(2index-real-vector *real*)
(2index-ptr-vector *pointer*)
(2index-ary-vector *array*)
(2index-bp-vector *bitplane*)
(2index-extents-vector *extents*)
(2index-handle-vector *handle*)
(2index-string-vector *string*)
))
(write-byte16 file type-code)
(write-byte16 file (count-used-blocks 2vv))
(let* ((outer-vec (2index-vector-vector-data 2vv))
(max-ov (fill-pointer outer-vec))
ivec-block ivec)
(dotimes (ov max-ov)
(when (setf ivec-block (aref outer-vec ov))
(write-byte32 file (2index-vector-start-index ivec-block))
(setf ivec (2index-vector-data-vector ivec-block))
(cond ((= type-code *boolean*)
(write-bits-from-bvec file ivec *default-2index-vector-size*))
(t (dotimes (iv *default-2index-vector-size*)
(case type-code
(#.*int* (write-int32 file (aref ivec iv)))
(#.*real* (write-float32 file (aref ivec iv)))
(#.*handle* (write-isr2-handle file (aref ivec iv)))
(#.*extents* (write-isr2-extents file (aref ivec iv)))
(#.*bitplane* (write-isr2-bitplane file (aref ivec iv)))
(#.*array* (write-isr2-array file (aref ivec iv)))
(#.*string* (write-isr2-string file (aref ivec iv)))
(#.*pointer* (write-isr2-sexpr-pkg
file
(aref ivec iv)
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
))
)
)
)
)
2vv)
(defun write-partial-2vv (file exist-vect-2vv 2vv &aux type-code)
(setf type-code (case (2index-vector-vector-resource-type 2vv)
(2index-bin-vector *boolean*)
(2index-int-vector *int*)
(2index-real-vector *real*)
(2index-ptr-vector *pointer*)
(2index-ary-vector *array*)
(2index-bp-vector *bitplane*)
(2index-extents-vector *extents*)
(2index-handle-vector *handle*)
(2index-string-vector *string*)
))
(write-byte16 file type-code)
(write-byte16 file (count-used-blocks-exist 2vv exist-vect-2vv))
(let* ((outer-data-vec (2index-vector-vector-data 2vv))
(outer-exist-vec (2index-vector-vector-data exist-vect-2vv))
(max-ov (min (fill-pointer outer-data-vec)
(fill-pointer outer-exist-vec)))
ivec-data-block ivec-data ivec-exist-block ivec-exist)
(dotimes (ov max-ov)
(setf ivec-data-block (aref outer-data-vec ov))
(setf ivec-exist-block (aref outer-exist-vec ov))
(when (and ivec-data-block ivec-exist-block)
(write-byte32 file (2index-vector-start-index ivec-data-block))
(setf ivec-data (2index-vector-data-vector ivec-data-block))
(setf ivec-exist (2index-vector-data-vector ivec-exist-block))
(cond ((= type-code *boolean*)
(write-bits-from-bvec-logand
file ivec-exist
ivec-data *default-2index-vector-size*))
(t (dotimes (iv *default-2index-vector-size*)
(case type-code
(#.*int* (write-int32
file
(if (= (aref ivec-exist iv) 1)
(aref ivec-data iv)
*int-undefined*)))
(#.*real* (write-float32
file
(if (= (aref ivec-exist iv) 1)
(aref ivec-data iv)
*real-undefined*)))
(#.*handle* (write-isr2-handle
file
(if (= (aref ivec-exist iv) 1)
(aref ivec-data iv)
*ptr-undefined*)))
(#.*extents* (write-isr2-extents
file
(if (= (aref ivec-exist iv) 1)
(aref ivec-data iv)
*ptr-undefined*)))
(#.*bitplane* (write-isr2-bitplane
file
(if (= (aref ivec-exist iv) 1)
(aref ivec-data iv)
*ptr-undefined*)))
(#.*array* (write-isr2-array
file
(if (= (aref ivec-exist iv) 1)
(aref ivec-data iv)
*ptr-undefined*)))
(#.*string* (write-isr2-sexpr-pkg
file
(if (= (aref ivec-exist iv) 1)
(aref ivec-data iv)
*ptr-undefined*)
(find-package (if (= *file-version-number* 0) 'user 'isr2))))
(#.*pointer* (write-isr2-sexpr-pkg
file
(if (= (aref ivec-exist iv) 1)
(aref ivec-data iv)
*ptr-undefined*)
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
))
)
)
)
)
2vv)
(defun count-used-blocks (2vv)
(let* ((outer-vec (2index-vector-vector-data 2vv))
(max-ov (fill-pointer outer-vec))
(blocks 0))
(dotimes (ov max-ov)
(when (aref outer-vec ov)
(incf blocks)))
blocks)
)
(defun count-used-blocks-exist (2vv e2vv)
(let* ((outer-vec (2index-vector-vector-data 2vv))
(outer-evec (2index-vector-vector-data e2vv))
(max-ov (min (fill-pointer outer-vec) (fill-pointer outer-evec)))
(blocks 0))
(dotimes (ov max-ov)
(when (and (aref outer-vec ov) (aref outer-evec ov))
(incf blocks)))
blocks)
)
(defun make-handle-path-into-string (path-list &aux (result ""))
(dolist (elt path-list)
(if (or (char= (aref elt 0) #\<)
(= (length result) 0)
(char= (aref result (1- (length result))) #\>))
(setf result (concatenate 'string result elt))
(setf result (concatenate 'string result "$" elt)))
)
result)
(defun write-isr2-handle (file handle)
; For reasons's I don't understand, handles get corrupted and stored in single element
; lists, this hack helps. Ross 10/28/91
(if (typep handle 'cons) (setf handle (handle handle)))
(cond ((and (handle-p handle)
(eq (handle-type handle) :token-subset))
(write-isr2-tss file handle))
((and (handle-p handle)
(eq (handle-type handle) :token-sort))
(write-isr2-tsort file handle))
(t (write-isr2-sexpr-pkg file (if (member handle
`(,*ptr-undefined* ,*ptr-undefinable*))
handle
(make-handle-path-into-string
(handle-canonical-path handle)))
(find-package (if (= *file-version-number* 0) 'user 'isr2))))
)
handle)
(defun write-isr2-extents (file extents)
(if (eq extents *ptr-undefined*)
(write-byte32 file 0)
(if (eq extents *ptr-undefinable*)
(write-byte32 file MAXINT32)
(if (zerop (extents-pixel-count extents))
(write-byte32 file 0)
(progn
(write-byte32 file (extents-pixel-count extents))
(write-byte16 file (extents-minx extents))
(write-byte16 file (extents-miny extents))
(write-byte16 file (extents-maxx extents))
(write-byte16 file (extents-maxy extents))))))
extents)
(defun write-isr2-bitplane (file bitplane)
(if (eq bitplane *ptr-undefined*)
(write-byte32 file 0)
(if (eq bitplane *ptr-undefinable*)
(write-byte32 file MAXINT32)
(let* ((bit-height (array-dimension bitplane 0))
(bit-width (array-dimension bitplane 1))
(byte-width (ceiling bit-width 8))
(numbytes (* bit-height byte-width))
)
(if (zerop numbytes)
(write-byte32 file 0)
(progn
(write-byte32 file numbytes)
(write-byte16 file bit-width)
(write-byte16 file bit-height)
(write-bits-from-bvec file bitplane (* numbytes 8)))))))
bitplane)
#-(or :allegro :lispworks)
(defun write-bits-from-bvec (file vec size &aux byte-vec)
(setf byte-vec (make-array (ceiling size 8) :element-type '(unsigned-byte 8)
:displaced-to vec))
(dotimes (ib (ceiling size 8))
(write-byte8 file (aref byte-vec ib)))
vec)
#+(or :allegro :lispworks)
(defun write-bits-from-bvec (file vec size &aux flat-bits)
(setf flat-bits (make-array size :element-type 'bit :displaced-to vec))
(dotimes (ib (ceiling size 8))
(let ((abyte 0))
(dotimes (ibit 8)
(setbit abyte ibit (aref flat-bits (+ (* ib 8) ibit)))
)
(write-byte8 file abyte))
)
vec)
#-(or :allegro :lispworks)
(defun write-bits-from-bvec-logand (file mask-vec vec size
&aux mask-byte-vec byte-vec)
(setf mask-byte-vec (make-array (ceiling size 8) :element-type '(unsigned-byte 8)
:displaced-to mask-vec))
(setf byte-vec (make-array (ceiling size 8) :element-type '(unsigned-byte 8)
:displaced-to vec))
(dotimes (ib (ceiling size 8))
(write-byte8 file (logand (aref mask-byte-vec ib)
(aref byte-vec ib))))
vec)
#+(or :allegro :lispworks)
(defun write-bits-from-bvec-logand (file mask-vec vec size
&aux mask-flat-bits flat-bits)
(setf mask-flat-bits (make-array size :element-type 'bit
:displaced-to mask-vec))
(setf flat-bits (make-array size :element-type 'bit
:displaced-to vec))
(dotimes (ib (ceiling size 8))
(let ((abyte 0))
(dotimes (ibit 8)
(unless (zerop (aref mask-flat-bits (+ (* ib 8) ibit)))
(setbit abyte ibit (aref flat-bits (+ (* ib 8) ibit)))
))
(write-byte8 file abyte)))
vec)
(defun write-isr2-array (file array)
(if (eq array *ptr-undefined*)
(write-byte16 file #xFFFF)
(if (eq array *ptr-undefinable*)
(write-byte16 file #xFFFE)
(let* ((dimlist (array-dimensions array))
(numdims (length dimlist))
flat-array array-elt-count)
(write-byte16 file numdims)
(dolist (d dimlist)
(write-byte32 file d))
(setf flat-array (make-array (length array)
:element-type (array-element-type array)
:displaced-to array)
array-elt-count (array-dimension flat-array 0))
(case (array-element-type flat-array)
(bit (write-byte16 file *boolean*)
(write-bits-from-bvec file array (length array)))
(single-float
(write-byte16 file *real*)
(dotimes (i array-elt-count)
(write-float32 file (aref flat-array i))))
(fixnum
(write-byte16 file *int*)
(dotimes (i array-elt-count)
(write-int32 file (aref flat-array i))))
(t (write-byte16 file *pointer*)
(dotimes (i array-elt-count)
(write-isr2-sexpr-pkg
file
(aref flat-array i)
(find-package (if (= *file-version-number* 0)
'user 'isr2)))))
)
)
))
array)
(defun isect-2vv (real-2vv-bit tss)
(let ((new-2vv (make-2index-vector-vector 0)))
(cond ((null tss) nil)
((and (handle-p tss) (eq (handle-type tss) :token-subset))
(logand-isect-into real-2vv-bit
(handle-token-existence-array tss)
new-2vv))
(t (error "Not a legal token subset: ~S" tss)))
new-2vv)
)
(defun logand-isect-into (real-2vv-bit tss-ea new-2vv)
(if (typep tss-ea '2index-vector-vector)
(let* ((real-outer-vector (2index-vector-vector-data real-2vv-bit))
(new-outer-vector (2index-vector-vector-data new-2vv))
(tss-outer-vector (2index-vector-vector-data tss-ea))
(real-fill-pointer (fill-pointer real-outer-vector))
(tss-fill-pointer (fill-pointer tss-outer-vector))
real-inner-vector real-iv
new-inner-vector new-iv
tss-inner-vector tss-iv
)
(dotimes (ov (min tss-fill-pointer real-fill-pointer))
(vector-push-extend nil new-outer-vector)
(when (and (setf tss-inner-vector (aref tss-outer-vector ov))
(setf real-inner-vector (aref real-outer-vector ov)))
(setf new-inner-vector
(allocate-resource
'2index-bin-vector
(* ov *default-2index-vector-size*))
(aref new-outer-vector ov) new-inner-vector
tss-iv (2index-vector-data-vector tss-inner-vector)
real-iv (2index-vector-data-vector real-inner-vector)
new-iv (2index-vector-data-vector new-inner-vector))
(dotimes (iv *default-2index-vector-size*)
(setf (aref new-iv iv)
(logand (aref real-iv iv)
(aref tss-iv iv))))
)
)
)
(map nil #'(lambda (index)
(when (= (vvref real-2vv-bit index) 1)
(setf (vvref new-2vv index) 1)))
tss-ea)
)
new-2vv)
(defun isect-2vv-fval (real-2vv tss)
(let ((new-2vv (make-2index-vector-vector
(case (2index-vector-vector-resource-type real-2vv)
(2index-bin-vector *boolean*)
(2index-int-vector *int*)
(2index-real-vector *real*)
(2index-ptr-vector *pointer*)
(2index-ary-vector *array*)
(2index-bp-vector *bitplane*)
(2index-extents-vector *extents*)
(2index-handle-vector *handle*)
(2index-string-vector *string*)
))))
(cond ((null tss) nil)
((and (handle-p tss) (eq (handle-type tss) :token-subset))
(if-bit-isect-into real-2vv
(handle-token-existence-array tss)
new-2vv))
(t (error "Not a legal token subset: ~S" tss)))
new-2vv)
)
(defun if-bit-isect-into (real-2vv tss-ea new-2vv)
(if (typep tss-ea '2index-vector-vector)
(let* ((real-outer-vector (2index-vector-vector-data real-2vv))
(new-outer-vector (2index-vector-vector-data new-2vv))
(tss-outer-vector (2index-vector-vector-data tss-ea))
(real-fill-pointer (fill-pointer real-outer-vector))
(tss-fill-pointer (fill-pointer tss-outer-vector))
real-inner-vector real-iv
new-inner-vector new-iv
tss-inner-vector tss-iv
)
(dotimes (ov (min tss-fill-pointer real-fill-pointer))
(vector-push-extend nil new-outer-vector)
(when (and (setf tss-inner-vector (aref tss-outer-vector ov))
(setf real-inner-vector (aref real-outer-vector ov)))
(setf new-inner-vector
(allocate-resource
'2index-bin-vector
(* ov *default-2index-vector-size*))
(aref new-outer-vector ov) new-inner-vector
tss-iv (2index-vector-data-vector tss-inner-vector)
real-iv (2index-vector-data-vector real-inner-vector)
new-iv (2index-vector-data-vector new-inner-vector))
(dotimes (iv *default-2index-vector-size*)
(when (= (aref tss-iv iv) 1)
(setf (aref new-iv iv)
(aref real-iv iv)
)))
)
)
)
(map nil #'(lambda (index)
(setf (vvref new-2vv index)
(vvref real-2vv index)))
tss-ea)
)
new-2vv)
(defun free-2vv (evv)
(when (typep evv '2index-vector-vector)
(with-lock ((2index-vector-vector-lock evv))
(let* ((outer-vect (2index-vector-vector-data evv))
(ov-size (fill-pointer outer-vect))
ivect)
(dotimes (ov ov-size)
(setf ivect (aref outer-vect ov))
(when ivect
(deallocate-resource
(type-of ivect) ivect)
(setf (aref outer-vect ov) nil)
))
)
)
)
nil)
(defun select-frame-features (flist falist)
(do ((feature flist (rest feature))
(result nil)
temp fdescr)
((null feature) (nreverse result))
(setf temp (parse-token-name (first feature)))
(cond ((and (null (rest temp))
(setf fdescr (assoc (first temp)
falist
:test #'equalp)))
(push (rest fdescr) result))
((null (rest temp))
(warn "~&Undefined frame feature \"~A\" NOT written to file"
(first temp)))
(t t))
)
)
(defun select-token-features (flist fvector)
(do ((feature flist (rest feature))
(result nil)
temp fdescr)
((null feature) (nreverse result))
(setf temp (parse-token-name (first feature)))
(cond ((and (rest temp)
(eq (first temp) :?)
(setf fdescr (member (second temp)
fvector
:test #'equalp
:key #'fdescr-featurename)))
(push (first fdescr) result))
((and (rest temp) (eq (first temp) :?))
(warn "~&Undefined token feature \"<?>~A\" NOT written to file"
(second temp)))
(t t))
)
)
(defun merge-bit-vectors (in-2vv-bit out-2vv-bit)
(do-active-tokens (tindex in-2vv-bit)
(setf (vvref out-2vv-bit tindex) 1)))
(defun make-stub-frame (parsed-path docstring sources &aux handle more-path)
(multiple-value-setq (handle more-path)
(make-handle-from-parsed-path parsed-path))
(unless (and handle
(handle-p handle)
(check-terminal-path handle more-path)
(eq (handle-type handle) :frame))
(error "Bogus sub-frame path ~S: " parsed-path))
(when (and more-path (null (rest more-path)) (stringp (first more-path))
(not (string= (subseq (first more-path) 0 2) "F_")))
(let* ((new-frame-name (first more-path))
(new-frame (make-frame new-frame-name
:parent (copy-handle handle)
:documentation docstring))
(new-frame-handle (make-handle :type :frame :frame new-frame))
(fdescr (make-fdescr :type *handle*
:featurename new-frame-name
:docstring docstring
:value new-frame-handle
:if-needed (list 'isr2::default-if-needed-function)
:if-getting nil
:if-setting nil))
)
(setf (frame-feature-alist (handle-frame handle))
(acons new-frame-name fdescr
(frame-feature-alist (handle-frame handle)))
(frame-is-loaded-p new-frame) nil
(frame-source-file-list new-frame) sources)
new-frame-handle)
)
)
(defvar *stub-frame-reference-action* :ask-user
"Action to take if a stub frame is referenced")
(defun check-load-stub-frame (frame-handle)
(unless (member *stub-frame-reference-action*
'(:ask-user :ask-user-always :error :load))
(warn "The variable ISR2::*STUB-FRAME-REFERENCE-ACTION* has been munged.~
~%Reseting to :ASK-USER")
(setf *stub-frame-reference-action* :ask-user))
(case *stub-frame-reference-action*
(:load (read-sub-frame frame-handle nil (frame-documentation
(handle-frame frame-handle))
(frame-source-file-list
(handle-frame frame-handle))
:sub-frame-action :load))
(:ask-user-always
(cond
((yes-or-no-p "Reference to frame ~S, which is not loaded - load?"
frame-handle)
(read-sub-frame frame-handle nil (frame-documentation
(handle-frame frame-handle))
(frame-source-file-list
(handle-frame frame-handle))
:sub-frame-action :ask-user-always))
(t (error "Reference to frame ~S, which is not loaded"
frame-handle))))
(:ask-user
(cond
((yes-or-no-p "Reference to frame ~S, which is not loaded - load?"
frame-handle)
(read-sub-frame frame-handle nil (frame-documentation
(handle-frame frame-handle))
(frame-source-file-list
(handle-frame frame-handle))
:sub-frame-action :ask-user))
(t (error "Reference to frame ~S, which is not loaded"
frame-handle))))
(:error (error "Reference to frame ~S, which is not loaded"
frame-handle)))
)
(defvar *global-filename-variable* nil "needed by w:choose-variable-values")
(defvar *global-directory-search-list* nil "list of directories to search through")
(defun check-file (ignore1 ignore2 ignore3 filename)
(declare (ignore ignore1 ignore2 ignore3))
(unless (probe-file filename)
(format nil "file ~a not found" filename)))
(defun search-for-file-choices (filename-list &aux pathnames)
(dolist (directory (append filename-list *global-directory-search-list*))
(dolist (filename filename-list)
(let* ((filepathname (pathname filename))
(filestring (format nil "~a.~a" (pathname-name filepathname) (pathname-type filepathname))))
(let ((path (merge-pathnames filestring directory nil)))
(dolist (file (reverse (directory-safe path))) ;;so they come in reverse version order
(pushnew file pathnames :test #'equalp))))))
(reverse pathnames))
;;; This is Ross's addition, attempting to avoid error of searching directories that no longer exist.
(defun directory-safe (pathname)
"
Unlike the default verions provided by TI, this directory command checks with
probe and does not attempt to open non-existent files/directories.
"
(if (probe-file pathname)
(directory pathname)
nil)
)
(defun get-file-date-string (pathname)
(let ((file-date (file-write-date pathname)))
(if file-date
(multiple-value-bind (second minute hour date month year day-of-week)
(decode-universal-time file-date)
(format nil "~[Mon~;Tue~;Wed~;Thu~;Fri~;Sat~;Sun~] ~[Jan~;Feb~;Mar~;Apr~;May~;Jun~;Jul~;Aug~;Sep~;Oct~;Nov~;Dec~] ~d,~d ~2,'0d:~2,'0d:~2,'0d"
day-of-week (1- month) date year hour minute second))
"")))
(defun format-file-choice-list (filename-list sub-frame-action)
(mapcar #'(lambda (path)
(list (format nil "~a (~a)" path
(get-file-date-string path))
:value
path))
(search-for-file-choices filename-list)))
#+:EXPLORER
;;WE MAY AT SOME POINT WANT TO MAKE FILENAME-DEFAULT GET ITS VALUE FROM A GLOBAL VARIABLE
(defun enter-file-name (&optional (filename-default nil))
(setf *global-filename-variable* filename-default)
(w:choose-variable-values
`((*global-filename-variable* "Pathname"
:documentation "right button to edit, left button to enter from scratch"
:constraint check-file
:pathname ,filename-default))
:extra-width 40 ;leave space so name can get bigger
:label "Enter New Pathname")
*global-filename-variable*)
#+:EXPLORER
(defun menu-choose-source-file (source-file-list menu-label &OPTIONAL (sub-frame-action :ask-user))
(unless (listp source-file-list) (setf source-file-list (list source-file-list)))
(let ((choice-list (format-file-choice-list source-file-list sub-frame-action)))
(if (null choice-list)
(enter-file-name (car source-file-list)) ;ENTER FILENAME FROM SCRATCH IF NO PREDEFINED CHOICES
(do ((choice nil))
(choice (if (eq choice :newpath) (enter-file-name (car source-file-list)) choice))
(setf choice
(w::menu-choose ;CHOOSE FILENAME FROM MENU
(cons '("<<Enter new pathname>>" . :newpath) choice-list)
:label menu-label))))))
#-:EXPLORER
(defun menu-choose-source-file (source-file-list menu-label &OPTIONAL (sub-frame-action :ask-user))
(unless (listp source-file-list) (setf source-file-list (list source-file-list)))
(let ((choice-list (format-file-choice-list source-file-list sub-frame-action)))
(if (null choice-list)
(enter-file-name (car source-file-list)) ;ENTER FILENAME FROM SCRATCH IF NO PREDEFINED CHOICES
(do ((choice nil))
(choice (if (eq choice :newpath) (enter-file-name (car source-file-list)) choice))
(setf choice
(tty33-menu-choose ;CHOOSE FILENAME FROM MENU
(cons '("<<Enter new pathname>>" . :newpath) choice-list)
:label menu-label))))))
#-:EXPLORER
;;WE MAY AT SOME POINT WANT TO MAKE FILENAME-DEFAULT GET ITS VALUE FROM A GLOBAL VARIABLE
(defun enter-file-name (&optional (filename-default
*default-pathname-defaults*))
(setf filename-default (pathname filename-default))
(do ((filename nil)) (filename filename)
(format *query-io* "~&Enter filename [~A]: " filename-default)
(setf filename (namestring (merge-pathnames (read-line *query-io*)
filename-default)))
(unless (probe-file filename)
(format *query-io* "~&File not accessable: ~A" filename)
(setf filename-default (pathname filename) filename nil))
)
)
#-:EXPLORER
(defun tty33-menu-choose (choices &key (label "Select from"))
(do ((ichoice nil)(answer ""))
(ichoice (let ((choice (elt choices ichoice)))
(or (getf (rest choice) :value)
(rest choice))))
(format *query-io* "~&~A:" label)
(dotimes (i (length choices))
(format *query-io* "~&~2T~d) ~A" i (first (elt choices i))))
(format *query-io* "~&Enter a number between 0 and ~D: "
(1- (length choices)))
(setf ichoice (parse-integer (setf answer (read-line *query-io*))
:junk-allowed t
:radix #x0a))
(unless (and ichoice (>= ichoice 0) (< ichoice (length choices)))
(format *query-io* "~&*** Bad input ~S, try again" answer)
(setf ichoice nil))
)
)
(defun ask-user-for-source-files-to-load (new-path old-path docstring source-list &OPTIONAL (sub-frame-action :ask-user))
(list (menu-choose-source-file source-list
(format nil "Select source file for frame path ~S (old path ~S)~%~A"
new-path old-path docstring)
sub-frame-action)))
(defun read-sub-frame (parsed-path old-path docstring sources &key sub-frame-action parent-path &aux
new-path)
(setf new-path parsed-path)
(do ()
((and (handle-p new-path) (handle-p parsed-path))
t)
(multiple-value-bind (h m) (make-handle-from-parsed-path
parsed-path)
(cond ((null m)
(cond ((not (eq (handle-type h) :frame))
(setf new-path (create parsed-path))
(multiple-value-setq (h m) (make-handle-from-parsed-path
parsed-path)
)
)
(t (setf new-path h)))
)
(t (setf new-path (create parsed-path))
(multiple-value-setq (h m) (make-handle-from-parsed-path
parsed-path)
))
)
(setf parsed-path (cond ((and (handle-p h) (eq (handle-type h) :token-feature))
parsed-path)
((null m) h)
(t (cons h m)))))
)
#|
(setf sources (find-sources-from-public-data-base (or old-path new-path)
docstring
(if (member sub-frame-action '(:ask-user :ask-user-always)))))
|#
(when (member sub-frame-action '(:ask-user :ask-user-always))
(setf sources (ask-user-for-source-files-to-load new-path old-path
docstring sources sub-frame-action))
)
; Bob, Bruce and Ross Drastically simplified this now that read-frame
; Will prompt user for valid file!
(dolist (file sources)
(when parent-path
(setf file (make-pathname :name (pathname-name file) :type (pathname-type file)
:defaults parent-path)))
(read-frame new-path file :all :all :merge-p t
:sub-frame-action sub-frame-action
; (if interact-p :ask-user :load) ;; ADDED THIS LINE 7/31/90 JRB
:merge-overlap-action :new))
)
(defun write-frame (frame-path filename features tss &optional
frame-source-file-replace)
"WRITE-FRAME frame-path filename features tss &OPTIONAL frame-source-file-replace -
Writes out the frame specified by frame-path out to the file named by
filename. If features is :ALL, all token features are written, otherwise
only the token features specified in the list features are written. If tss
is :ALL, all tokens are written, otherwise only the tokens in tss are written.
If frame-source-file-replace is non-NIL, the frame's source file is replaced
with the filename specified (illegal if either features or tss is not :ALL),
otherwise the filename is *added* to the list of previous source file names."
(let ((frame (%internal-handle frame-path :error-p nil :terminal-p t))
sourcefiles
frame-pointer)
(unless (and frame
(handle-p frame)
(eq (handle-type frame) :frame))
(error "Not a frame: ~S!" frame-path))
(setf frame-pointer (handle-frame frame))
(when frame-source-file-replace
(unless (and (eq features :all) (eq tss :all))
(error "Cannot replace source file when only saving a partial frame: ~S"
frame-path)))
(with-open-isr2-frame-file (frame-stream filename :output)
(setf sourcefiles (cons (namestring
(truename frame-stream))
(if frame-source-file-replace
nil
(frame-source-file-list
frame-pointer))))
(setf (frame-source-file-list frame-pointer) sourcefiles)
(write-isr2-header frame-stream)
(write-isr2-string frame-stream (frame-name frame-pointer))
(write-isr2-string frame-stream (frame-documentation frame-pointer))
(write-byte16 frame-stream (length sourcefiles))
(map nil #'(lambda (s) (write-isr2-string frame-stream s))
sourcefiles)
(write-isr2-string frame-stream (frame-path frame-pointer))
(let ((decendants (sort-by-tree-depth (find-all-decendants frame))))
(write-byte16 frame-stream (length decendants))
(map nil #'(lambda (fh)
(write-isr2-string
frame-stream
(frame-path (handle-frame fh)))
(write-isr2-string
frame-stream
(frame-documentation
(handle-frame fh)))
(write-isr2-sexpr-pkg
frame-stream
(frame-source-file-list
(handle-frame fh))
(find-package (if (= *file-version-number* 0) 'user 'isr2))))
decendants)
)
(let ((exist-intersect (if (eq tss :all)
(frame-token-set-existence-vector
frame-pointer)
(isect-2vv (frame-token-set-existence-vector
frame-pointer)
tss)))
(globalp-intersect (if (eq tss :all)
(frame-token-set-globalp-vector
frame-pointer)
(isect-2vv (frame-token-set-globalp-vector
frame-pointer)
tss)))
)
(write-isr2-2vv frame-stream exist-intersect)
(write-isr2-2vv frame-stream globalp-intersect)
(let ((frame-feature-list
(if (eq features :all)
(mapcar #'rest (frame-feature-alist frame-pointer))
(select-frame-features
features
(frame-feature-alist frame-pointer)))))
(write-byte16 frame-stream (length frame-feature-list))
(dolist (fdescr frame-feature-list)
(write-isr2-string frame-stream
(fdescr-featurename fdescr))
(write-isr2-string frame-stream
(fdescr-docstring fdescr))
(write-byte16 frame-stream
(fdescr-type fdescr))
(write-byte16 frame-stream
(length (fdescr-if-needed fdescr)))
(dolist (fn (fdescr-if-needed fdescr))
(write-isr2-sexpr-pkg
frame-stream
fn
(find-package (if (= *file-version-number* 0) 'user 'isr2))))
(write-byte16 frame-stream
(length (fdescr-if-setting fdescr)))
(dolist (fn (fdescr-if-setting fdescr))
(write-isr2-sexpr-pkg
frame-stream
fn
(find-package (if (= *file-version-number* 0) 'user 'isr2))))
(write-byte16 frame-stream
(length (fdescr-if-getting fdescr)))
(dolist (fn (fdescr-if-getting fdescr))
(write-isr2-sexpr-pkg
frame-stream
fn
(find-package (if (= *file-version-number* 0) 'user 'isr2))))
(case (fdescr-type fdescr)
((#.*boolean* #.*int*)
(write-int32 frame-stream (fdescr-value fdescr)))
(#.*real*
(write-float32 frame-stream (fdescr-value fdescr)))
(#.*handle*
(write-isr2-handle frame-stream
(fdescr-value fdescr)))
(#.*extents*
(write-isr2-extents frame-stream
(fdescr-value fdescr)))
(#.*bitplane*
(write-isr2-bitplane frame-stream
(fdescr-value fdescr)))
(#.*array*
(write-isr2-array frame-stream
(fdescr-value fdescr)))
(#.*string*
(write-isr2-sexpr-pkg
frame-stream
(fdescr-value fdescr)
(find-package (if (= *file-version-number* 0) 'user 'isr2))))
(#.*pointer*
(write-isr2-sexpr-pkg
frame-stream
(fdescr-value fdescr)
(find-package (if (= *file-version-number* 0) 'user 'isr2))))
)
)
)
(let ((token-feature-list
(if (eq features :all)
(frame-token-set-feature-vector frame-pointer)
(select-token-features
features
(frame-token-set-feature-vector frame-pointer))
))
)
(write-byte16 frame-stream (length token-feature-list))
(dolist (fdescr token-feature-list)
(write-isr2-string frame-stream
(fdescr-featurename fdescr))
(write-isr2-string frame-stream
(fdescr-docstring fdescr))
(write-byte16 frame-stream
(fdescr-type fdescr))
(write-byte16 frame-stream
(length (fdescr-if-needed fdescr)))
(dolist (fn (fdescr-if-needed fdescr))
(write-isr2-sexpr-pkg
frame-stream
fn
(find-package (if (= *file-version-number* 0) 'user 'isr2))))
(write-byte16 frame-stream
(length (fdescr-if-setting fdescr)))
(dolist (fn (fdescr-if-setting fdescr))
(write-isr2-sexpr-pkg
frame-stream
fn
(find-package (if (= *file-version-number* 0) 'user 'isr2))))
(write-byte16 frame-stream
(length (fdescr-if-getting fdescr)))
(dolist (fn (fdescr-if-getting fdescr))
(write-isr2-sexpr-pkg
frame-stream
fn
(find-package (if (= *file-version-number* 0) 'user 'isr2))))
(write-partial-2vv frame-stream
exist-intersect
(fdescr-value fdescr))
)
)
(unless (eq tss :all) (free-2vv exist-intersect))
(unless (eq tss :all) (free-2vv globalp-intersect))
)
(namestring (truename frame-stream))
)
)
)
(defun read-in-decendants (frame-stream sub-frame-action &OPTIONAL (parent-path nil))
(when (eq sub-frame-action :ask-user)
(push frame-stream *global-directory-search-list*))
(let (decendant-path decendant-doc decendant-sources dec-parsed-path
dec-handle dec-more-path)
(prog1
(dotimes (i (read-ubyte16 frame-stream))
(setf decendant-path (read-isr2-string frame-stream)
decendant-doc (read-isr2-string frame-stream)
decendant-sources (read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2)))
dec-parsed-path (adjust-path (parse-token-name decendant-path)))
(multiple-value-setq (dec-handle dec-more-path)
(make-handle-from-parsed-path dec-parsed-path))
(unless (and (handle-p dec-handle)
(null dec-more-path)
(eq (handle-type dec-handle) :frame)
(frame-is-loaded-p (handle-frame dec-handle))
)
(case sub-frame-action
(:stub (make-stub-frame (cons dec-handle dec-more-path)
decendant-doc decendant-sources))
(:error (error "Unloaded sub frame: ~S"
(cons dec-handle dec-more-path)))
(:load (read-sub-frame (cons dec-handle dec-more-path)
decendant-path
decendant-doc
decendant-sources
:sub-frame-action sub-frame-action)
)
(:inherit-path (read-sub-frame (cons dec-handle dec-more-path)
decendant-path
decendant-doc
decendant-sources
:sub-frame-action sub-frame-action
:parent-path parent-path))
(:ask-user-always (read-sub-frame (cons dec-handle dec-more-path)
decendant-path
decendant-doc
decendant-sources
:sub-frame-action sub-frame-action))
(:ask-user (read-sub-frame (cons dec-handle dec-more-path)
decendant-path
decendant-doc
decendant-sources
:sub-frame-action sub-frame-action)))))
(when (member sub-frame-action '(:ask-user :ask-user-always))
(pop *global-directory-search-list*)))))
(defun read-in-token-features (frame-stream frame-pointer
exist-bit-vector merge-overlap-action
new-frame-p features tss)
(let (fname fdoc ftype f-if-needed f-if-getting f-if-setting
fvalue)
#|(declare (special fname fdoc ftype f-if-needed f-if-getting f-if-setting
fvalue))|#
(dotimes (i (read-ubyte16 frame-stream))
#|(declare (special i))|#
(setf fname (read-isr2-string frame-stream)
fdoc (read-isr2-string frame-stream)
ftype (read-ubyte16 frame-stream)
f-if-needed (make-list (read-ubyte16 frame-stream)))
(do ((p f-if-needed (rest p)))
((null p))
(setf (first p)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
(setf f-if-setting (make-list (read-ubyte16 frame-stream)))
(do ((p f-if-setting (rest p)))
((null p))
(setf (first p)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
(setf f-if-getting (make-list (read-ubyte16 frame-stream)))
(do ((p f-if-getting (rest p)))
((null p))
(setf (first p)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
(let ((temp-fvalue (read-isr2-2vv frame-stream)))
#|(declare (special temp-fvalue))|#
(if (eq tss :all)
(setf fvalue temp-fvalue)
(progn
(setf fvalue (isect-2vv-fval temp-fvalue tss))
(free-2vv temp-fvalue))))
(if (or (eq features :all)
(member fname features
:test #'equalp
:key #'(lambda (fn &aux (pfn (parse-token-name fn)))
(if (eq (first pfn) :?)
(second pfn)
nil))))
(if new-frame-p
(pushnew (make-fdescr
:featurename fname
:docstring fdoc
:type ftype
:if-needed f-if-needed
:if-getting f-if-getting
:if-setting f-if-setting
:value fvalue)
(frame-token-set-feature-vector frame-pointer)
:test #'equalp)
(let ((old-fdescr (member fname
(frame-token-set-feature-vector
frame-pointer)
:test #'equalp
:key #'fdescr-featurename)))
(if (null old-fdescr)
(setf (frame-token-set-feature-vector frame-pointer)
(cons (make-fdescr
:featurename fname
:docstring fdoc
:type ftype
:if-needed f-if-needed
:if-getting f-if-getting
:if-setting f-if-setting
:value fvalue)
(frame-token-set-feature-vector frame-pointer)))
(progn
(setf old-fdescr (first old-fdescr))
(unless (= ftype (fdescr-type old-fdescr))
(error
"Token feature type mismatch, feature=~A old=~A, new=~A"
fname
(elt *type-names*
(fdescr-type old-fdescr))
(elt *type-names* ftype)))
(let (old-tok-f-value new-tok-f-value)
(do-active-tokens (tindex exist-bit-vector)
(setf old-tok-f-value (vvref (fdescr-value
old-fdescr)
tindex)
new-tok-f-value (vvref fvalue
tindex))
(if (or (equalp old-tok-f-value
(cond ((= ftype *int*)
*int-undefined*)
((= ftype *real*)
*real-undefined*)
(t *ptr-undefined*)))
(and (= ftype *handle*)
(handle-p new-tok-f-value)
(handle-p old-tok-f-value)
(equalp new-tok-f-value
old-tok-f-value)))
(setf (vvref
(fdescr-value old-fdescr)
tindex)
new-tok-f-value)
(unless (equalp new-tok-f-value
(cond ((= ftype *int*)
*int-undefined*)
((= ftype *real*)
*real-undefined*)
(t *ptr-undefined*
)))
(case merge-overlap-action
(:error
(error "Merge overlap - token feature ~A, for token ~D"
fname tindex))
(:old t)
(:new (setf (vvref
(fdescr-value
old-fdescr)
tindex)
new-tok-f-value))
(:warn-new
(warn "~&Replacing value of token feature ~A; token ~D, old value was ~S, new value is ~S"
fname tindex
old-tok-f-value
new-tok-f-value)
(setf (vvref
(fdescr-value
old-fdescr)
tindex)
new-tok-f-value)
)
(:ask-user
(when
(yes-or-no-p
"Replace value of token feature ~A; token ~D, old value was ~S, new value is ~S?"
fname tindex
old-tok-f-value
new-tok-f-value)
(setf (vvref
(fdescr-value
old-fdescr)
tindex)
new-tok-f-value)
))
)
)
)
)
)
(free-2vv fvalue)
)
)
)
)
(free-2vv fvalue)
)
)
)
)
(defun read-in-frame-features (frame-stream frame-pointer merge-overlap-action
new-frame-p features)
(let (fname fdoc ftype f-if-needed f-if-getting f-if-setting
fvalue)
(dotimes (i (read-ubyte16 frame-stream))
(setf fname (read-isr2-string frame-stream)
fdoc (read-isr2-string frame-stream)
ftype (read-ubyte16 frame-stream)
f-if-needed (make-list (read-ubyte16 frame-stream)))
(do ((p f-if-needed (rest p)))
((null p))
(setf (first p)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
(setf f-if-setting (make-list (read-ubyte16 frame-stream)))
(do ((p f-if-setting (rest p)))
((null p))
(setf (first p)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
(setf f-if-getting (make-list (read-ubyte16 frame-stream)))
(do ((p f-if-getting (rest p)))
((null p))
(setf (first p)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
(setf fvalue
(case ftype
((#.*boolean* #.*int*)
(read-sbyte32 frame-stream))
(#.*real*
(read-float32 frame-stream))
(#.*handle*
(read-isr2-handle frame-stream))
(#.*extents*
(read-isr2-extents frame-stream))
(#.*bitplane*
(read-isr2-bitplane frame-stream))
(#.*array*
(read-isr2-array frame-stream))
((#.*string* #.*pointer*)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2))))))
(when (or (eq features :all)
(member fname features
:test #'equalp
:key #'(lambda (fn)
(first (parse-token-name fn)))))
(if new-frame-p
(pushnew (cons fname
(make-fdescr
:featurename fname
:docstring fdoc
:type ftype
:if-needed f-if-needed
:if-getting f-if-getting
:if-setting f-if-setting
:value fvalue))
(frame-feature-alist frame-pointer)
:test #'equalp)
(let ((old-fdescr (assoc fname
(frame-feature-alist
frame-pointer)
:test #'equalp)))
(if (null old-fdescr)
(setf (frame-feature-alist frame-pointer)
(acons fname
(make-fdescr
:featurename fname
:docstring fdoc
:type ftype
:if-needed f-if-needed
:if-getting f-if-getting
:if-setting f-if-setting
:value fvalue)
(frame-feature-alist frame-pointer)))
(progn
(setf old-fdescr (rest old-fdescr))
(unless (= ftype (fdescr-type old-fdescr))
(error
"Frame feature type mismatch, feature=~A old=~A, new=~A"
fname
(elt *type-names*
(fdescr-type old-fdescr))
(elt *type-names* ftype)))
(if (or (equalp (fdescr-value old-fdescr)
(cond ((= ftype *int*) *int-undefined*)
((= ftype *real*) *real-undefined*)
(t *ptr-undefined*)))
(and (= ftype *handle*)
(handle-p fvalue)
(handle-p (fdescr-value old-fdescr))
(equalp fvalue (fdescr-value old-fdescr))))
(setf (fdescr-value old-fdescr) fvalue)
(unless (equalp fvalue
(cond ((= ftype *int*) *int-undefined*)
((= ftype *real*) *real-undefined*)
(t *ptr-undefined*)))
(case merge-overlap-action
(:error
(error "Merge overlap - frame feature ~A"
fname))
(:old t)
(:new (setf (fdescr-value old-fdescr)
fvalue))
(:warn-new
(warn "~&Replacing value of frame feature ~A, old value was ~S, new value is ~S"
fname (fdescr-value old-fdescr)
fvalue)
(setf (fdescr-value old-fdescr)
fvalue)
)
(:ask-user
(when
(yes-or-no-p
"Replace value of frame feature ~A, old value was ~S, new value is ~S?"
fname (fdescr-value old-fdescr)
fvalue)
(setf (fdescr-value old-fdescr)
fvalue)))
)
)
)
)
)
)
)
)
)
)
)
(defun read-frame (frame-path filename features tss &key
merge-p (sub-frame-action :ask-user)
(frame-ask-user nil)
(merge-overlap-action :error)
&aux *sort-fixup-list* (*file-version-number* 1))
"READ-FRAME frame-path filename features tss &KEY merge-p (sub-frame-action :ask-user)
(merge-overlap-action :error) -
Read in a frame from file filename into the frame structure at frame-path. If
merge-p is non-NIL, merge the new data with an existing frame, otherwise signal
an error if frame-path already exists.
Sub-frame-action specifies what to do
about sub-frames referenced by the frame being loaded. Values can be
:ASK-USER - ask the user what to do for each sub-frame,
:ASK-USER-ALWAYS - ask the user, but ignores descendant file paths,
:LOAD - load the sub-frame if posible,
:INHERIT-PATH - load using the device and directory of the root frame.
:STUB - make a stub-frame, or
:ERROR - raise an error if an unresolved
sub-frame is referenced.
Merge-overlap-action specifies what to do if merge-p
is non-NIL and there is data-overlap. Posible values are :ERROR - raise an
error, :ASK-USER - ask the user for each instance, :OLD - use existing data,
:NEW - use new data, or :WARN-NEW - use new data and issue a warning message
(with WARN). Features and TSS control which features and/or tokens to load.
:ALL means all, NIL means none. Features should be :ALL, NIL, or a list a feature
names, with a posible <?> in front, TSS should be :ALL, NIL, or a TSS.
"
(unless (member sub-frame-action '(:stub :error :load :inherit-path :ask-user :ask-user-always))
(error "Bad keyword value for :sub-frame-action - ~S" sub-frame-action))
(when merge-p
(unless (member merge-overlap-action
'(:error :ask-user :old :new :warn-new))
(error "Bad keyword value for :merge-overlap-action - ~S"
merge-overlap-action)))
(let ((*new-frame-path* (parse-token-name frame-path))
new-handle new-more-path
frame-pointer *old-frame-path*
sourcefiles frame-name frame-documentation file-frame-path
(new-frame-p nil)
)
(unwind-protect
(progn
(multiple-value-setq (new-handle new-more-path)
(make-handle-from-parsed-path *new-frame-path*))
(when frame-ask-user
(setf filename (menu-choose-source-file filename
(format nil "Choose source file for frame path ~s" frame-path))))
(with-open-isr2-read-frame-file (frame-stream filename frame-path)
(unless (setf *file-version-number*
(read-and-check-isr2-header frame-stream))
(error "Not a frame file: ~S" filename))
(setf frame-name (read-isr2-string frame-stream)
frame-documentation (read-isr2-string frame-stream)
sourcefiles (make-list (read-ubyte16 frame-stream)))
(do ((p sourcefiles (rest p)))
((null p))
(setf (first p) (read-isr2-string frame-stream)))
(setf file-frame-path (read-isr2-string frame-stream)
*old-frame-path* (parse-token-name file-frame-path))
(when (null new-handle)
(setf *new-frame-path* *old-frame-path*)
(multiple-value-setq (new-handle new-more-path)
(make-handle-from-parsed-path *new-frame-path*)))
(cond ((null new-handle)
(error "Bogus frame file: bad frame path - ~S" file-frame-path))
((and (null new-more-path)
(not (member (handle-type new-handle)
'(:frame-feature :token-feature))))
(unless merge-p
(error "Frame already exists: ~S!" frame-path)))
((not (check-terminal-path new-handle new-more-path))
(error "Bad path: ~S!" frame-path))
(t (setf new-handle (create frame-path)
new-frame-p t)))
(unless (eq (handle-type new-handle) :frame)
(error "Bad path (not a frame!): ~S" frame-path))
(setf frame-pointer (handle-frame new-handle))
(cond
(new-frame-p
(setf (frame-documentation frame-pointer) frame-documentation
(frame-source-file-list frame-pointer) sourcefiles))
(t (setf (frame-source-file-list frame-pointer)
(nunion sourcefiles (frame-source-file-list frame-pointer)
:test #'equalp))))
(read-in-decendants frame-stream sub-frame-action
(if (eq sub-frame-action :inherit-path) filename nil))
(let ((exist-bit-vector (read-isr2-2vv frame-stream))
(globalp-bit-vector (read-isr2-2vv frame-stream)))
(if new-frame-p
(setf (frame-token-set-existence-vector frame-pointer)
(if (eq tss :all)
exist-bit-vector
(isect-2vv exist-bit-vector tss))
(frame-token-set-globalp-vector frame-pointer)
(if (eq tss :all)
globalp-bit-vector
(isect-2vv globalp-bit-vector tss))
)
(progn
(merge-bit-vectors
exist-bit-vector
(frame-token-set-existence-vector frame-pointer))
(merge-bit-vectors
globalp-bit-vector
(frame-token-set-globalp-vector frame-pointer))
)
)
(read-in-frame-features frame-stream frame-pointer
merge-overlap-action new-frame-p
features)
(read-in-token-features frame-stream frame-pointer
exist-bit-vector merge-overlap-action
new-frame-p features tss)
(unless (eq exist-bit-vector
(frame-token-set-existence-vector
frame-pointer))
(free-2vv exist-bit-vector)
(free-2vv globalp-bit-vector))
(fixup-sorts)
)
(setf new-frame-p nil)
(setf (frame-is-loaded-p frame-pointer) t)
(namestring (truename frame-stream))
)
)
(when (and new-frame-p (handle-p new-handle))
(destroy new-handle))
)
)
)
(defun save (path filename &key (features t) &aux path-handle frame-path tss)
"SAVE path filename &KEY (features t) - save a frame path to a file."
(setf path-handle (%internal-handle path :terminal-p t :error-p nil))
(when (null path-handle)
(error "~S is not a known path!" path))
(unless (and (handle-p path-handle)
(member (handle-type path-handle) '(:frame :token-subset
:token-sort)))
(error "~S [~S] is not a savable path!" path path-handle))
(when (eq (handle-type path-handle) :token-sort)
(setf path-handle (make-tss path-handle)))
(setf frame-path (frame path-handle)
tss (if (eq (handle-type path-handle) :frame)
:all
path-handle))
(prog1
(write-frame frame-path filename (if (listp features) features :all)
tss)
(unless (eq tss path) (make-null-tss! tss)))
)
(defun get-frame-name-from-file (filename &aux frame-name)
(with-open-isr2-frame-file (frame-stream filename :input)
(unless (read-and-check-isr2-header frame-stream)
(error "Not a frame file: ~S" filename))
(setf frame-name (read-isr2-string frame-stream)))
frame-name)
(defun load-frame (path filename &KEY (features t) (override :error) &aux
path-handle)
"LOAD-FRAME path filename &KEY (features t) (override :error) - load a frame
*under* path."
(declare (ignore override))
(setf path-handle (%internal-handle path :terminal-p t :error-p nil))
(when (null path-handle)
(error "~S is not a known path!" path))
(cond ((not (handle-p path-handle))
(read-frame path-handle filename (if (listp features) features :all) :all
))
((eq (handle-type path-handle) :frame)
(read-frame
(list path-handle (get-frame-name-from-file filename))
filename
(if (listp features) features :all) :all))
((eq (handle-type path-handle) :frame-feature)
(read-frame
(list (frame path-handle) (handle-feature path-handle))
filename
(if (listp features) features :all) :all))
(t (error "The path ~S [~S] is not legal in this context!"
path path-handle))
)
)
(defun load-data (path filename &key (features t) (override :error) &aux
path-handle frame tss)
"LOAD-DATA path filename &KEY (features t) (override :error) - load a frame
*at* path."
(setf path-handle (%internal-handle path :terminal-p t :error-p nil))
(when (null path-handle)
(error "~S is not a known path!" path))
(cond ((handle-p path-handle)
(case (handle-type path-handle)
(:frame (setf tss :all
frame path-handle))
(:token-subset (setf tss path-handle
frame (frame path-handle)))
(:token-sort (setf tss (make-tss path-handle)
frame (frame path-handle)))
(t (error "The path ~S [~S] is not legal in this context!"
path path-handle))))
(t (setf frame path-handle
tss :all)))
(read-frame frame filename (if (listp features) features :all) tss
:merge-p (handle-p frame)
:merge-override-action override)
)
(defun describe-decendants (stream frame-stream verbose)
(let (decendant-path decendant-doc decendant-sources num-decendants)
(setf num-decendants (read-ubyte16 frame-stream))
(when verbose
(format stream "~&Frame decendant~p:" num-decendants))
(dotimes (i num-decendants)
(setf decendant-path (read-isr2-string frame-stream)
decendant-doc (read-isr2-string frame-stream)
decendant-sources (read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2))))
(when verbose
(format
stream
"~& ~3d. Path: ~A~& Doc: ~A~& Sources: ~S"
(1+ i) decendant-path decendant-doc decendant-sources))
)
)
)
(defun describe-frame-features (stream frame-stream verbose)
(let (fname fdoc ftype f-if-needed f-if-getting f-if-setting
fvalue
(fcount (read-ubyte16 frame-stream))
)
(when stream (format stream "~&Frame feature~p: " fcount))
(dotimes (i fcount)
(setf fname (read-isr2-string frame-stream)
fdoc (read-isr2-string frame-stream)
ftype (read-ubyte16 frame-stream)
f-if-needed (make-list (read-ubyte16 frame-stream)))
(do ((p f-if-needed (rest p)))
((null p))
(setf (first p)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
(setf f-if-setting (make-list (read-ubyte16 frame-stream)))
(do ((p f-if-setting (rest p)))
((null p))
(setf (first p)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
(setf f-if-getting (make-list (read-ubyte16 frame-stream)))
(do ((p f-if-getting (rest p)))
((null p))
(setf (first p)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
(setf fvalue
(case ftype
((#.*boolean* #.*int*)
(read-sbyte32 frame-stream))
(#.*real*
(read-float32 frame-stream))
(#.*handle*
(read-isr2-handle frame-stream t))
(#.*extents*
(read-isr2-extents frame-stream))
(#.*bitplane*
(read-isr2-bitplane frame-stream))
(#.*array*
(read-isr2-array frame-stream))
((#.*string* #.*pointer*)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2))))))
(when stream
(format
stream
"~& ~3d. Name: ~A~& Doc: ~A~& Type: ~A"
(1+ i) fname fdoc (elt *type-names* ftype))
(when verbose
(format
stream
"~& If-Needed: ~S~& If-Getting: ~S~& If-Setting: ~S"
f-if-needed f-if-getting f-if-setting)))
)
)
)
(defun describe-token-features (stream frame-stream verbose)
(let (fname fdoc ftype f-if-needed f-if-getting f-if-setting
(fcount (read-ubyte16 frame-stream))
)
(format stream "~&Token feature~p: " fcount)
(dotimes (i fcount)
(setf fname (read-isr2-string frame-stream)
fdoc (read-isr2-string frame-stream)
ftype (read-ubyte16 frame-stream)
f-if-needed (make-list (read-ubyte16 frame-stream)))
(do ((p f-if-needed (rest p)))
((null p))
(setf (first p)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
(setf f-if-setting (make-list (read-ubyte16 frame-stream)))
(do ((p f-if-setting (rest p)))
((null p))
(setf (first p)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
(setf f-if-getting (make-list (read-ubyte16 frame-stream)))
(do ((p f-if-getting (rest p)))
((null p))
(setf (first p)
(read-isr2-sexpr-pkg
frame-stream
(find-package (if (= *file-version-number* 0) 'user 'isr2)))))
(free-2vv (read-isr2-2vv frame-stream t))
(format
stream
"~& ~3d. Name: ~A~& Doc: ~A~& Type: ~A"
(1+ i) fname fdoc (elt *type-names* ftype))
(when verbose
(format
stream
"~& If-Needed: ~S~& If-Getting: ~S~& If-Setting: ~S"
f-if-needed f-if-getting f-if-setting))
)
)
)
(defun describe-file (filename &key (stream *standard-output*) (features nil)
(verbose nil) &aux *file-version-number*)
"DESCRIBE-FILE filename &KEY (stream *standard-output*) (features nil)
(verbose nil) -
Describes the contents of the frame file specified. Output is sent to stream.
Features specifies which features to give info on and verbose specifies how
verbose the output should be. Features can be NIL (no feature info), :FRAME
(give frame feature info), :TOKEN (give token feature info), or :ALL (both kinds
features)."
(unless (member features '(nil :frame :token :all))
(error "Bad keyword value for :features - ~S" features))
(setf filename (truename filename))
(format stream "~2&Description of file ~A" (namestring filename))
(with-open-isr2-frame-file (frame-stream filename :input)
(unless (setf *file-version-number*
(read-and-check-isr2-header frame-stream))
(error "Not a frame file: ~S" filename))
(format stream "~&Frame name: ~A" (read-isr2-string frame-stream))
(if verbose
(read-isr2-string frame-stream)
(format stream "~&Feame documentation: ~A" (read-isr2-string frame-stream)))
(let ((sourcefiles (make-list (read-ubyte16 frame-stream))))
(do ((p sourcefiles (rest p)))
((null p))
(setf (first p) (read-isr2-string frame-stream)))
(when verbose
(format stream "~&Source file~p: ~{~& ~A~}"
(length sourcefiles)
sourcefiles))
)
(if verbose
(format stream "~&Frame path: ~A" (read-isr2-string frame-stream))
(read-isr2-string frame-stream))
(describe-decendants stream frame-stream verbose)
(let ((exist-bit-vector (read-isr2-2vv frame-stream))
(globalp-bit-vector (read-isr2-2vv frame-stream)))
(format stream "~&Token count: ~D/~D"
(active-token-count-2vv exist-bit-vector)
(total-token-count-2vv exist-bit-vector))
(when verbose
(format stream ", global token count: ~D/~D"
(active-token-count-2vv globalp-bit-vector)
(total-token-count-2vv globalp-bit-vector))
)
(free-2vv exist-bit-vector)
(free-2vv globalp-bit-vector))
(when features
(describe-frame-features (if (member features '(:frame :all))
stream
nil)
frame-stream verbose)
(when (member features '(:all :token))
(describe-token-features stream frame-stream verbose)))
(namestring (truename frame-stream))
)
)
(defun store (frame-path filename &aux (handle (handle frame-path :error-p nil)))
"STORE frame-path filename - saves a complete frame in the specified file."
(unless handle
(error "Not a defined path: ~S" frame-path))
(write-frame (frame handle) filename :all :all t))
(defun restore (frame-path filename &aux path-handle)
"RESTORE frame-path filename - loads a complete frame from the specified
file."
(setf path-handle (handle frame-path :error-p nil))
(when (and path-handle (eq (handle-type path-handle) :frame))
(error "Frame already exists: ~S" frame-path))
;; Ross's change, this will never prompt unless root file is not found!
(read-frame frame-path filename :all :all
:merge-p nil
:sub-frame-action :load
:merge-overlap-action :error)
)
(defun restore-with-prompts (frame-path filename &aux path-handle)
"RESTORE frame-path filename - loads a complete frame from the specified
file."
(setf path-handle (handle frame-path :error-p nil))
(when (and path-handle (eq (handle-type path-handle) :frame))
(error "Frame already exists: ~S" frame-path))
;; Ross's change, this will never prompt unless root file is not found!
(read-frame frame-path filename :all :all
:merge-p nil
:frame-ask-user t
:merge-overlap-action :error)
)
(defun restore-inherit-path (frame-path filename &aux path-handle)
"RESTORE frame-path filename - loads a complete frame from the specified
file.
Always assume when loading subframes that the device and directory from
which to load is the same as that specified with the file name passed in.
"
(setf path-handle (handle frame-path :error-p nil))
(when (and path-handle (eq (handle-type path-handle) :frame))
(error "Frame already exists: ~S" frame-path))
(read-frame frame-path filename :all :all
:merge-p nil
:sub-frame-action :inherit-path
:frame-ask-user nil
:merge-overlap-action :error)
)