;;; -*- Mode:LISP; Package:USER; Readtable:CL; Base:10 -*- ;;; parse the output of the ITS DUMP program and find the ;;; optimal tapes to get the latest versions of a set of files. (defvar *its-dump-data* nil) (defstruct (tape-file (:print-function tape-file-print-function)) tape index directory name type version creation-date) (defun tape-file-print-function (object stream level) level (format stream "#<~A;~A ~A on TAPE ~A>" (tape-file-directory object) (tape-file-name object) (or (tape-file-version object) (tape-file-type object)) (tape-file-tape object))) (defun load-its-dump-data (filename) (with-open-file (stream filename) (do ((line)) ((not (setq line (readline stream nil)))) (when (string-equal " TAPE" line :start2 0 :end2 5) (let* ((type (substring line 29 35)) (version (ignore-errors (parse-integer type)))) (cond (version (setq type nil)) ('else (setq type (intern (string-trim '(#\space) type) "")))) (push (make-tape-file :tape (subtoken line 8 14) :directory (subtoken line 15 21) :name (subtoken line 22 28) :version version :type type :index (parse-integer line :start 37 :end 41) :creation-date (time:parse-universal-time line 41 (string-search "." line 41))) *its-dump-data*)))))) (defun subtoken (line start end) (intern (string-trim '(#\space) (substring line start end)) "")) (defun latest-versions () (let ((list)) (dolist (e *its-dump-data*) (when (tape-file-version e) (let ((cell (CAR (MEM #'(lambda (e1 e2) (and (eq (tape-file-directory e1) (tape-file-directory e2)) (eq (tape-file-name e1) (tape-file-name e2)))) e list)))) (cond ((not cell) (push (make-tape-file :directory (tape-file-directory e) :name (tape-file-name e) :version (tape-file-version e)) list)) ('else (setf (tape-file-version cell) (max (tape-file-version cell) (tape-file-version e)))))))) (dolist (e1 *its-dump-data*) (dolist (e2 list) (when (and (eq (tape-file-directory e1) (tape-file-directory e2)) (eq (tape-file-name e1) (tape-file-name e2)) (eq (tape-file-version e1) (tape-file-version e2))) (push (tape-file-tape e1) (tape-file-tape e2))))) list)) (defun tape-summary (tape-files) "Print a tape of tapes, percent winnage and filenames" (let (alist) (dolist (f tape-files) (dolist (tf (tape-file-tape f)) (let ((cell (assq tf alist))) (cond ((not cell) (push (cons tf (list f)) alist)) ('else (push f (cdr cell))))))) (format t "~&TAPE %WIN Files~%") (setq alist (sort alist #'(lambda (a b) (> (length a) (length b))))) (dolist (a alist) (format t "~6A ~3D ~{~A~^ ~}~%" (car a) (quotient (times (length (cdr a)) 100) (length tape-files)) (sort (mapcar #'tape-file-name (cdr a)) #'string-lessp)))))