#!/mfs/pkgs/chicken/4.8.0.5/bin/csi -nbq
;; Copyright 2006-2017, Matthew Welland.
;;
;; This file is part of Megatest.
;;
;; Megatest is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; Megatest is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with Megatest. If not, see <http://www.gnu.org/licenses/>.
;;
;; Coming soon (right?) Usage: plot-code file1.scm,file2.scm "fun1,fun2,x*" *.scm > plot.dot
;; Usage: plot-code file1.scm,file2.scm *.scm > plot.dot
;; dot -Tpdf plot.dot > plot.pdf
;; first param is comma separated list of files to include in the map, use - to do all
;; second param is list of regexs for functions to include in the map
;; third param is list of files to scan
(module plot-uses
*
(import scheme chicken)
(use regex srfi-69 srfi-13)
(use matchable data-structures ports extras)
(define unituses-rx (regexp "^\\(declare \\((unit|uses) ([^\\(\\)]+)\\).*"))
(define (print-err . data)
(with-output-to-port (current-error-port)
(lambda ()
(apply print data))))
(define (process-file ignores fname)
(with-input-from-file fname
(lambda ()
(let loop ((modname "DUMMYMOD"))
(let* ((inl (read-line)))
(if (eof-object? inl)
#t
(match (string-search unituses-rx inl)
((_ dtype unitname)
(if (equal? dtype "unit")
(loop unitname)
(begin
(if (equal? dtype "uses")
(if (not (or (member modname '("DUMMYMOD"))
(member modname ignores)
(member unitname ignores)))
(print " \""unitname"\" -> \""modname"\";"))
(print-err "ERROR: bad declare line \""inl"\""))
(loop modname))))
(else
(loop modname)))))))))
;; ./utils/plot-uses todot portlogger,stml2,debugprint,mtargs
;; apimod.scm commonmod.scm configfmod.scm dbmod.scm megatestmod.scm
;; mtmod.scm processmod.scm rmtmod.scm servermod.scm
;; tcp-transportmod.scm > uses.dot
;; dot uses.dot -Tpdf -o uses.pdf
(define (main)
(match (command-line-arguments)
(("todot" ignoreunits . files)
(let* ((ignores (string-split ignoreunits ",")))
(print-err "Making graph for files: " (string-intersperse files ", "))
(print "digraph uses_unit {")
(for-each
(lambda (fname)
(print "// Filename: "fname)
(process-file ignores fname))
files)
(print "}")))
(else
(print-err "Usage: plot-uses u1,u2... file1.scm ...")
(print-err " where u1,u2... are units to ignore and file1.scm... are the files to process."))))
(main)
)
;;
;; ;; Gather the usages
;; (print "digraph G {")
;; (define curr-cluster-num 0)
;; (define function-calls '())
;;
;; (for-each
;; (lambda (fname)
;; (let ((last-func #f))
;; (print-err "Processing file " fname)
;; (print "subgraph cluster_" curr-cluster-num " {")
;; (set! curr-cluster-num (+ curr-cluster-num 1))
;; (with-input-from-file fname
;; (lambda ()
;; (with-output-to-port (current-error-port)
;; (lambda ()
;; (print "Analyzing file " fname)))
;; (print "label=\"" fname "\";")
;; (let loop ((inl (read-line))
;; (fnname "toplevel")
;; (allcalls '()))
;; (if (eof-object? inl)
;; (begin
;; (set! function-calls (cons (list fnname allcalls) function-calls))
;; (for-each
;; (lambda (call-name)
;; (hash-table-set! breadcrumbs call-name #t))
;; allcalls)
;; (print-err "function: " fnname " allcalls: " allcalls))
;; (let ((match (string-match defn-rx inl)))
;; (if match
;; (let ((func-name (cadr match)))
;; (if last-func
;; (print "\"" func-name "\" -> \"" last-func "\";")
;; (print "\"" func-name "\";"))
;; (set! last-func func-name)
;; (hash-table-set! breadcrumbs func-name #t)
;; (loop (read-line)
;; func-name
;; allcalls))
;; (let ((calls (look-for-all-calls inl fnname)))
;; (loop (read-line) fnname (append allcalls calls)))))))))
;; (print "}")))
;; targs)
;;
;; (print-err "breadcrumbs: " (hash-table-keys breadcrumbs))
;; (print-err "function-calls: " function-calls)
;;
;; (for-each
;; (lambda (function-call)
;; (print-err "function-call: " function-call)
;; (let ((fnname (car function-call))
;; (calls (cadr function-call)))
;; (for-each
;; (lambda (callname)
;; (print (if (hash-table-ref/default breadcrumbs callname #f) "" "// ")
;; "\"" fnname "\" -> \"" callname "\";"))
;; calls)))
;; function-calls)
;;
;; (print "}")
;;
;; (exit)
;;