(require 'cl)
(load (concat (getenv "SWARMDOCS") "common.el"))
(defvar *protocol-hash-table* (make-hash-table :test #'equal))
(defvar *module-hash-table* (make-hash-table))
(defconst *phases* '(:creating :setting :using))
(defvar *protocol-list*)
(defvar *method-signature-hash-table* (make-hash-table :test #'equal))
(defvar *method-signature-list*)
(defvar *general-example-counter-hash-table* (make-hash-table :test #'eq))
(defvar *method-example-counter-hash-table* (make-hash-table :test #'equal))
(defvar *macro-name-hash-table* (make-hash-table :test #'equal))
(defstruct module
sym
summary
description-list
function-list
global-list
macro-list
typedef-list
example-list)
(defstruct protocol
module
name
summary
description-list
included-protocol-list
macro-list
function-list
global-list
typedef-list
example-list
method-list
expanded-methodinfo-list)
(defstruct method
phase
factory-flag
return-type
arguments
description-list
example-list)
(defstruct global
name
module
protocol
type
description-list)
(defstruct macro
name
module
protocol
arguments
description-list)
(defstruct typedef
name
module
protocol
type
description-list)
(defstruct function
name
module
protocol
return-type
arguments
description-list
example-list)
(defstruct parse-state
tag
last-tag
phase
line
buf
summary-doc
description-doc-list
global-type
global-name
global-names
global-list
function-return-type
function-name
function-list
macro-name
macro-list
item-doc-list
method-list
typedef-list
scratch-example-list
example-list)
(defconst *doc-types* '(:method-doc :summary-doc :description-doc
:function-doc :macro-doc :typedef-doc
:global-doc :global-begin :global-end :global-break
:example-doc))
(defconst *protocol-regexp* "^@\\(protocol\\|deftype\\)")
(defconst *funcptr-regexp* "\\([^;()]*(\\s-*[*]*\\s-*\\([^*);]+\\))[^;]*\\);")
(defun find-protocol ()
(interactive)
(re-search-forward *protocol-regexp* nil t))
(defun skip-whitespace ()
(skip-chars-forward " \t\r\n"))
(defun skip-whitespace-backward ()
(skip-chars-backward " \t\r\n"))
(defun skip-backward-to-nonwhite ()
(when (looking-at "\\s-")
(skip-whitespace-backward))
(when (looking-at "\\s-")
(backward-char)))
(defun skip-name ()
(skip-chars-forward "[a-zA-Z_.][a-zA-Z0-9_.]")
(point))
(defun next-paren-expr ()
(when (looking-at "(")
(let ((beg (point)))
(forward-sexp)
(buffer-substring (1+ beg) (- (point) 1)))))
(defun next-expr ()
(list
(progn
(skip-whitespace)
(next-paren-expr))
(progn
(skip-whitespace)
(next-name))))
(defun end-of-line-position ()
(save-excursion
(end-of-line)
(point)))
(defun parse-included-protocol-list ()
(let ((eolpos (end-of-line-position)))
(loop
with beg = (search-forward "<" eolpos t)
while beg
for end = (re-search-forward "[ \t,>]" eolpos t)
unless end do (error "Bad protocol syntax")
do (backward-char)
for next = (cond ((looking-at "[ \t,>]")
(skip-chars-forward ", \t")
(if (looking-at ">")
nil
(point)))
(t (point)))
collect (buffer-substring beg (- end 1))
and do (setq beg next))))
(defun next-name ()
(let* ((beg (point))
(end (skip-name)))
(prog1
(buffer-substring beg end)
(skip-whitespace))))
(defun parse-method (protocol
factory-flag
parse-state)
(let ((phase (parse-state-phase parse-state))
(method-description-list
(reverse (parse-state-item-doc-list parse-state)))
(method-example-list
(reverse (parse-state-scratch-example-list parse-state))))
(forward-char)
(skip-whitespace)
(let* ((return-type (next-paren-expr))
arguments name)
(loop
unless (looking-at ":")
do
(setq name (next-name))
(when (looking-at ";")
(push (cons name nil) arguments))
when (looking-at ":")
do
(forward-char)
(push (cons name (next-expr)) arguments)
(setq name nil)
(while (looking-at ",")
(forward-char)
(push (cons nil (next-expr)) arguments))
(when (looking-at "//")
(beginning-of-line 2))
until (looking-at ";"))
(unless phase
(error "No phase in protocol: %s" (protocol-name protocol)))
(make-method
:phase phase
:factory-flag factory-flag
:arguments (reverse arguments)
:return-type return-type
:description-list method-description-list
:example-list method-example-list))))
(defun parse-function (module
protocol
parse-state)
(prog1
(make-function
:name (parse-state-function-name parse-state)
:module module
:protocol protocol
:return-type (parse-state-function-return-type parse-state)
:description-list (reverse (parse-state-item-doc-list parse-state))
:example-list (reverse (parse-state-scratch-example-list parse-state))
:arguments
(progn
(search-forward "(")
(loop do (skip-whitespace)
for start-pos = (point)
do
(re-search-forward "[),]")
(backward-char 2)
(skip-backward-to-nonwhite)
for arg = (buffer-substring start-pos (1+ (point)))
collect
(if (string-match "\\(.*[^a-zA-Z_]\\)\\([a-zA-Z_]+\\)" arg)
(cons (match-string 1 arg) (match-string 2 arg))
(cons arg nil))
do
(re-search-forward "[),]")
(backward-char)
until (looking-at ")")
do
(forward-char))))
(search-forward ";")))
(defun handle-function (module protocol parse-state)
(prog1
(push (parse-function module protocol parse-state)
(parse-state-function-list parse-state))
(setf (parse-state-item-doc-list parse-state) nil)))
(defun line-text ()
(buffer-substring (point) (end-of-line-position)))
(defun general-example-counter (protocol)
(let ((index
(let ((val (gethash protocol *general-example-counter-hash-table*)))
(if val
(progn
(incf (gethash protocol *general-example-counter-hash-table*))
val)
(progn
(setf (gethash protocol *general-example-counter-hash-table*) 1)
0)))))
(1+ index)))
(defun method-example-counter (protocol method)
(let ((index
(let* ((key (cons protocol method))
(val (gethash key *general-example-counter-hash-table*)))
(if val
(progn
(incf (gethash key *general-example-counter-hash-table*))
val)
(progn
(setf (gethash key *general-example-counter-hash-table*) 1)
0)))))
(1+ index)))
(defun extract-doc-string (str)
(if (> (length str) 5)
(substring str 5)
""))
(defun parse-global-using-parse-state (module protocol parse-state)
(prog1
(make-global
:name (parse-state-global-name parse-state)
:module module
:protocol protocol
:type (parse-state-global-type parse-state)
:description-list
(if (eq (parse-state-tag parse-state) :global)
(parse-state-item-doc-list parse-state)
(list (extract-doc-string (parse-state-line parse-state)))))
(setf (parse-state-item-doc-list parse-state) nil)))
(defun immediate-global-tag-processed (module protocol parse-state)
(when (member (parse-state-tag parse-state)
'(:global-begin :global-end :global-break))
(parse-global-using-parse-state module protocol parse-state)))
(defun is-doc-type (parse-state)
(member (parse-state-tag parse-state) *doc-types*))
(defun set-buf (parse-state)
(setf (parse-state-buf parse-state)
(extract-doc-string (parse-state-line parse-state))))
(defun append-buf (parse-state)
(let ((tag (parse-state-tag parse-state)))
(when (is-doc-type parse-state)
(let ((buf (parse-state-buf parse-state)))
(setf (parse-state-buf parse-state)
(let ((line (parse-state-line parse-state)))
(if (eq tag :example-doc)
(concat buf "\n" (extract-doc-string line))
(concat
(if (string-match " $" buf) buf (concat buf " "))
(extract-doc-string line)))))))))
(defun extract-funcptr-name ()
(save-excursion
(forward-char)
(backward-sexp)
(let ((end (save-excursion
(search-backward ")")
(point))))
(backward-sexp)
(search-forward "*")
(buffer-substring (point) end))))
(defun extract-funcptr-type ()
(let ((name (extract-funcptr-name)))
(save-excursion
(forward-char)
(let ((end (point)))
(backward-sexp 3)
(strip-regexp (buffer-substring (point) end) name)))))
(defun update-global-state (parse-state)
(unless (save-excursion
(beginning-of-line)
(looking-at "\\s-+//G:"))
(let ((is-terminated (looking-at ";")))
(backward-char)
(skip-backward-to-nonwhite)
(if (looking-at ")")
(let ((name (extract-funcptr-type))
(type (extract-funcptr-name)))
(setf (parse-state-global-type parse-state) name)
(setf (parse-state-global-name parse-state) type))
(progn
(backward-sexp)
(let ((name-beg (point)))
(forward-sexp)
(let ((name (buffer-substring name-beg (point))))
(setf (parse-state-global-name parse-state) name))
(when is-terminated
(beginning-of-line)
(forward-sexp)
(skip-whitespace)
(let ((type-beg (point)))
(goto-char name-beg)
(backward-char)
(skip-backward-to-nonwhite)
(let ((type (buffer-substring type-beg (1+ (point)))))
(setf (parse-state-global-type parse-state) type))))))))
(unless (parse-state-global-name parse-state)
(error "nil name (non-funcptr)"))
(unless (parse-state-global-type parse-state)
(error "nil type (non-funcptr)"))))
(defun check-global-doc-post (parse-state)
(search-forward "//G:")
(backward-char 4)
(save-excursion
(let ((last-extern (parse-state-global-name parse-state)))
(update-global-state parse-state)
(cond ((save-excursion
(beginning-of-line)
(looking-at ".*;.*//G:"))
:global-end)
((not (string= last-extern
(parse-state-global-name parse-state)))
:global-break)
(t :global-doc)))))
(defun globaldocp ()
(save-excursion
(search-forward "//G:" (end-of-line-position) t)))
(defun check-global (parse-state)
(let ((tag :global))
(re-search-forward "\\s-+")
(let ((not-eol-flag
(re-search-forward "\\(;\\|//G:\\|,\\)" (end-of-line-position) t)))
(when not-eol-flag
(backward-char))
(cond ((or (not not-eol-flag) (looking-at ":"))
(save-excursion
(let ((end (if not-eol-flag
(point)
(end-of-line-position))))
(beginning-of-line)
(forward-sexp)
(skip-whitespace)
(let ((beg (point)))
(goto-char end)
(skip-whitespace-backward)
(setf (parse-state-global-type parse-state)
(buffer-substring beg (point))))))
(if not-eol-flag
(progn
(setq tag :global-begin)
(forward-char 2))
(setq tag :global-type-only)))
((looking-at ",")
(if (globaldocp) ; implies only one
(update-global-state parse-state)
(progn
(let ((start (point)))
(setf (parse-state-global-name parse-state) nil)
(setq tag :global-names)
(save-excursion
(backward-char)
(backward-sexp)
(let ((name-beg (point)))
(search-forward ";")
(backward-char 2)
(skip-backward-to-nonwhite)
(let ((names (buffer-substring name-beg
(1+ (point)))))
(setf (parse-state-global-names parse-state)
names))
(goto-char start)
(beginning-of-line)
(forward-sexp)
(forward-char)
(let* ((type-beg (point))
(type
(buffer-substring
type-beg
(save-excursion
(goto-char name-beg)
(backward-char)
(skip-backward-to-nonwhite)
(1+ (point))))))
(setf (parse-state-global-type parse-state)
type))))))))
((looking-at ";")
(update-global-state parse-state)
(when (globaldocp)
(setq tag :global-end))))
(case tag
((:global-begin :global-end)
(search-forward "//G: ")
(backward-char 5))
(:global-names
(search-forward ";")
(setq tag :global))
((:global :global-type-only))
(otherwise
(error "unknown global tag: %s" tag))))
tag))
(defun skip-c-comment ()
(interactive)
(search-forward "*/")
(beginning-of-line 2))
(defun check-common-tags (parse-state)
(cond ((looking-at "[ \t]*$") :newline)
((looking-at "//S:") :summary-doc)
((looking-at "//D:") :description-doc)
((looking-at "//#:") :macro-doc)
((looking-at "//F:") :function-doc)
((looking-at "//T:") :typedef-doc)
((looking-at "extern\\s-\\([^(]*\\|[^()]*(\\s-*[*][^)]+)([^)]*)[^()]*\\)$")
(check-global parse-state))
((looking-at "//G:") :global-doc)
((looking-at ".+//G:") (check-global-doc-post parse-state))
((looking-at "#if 0")
(c-forward-conditional 1)
(beginning-of-line 0)
:ifdef-comment)
((looking-at "#ifndef")
:ifndef)
((looking-at "#if [^0]")
:if)
((looking-at "#endif")
:endif)
((looking-at "#else")
:else)
((looking-at "#undef")
:undef)
((looking-at "/\\*")
(skip-c-comment)
:c-comment)
((looking-at "#import")
:import)
((looking-at "")
:page-break)
((looking-at "typedef\\s-+")
:typedef)
((or (looking-at "// ") (looking-at "//$")) :objc-comment)
((looking-at "#define\\s-+\\([^() \t\n]+\\)\\(\\s-+[^()\n]+\\)?$")
(setf (parse-state-macro-name parse-state) (match-string 1))
:define)
((looking-at "#define\\s-+\\([^(\n]+\\)\\(([^)\n]*)\\)")
(setf (parse-state-macro-name parse-state) (match-string 1))
:macro)
((looking-at "@class")
:class)
((looking-at "extern\\s-+\\(Class\\s-+\\|int\\s-+\\|void\\s-\\|id\\s-+<.*\\s-\\|id\\s-\\|const\\s-+char\\s-*\\*\\|BOOL\\)\\s-*\\([^ (]+\\)\\s-*(")
(let ((return-type (match-string 1))
(function-name (match-string 2)))
(setf (parse-state-function-return-type parse-state)
(strip-regexp return-type "\\s+$"))
(setf (parse-state-function-name parse-state)
function-name))
:function)
(t nil)))
(defun check-protocol-tags (parse-state)
(let ((tag
(cond ((looking-at "CREATING") :creating)
((looking-at "SETTING") :setting)
((looking-at "USING") :using)
((looking-at "-") :method)
((looking-at "+") :factory-method)
((looking-at "//M:") :method-doc)
((looking-at "@end") :protocol-end)
((looking-at "//E:") :example-doc)
((looking-at "///M:") :bogus-method)
(t nil))))
(when (member tag '(:creating :setting :using))
(setf (parse-state-phase parse-state) tag))
tag))
(defun protocol-tag-change (parse-state)
(let ((buf (parse-state-buf parse-state)))
(case (parse-state-last-tag parse-state)
(:example-doc
(push (concat buf "\n") (parse-state-scratch-example-list parse-state))
(unless (or (parse-state-method-list parse-state)
(parse-state-item-doc-list parse-state))
(setf (parse-state-example-list parse-state)
(parse-state-scratch-example-list parse-state))
(setf (parse-state-scratch-example-list parse-state) nil)))
(:method-doc
(push buf (parse-state-item-doc-list parse-state))))))
(defun common-tag-change (parse-state)
(let ((buf (parse-state-buf parse-state)))
(case (parse-state-last-tag parse-state)
((:function-doc :macro-doc :global-doc :typedef-doc)
(push buf (parse-state-item-doc-list parse-state)))
(:summary-doc
(if (parse-state-summary-doc parse-state)
(error "summary already set")
(setf (parse-state-summary-doc parse-state) buf)))
(:description-doc
(push buf (parse-state-description-doc-list parse-state))))))
(defun handle-method (protocol factory-flag parse-state)
(push (parse-method protocol
factory-flag
parse-state)
(parse-state-method-list parse-state))
(setf (parse-state-scratch-example-list parse-state) nil)
(setf (parse-state-item-doc-list parse-state) nil)
t)
(defun parse-typedef (module protocol parse-state)
(forward-char 7)
(skip-whitespace)
(let ((type-beg (point))
(description-list (reverse (parse-state-item-doc-list parse-state))))
(if (looking-at ".*\\(union\\|struct\\)")
(progn
(search-forward "{")
(backward-char)
(forward-sexp)
(let ((type-end (point)))
(skip-whitespace)
(let ((name-beg (point)))
(search-forward ";")
(backward-char 2)
(skip-backward-to-nonwhite)
(make-typedef
:name (buffer-substring name-beg (1+ (point)))
:module module
:protocol protocol
:type (buffer-substring type-beg type-end)
:description-list description-list))))
(if (looking-at *funcptr-regexp*)
(let* ((name (match-string 2))
(type (strip-regexp (match-string 1) name)))
(make-typedef
:name name
:module module
:protocol protocol
:type type
:description-list description-list))
(progn
(search-forward ";")
(backward-char 2)
(skip-backward-to-nonwhite)
(let ((name-end (1+ (point))))
(backward-sexp)
(let ((name-beg (point)))
(skip-whitespace-backward)
(let ((type-end (point)))
(make-typedef
:name (buffer-substring name-beg name-end)
:module module
:protocol protocol
:type (buffer-substring type-beg type-end)
:description-list description-list)))))))))
(defun handle-typedef (module protocol parse-state)
(push (parse-typedef module
protocol
parse-state)
(parse-state-typedef-list parse-state))
(setf (parse-state-item-doc-list parse-state) nil)
t)
(defun parse-macro (module protocol parse-state)
(prog1
(let ((dl (parse-state-item-doc-list parse-state))
(name (parse-state-macro-name parse-state)))
(search-forward "(")
(let ((arguments
(loop do (skip-whitespace)
for start-pos = (point)
do
(re-search-forward "[),]")
(backward-char 2)
(skip-backward-to-nonwhite)
for arg = (buffer-substring start-pos (1+ (point)))
collect arg
do
(re-search-forward "[),]")
(backward-char)
until (looking-at ")")
do
(forward-char))))
(make-macro
:name name
:module module
:protocol protocol
:arguments arguments
:description-list dl)))
(while (looking-at ".*\\\\\\s-*$")
(forward-line))))
(defun parse-define (module protocol parse-state)
(prog1
(let ((dl (parse-state-item-doc-list parse-state))
(name (parse-state-macro-name parse-state)))
(let ((macro (gethash name *macro-name-hash-table*)))
(if macro
(progn
(message "duplicate #define: %s" name)
nil)
(setf (gethash name *macro-name-hash-table*)
(make-macro
:name name
:module module
:protocol protocol
:arguments :no-arguments
:description-list dl)))))
(while (looking-at ".*\\\\\\s-*$")
(forward-line))))
(defun handle-macro (module protocol parse-state)
(push (parse-macro module protocol parse-state)
(parse-state-macro-list parse-state))
(setf (parse-state-item-doc-list parse-state) nil)
t)
(defun handle-define (module protocol parse-state)
(let ((macro (parse-define module protocol parse-state)))
(when macro
(push macro (parse-state-macro-list parse-state))))
(setf (parse-state-item-doc-list parse-state) nil)
t)
(defun handle-global (module protocol parse-state)
(let ((names (parse-state-global-names parse-state)))
(if names
(progn
(loop for name in (split-string names ",")
for stripped-name = (strip-regexp name "\\s-+")
do
(push (make-global
:name stripped-name
:module module
:protocol protocol
:type (parse-state-global-type parse-state)
:description-list
(reverse
(parse-state-item-doc-list parse-state)))
(parse-state-global-list parse-state)))
(setf (parse-state-global-names parse-state) nil))
(push (parse-global-using-parse-state module protocol parse-state)
(parse-state-global-list parse-state)))
(setf (parse-state-item-doc-list parse-state) nil))
t)
(defun handle-protocol-tag (protocol parse-state)
(let ((tag (parse-state-tag parse-state))
(module (protocol-module protocol)))
(case tag
((:method :factory-method)
(handle-method protocol
(eq (parse-state-tag parse-state) :factory-method)
parse-state))
(:global
(handle-global module protocol parse-state))
(:macro
(handle-macro module protocol parse-state))
(:define
(handle-define module protocol parse-state))
(:typedef
(handle-typedef module protocol parse-state))
(:function
(handle-function module protocol parse-state))
(:protocol-end t)
(otherwise nil))))
(defun handle-common-tag (module protocol parse-state)
(let ((tag (parse-state-tag parse-state)))
(case tag
(:global
(handle-global module protocol parse-state))
(:macro
(handle-macro module protocol parse-state))
(:typedef
(handle-typedef module protocol parse-state))
(:define
(handle-define module protocol parse-state))
(:function
(handle-function module protocol parse-state))
(otherwise nil))))
(defun same-tag-p (parse-state)
(eq (parse-state-tag parse-state)
(parse-state-last-tag parse-state)))
(defun end-tag-p (parse-state)
(eq (parse-state-tag parse-state) :protocol-end))
(defun process-header-file (module protocol)
(let ((parse-state (make-parse-state)))
(beginning-of-line 1)
(while (and (zerop (forward-line 1))
(not (and protocol (end-tag-p parse-state))))
(beginning-of-line)
(let ((tag (check-common-tags parse-state)))
(unless tag
(if protocol
(progn
(setq tag (check-protocol-tags parse-state))
(unless tag
(error "Unrecognized text (protocol): [%s]"
(line-text))))
(if (looking-at *protocol-regexp*)
(progn
(re-search-forward "^@end")
(setq tag :skipped-protocol))
(error "Unrecognized text (non-protocol): [%s]"
(line-text)))))
(setf (parse-state-tag parse-state) tag))
(setf (parse-state-line parse-state) (line-text))
(let ((immediate-object
(immediate-global-tag-processed module
protocol
parse-state)))
(if immediate-object
(push immediate-object (parse-state-global-list parse-state))
(progn
(if (same-tag-p parse-state)
(append-buf parse-state)
(progn
(if protocol
(unless (protocol-tag-change parse-state)
(common-tag-change parse-state))
(common-tag-change parse-state))
(when (is-doc-type parse-state)
(set-buf parse-state)))))))
(if protocol
(unless (handle-protocol-tag protocol parse-state)
(handle-common-tag module protocol parse-state))
(handle-common-tag module protocol parse-state))
(setf (parse-state-last-tag parse-state)
(parse-state-tag parse-state)))
parse-state))
(defun load-protocol (module)
(interactive)
(skip-whitespace)
(let* ((protocol-name
(let ((beg (point)))
(skip-name)
(buffer-substring beg (point))))
(included-protocol-list
(parse-included-protocol-list))
(protocol (make-protocol
:module module
:name protocol-name
:included-protocol-list included-protocol-list)))
(let ((parse-state (process-header-file module protocol)))
(setf (protocol-summary protocol)
(parse-state-summary-doc parse-state)
(protocol-description-list protocol)
(reverse (parse-state-description-doc-list parse-state))
(protocol-macro-list protocol)
(reverse (parse-state-macro-list parse-state))
(protocol-global-list protocol)
(reverse (parse-state-global-list parse-state))
(protocol-method-list protocol)
(reverse (parse-state-method-list parse-state))
(protocol-typedef-list protocol)
(reverse (parse-state-typedef-list parse-state))
(protocol-example-list protocol)
(reverse (parse-state-example-list parse-state))))
protocol))
(defun load-protocols (module)
(interactive)
(goto-char (point-min))
(loop
while (find-protocol)
collect (load-protocol module)))
(defun load-module (module-sym)
(goto-char (point-min))
(let* ((module (make-module :sym module-sym))
(parse-state (process-header-file module nil)))
(setf (module-summary module) (parse-state-summary-doc parse-state))
(setf (module-description-list module)
(reverse (parse-state-description-doc-list parse-state)))
(setf (module-example-list module)
(reverse (parse-state-example-list parse-state)))
(setf (module-function-list module)
(reverse (parse-state-function-list parse-state)))
(setf (module-global-list module)
(reverse (parse-state-global-list parse-state)))
(setf (module-macro-list module)
(reverse (parse-state-macro-list parse-state)))
(setf (module-typedef-list module)
(reverse (parse-state-typedef-list parse-state)))
module))
(defun create-included-protocol-list (protocol)
(loop for included-protocol-name in (protocol-included-protocol-list protocol)
for included-protocol = (lookup-protocol included-protocol-name)
unless included-protocol do (error "Could not find protocol %s"
included-protocol-name)
collect included-protocol))
(defun lookup-module (module-sym)
(car (remove-if-not #'module-p (gethash module-sym *module-hash-table*))))
(defun lookup-protocol (name)
(gethash name *protocol-hash-table*))
(defun CREATABLE-protocol ()
(let ((description "Declare that a defined type supports creation."))
(make-protocol
:name "CREATABLE"
:module (lookup-module 'defobj)
:included-protocol-list nil
:summary description
:description-list (list description)
:method-list nil)))
(defun add-protocol (module-sym protocol)
(setf (gethash (protocol-name protocol) *protocol-hash-table*) protocol)
(push protocol (gethash module-sym *module-hash-table*)))
(defun module-sym-from-spec (module-spec)
(if (consp module-spec) (car module-spec) module-spec))
(defun ensure-module (module-sym)
(let ((module (lookup-module module-sym)))
(if module
module
(progn
(setq module (load-module module-sym))
(push module (gethash module-sym *module-hash-table*))))
module))
(defun load-all-modules ()
(interactive)
(let ((old-push-mark (symbol-function 'push-mark)))
(when noninteractive
(setf (symbol-function 'push-mark)
#'(lambda ()
(funcall old-push-mark nil t))))
(clrhash *protocol-hash-table*)
(clrhash *module-hash-table*)
(loop for module-spec in *swarm-modules*
for module-sym = (module-sym-from-spec module-spec)
do
(if (consp module-spec)
(find-file-read-only
(pathname-for-module-sym module-sym (cdr module-spec)))
(find-file-read-only (pathname-for-module-sym module-sym)))
(let ((module (ensure-module module-sym)))
(loop for protocol in (load-protocols module)
for name = (protocol-name protocol)
for exist = (gethash name *protocol-hash-table*)
when exist do (error "Protocol %s already exists" name)
do (add-protocol module-sym protocol)))
(kill-buffer (current-buffer)))
(add-protocol 'defobj (CREATABLE-protocol))
(when noninteractive
(setf (symbol-function 'push-mark) old-push-mark))
(loop for protocol being each hash-value of *protocol-hash-table*
do
(setf (protocol-included-protocol-list protocol)
(create-included-protocol-list protocol)))))
(defun compare-string-lists (a b)
(let ((diff
(loop for a-arg in a
for b-arg in b
if (string< a-arg b-arg) return -1
else if (not (string= a-arg b-arg)) return 1
finally return 0)))
(if (zerop diff)
(< (length a) (length b))
diff)))
(defun generate-expanded-methodinfo-list (protocol)
(let ((expanded-protocols-hash-table (make-hash-table))
(method-hash-table (make-hash-table)))
(flet ((expand-protocol-level (protocol level)
(setf (gethash protocol expanded-protocols-hash-table) t)
(loop for method in (protocol-method-list protocol)
do (setf (gethash method method-hash-table) (cons level protocol)))
(loop for included-protocol in
(protocol-included-protocol-list protocol)
do
(unless (gethash included-protocol expanded-protocols-hash-table)
(expand-protocol-level included-protocol (1+ level))))))
(expand-protocol-level protocol 0))
(sort
(loop for method being each hash-key of method-hash-table using (hash-value level.protocol)
collect (list (car level.protocol)
(cdr level.protocol)
method))
#'(lambda (a b)
(flet ((phase-pos (phase)
(case phase
(:creating 0)
(:setting 1)
(:using 2)))
(compare-arguments (a b)
(flet ((get-key-list (item) (mapcar #'first item)))
(compare-string-lists
(get-key-list a)
(get-key-list b)))))
(let ((level-diff (- (first a) (first b))))
(if (zerop level-diff)
(let* ((method-a (third a))
(method-b (third b))
(phase-diff (- (phase-pos (method-phase method-a))
(phase-pos (method-phase method-b)))))
(if (zerop phase-diff)
(compare-arguments (method-arguments method-a)
(method-arguments method-b))
(< phase-diff 0)))
(< level-diff 0))))))))
(defun generate-expanded-methodinfo-lists ()
(interactive)
(loop for protocol being each hash-value of *protocol-hash-table*
do
(setf (protocol-expanded-methodinfo-list protocol)
(generate-expanded-methodinfo-list protocol))))
(defun external-protocol-name (protocol)
(let ((raw-protocol-name (protocol-name protocol)))
(if (internal-protocol-p protocol)
(substring raw-protocol-name 1)
raw-protocol-name)))
(defun get-method-signature (method)
(with-output-to-string (print-method-signature method)))
(defun protocol-index (protocol)
(position protocol *protocol-list*))
(defun method-signature-index (method-signature)
(position method-signature *method-signature-list* :test #'string=))
(defun module-name (module)
(symbol-name (module-sym module)))
(defun sgml-object-id (type module protocol &optional name)
(cook-id
(let* ((type-str (upcase (symbol-name type)))
(base-id
(if protocol
(let* ((cooked-protocol-name (external-protocol-name protocol)))
(concat "SWARM."
(upcase (module-name (protocol-module protocol)))
"."
(upcase cooked-protocol-name)
"."
type-str))
(concat "SWARM."
(upcase (module-name module))
".GENERIC."
type-str))))
(if name
(concat base-id "." (upcase name))
base-id))))
(defun sgml-protocol-id (protocol)
(sgml-object-id 'protocol
(protocol-module protocol)
protocol))
(defun sgml-method-signature-id (protocol phase method-signature)
(sgml-object-id 'method
(protocol-module protocol)
protocol
(format "P%s.M%d"
(case phase
(:creating "C")
(:setting "S")
(:using "U")
(otherwise (error "bad phase")))
(method-signature-index method-signature))))
(defun sgml-module-id (module)
(sgml-object-id 'module
module
nil))
(defun object-type (object)
(cond ((protocol-p object) 'protocol)
((module-p object) 'module)
((global-p object) 'global)
((function-p object) 'function)
((macro-p object) 'macro)
((typedef-p object) 'typedef)
(t (error "unknown object type"))))
(defun generic-module (object)
(let ((type (object-type object)))
(case type
(protocol (protocol-module object))
(module object)
(function (function-module object))
(global (global-module object))
(macro (macro-module object))
(typedef (typedef-module object))
(otherwise (error "unknown type: %s" type)))))
(defun generic-summary (object)
(cond ((protocol-p object) (protocol-summary object))
((module-p object) (module-summary object))
(t (error "unknown object"))))
(defun generic-description-list (object)
(reverse
(cond ((protocol-p object)
(protocol-description-list object))
((module-p object)
(module-description-list object))
(t (error "unknown object")))))
(defun generic-protocol (object)
(case (object-type object)
(function (function-protocol object))
(global (global-protocol object))
(macro (macro-protocol object))
(typedef (typedef-protocol object))
(otherwise (error "unknown type"))))
(defun generic-name (object)
(case (object-type object)
(protocol (protocol-name object))
(module (module-name object))
(function (function-name object))
(global (global-name object))
(macro (macro-name object))
(typedef (typedef-name object))
(otherwise (error "unknown type"))))
(defun generic-macro-list (object)
(case (object-type object)
(protocol (protocol-macro-list object))
(module (module-macro-list object))))
(defun generic-typedef-list (object)
(case (object-type object)
(protocol (protocol-typedef-list object))
(module (module-typedef-list object))))
(defun generic-function-list (object)
(case (object-type object)
(protocol (protocol-function-list object))
(module (module-function-list object))))
(defun generic-global-list (object)
(case (object-type object)
(protocol (protocol-global-list object))
(module (module-global-list object))))
(defun sgml-id (object)
(sgml-object-id (object-type object)
(generic-module object)
(generic-protocol object)
(generic-name object)))
(defun sgml-refentry-start (obj)
(insert "\n"))
(defun sgml-refmeta (object)
(let (title module-name)
(cond ((protocol-p object)
(setq title (protocol-name object))
(setq module-name (module-name (protocol-module object))))
((module-p object)
(setq title "General")
(setq module-name (module-name object)))
(t (error "unknown object")))
(insert "\n")
(insert "")
(insert title)
(insert "\n")
(insert "")
(insert module-name)
(insert "\n")
(insert "\n")))
(defun sgml-namediv (object)
(insert "\n")
(insert "")
(insert (generic-name object))
(insert "\n")
(insert "\n")
(insert (generic-summary object))
(insert "\n\n")
(insert "\n"))
(defun sgml-refsect1-text-list (title text-list)
(when text-list
(insert "\n")
(insert "")
(insert-text title)
(insert "\n")
(loop for text in text-list
do
(insert "\n")
(insert-text text)
(insert "\n\n"))
(insert "\n")))
(defun sgml-refsect1-description (object)
(sgml-refsect1-text-list "Description" (generic-description-list object)))
(defun sgml-funcsynopsisinfo (class-name description-list)
(insert "\n")
(insert "")
(insert class-name)
(insert "\n")
(loop for description in description-list
do
(insert-text description)
(insert "\n"))
(insert "\n"))
(defun print-method-signature (method &optional stream)
(if (method-factory-flag method)
(princ "+" stream)
(princ "-" stream))
(loop for arguments in (method-arguments method)
for key = (first arguments)
when key do (princ key stream)
when (third arguments) do (princ ":" stream)))
(defun sgml-method-funcsynopsis (owner-protocol method)
(insert "\n")
(insert "\n")
(insert "")
(let ((return-type (method-return-type method)))
(when return-type
(insert-text return-type)))
(insert "")
(print-method-signature method (current-buffer))
(insert "")
(insert "\n")
(let ((arguments (method-arguments method)))
(if (and (eql (length arguments) 1)
(null (third (first arguments))))
(insert "\n")
(loop for arg in arguments
for type = (second arg)
do
(insert "")
(when type
(insert-text type))
(insert "")
(insert-text (third arg))
(insert "")
(insert "\n"))))
(insert "\n")
(sgml-funcsynopsisinfo (protocol-name owner-protocol)
(method-description-list method))
(insert "\n"))
(defun sgml-link-to-protocol (protocol)
(insert "")
(insert (external-protocol-name protocol))
(insert ""))
(defun methodinfo-list-for-phase (protocol phase)
(loop for methodinfo in (protocol-expanded-methodinfo-list protocol)
when (eq (method-phase (third methodinfo)) phase)
collect methodinfo))
(defun include-p (level protocol owner-protocol)
(or (zerop level)
(let ((owner-protocol-name (protocol-name owner-protocol)))
(when (internal-protocol-p owner-protocol)
(string=
(substring (protocol-name owner-protocol) 1)
(protocol-name protocol))))))
(defun count-included-methodinfo-entries (protocol phase)
(loop for methodinfo in (methodinfo-list-for-phase protocol phase)
count (include-p (first methodinfo)
protocol
(second methodinfo))))
(defun count-included-methodinfo-entries-for-all-phases (protocol)
(loop for phase in *phases*
sum (count-included-methodinfo-entries protocol phase)))
(defun sgml-method-definitions (protocol
phase
&optional protocol-listitem-flag)
(unless (zerop (count-included-methodinfo-entries protocol phase))
(let ((methodinfo-list (methodinfo-list-for-phase protocol phase))
have-list have-item)
(when protocol-listitem-flag
(insert "\n"))
(loop with last-protocol = nil
for methodinfo in methodinfo-list
for level = (first methodinfo)
for owner-protocol = (second methodinfo)
for method = (third methodinfo)
for new-group-flag = (not (eq owner-protocol last-protocol))
when new-group-flag do
(when have-list
(insert "\n")
(setq have-list nil))
(when have-item
(insert "\n")
(setq have-item nil))
(when protocol-listitem-flag
(when (include-p level protocol owner-protocol)
(insert "\n")
(setq have-item t)
(insert "")
(insert (external-protocol-name owner-protocol))
(insert "\n")))
(when (include-p level protocol owner-protocol)
(setq have-list t)
(insert "\n"))
do
(when (include-p level protocol owner-protocol)
(insert "\n")
(sgml-method-funcsynopsis owner-protocol method)
(sgml-method-examples owner-protocol method)
(insert "\n"))
for last-protocol = owner-protocol)
(when have-list
(insert "\n"))
(when protocol-listitem-flag
(when have-item
(insert "\n"))
(insert "\n")))))
(defun sgml-macro (macro)
(if (eq :no-arguments (macro-arguments macro))
(progn
(insert "\n")
(insert-text (macro-name macro))
(insert "\n\n")
(loop for text in (macro-description-list macro)
do
(insert "\n")
(insert-text text)
(insert "\n")))
(progn
(insert "\n")
(insert "\n")
(insert "")
(insert "")
(insert-text (macro-name macro))
(insert "")
(insert "\n")
(loop for arg in (macro-arguments macro)
do
(when arg
(insert "")
(insert "")
(insert arg)
(insert "")
(insert "\n")))
(insert "\n")
(sgml-funcsynopsisinfo "(MACRO)"
(macro-description-list macro))
(insert "\n"))))
(defun sgml-function (function)
(insert "\n")
(insert "\n")
(insert "")
(insert-text (function-return-type function))
(insert "")
(insert-text (function-name function))
(insert "")
(insert "\n")
(loop for type.name in (function-arguments function)
do
(insert "")
(insert-text (car type.name))
(insert "")
(let ((name (cdr type.name)))
(when name
(insert-text name)))
(insert "")
(insert "\n"))
(insert "\n")
(sgml-funcsynopsisinfo "(FUNCTION)"
(function-description-list function))
(insert "\n"))
(defun sgml-typedef (typedef)
(insert "\n")
(insert (typedef-name typedef))
(insert "\n\n")
(insert (typedef-type typedef))
(insert "\n")
(insert "\n"))
(defun name< (a b)
(string< (generic-name a) (generic-name b)))
(defun sgml-refsect1-object-list (title
object-list
print-object-func)
(when object-list
(insert "\n")
(insert "")
(insert-text title)
(insert "\n")
(insert "\n")
(loop for object in (sort object-list #'name<)
do
(insert "\n")
(funcall print-object-func object)
(insert "\n"))
(insert "\n")
(insert "\n")))
(defun sgml-refsect1-macro-list (object)
(sgml-refsect1-object-list "Macros"
(generic-macro-list object)
#'sgml-macro))
(defun sgml-refsect1-typedef-list (object)
(sgml-refsect1-object-list "Typedefs"
(generic-typedef-list object)
#'sgml-typedef))
(defun sgml-refsect1-function-list (object)
(sgml-refsect1-object-list "Functions"
(generic-function-list object)
#'sgml-function))
(defun sgml-refsect1-global-list (object)
(let ((global-list (generic-global-list object)))
(when global-list
(insert "\n")
(insert "")
(insert "Globals")
(insert "\n")
(insert "\n")
(loop for global in global-list
do
(insert "\n")
(insert "")
(insert-text (global-type global))
(insert "\n")
(insert "")
(insert-text (global-name global))
(insert "\n")
(let ((description-list (global-description-list global)))
(if description-list
(progn
(insert "\n")
(loop for text in description-list
do
(insert "\n")
(insert-text text)
(insert "\n"))
(insert "\n"))
(insert "No description available.\n")))
(insert "\n"))
(insert "\n")
(insert "\n"))))
(defun sgml-examples (object)
(let ((example-list (protocol-example-list object)))
(when example-list
(insert "")
(insert "\n")
(insert "\n")
(loop for example in example-list
do
(insert "\n\n\n"))
(insert "\n"))))
(defun count-method-examples (protocol phase)
(loop for methodinfo in (methodinfo-list-for-phase protocol phase)
for method = (third methodinfo)
count (method-example-list method)))
(defun count-noninternal-protocols (protocol)
(loop for included-protocol in (protocol-included-protocol-list protocol)
count (not (internal-protocol-p included-protocol))))
(defun compare-method-signatures (method-a method-b)
(let* ((method-a-signature (get-method-signature method-a))
(method-b-signature (get-method-signature method-b)))
(string< method-a-signature method-b-signature)))
(defun compare-methodinfo (a b)
(let ((protocol-name-a (protocol-name (second a)))
(protocol-name-b (protocol-name (second b))))
(if (string= protocol-name-a protocol-name-b)
(compare-method-signatures (third a) (third b))
(string< protocol-name-a protocol-name-b))))
(defun sgml-method-examples (protocol method)
(when (method-example-list method)
(insert "")
(insert "")
(insert "\n")
(insert "\n")
(loop for example in (method-example-list method)
do
(insert example)
(insert "\n"))
(insert "\n")
(insert "\n")))
(defun sgml-methods-for-phase (protocol phase)
(unless (zerop (count-included-methodinfo-entries protocol phase))
(insert "\n")
(insert "Phase: ")
(insert (capitalize (substring (prin1-to-string phase) 1)))
(insert "\n")
(sgml-method-definitions protocol phase)
(insert "\n")))
(defun sgml-refsect1-protocol-list (protocol &optional expand-flag)
(insert "\n")
(insert "Protocols adopted by ")
(insert (protocol-name protocol))
(insert "\n")
(if (zerop (count-noninternal-protocols protocol))
(insert "None\n")
(flet ((print-expanded-protocol-list (protocol)
(insert "\n")
(loop for included-protocol in
(protocol-included-protocol-list protocol)
do
(unless (internal-protocol-p protocol)
(insert "\n")
(insert "")
(sgml-link-to-protocol included-protocol)
(insert "\n")
(print-expanded-protocol-list included-protocol)
(insert "\n")))
(insert "\n"))
(print-unexpanded-protocol-list (protocol)
(insert "")
(loop for included-protocol in
(protocol-included-protocol-list protocol)
do
(unless (internal-protocol-p protocol)
(insert " ")
(sgml-link-to-protocol included-protocol)))
(insert "\n")))
(if expand-flag
(print-expanded-protocol-list protocol)
(print-unexpanded-protocol-list protocol))))
(insert "\n"))
(defun sgml-refsect1-method-list (protocol)
(insert "Methods\n")
(if (zerop (count-included-methodinfo-entries-for-all-phases protocol))
(insert "None\n")
(loop for phase in *phases*
do (sgml-methods-for-phase protocol phase)))
(insert "\n"))
(defun sgml-refsect1-examples (protocol)
(when (protocol-example-list protocol)
(insert "Examples\n")
(sgml-examples protocol)
(insert "\n")))
(defun internal-protocol-p (protocol)
(string= (substring (protocol-name protocol) 0 1) "_"))
(defun generate-refentry (object)
(unless (and (protocol-p object) (internal-protocol-p object))
(sgml-refentry-start object)
(sgml-refmeta object)
(sgml-namediv object)
(sgml-refsect1-description object)
(when (protocol-p object)
(sgml-refsect1-protocol-list object)
(sgml-refsect1-method-list object))
(sgml-refsect1-macro-list object)
(sgml-refsect1-function-list object)
(sgml-refsect1-typedef-list object)
(sgml-refsect1-global-list object)
(when (protocol-p object)
(sgml-refsect1-examples object))
(insert "\n")))
(defun sgml-generate-refentries-for-module (module-sym)
(loop for object in (sort (gethash module-sym *module-hash-table*)
#'name<)
do (generate-refentry object)))
(defun sgml-create-refentries-for-module (module-sym)
(let ((module-name (symbol-name module-sym)))
(with-temp-file (pathname-for-swarmdocs-pages-output module-sym)
(sgml-generate-refentries-for-module module-sym))))
(defun sgml-create-refentries-for-all-modules ()
(interactive)
(loop for module-sym being each hash-key of *module-hash-table*
do
(sgml-create-refentries-for-module module-sym)))
(defun build-method-signature-hash-table ()
(loop for protocol being each hash-value of *protocol-hash-table*
do
(loop for method in (protocol-method-list protocol)
do
(push (cons protocol method)
(gethash (get-method-signature method)
*method-signature-hash-table*)))))
(defun build-protocol-vector ()
(setq *protocol-list*
(sort
(loop for protocol being each hash-value of *protocol-hash-table*
collect protocol)
#'name<)))
(defun build-method-signature-vector ()
(setq *method-signature-list*
(sort
(loop for method-signature being each hash-key of
*method-signature-hash-table*
collect method-signature)
#'string<)))
(defun sgml-protocol-indexentry (protocol)
(insert "\n")
(insert "")
(insert (external-protocol-name protocol))
(insert "\n")
(insert "\n"))
(defun sgml-generate-protocol-index ()
(insert "\n")
(insert "Protocol Index\n")
(loop for protocol in *protocol-list*
unless (internal-protocol-p protocol)
do (sgml-protocol-indexentry protocol))
(insert "\n"))
(defun sgml-method-signature-indexentry (method-signature)
(insert "\n")
(insert "")
(insert method-signature)
(insert "\n")
(insert "\n"))
(defun sgml-generate-method-signature-index ()
(insert "\n")
(insert "Method Index\n")
(loop for method-signature in *method-signature-list*
do (sgml-method-signature-indexentry method-signature))
(insert "\n"))
(defun collect-objects-of-type (type)
(let ((object-accessor
(case type
(function #'generic-function-list)
(global #'generic-global-list)
(macro #'generic-macro-list)
(typedef #'generic-typedef-list)
(otherwise (error "unknown type")))))
(loop for module-sym being each hash-key of *module-hash-table*
append
(loop for object in (gethash module-sym *module-hash-table*)
append (funcall object-accessor object)))))
(defun sgml-indexentry (object)
(insert "\n")
(insert "")
(insert (generic-name object))
(insert "\n")
(insert "\n"))
(defun sgml-generate-index-of-type (type)
(insert "\n")
(insert "")
(insert (capitalize (symbol-name type)))
(insert " Index")
(insert "\n")
(loop for object in (sort (collect-objects-of-type type) #'name<)
do (sgml-indexentry object))
(insert "\n"))
(defun sgml-generate-indices ()
(with-temp-file (concat (get-swarmdocs-build-area) "refbook/refindex.sgml")
(sgml-generate-protocol-index)
(sgml-generate-method-signature-index)
(loop for type in '(function global macro typedef)
do (sgml-generate-index-of-type type))))
(defun load-and-process-modules ()
(interactive)
(load-all-modules)
(generate-expanded-methodinfo-lists)
(build-method-signature-hash-table)
(build-protocol-vector)
(build-method-signature-vector))
(defun run-all ()
(interactive)
(load-and-process-modules)
(sgml-create-refentries-for-all-modules) (sgml-generate-indices)
nil)
(defun vcg-graph-all-protocols ()
(loop for module-sym being each hash-key of *module-hash-table*
using (hash-values module-items)
for module-name = (concat "M:" (symbol-name module-sym))
do
(insert "graph: {\nfolding: 1 color: blue title: \"")
(insert (capitalize module-name))
(insert "\"\n")
(insert "node: { title: \"")
(insert module-name)
(insert "\" }\n")
(loop for module-item in module-items do
(cond ((and (protocol-p module-item)
(not (internal-protocol-p module-item)))
(let ((protocol-name (protocol-name module-item)))
(insert "node: { title: \"")
(insert protocol-name)
(insert "\" shape: ellipse color: red }\n")
(insert "edge: { targetname: \"")
(insert protocol-name)
(insert "\" sourcename: \"")
(insert module-name)
(insert "\" }\n"))
(loop for included-protocol in
(protocol-included-protocol-list module-item)
unless (internal-protocol-p included-protocol)
do
(insert "backedge: { targetname: \"")
(insert (protocol-name module-item))
(insert "\" sourcename: \"")
(insert (protocol-name included-protocol))
(insert "\" }\n")))))
(insert "}\n")))
(defun vcg-output-protocols-graph ()
(interactive)
(with-temp-file (concat (get-swarmdocs-build-area) "protocols.vcg")
(insert "graph: {\n")
(insert "orientation: left_to_right\n")
(vcg-graph-all-protocols)
(insert "}\n")))
(defun dot-graph-all-protocols ()
(loop for module-sym being each hash-key of *module-hash-table*
using (hash-values module-items)
for module-name = (symbol-name module-sym)
do
(loop for module-item in module-items do
(cond ((and (protocol-p module-item)
(not (internal-protocol-p module-item)))
(loop for included-protocol in
(protocol-included-protocol-list module-item)
unless (internal-protocol-p included-protocol)
do
(insert "\"")
(insert (protocol-name module-item))
(insert "\" -> \"")
(insert (protocol-name included-protocol))
(insert "\"\n")))))
(insert "subgraph cluster_")
(insert module-name)
(insert " { label=\"")
(insert (capitalize module-name))
(insert "\"\n")
(loop for module-item in module-items do
(cond ((and (protocol-p module-item)
(not (internal-protocol-p module-item)))
(insert "\"")
(insert (protocol-name module-item))
(insert "\"; "))))
(insert "}\n")))
(defun dot-output-protocols-graph ()
(interactive)
(with-temp-file (concat (get-swarmdocs-build-area) "protocols.dot")
(insert "digraph \"Swarm Protocols\" {\n");
(insert "page=\"10,7.5\"\n")
(insert "ratio=auto\n")
(dot-graph-all-protocols)
(insert "}\n")))
(defun dot-graph-module (edge-hash-table module-sym &optional module-items)
(unless module-items
(setq module-items (gethash module-sym *module-hash-table*)))
(let ((module-name (symbol-name module-sym))
(included-module-hash-table (make-hash-table))
local-protocols)
(loop for module-item in module-items do
(cond ((and (protocol-p module-item)
(not (internal-protocol-p module-item)))
(loop for included-protocol in
(protocol-included-protocol-list module-item)
for included-module-sym =
(module-sym (protocol-module included-protocol))
unless (internal-protocol-p included-protocol)
do
(let ((edge-key (cons module-item included-protocol)))
(unless (gethash edge-key edge-hash-table)
(insert "\"")
(insert (protocol-name module-item))
(insert "\" -> \"")
(insert (protocol-name included-protocol))
(insert "\"\n")
(setf (gethash edge-key edge-hash-table) t)))
(if (eq included-module-sym module-sym)
(push included-protocol local-protocols)
(push included-protocol
(gethash included-module-sym
included-module-hash-table))
)))))
(insert "subgraph cluster_")
(insert module-name)
(insert " { label=\"")
(insert (capitalize module-name))
(insert "\"\n")
(loop for module-item in (append module-items local-protocols) do
(cond ((and (protocol-p module-item)
(not (internal-protocol-p module-item)))
(insert "\"")
(insert (protocol-name module-item))
(insert "\"; "))))
(insert "}\n")
(loop for included-module-sym being each hash-key of
included-module-hash-table
do
(dot-graph-module edge-hash-table
included-module-sym
(gethash included-module-sym
included-module-hash-table)))))
(defun dot-output-module-graph (module-sym)
(let ((edge-hash-table (make-hash-table :test #'equal)))
(with-temp-file (concat (get-swarmdocs-build-area)
(symbol-name module-sym)
".dot")
(insert "digraph ")
(insert (capitalize (symbol-name module-sym)))
(insert " {\n")
(insert "size=\"10,7.5\"\n")
(insert "ratio=compress\n")
(insert "rotate=90\n")
(dot-graph-module edge-hash-table module-sym)
(insert "}\n"))))
(defun dot-output-each-module-graph ()
(interactive)
(loop for module-sym being each hash-key of *module-hash-table* do
(dot-output-module-graph module-sym)))