about summary refs log blame commit diff
path: root/fun/wcl/wc.lisp
blob: 83c7e8c4f1ccf4305671d615b06a39ce859c9ebf (plain) (tree)
1
2
3
4
5
6
7
8





                                         
                                     




                                                                           
                                             






                                                                     
                                                              
                                             
                                      
                           
                                                  


                                                                                
(defpackage wc
  (:use #:cl #:iterate)
  (:export :main))
(in-package :wc)
(declaim (optimize (speed 3) (safety 0)))

(defun main ()
  (let ((filename (cadr (opts:argv)))
        (space (char-code #\Space))
        (newline (char-code #\Newline)))
    (with-open-file (file-stream filename :element-type '(unsigned-byte 8))
      (iter
        (for byte in-stream file-stream using #'read-byte)
        (for previous-byte previous byte)
        (for is-newline = (eql newline byte))

        ;; Count each byte
        (sum 1 into bytes)

        ;; Count every newline
        (counting is-newline into newlines)

        ;; Count every "word", unless the preceding character already
        ;; was a space or we are at the beginning of the file.
        (when (or (eql space previous-byte)
                  (eql newline previous-byte)
                  (not previous-byte))
          (next-iteration))

        (counting (or is-newline (eql space byte))
                  into words)

        (declare (fixnum bytes newlines words))
        (finally (format t "  ~A ~A ~A ~A~%" newlines words bytes filename))))))