home *** CD-ROM | disk | FTP | other *** search
- ;;; (C) Copyright 1984 by Gold Hill Computers
-
- ;; This file contains routines to dump lisp objects to a
- ;; FASL (object code) file.
-
- ; "This is used to create a FASL stream to which lisp objects may be
- ;dumped. Currently :PROPERTY-LIST is the only supported option. It is
- ;a property list that is placed at the beginning of the FASL file. The
- ;stream returned by this function accepts the following messages:
- ; :DUMP <obj>, dump object to the fasl file. <obj> can be
- ; a SYMBOL, STRING, FIXNUM, STRUCTURE, or LIST.
- ; :NOP, insert a NOP operator.
- ; :POP-FOR-EFFECT, pop and discard the top of stack.
- ; :ALTER <idx>, alter the second item on the stack in the way
- ; specified by index depending on type of second item on
- ; stack (LIST or SYMBOL): 0 - RPLACA, SET, 1 - RPLACD, FSET,
- ; 2 - SETPLIST. The top of stack will be the new value.
- ; :EVAL, eval top of stack and then put in back.
- ; :EVAL-FOR-EFFECT, eval top of stack and discard.
- ; :FUNCALL <n>, take n items on stack top as args, funcall the n+1
- ; item on these args (top of stack is last arg), push result to
- ; stack.
- ; :DUMP-PACKAGE pkg-name, dump package of specified name, returns idx.
- ; :SET-PACKAGE pkg-name, sets the default package.
- ; :CLOSE, close the FASL file."
- (DEFUN MAKE-FASL-OUTPUT-STREAM (FNAME &REST OPTIONS
- &aux notice comment)
- (LET (PLIST
- STRM
- (TBL-IDX 0) ;the fop table index
- (PKG (AREF *PACKAGE* 1)) :pkg name
- (PKG-ALIST NIL)
- (DEF-PATHNAME (MAKE-PATHNAME :TYPE "FAS"
- :DEFAULTS *DEFAULT-PATHNAME-DEFAULTS*))
- )
- (DO ((I OPTIONS (CDDR I)))
- ((NULL I))
- (CASE (CAR I)
- (:PROPERTY-LIST (SETF PLIST (SECOND I)))
- (:NOTICE (setf notice (cadr i)))
- (:COMMENT (setf comment (cadr i)))
- (OTHERWISE
- (ERROR "MAKE-FASL-OUTPUT-STREAM: Unknown option: ~S" (CAR I)))))
- (SETF STRM (OPEN (MERGE-PATHNAMES FNAME DEF-PATHNAME)
- :DIRECTION :OUTPUT :ELEMENT-TYPE 'UNSIGNED-BYTE))
- ;; put the header things in.
- (PRINC "FASL FILE" STRM)
- (WRITE-BYTE #\RETURN STRM) ; TERPRI won't work quit right since
- (WRITE-BYTE #\LINEFEED STRM) ; we are in unsigned-byte mode.
- (WHEN NOTICE (PRINC NOTICE STRM)
- (WRITE-BYTE #\RETURN STRM) ; TERPRI won't work quit right since
- (WRITE-BYTE #\LINEFEED STRM)) ; we are in unsigned-byte mode.
- (WHEN COMMENT
- (PRINC COMMENT STRM)
- (WRITE-BYTE #\RETURN STRM) ; TERPRI won't work quit right since
- (WRITE-BYTE #\LINEFEED STRM)) ; we are in unsigned-byte mode.
- ;; dump out the files properties
- (DO ((I PLIST (CDDR I)))
- ((NULL I))
- (PRINC (CAR I) STRM)
- (WRITE-BYTE #\RETURN STRM)
- (WRITE-BYTE #\LINEFEED STRM)
- (WRITE-BYTE #\TAB STRM)
- (PRINC (SECOND I) STRM)
- (WRITE-BYTE #\RETURN STRM)
- (WRITE-BYTE #\LINEFEED STRM))
- (WRITE-BYTE 26 STRM) ; EOF if you look at this as text.
- (WRITE-BYTE 255 STRM) ; end of header
- ;; return stream
- (LET ((S (CLOSURE '(STRM TBL-IDX PKG PKG-ALIST) 'FASDUMP-INTERNAL)))
- (SEND S :SET-PACKAGE PKG) ;set default package
- S)))
-
- ;;; The closure variables are:
- ;;; STRM - the dumping stream
- ;;; TBL-IDX - the index into the table of the next free spot
- ;;; PKG - the current default package name.
- ;;; PKG-ALIST - an alist of packages and table indexes.
- ;;;
- (DEFUN FASDUMP-INTERNAL (OP &OPTIONAL ARG)
- "Internal function for fasl streams. See MAKE-FASL-OUTPUT-STREAM."
- (CASE OP
- ;; DUMP arg to fasl file
- (:DUMP
- (CASE (TYPE-OF ARG)
- ((SYMBOL KEYWORD)
- (LET ((PNAME (SYMBOL-NAME ARG))
- (PG (AREF (SYMBOL-PACKAGE ARG) 1))
- (IDX NIL))
- (WHEN (> (LENGTH PNAME) 255.)
- (ERROR "Can't dump symbol longer that 255 characters: ~S"
- ARG))
- (COND ((EQUAL PG PKG) ;package is same as default
- (WRITE-BYTE 7 STRM) ;small symbol save operator.
- (WRITE-BYTE (LENGTH PNAME) STRM))
- (T
- (SETQ IDX (FASDUMP-INTERNAL :DUMP-PACKAGE PG))
- (IF (< IDX 256)
- (PROGN
- (WRITE-BYTE 11 STRM)
- (WRITE-BYTE IDX STRM))
- (PROGN
- (WRITE-BYTE 9 STRM)
- (WRITE-4-BYTE IDX STRM)))
- (WRITE-BYTE (LENGTH PNAME) STRM)))
- (PRINC PNAME STRM)))
- (NULL
- (WRITE-BYTE 4 STRM)) ; NIL
- (FIXNUM
- (WRITE-BYTE 35. STRM)
- (WRITE-4-BYTE ARG STRM))
- (CONS
- (DO ((I ARG (CDR I)))
- ((NOT (CONSP I))(FASDUMP-INTERNAL :DUMP I))
- (FASDUMP-INTERNAL :DUMP (CAR I)))
- (DO ((I (LENGTH ARG) (- I 254))
- (1STP T NIL))
- ((<= I 0))
- (WRITE-BYTE 16 STRM) ; LIST or LIST*
- (WRITE-BYTE (MIN 254 I) STRM))) ; dump list item
- (OTHERWISE
- (COND ((TYPEP ARG '(VECTOR STRING-CHAR))
- (IF (< (LENGTH ARG) 256)
- (PROGN
- (WRITE-BYTE 38. STRM)
- (WRITE-BYTE (LENGTH ARG) STRM))
- (LET ((LEN (LENGTH ARG)))
- (WRITE-BYTE 37. STRM)
- (WRITE-BYTE (LOGAND #XFF LEN) STRM)
- (WRITE-BYTE (LSH LEN -8) STRM)
- (WRITE-BYTE 0 STRM)
- (WRITE-BYTE 0 STRM)))
- (PRINC ARG STRM))
- ((OR (TYPEP ARG 'STRUCTURE) ;a structure or general vector
- (TYPEP ARG '(VECTOR T)))
- (DOTIMES (I (LENGTH ARG))
- (FASDUMP-INTERNAL :DUMP (AREF ARG I)))
- (WRITE-BYTE 39. STRM) ;vector
- (WRITE-4-BYTE (LENGTH ARG) STRM) ;length
- (WHEN (TYPEP ARG 'STRUCTURE)
- (WRITE-BYTE 46. STRM))); turn vector into structure
- (T (ERROR "Don't know how to dump: ~S" ARG))))))
- ;; close the stream
- (:CLOSE
- (WRITE-BYTE 64. STRM) ; end the group
- (SEND STRM :CLOSE))
- ;; NOP operator
- (:NOP
- (WRITE-BYTE 0 STRM))
- (:SET-PACKAGE
- (LET ((IDX (FASDUMP-INTERNAL :DUMP-PACKAGE ARG)))
- (SETQ PKG ARG)
- (WRITE-BYTE 13 STRM)
- (WRITE-4-BYTE IDX STRM))) ;set default package
- (:DUMP-PACKAGE ;dump package if not already dumped
- (LET ((IDX (CDR (ASSOC (SETQ ARG (STRING ARG)) PKG-ALIST
- :TEST #'EQUAL))))
- (IF IDX
- IDX ;have it, just return index
- (PROGN
- (WRITE-BYTE 7 STRM) ;send the package name
- (WRITE-BYTE (LENGTH ARG) STRM) ;its length
- (PRINC ARG STRM) ;its pname
- (WRITE-BYTE 14 STRM) ;fop-package
- (PUSH (CONS ARG TBL-IDX) PKG-ALIST) ;add to pkg table
- (PROG1 TBL-IDX (INCF TBL-IDX))))))
- ;; POP stack and discard
- (:POP-FOR-EFFECT
- (WRITE-BYTE 65. STRM))
- ;; EVAL for top of stack, then put it back
- (:EVAL
- (WRITE-BYTE 53. STRM))
- (:EVAL-FOR-EFFECT
- (WRITE-BYTE 54. STRM))
- ;; ALTER 2 item on stack with stack top
- (:ALTER
- (WRITE-BYTE 52. STRM)
- (WRITE-BYTE ARG STRM))
- (:WHICH-OPERATIONS
- '(:DUMP :NOP :SET-PACKAGE :POP-FOR-EFFECT :ALTER :EVAL :EVAL-FOR-EFFECT :FUNCALL :CLOSE))
- (OTHERWISE
- (ERROR "FASDUMP-INTERNAL: Bad stream operation: ~S" OP))))
-
- (DEFUN WRITE-4-BYTE (I STRM)
- (WRITE-BYTE (LOGAND #XFF I) STRM) ;dump index
- (WRITE-BYTE (LSH I -8) STRM)
- (WRITE-BYTE 0 STRM)
- (WRITE-BYTE 0 STRM)
- )
-
- ;; This is for faslfying a file so that it will load faster (when the
- ;; fasloader gets compiled).
- (DEFUN FASLFY-FILE (PN &rest OPTIONS)
- (LET ((IN (MERGE-PATHNAMES PN))
- (INS NIL)
- (OUTS NIL)
- (EOF (NCONS NIL))
- (OBJ NIL))
- (SETQ INS (OPEN IN))
- (SETQ OUTS (apply 'MAKE-FASL-OUTPUT-STREAM (cons(MAKE-PATHNAME :TYPE "FAS"
- :DEFAULTS IN) OPTIONS)))
- (UNWIND-PROTECT
- (LOOP
- (SETQ OBJ (READ INS NIL EOF))
- (WHEN (EQ OBJ EOF) (RETURN NIL))
- (SEND OUTS :DUMP OBJ)
- (SEND OUTS :EVAL-FOR-EFFECT))
- (CLOSE INS)
- (CLOSE OUTS))))