;;; -*- Mode:LISP; Package:USER; Base:10; Readtable:CL -*-

(defun dump-file (infile &rest arguments &key outfile (outstream *terminal-io*) (byte-size 8) (start 0) end
		  (line-bytes 16) (mark-interval 4) (base 10.))
  (if outfile
    (with-open-file (outstream (open outfile :direction :output :characters t))
      (apply #'dump-file infile :outstream outstream :outfile nil arguments))
    (with-open-stream (instream :direction :input :characters nil :byte-size byte-size)
      (unless (zerop start)
	(send stream :set-pointer start))
      (loop with buffer = (make-array 1024 :element-type `(unsigned-byte ,byte-size))
	    with char-buffer = (make-string (+ line-bytes (ceiling line-bytes mark-interval) 1))
	    with length = (send stream :length)
	    with bpos = 1024.
	    for cpos = 0			;Character position in char buffer
	    for pos from start to (if end (max end length) length) by mark-interval
	    for lpos = 0 then (if ( lpos line-bytes) 0 (1+ lpos))
	    do
	    (macrolet ((next-byte ()
			`(progn (when ( bpos 1024.)
				  (send instream :string-in buffer)
				  (setq bpos 0))
				(aref buffer (prog1 bpos (incf bpos))))))
	      (loop for bpos from pos
		    ;; Until out of room in the group, the line, or the file range requested.
		    repeat (max mark-interval (- lpos line-bytes) (- length pos))
		    for byte = (next-byte)
		    for char = (if (and (< byte (char-code #\Null))
					(not (= byte (char-code #\Altmode))))
				   (code-char byte)
				 #\ )
		    do
		    (write byte :stream outstream :radix nil :base base :pretty nil :circle nil)
		    (setf (aref char-buffer cpos) char)
		    (incf cpos)
		    finally
		    (write-char #\| stream)
		    (setf (aref char-buffer cpos) #\Space)
		    (incf cpos)))))))

		  
	    
