#!/bin/sh
: ; exec klone $0 "$@"
; The above line finds the klone executable in the $PATH
;;Skeleton of a typical klone script

(setq args (getopts "USAGE: %0 [options] file1 file2
tests if file2 contains file1 at its beginning. Similar to the cmp command
but can check is file1 is a subset of file2.
file2 can be - for stdin.
"
    ("-v" () verbose "verbose operation")
    ("-g" () graph-bar "graphical bar display")
    ("-s" () showspeed "show instant speed in graphical bar mode")
    ("-l" () all "list all differences, defaults stop at first")
    ("-o" filename outfile "sends this list to file instead of stdout")
    ("-b" N given-size "compares only the first N bytes (otherwise size of file1)")
    ("-B" k bufsize "buffer size in k. defaults to 1024 (1M)")
))

(if (not (= 2 (length args))) (progn
    (PF "usage: cmpfirst file1 file2")
    (exit 1)
))

(if outfile (setq outfd
    (open outfile :direction :output :if-exists :supersede))
  (setq outfd *standard-output*)
)
(setq bufsize (if bufsize (Int bufsize) 1024))
(if (<= bufsize 0) (setq bufsize 1024))

(setq graphic (if graph-bar 
    (if showspeed ascii-progress-bar-with-speed ascii-progress-bar)
    ()
))

(defun main (&aux
    (f1 (open (get args 0)))
    (f2 (if (= "-" (get args 1)) *standard-input* (open (get args 1))))
    (size (if given-size (Int given-size) (get (file-stats f1) 'size)))
    (toread size)
    buffer1
    buffer2
    (offset 0)
    i
    (bufsize (* 1024 bufsize))
    (M (* 1024 1024))			; 1M
  )
  (graphic 0 size)
  (while (> toread 0)
    (setq buffer1 (read-chars bufsize f1))
    (catch 'EOF 
      (setq buffer2 (read-chars (length buffer1) f2))
    )
    (graphic (+ offset (length buffer1)))
    (if (/= buffer1 buffer2) 
      (dotimes (i (length buffer1))
	(verbose? :n "  Comparing: %0 / %1\r" (/ offset M) (/ size M))
	(if (= (get buffer1 i '(EOF-found outfd (get args 0) (+ offset i))) 
	    (get buffer2 i '(EOF-found outfd (get args 1) (+ offset i))))
	  (incf i)
	  (if all
	    (PF outfd 
	      " %0 %1 %2\n" (+ offset i) (getn buffer1 i) (getn buffer2 i))
	    (progn
	      (PF "%0 %1 differ: char %2  \n" (get args 0) (get args 1)
		(+ offset i)
	      )
	      (exit 1))
	  )
    )))
    (incf toread (- (length buffer1)))
    (incf offset (length buffer1))
  )
  (verbose? "OK")
  (exit 0)
)

(defun EOF-found (outfd filename pos)
  (PF outfd "cmpfirst: EOF on %0 at %1\n" filename pos)
  (exit 1)
)

(main)

;;; EMACS MODES
;;; Local Variables: ***
;;; mode:lisp ***
;;; End: ***

