Sum, Revisited
October 21, 2011
Let’s begin by writing the two checksum algorithms; the System V algorithm is copied (with a small modification) from the previous exercise, the BSD algorithm follows the specification given above:
(define (sum-sysv)
(let loop ((c (read-char)) (b 0) (s 0))
(if (eof-object? c)
(values s (ceiling (/ b 512)))
(loop (read-char) (+ b 1)
(modulo (+ s (char->integer c)) 65535)))))
(define (sum-bsd)
(let loop ((c (read-char)) (b 0) (s 0))
(if (eof-object? c)
(values s (ceiling (/ b 1024)))
(loop (read-char) (+ b 1)
(modulo (+ (quotient s 2)
(if (even? s) 0 32768)
(char->integer c))
65536)))))
It is normal to use bit operations to specify these algorithms, but we used arithmetic operations to illustrate an alternative, for easy portability, and because versions of Scheme prior to R6RS did not provide a standard set of bit operations.
The main program first handles the options, then an if
splits the processing depending on whether or not the user specified a list of input files:
(call-with-values
(lambda () (getopt "rs" "usage: [-r | -s] [file ...]"
(cdr (command-line))))
(lambda (opts files)
(do ((opts opts (cdr opts))) ((null? opts))
(case (caar opts)
((#\r) (set! sum sum-bsd))
((#\s) (set! sum sum-sysv))))
(if (null? files)
(call-with-values
(lambda () (sum))
(lambda (s b)
(display s) (display " ")
(display b) (newline)))
(do ((files files (cdr files))) ((null? files))
(with-input-from-file (car files)
(lambda ()
(call-with-values
(lambda () (sum))
(lambda (s b)
(display s) (display " ")
(display b) (display " ")
(display (car files)) (newline)))))))))
We used getopt
from a previous exercise. You can see the program assembled at http://programmingpraxis.codepad.org/KwePb916, but of course you can’t run it there.
One Response to “Sum, Revisited”