Refactor compressor/decompressor to use bytevectors and binary ports.
authorChris Hanson <org/chris-hanson/cph>
Sat, 29 Apr 2017 08:00:17 +0000 (01:00 -0700)
committerChris Hanson <org/chris-hanson/cph>
Sat, 29 Apr 2017 08:00:17 +0000 (01:00 -0700)
src/runtime/cpress.scm
src/runtime/infutl.scm
src/runtime/runtime.pkg

index b40a87f9c76f17937c5f8689aca011c7fab5894e..3e99f55270e5a1a5910bd6aa6bf5361a929bb09c 100644 (file)
@@ -86,11 +86,11 @@ USA.
 ;;; determines the algorithm.
 \f
 (define (compress ifile ofile)
-  (call-with-legacy-binary-input-file (merge-pathnames ifile)
+  (call-with-binary-input-file (merge-pathnames ifile)
     (lambda (input)
-      (call-with-legacy-binary-output-file (merge-pathnames ofile)
+      (call-with-binary-output-file (merge-pathnames ofile)
         (lambda (output)
-         (write-string "Compressed-B1-1.00" output)
+         (write-compressed-file-marker output)
          (compress-ports input output))))))
 
 (define-structure (compression-state
@@ -118,11 +118,11 @@ USA.
   output-port)
 
 (define (compress-ports input output)
-  (let ((state (make-compression-state
-               (make-vector 256 false)
-               (make-byte-buffer)
-               (make-output-buffer)
-               input output)))
+  (let ((state
+        (make-compression-state (make-vector 256 #f)
+                                (make-byte-buffer)
+                                (make-output-buffer)
+                                input output)))
     (call-with-current-continuation
      (lambda (continuation)
        (set-compress-continuation! state continuation)
@@ -240,7 +240,7 @@ USA.
   (let ((byte (read-byte state)))
     (let ((node (vector-ref (root-nodes state) byte)))
       (if (not node)
-         (add-child state false byte (make-node state 0)))
+         (add-child state #f byte (make-node state 0)))
       node)))
 
 (define (match-next state node nb)
@@ -251,7 +251,7 @@ USA.
          (let loop ((child (node-children node)))
            (cond ((not child)
                   (add-child state node byte (make-node state 0))
-                  false)
+                  #f)
                  ((fix:= byte (node-byte child))
                   (discard-byte state)
                   child)
@@ -267,25 +267,25 @@ USA.
                  (replace-child state node parent)
                  (add-child state parent byte* node)
                  (add-child state parent byte (make-node state 0)))
-               false))))))
+               #f))))))
 \f
 ;;;; PATRICIA Tree Database
 
 (define-structure (node (constructor %make-node (nb older pointer bp)))
   ;; The parent of this node, or #F for a root node.
-  (parent false)
+  (parent #f)
 
   ;; The children of this node.  Either #F for no children, or the
   ;; first child.  The remaining children are accessed through the
   ;; NODE-NEXT fields.  A node will never have exactly one child.
-  (children false)
+  (children #f)
 
   ;; The adjacent siblings of this node, or #F if none.
-  (previous false)
-  (next false)
+  (previous #f)
+  (next #f)
 
   ;; The first byte of the substring between the parent and this node.
-  (byte false)
+  (byte #f)
 
   ;; The number of bytes in the string represented by this node,
   ;; counting down from the root of the tree.
@@ -293,8 +293,8 @@ USA.
 
   ;; The adjacent nodes in the node pointer ordering.  The OLDER node
   ;; has less recent POINTER and BP, while the newer node has more recent.
-  (older false)
-  (newer false)
+  (older #f)
+  (newer #f)
 
   ;; The command pointer for this node.
   pointer
@@ -322,7 +322,7 @@ USA.
          (if older
              (set-node-newer! older newer)
              (set-oldest-node! state newer))
-         (set-node-newer! node false)
+         (set-node-newer! node #f)
          (set-node-older! node (newest-node state))
          (set-node-newer! (newest-node state) node)
          (set-newest-node! state node)
@@ -362,7 +362,7 @@ USA.
             ((not (fix:= (node-pointer node) pointer)) node))))
     (if (not (eq? node oldest-node))
        (let ((older (node-older node)))
-         (set-node-older! node false)
+         (set-node-older! node #f)
          (set-oldest-node! state node)
          ;; We don't have to do anything complicated to delete a node.
          ;; If the node has any children, we know that they are also
@@ -373,15 +373,15 @@ USA.
          ;; only do the deletion if the parent is not marked.
          (do ((node older (node-older node)))
              ((not node))
-           (set-node-nb! node false))
+           (set-node-nb! node #f))
          (do ((node older (node-older node)))
              ((not node))
            (let ((parent (node-parent node)))
              (cond ((not parent)
-                    (vector-set! (root-nodes state) (node-byte node) false))
+                    (vector-set! (root-nodes state) (node-byte node) #f))
                    ((node-nb parent)
                     (delete-child state parent node))))
-           (set-node-nb! node true))
+           (set-node-nb! node #t))
          unspecific))))
 
 (define (delete-child state parent child)
@@ -415,7 +415,7 @@ USA.
 ;;; The optimal size for this buffer is
 ;;;  (+ (* COPY-MAX POINTER-MAX) BUFFER-READ)
 (define-integrable buffer-size 69632)
-(define-integrable buffer-size-optimal? true)
+(define-integrable buffer-size-optimal? #t)
 
 ;;; When input is needed from the input port, we attempt to read this
 ;;; many bytes all at once.  It is assumed that BUFFER-SIZE is an
@@ -423,16 +423,16 @@ USA.
 (define-integrable buffer-read 4096)
 
 (define-structure (bb (constructor make-byte-buffer ()))
-  (vector (make-legacy-string buffer-size) read-only true)
+  (vector (make-bytevector buffer-size) read-only #t)
   (ptr 0)
   (end 0)
-  (eof? false))
+  (eof? #f))
 
 (define (byte-ready? state)
   (let ((bb (byte-buffer state)))
     (if (fix:= (bb-ptr bb) (bb-end bb))
-       (guarantee-buffer-data state bb true)
-       true)))
+       (guarantee-buffer-data state bb #t)
+       #t)))
 
 (define (read-byte state)
   ;; Get a byte from the byte buffer.  If we are reading bytes in the
@@ -454,8 +454,8 @@ USA.
 
 (define (%peek-byte state bb)
   (if (fix:= (bb-ptr bb) (bb-end bb))
-      (guarantee-buffer-data state bb false))
-  (vector-8b-ref (bb-vector bb) (bb-ptr bb)))
+      (guarantee-buffer-data state bb #f))
+  (bytevector-u8-ref (bb-vector bb) (bb-ptr bb)))
 
 (define (%discard-byte bb)
   (set-bb-ptr! bb
@@ -480,11 +480,11 @@ USA.
 
 (define (node-ref node nb state)
   ;; Read byte NB in the string for NODE.
-  (vector-8b-ref (bb-vector (byte-buffer state))
-                (let ((bp (fix:+ (node-bp node) nb)))
-                  (if (fix:< bp buffer-size)
-                      bp
-                      (fix:- bp buffer-size)))))
+  (bytevector-u8-ref (bb-vector (byte-buffer state))
+                    (let ((bp (fix:+ (node-bp node) nb)))
+                      (if (fix:< bp buffer-size)
+                          bp
+                          (fix:- bp buffer-size)))))
 \f
 (define (guarantee-buffer-data state bb probe?)
   ;; We have read all of the bytes in the buffer, so it's time to get
@@ -493,7 +493,7 @@ USA.
   ;; means we are now at EOF.
   (if (bb-eof? bb)
       (if probe?
-         false
+         #f
          (compress-finished state))
       (let* ((end (bb-end bb))
             (end* (fix:+ end buffer-read)))
@@ -504,34 +504,32 @@ USA.
        ;; couldn't be sure that any nodes we were holding were valid
        ;; across a call to READ-BYTE.
        (let ((nb
-              (input-port/read-substring! (input-port state)
-                                          (bb-vector bb) end end*)))
+              (read-bytevector! (bb-vector bb) (input-port state) end end*)))
          (cond ((not nb)
                 (error "Input port must be in blocking mode:"
                        (input-port state))
-                false)
-               ((fix:= nb buffer-read)
-                ;; A full block was read.
-                (set-bb-end! bb (if (fix:= end* buffer-size) 0 end*))
-                true)
-               ((fix:= nb 0)
-                ;; We're at EOF.
+                #f)
+               ((eof-object? nb)
                 (if probe?
                     (begin
-                      (set-bb-eof?! bb true)
-                      false)
+                      (set-bb-eof?! bb #t)
+                      #f)
                     (compress-finished state)))
+               ((fix:= nb buffer-read)
+                ;; A full block was read.
+                (set-bb-end! bb (if (fix:= end* buffer-size) 0 end*))
+                #t)
                ((and (fix:< 0 nb) (fix:< nb buffer-read))
                 ;; A partial block was read, meaning that
                 ;; this is the last block.  Set BB-EOF? to
                 ;; indicate that there is no more data after
                 ;; this block is exhausted.
-                (set-bb-eof?! bb true)
+                (set-bb-eof?! bb #t)
                 (set-bb-end! bb (fix:+ end nb))
-                true)
+                #t)
                (else
                 (error "Illegal result from read:" nb buffer-read)
-                false))))))
+                #f))))))
 
 (define (compress-finished state)
   ;; This is called from GUARANTEE-BUFFER-DATA when EOF is
@@ -665,7 +663,7 @@ USA.
         (let ((pointer (fix:+ (current-pointer state) 1)))
           (if (fix:= pointer pointer-max)
               (begin
-                (set-window-filled?! state true)
+                (set-window-filled?! state #t)
                 0)
               pointer))))
     (set-current-pointer! state pointer)
@@ -676,15 +674,15 @@ USA.
        (set-oldest state (oldest-node state) pointer))))
 
 (define (make-output-buffer)
-  (cons 0 (make-legacy-string 4096)))
+  (cons 0 (make-bytevector 4096)))
 
 (define (write-byte state byte)
   (let ((ob (output-buffer state)))
     (let ((index (car ob)))
-      (vector-8b-set! (cdr ob) index byte)
+      (bytevector-u8-set! (cdr ob) index byte)
       (if (fix:= index 4095)
          (begin
-           (output-port/write-string (output-port state) (cdr ob))
+           (write-bytevector (cdr ob) (output-port state))
            (set-car! ob 0))
          (set-car! ob (fix:+ index 1))))))
 
@@ -698,18 +696,19 @@ USA.
                (do ((start start (fix:+ start 1))
                     (index index (fix:+ index 1)))
                    ((fix:= start end))
-                 (vector-8b-set! buffer index (vector-8b-ref string start))))
+                 (bytevector-u8-set! buffer index
+                                     (bytevector-u8-ref string start))))
              (set-car! ob new-index))
            (do ((start start (fix:+ start 1)))
                ((fix:= start end))
-             (write-byte state (vector-8b-ref string start))))))))
+             (write-byte state (bytevector-u8-ref string start))))))))
 
 (define (flush-output-buffer state)
   (let ((ob (output-buffer state))
        (op (output-port state)))
     (if (fix:< 0 (car ob))
-       (output-port/write-substring op (cdr ob) 0 (car ob)))
-    (output-port/flush-output op)))
+       (write-bytevector (cdr ob) op 0 (car ob)))
+    (flush-output-port op)))
 
 (define (uncompress ifile ofile)
   (uncompress-internal ifile ofile
index 3e50b8aeb922badccb9354bd53ec105a6408c796..1727522d5b3f8046427683decaa766fba33da715 100644 (file)
@@ -30,16 +30,6 @@ USA.
 (declare (usual-integrations))
 (declare (integrate-external "infstr" "char"))
 \f
-(define (initialize-package!)
-  (set! special-form-procedure-names
-       `((,lambda-tag:unnamed . LAMBDA)
-         (,lambda-tag:internal-lambda . LAMBDA)
-         (,lambda-tag:let . LET)
-         (,lambda-tag:fluid-let . FLUID-LET)))
-  (set! directory-rewriting-rules (make-settable-parameter '()))
-  (set! wrappers-with-memoized-debugging-info (make-serial-population))
-  (add-secondary-gc-daemon! discard-debugging-info!))
-
 (define (compiled-code-block/dbg-info block demand-load?)
   (let ((wrapper (compiled-code-block/debugging-wrapper block)))
     (and wrapper
@@ -82,6 +72,15 @@ USA.
                    (loop (cdr left) time* file* receiver*)
                    (loop (cdr left) time file receiver))))))))
 
+(define (fasload-loader filename)
+  (call-with-current-continuation
+    (lambda (if-fail)
+      (bind-condition-handler (list condition-type:fasload-error
+                                   condition-type:file-error
+                                   condition-type:bad-range-argument)
+         (lambda (condition) condition (if-fail #f))
+       (lambda () (fasload filename #t))))))
+
 (define (memoize-debugging-info! wrapper info)
   (without-interruption
    (lambda ()
@@ -94,7 +93,12 @@ USA.
                         (set-debugging-wrapper/info! wrapper #f)))
   (empty-population! wrappers-with-memoized-debugging-info))
 
-(define wrappers-with-memoized-debugging-info)
+(define-deferred wrappers-with-memoized-debugging-info
+  (make-serial-population))
+
+(add-boot-init!
+ (lambda ()
+   (add-secondary-gc-daemon! discard-debugging-info!)))
 \f
 (define (compiled-entry/dbg-object entry #!optional demand-load?)
   (let ((block (compiled-entry/block entry))
@@ -139,7 +143,7 @@ USA.
   (if (compiled-closure? entry)
       (compiled-entry/offset (compiled-closure->entry entry))
       (compiled-code-address->offset entry)))
-\f
+
 (define (compiled-entry/filename-and-index entry)
   (compiled-code-block/filename-and-index (compiled-entry/block entry)))
 
@@ -209,7 +213,8 @@ USA.
                 (pathname=? (debugging-wrapper/pathname wrapper) pathname))
            (set-debugging-wrapper/pathname! wrapper pathname*))))))
 \f
-(define directory-rewriting-rules)
+(define-deferred directory-rewriting-rules
+  (make-settable-parameter '()))
 
 (define (with-directory-rewriting-rule match replace thunk)
   (parameterize*
@@ -341,7 +346,11 @@ USA.
     (and association
         (symbol->string (cdr association)))))
 
-(define special-form-procedure-names)
+(define-deferred special-form-procedure-names
+  `((,lambda-tag:unnamed . LAMBDA)
+    (,lambda-tag:internal-lambda . LAMBDA)
+    (,lambda-tag:let . LET)
+    (,lambda-tag:fluid-let . FLUID-LET)))
 
 (define (compiled-procedure/lambda entry)
   (let ((procedure (compiled-entry/dbg-object entry)))
@@ -396,7 +405,7 @@ USA.
         (if (equal? "bcs" (pathname-type pathname))
             (compressed-loader pathname)
             (fasload-loader pathname)))))
-\f
+
 ;;;; Splitting of info structures
 
 (define (inf->bif/bsm inffile)
@@ -434,29 +443,44 @@ USA.
 ;;;; UNCOMPRESS
 ;;;  A simple extractor for compressed binary info files.
 
-(define-integrable window-size 4096)
+(define (compressed-loader compressed-file)
+  (call-with-temporary-file-pathname
+   (lambda (temporary-file)
+     (call-with-current-continuation
+      (lambda (k)
+       (uncompress-internal compressed-file
+                            temporary-file
+                            (lambda (message . irritants)
+                              message irritants
+                              (k #f)))
+       (fasload-loader temporary-file))))))
 
-(define (uncompress-ports input-port output-port #!optional buffer-size)
-  (uncompress-kernel-by-blocks
-   input-port output-port
-   (if (default-object? buffer-size) 4096 buffer-size)
-   input-port/read-substring!))
-
-(define (uncompress-read-substring port buffer start end)
-  (let loop ((i start))
-    (if (fix:>= i end)
-       (fix:- i start)
-       (let ((char (read-char port)))
-         (if (not (char? char))
-             (fix:- i start)
-             (begin
-               (string-set! buffer i char)
-               (loop (fix:1+ i))))))))
+(define (uncompress-internal ifile ofile if-fail)
+  (call-with-binary-input-file (merge-pathnames ifile)
+    (lambda (input)
+       ;; This may get more hairy as we up versions
+      (if (read-compressed-file-marker input)
+         (call-with-binary-output-file (merge-pathnames ofile)
+           (lambda (output)
+             (uncompress-ports input output
+                               (fix:* (file-length ifile) 2))))
+         (if-fail "Not a recognized compressed file:" ifile)))))
+
+(define (read-compressed-file-marker input)
+  (let ((n (bytevector-length compressed-file-marker)))
+    (let ((marker (read-bytevector n input)))
+      (and marker
+          (not (eof-object? marker))
+          (bytevector=? marker compressed-file-marker)))))
+
+(define (write-compressed-file-marker output)
+  (write-bytevector compressed-file-marker output))
+
+(define-deferred compressed-file-marker
+  (string->utf8 "Compressed-B1-1.00"))
 \f
 ;; This version will uncompress any input that can be read in chunks by
-;; applying parameter READ-SUBSTRING to INPUT-PORT and a substring
-;; reference.  These do not necesarily have to be a port and a port
-;; operation, but that is the expected use.
+;; calling SOURCE on a bytevector range.
 ;;
 ;; This version is written for speed:
 ;;
@@ -490,130 +514,113 @@ USA.
 ;;    is no unprocessed input, in which case we just tail out of the
 ;;    loop.
 
-(define (uncompress-kernel-by-blocks input-port output-port buffer-size
-                                    read-substring)
-  (define-integrable input-size 4096)
-  (let ((cp-table (make-vector window-size))
-       (input-buffer (make-legacy-string input-size)))
-
-    (define (displacement->cp-index displacement cp)
-      (let ((index (fix:- cp displacement)))
-       (if (fix:< index 0) (fix:+ window-size index) index)))
-
-    (define-integrable (cp:+ cp n)
-      (fix:remainder (fix:+ cp n) window-size))
-
-    (define (short-substring-move! s1 start1 end1 s2 start2)
-      (do ((i1 start1 (fix:+ i1 1))
-          (i2 start2 (fix:+ i2 1)))
-         ((fix:= i1 end1))
-       (string-set! s2 i2 (string-ref s1 i1))))
+(define (uncompress-ports input-port output-port #!optional buffer-size)
+  (uncompress-kernel-by-blocks
+   (lambda (bytes start end)
+     (let ((n (read-bytevector! bytes input-port start end)))
+       (if (or (not n) (eof-object? n))
+          0
+          n)))
+   (lambda (bytes start end)
+     (write-bytevector bytes output-port start end))
+   (if (default-object? buffer-size) 4096 buffer-size)))
+\f
+(define (uncompress-kernel-by-blocks source sink output-size)
+  (define-integrable window-size #x1000)
+  (define-integrable input-size #x1000)
 
-    (let parse-command ((bp 0) (cp 0) (ip 0) (ip-end 0)
-                              (buffer (make-legacy-string buffer-size))
-                              (buffer-size buffer-size))
-      ;; Invariant: (SUBTRING BUFFER IP IP-END) is unprocessed input.
+  (let ((cp-table (make-vector window-size))
+       (input-buffer (make-bytevector input-size)))
+
+    (define-integrable (cp:++ cp)
+      (fix:and (fix:+ cp 1)
+              (fix:- window-size 1)))
+
+    (define-integrable (cp:- cp n)
+      (fix:and (fix:+ (fix:- cp n) window-size)
+              (fix:- window-size 1)))
+
+    (define (short-copy! to at from start end)
+      (do ((i start (fix:+ i 1))
+          (j at (fix:+ j 1)))
+         ((not (fix:< i end)) j)
+       (bytevector-u8-set! to j (bytevector-u8-ref from i))))
+
+    (let parse-command
+       ((ip 0)
+        (ip-end 0)
+        (cp 0)
+        (output-buffer (make-bytevector output-size))
+        (op 0)
+        (output-size output-size))
+
+      ;; Invariant:
+      ;; (BYTEVECTOR-COPY OUTPUT-BUFFER IP IP-END) is unprocessed input.
       (define (retry-with-bigger-output-buffer)
-       (let* ((new-size (fix:+ buffer-size (fix:quotient buffer-size 4)))
-              (nbuffer (make-legacy-string new-size)))
-         (string-copy! nbuffer 0 buffer)
-         (parse-command bp cp ip ip-end nbuffer new-size)))
+       (let* ((new-size (fix:+ output-size (fix:lsh output-size -2)))
+              (output-buffer* (make-bytevector new-size)))
+         (bytevector-copy! output-buffer* 0 output-buffer)
+         (parse-command ip ip-end cp
+                        output-buffer* op new-size)))
 
       (define (refill-input-buffer-and-retry needed)
-       (short-substring-move! input-buffer ip ip-end input-buffer 0)
-       (let* ((left (fix:- ip-end ip))
-              (count (read-substring input-port input-buffer
-                                     left input-size))
-              (total (fix:+ count left)))
-         (if (fix:= count 0)
-             (if (fix:< total needed)
-                 (error "Compressed input ends too soon"
-                        input-port 'UNCOMPRESS-KERNEL-BY-BLOCKS)
-                 (finished))
-             (parse-command bp cp 0  total buffer buffer-size))))
-
-      (define (finished)
-       (output-port/write-substring output-port buffer 0 bp)
-       bp)
-
+       (let* ((ip-end* (short-copy! input-buffer 0 input-buffer ip ip-end))
+              (n (source input-buffer ip-end* input-size)))
+         (if (fix:> n 0)
+             (parse-command 0 (fix:+ ip-end* n) cp
+                            output-buffer op output-size)
+             (begin
+               (if (fix:< ip-end* needed)
+                   (error "Compressed input ends too soon"
+                          'uncompress-kernel-by-blocks))
+               (sink output-buffer 0 op)
+               op))))
+
+      ;; Copy BYTE+1 bytes from input to output, and update CP-TABLE with their
+      ;; indices in the output buffer.
       (define (literal-command byte)
-       (let ((length (fix:+ byte 1))
-             (ip*    (fix:+ ip 1)))
-         (let ((nbp (fix:+ bp length))
-               (ncp (cp:+ cp length))
-               (nip (fix:+ ip* length)))
-           (if (fix:> nbp buffer-size)
-               (retry-with-bigger-output-buffer)
-               (if (fix:> nip ip-end)
-                   (refill-input-buffer-and-retry (fix:+ length 1))
-                   (begin
-                     (short-substring-move! input-buffer ip* nip buffer bp)
-                     (do ((bp bp (fix:+ bp 1)) (cp cp (cp:+ cp 1)))
-                         ((fix:= bp nbp))
-                       (vector-set! cp-table cp bp))
-                     (parse-command nbp ncp nip ip-end buffer
-                                    buffer-size)))))))
-
+       (let* ((ip (fix:+ ip 1))
+              (ip* (fix:+ ip (fix:+ byte 1)))
+              (op* (fix:+ op (fix:+ byte 1))))
+         (if (fix:<= op* output-size)
+             (if (fix:<= ip* ip-end)
+                 (begin
+                   (short-copy! output-buffer op input-buffer ip ip*)
+                   (do ((op op (fix:+ op 1))
+                        (cp cp (cp:++ cp)))
+                       ((not (fix:< op op*))
+                        (parse-command ip* ip-end cp
+                                       output-buffer op* output-size))
+                     (vector-set! cp-table cp op)))
+                 (refill-input-buffer-and-retry (fix:+ byte 2)))
+             (retry-with-bigger-output-buffer))))
+
+      ;; Copy bytes from earlier in the output to here.  Start and length are
+      ;; encoded in BYTE and the next input byte.
       (define (copy-command byte)
-       (let ((ip* (fix:+ ip 1)))
-         (if (fix:>= ip* ip-end)
-             (refill-input-buffer-and-retry 2)
-             (let ((cpi (displacement->cp-index
-                         (fix:+ (fix:* (fix:remainder byte 16) 256)
-                                (vector-8b-ref input-buffer ip*))
-                         cp))
-                   (length (fix:+ (fix:quotient byte 16) 1)))
-               (let ((bp* (vector-ref cp-table cpi))
-                     (nbp (fix:+ bp length))
-                     (ncp (cp:+ cp 1)))
-                 (if (fix:> nbp buffer-size)
-                     (retry-with-bigger-output-buffer)
-                     (let ((end-bp* (fix:+ bp* length)))
-                       (short-substring-move! buffer bp* end-bp* buffer bp)
-                       (vector-set! cp-table cp bp)
-                       (parse-command nbp ncp (fix:+ ip 2) ip-end
-                                      buffer buffer-size))))))))
-
-      (if (fix:>= ip ip-end)
-         (refill-input-buffer-and-retry 0)
-         (let ((byte  (vector-8b-ref input-buffer ip)))
-           (if (fix:< byte 16)
+       (let ((ip (fix:+ ip 1)))
+         (if (fix:< ip ip-end)
+             (let ((ostart
+                    (vector-ref cp-table
+                                (cp:- cp
+                                      (fix:or (fix:lsh (fix:and byte #x0F) 8)
+                                              (bytevector-u8-ref input-buffer
+                                                                 ip)))))
+                   (length (fix:+ (fix:lsh byte -4) 1)))
+               (let ((op* (fix:+ op length)))
+                 (if (fix:<= op* output-size)
+                     (begin
+                       (short-copy! output-buffer op
+                                    output-buffer ostart (fix:+ ostart length))
+                       (vector-set! cp-table cp op)
+                       (parse-command (fix:+ ip 1) ip-end (cp:++ cp)
+                                      output-buffer op* output-size))
+                     (retry-with-bigger-output-buffer))))
+             (refill-input-buffer-and-retry 2))))
+
+      (if (fix:< ip ip-end)
+         (let ((byte (bytevector-u8-ref input-buffer ip)))
+           (if (fix:< byte #x10)
                (literal-command byte)
-               (copy-command byte)))))))
-\f
-(define (fasload-loader filename)
-  (call-with-current-continuation
-    (lambda (if-fail)
-      (bind-condition-handler (list condition-type:fasload-error
-                                   condition-type:file-error
-                                   condition-type:bad-range-argument)
-         (lambda (condition) condition (if-fail #f))
-       (lambda () (fasload filename #t))))))
-
-(define (compressed-loader compressed-file)
-  (call-with-temporary-file-pathname
-   (lambda (temporary-file)
-     (call-with-current-continuation
-      (lambda (k)
-       (uncompress-internal compressed-file
-                            temporary-file
-                            (lambda (message . irritants)
-                              message irritants
-                              (k #f)))
-       (fasload-loader temporary-file))))))
-
-(define (uncompress-internal ifile ofile if-fail)
-  (call-with-legacy-binary-input-file (merge-pathnames ifile)
-    (lambda (input)
-      (let* ((file-marker "Compressed-B1-1.00")
-            (marker-size (string-length file-marker))
-            (actual-marker (make-legacy-string marker-size)))
-       ;; This may get more hairy as we up versions
-       (if (and (fix:= (uncompress-read-substring input
-                                                  actual-marker 0 marker-size)
-                       marker-size)
-                (string=? file-marker actual-marker))
-           (call-with-legacy-binary-output-file (merge-pathnames ofile)
-             (lambda (output)
-               (uncompress-ports input output (fix:* (file-length ifile) 2))))
-           (if-fail "Not a recognized compressed file:" ifile))))))
\ No newline at end of file
+               (copy-command byte)))
+         (refill-input-buffer-and-retry 0)))))
\ No newline at end of file
index 4040dcaa845a138b4d346ee481de1c374cc349c0..f313c27bbb53c5701c9c99903d72d4e35f751abe 100644 (file)
@@ -1464,7 +1464,8 @@ USA.
          dbg-procedure/source-code
          dbg-expression?)
   (export (runtime compress)
-         uncompress-internal)
+         uncompress-internal
+         write-compressed-file-marker)
   (export (runtime options)
          with-directory-rewriting-rule)
   (initialization (initialize-package!)))