0.9.2.43:
[sbcl/lichteblau.git] / contrib / sb-bsd-sockets / doc.lisp
blob534d61d14aabc037f5ae3a174bda5c7cd4c3d596
1 ;;;; the old documentation extracted / generator for db-sockets / sb-bsd-sockets
2 ;;;;
3 ;;;; Not used anymore as the documentation is now integrated into the user manual,
4 ;;;; but I didn't have heart yet to delete this. -- NS 20040801
6 (eval-when (:load-toplevel :compile-toplevel :execute)
7 (defpackage :db-doc (:use :cl :asdf #+sbcl :sb-ext #+cmu :ext )))
8 (in-package :db-doc)
9 ;;; turn water into wine ^W^W^W lisp into HTML
12 OK. We need a design
14 1) The aim is to document the current package, given a system.
15 2) The assumption is that the system is loaded; this makes it easier to
16 do cross-references and stuff
17 3) We output HTML on *standard-output*
18 4) Hyperlink wherever useful
19 5) We're allowed to intern symbols all over the place if we like
23 ;;; note: break badly on multiple packages
26 (defvar *symbols* nil
27 "List of external symbols to print; derived from parsing DEFPACKAGE form")
30 (defun worth-documenting-p (symbol)
31 (and symbol
32 (eql (symbol-package symbol) *package*)
33 (or (ignore-errors (find-class symbol))
34 (boundp symbol) (fboundp symbol))))
36 (defun linkable-symbol-p (word)
37 (labels ((symbol-char (c) (or (upper-case-p c) (digit-char-p c)
38 (eql c #\-))))
39 (and (every #'symbol-char word)
40 (some #'upper-case-p word)
41 (worth-documenting-p (find-symbol word)))))
43 (defun markup-word (w)
44 (if (symbolp w) (setf w (princ-to-string w)))
45 (cond ((linkable-symbol-p w)
46 (format nil "<a href=\"#~A\">~A</a>"
47 w w))
48 ((and (> (length w) 0)
49 (eql (elt w 0) #\_)
50 (eql (elt w (1- (length w))) #\_))
51 (format nil "<b>~A</b>" (subseq w 1 (1- (length w)))))
52 (t w)))
53 (defun markup-space (w)
54 (let ((para (search (coerce '(#\Newline #\Newline) 'string) w)))
55 (if para
56 (format nil "~A<P>~A"
57 (subseq w 0 (1+ para))
58 (markup-space (subseq w (1+ para) nil)))
59 w)))
61 (defun text-markup (text)
62 (let ((start-word 0) (end-word 0))
63 (labels ((read-word ()
64 (setf end-word
65 (position-if
66 (lambda (x) (member x '(#\Space #\, #\. #\Newline)))
67 text :start start-word))
68 (subseq text start-word end-word))
69 (read-space ()
70 (setf start-word
71 (position-if-not
72 (lambda (x) (member x '(#\Space #\, #\. #\Newline)))
73 text :start end-word ))
74 (subseq text end-word start-word)))
75 (with-output-to-string (o)
76 (loop for inword = (read-word)
77 do (princ (markup-word inword) o)
78 while (and start-word end-word)
79 do (princ (markup-space (read-space)) o)
80 while (and start-word end-word))))))
83 (defun do-defpackage (form stream)
84 (setf *symbols* nil)
85 (destructuring-bind (defn name &rest options) form
86 (when (string-equal name (package-name *package*))
87 (format stream "<h1>Package ~A</h1>~%" name)
88 (when (documentation *package* t)
89 (princ (text-markup (documentation *package* t))))
90 (let ((exports (assoc :export options)))
91 (when exports
92 (setf *symbols* (mapcar #'symbol-name (cdr exports)))))
93 1)))
95 (defun do-defclass (form stream)
96 (destructuring-bind (defn name super slots &rest options) form
97 (when (interesting-name-p name)
98 (let ((class (find-class name)))
99 (format stream "<p><a name=\"~A\"><i>Class: </i><b>~A</b></a>~%"
100 name name)
101 #+nil (format stream "<p><b>Superclasses: </b> ~{~A ~}~%"
102 (mapcar (lambda (x) (text-markup (class-name x)))
103 (mop:class-direct-superclasses class)))
104 (if (documentation class 'type)
105 (format stream "<blockquote>~A</blockquote>~%"
106 (text-markup (documentation class 'type))))
107 (when slots
108 (princ "<p><b>Slots:</b><ul>" stream)
109 (dolist (slot slots)
110 (destructuring-bind
111 (name &key reader writer accessor initarg initform type
112 documentation)
113 (if (consp slot) slot (list slot))
114 (format stream "<li>~A : ~A</li>~%" name
115 (if documentation (text-markup documentation) ""))))
116 (princ "</ul>" stream))
117 t))))
120 (defun interesting-name-p (name)
121 (cond ((consp name)
122 (and (eql (car name) 'setf)
123 (interesting-name-p (cadr name))))
124 (t (member (symbol-name name) *symbols* :test #'string=))))
126 (defun markup-lambdalist (l)
127 (let (key-p)
128 (loop for i in l
129 if (eq '&key i) do (setf key-p t)
131 if (and (not key-p) (consp i))
132 collect (list (car i) (markup-word (cadr i)))
133 else collect i)))
135 (defun do-defunlike (form label stream)
136 (destructuring-bind (defn name lambdalist &optional doc &rest code) form
137 (when (interesting-name-p name)
138 (when (symbolp name)
139 (setf *symbols* (remove (symbol-name name) *symbols* :test #'string=)))
140 (format stream "<p><a name=\"~A\"><table width=\"100%\"><tr><td width=\"80%\">(~A <i>~A</i>)</td><td align=right>~A</td></tr></table>~%"
141 name (string-downcase (princ-to-string name))
142 (string-downcase
143 (format nil "~{ ~A~}" (markup-lambdalist lambdalist)))
144 label)
145 (if (stringp doc)
146 (format stream "<blockquote>~A</blockquote>~%"
147 (text-markup doc)))
148 t)))
150 (defun do-defun (form stream) (do-defunlike form "Function" stream))
151 (defun do-defmethod (form stream) (do-defunlike form "Method" stream))
152 (defun do-defgeneric (form stream) (do-defunlike form "Generic Function" stream))
153 (defun do-boolean-sockopt (form stream)
154 (destructuring-bind (type lisp-name level c-name) form
155 (pushnew (symbol-name lisp-name) *symbols*)
157 (do-defunlike `(defun ,lisp-name ((socket socket) argument)
158 ,(format nil "Return the value of the ~A socket option for SOCKET. This can also be updated with SETF." (symbol-name c-name) ) 'empty)
159 "Accessor" stream)))
161 (defun do-form (form output-stream)
162 (cond ((not (listp form)) nil)
163 ((string= (symbol-name (car form)) "DEFINE-SOCKET-OPTION-BOOL")
164 (do-boolean-sockopt form output-stream))
165 ((eq (car form) 'defclass)
166 (do-defclass form output-stream))
167 ((eq (car form) 'eval-when)
168 (do-form (third form) output-stream))
169 ((eq (car form) 'defpackage)
170 (do-defpackage form output-stream))
171 ((eq (car form) 'defun)
172 (do-defun form output-stream))
173 ((eq (car form) 'defmethod)
174 (do-defmethod form output-stream))
175 ((eq (car form) 'defgeneric)
176 (do-defgeneric form output-stream))
177 (t nil)))
179 (defun do-file (input-stream output-stream)
180 "Read in a Lisp program on INPUT-STREAM and make semi-pretty HTML on OUTPUT-STREAM"
181 (let ((eof-marker (gensym)))
182 (if (< 0
183 (loop for form = (read input-stream nil eof-marker)
184 until (eq form eof-marker)
185 if (do-form form output-stream)
186 count 1 #| and
187 do (princ "<hr width=\"20%\">" output-stream) |# ))
188 (format output-stream "<hr>"
189 ))))
191 (defvar *standard-sharpsign-reader*
192 (get-dispatch-macro-character #\# #\|))
194 (defun document-system (system &key
195 (output-stream *standard-output*)
196 (package *package*))
197 "Produce HTML documentation for all files defined in SYSTEM, covering
198 symbols exported from PACKAGE"
199 (let ((*package* (find-package package))
200 (*readtable* (copy-readtable))
201 (*standard-output* output-stream))
202 (set-dispatch-macro-character
203 #\# #\|
204 (lambda (s c n)
205 (if (eql (peek-char nil s t nil t) #\|)
206 (princ
207 (text-markup
208 (coerce
209 (loop with discard = (read-char s t nil t)
210 ;initially (princ "<P>")
211 for c = (read-char s t nil t)
212 until (and (eql c #\|)
213 (eql (peek-char nil s t nil t) #\#))
214 collect c
215 finally (read-char s t nil t))
216 'string)))
217 (funcall *standard-sharpsign-reader* s c n))))
218 (dolist (c (cclan:all-components 'sb-bsd-sockets))
219 (when (and (typep c 'cl-source-file)
220 (not (typep c 'sb-bsd-sockets-system::constants-file)))
221 (with-open-file (in (component-pathname c) :direction :input)
222 (do-file in *standard-output*))))))
224 (defun start ()
225 (with-open-file (*standard-output* "index.html" :direction :output)
226 (format t "<html><head><title>SBCL BSD-Sockets API Reference</title></head><body>~%")
227 (format t
228 "<!--
229 This is a machine-generated file (from SB-BSD-SOCKETS source code, massaged
230 by doc.lisp), so do not edit it directly.
233 (asdf:operate 'asdf:load-op 'sb-bsd-sockets)
234 (document-system 'sb-bsd-sockets :package :sb-bsd-sockets)))
236 (start)