#| sbcl --script "$0" "${@:1}" exit |# (defun split (string split) (let ((parts ()) (buffer (make-string-output-stream))) (flet ((maybe-output () (let ((part (get-output-stream-string buffer))) (when (string/= part "") (push part parts))))) (loop for char across string do (if (char= char split) (maybe-output) (write-char char buffer)) finally (maybe-output)) (nreverse parts)))) (defun %ldd (file) (with-output-to-string (stream) (sb-ext:run-program "/usr/bin/ldd" (list (namestring (truename file))) :output stream))) (defun ldd (file) (loop for line in (split (%ldd file) #\Linefeed) for parts = (split (string-trim '(#\Tab) line) #\Space) collect (list (first parts) (when (< 2 (length parts)) (third parts))))) (defun ldd-tree (file &key ignore) (let ((total ())) (labels ((traverse (file depth) (format T "~&~v{ ~}~a" depth 0 (file-namestring file)) (loop for (dep src) in (ldd file) unless (find dep (append ignore '("linux-vdso.so.1" "ld-linux-x86-64.so.2")) :test (lambda (a b) (search b a))) do (pushnew dep total :test #'string-equal) (when src (traverse src (1+ depth)))))) (traverse file 0)) (format T "~&~%Total: ~{~a~^, ~}~%" total))) (defun main (&optional file &rest ignore) (if file (ldd-tree file :ignore ignore) (format T "~&Usage: lddtree [FILE] [[IGNORE]]~%"))) (apply #'main (rest *posix-argv*))