summaryrefslogtreecommitdiff
path: root/docsrc/s2h/s2h.lsp
diff options
context:
space:
mode:
Diffstat (limited to 'docsrc/s2h/s2h.lsp')
-rw-r--r--docsrc/s2h/s2h.lsp1642
1 files changed, 1642 insertions, 0 deletions
diff --git a/docsrc/s2h/s2h.lsp b/docsrc/s2h/s2h.lsp
new file mode 100644
index 0000000..09490e3
--- /dev/null
+++ b/docsrc/s2h/s2h.lsp
@@ -0,0 +1,1642 @@
+; s2h -- scribe to html
+
+; MajorHeading = H1
+; Chapter, Unnumbered, Appendix = H2
+; Section = Heading = H3
+; SubSection = SubHeading = H4
+; Paragraph = H5
+
+; Files:
+; *dest* -- the title and table of contents
+; part1.html -- for each unnumbered, chapter, appendix,
+; at end of each part, link to: next part,
+; index, and table of contents
+; at beginning of each part, link to: prev part,
+; next part, index, and table of contents
+; indx.html -- the index (not "index", because that's a special name)
+; title.html -- the title page and table of contents
+; guide.html -- the table of contents and index for left frame
+; home.html -- the top-level document with two frames, the actual name
+; of this file is given by the dest parameter of (G ...)
+; NyquistWords.txt -- completion list file
+
+
+; Fancy control:
+; add the following to Scribe file:
+; @textform(html = [])
+; @textform(htmltitle = [])
+; @textform(pragma = [])
+; To get a title, add this to the file:
+; @html(<head><title>Your Title Here</title></head><body>)
+; If you use frames, you should add this to the scribe document:
+; @htmltitle(Your Title Here)
+; This tells the translator the html title to use for the root
+; html file.
+; anything inside @html{...} is output directly to output html file
+; anything in the @pragma{...} is executed as a command to this translator
+; some pragma commands are:
+; defn -- the next @index() marks a term's definition in the manual
+; startscribe -- ignore scribe file starting here
+; endscribe -- stop ignoring scribe file
+; startref -- use text between here and an @ref or @pageref as link text
+; doinclude -- process the next include file (default is to ignore)
+; endcodef -- end a code definition (used for completion list)
+; citations are translated to links according to data in citations.lsp
+; (the actual bibliographic references must be hand-translated to HTML)
+; alter *bgcolorinfo* to set background color of html documents
+; set *8.3* to change from "indx.html" to "INDX.HTM" format for file names
+
+;; label-list shall look like this:
+;; ((label-symbol "label text" file-name number) ...)
+;; where label-symbol is the scribe label,
+;; and the rest is used like this:
+;; <a href = "file-name#number">label text</a>
+(cond ((boundp '*label-list*)
+ (setf *previous-label-list* *label-list*)))
+(setf *label-list* nil)
+
+;; number of parts must be obtained from previous pass
+(cond ((boundp '*number-of-parts*)
+ (setf *previous-number-of-parts* *number-of-parts*)))
+(setf *number-of-parts* nil)
+
+(cond ((not (boundp '*citations*))
+ (load (strcat (current-path) "/citations.lsp"))))
+
+;; set this to trace parser input to help locate errors in input file
+(cond ((not (boundp '*token-trace*))
+ (setf *token-trace* nil)))
+
+(cond ((and (boundp '*inf*) *inf*)
+ (format t "closing *inf*\n")
+ (setf *inf* nil)))
+(cond ((and (boundp '*footnotefile*) *footnotefile*)
+ (format t "closing *footnotefile*\n")
+ (close *footnotefile*)
+ (setf *footnotefile* nil)))
+(cond ((and (boundp '*outf*) *outf*)
+ (setf *outf* nil)))
+
+;; when @pragma(defn) is seen, this flag is set to t, when
+;; the following @index(...) is seen, the flag is cleared and
+;; the index is entered as a definition of the term, meaning
+;; the referenced location will go to the head of the list.
+;; Later, when we want to find help for a term, we know that
+;; the help information is located by the first entry in the
+;; index for this term.
+(setf definition-flag nil)
+
+(defun open-paren ()
+ (let ((tok (get-token)))
+ (cond ((member tok '(#\( #\{ #\[ #\<))
+ (push tok paren-stack))
+ (t
+ (push tok *next-tokens*)
+ ;; if no open paren, then fake open and close
+ (push #\( paren-stack)
+ (push #\) *next-tokens*)))))
+
+
+;; ((label-symbol "label text" file-name number) ...)
+(defun write-label ()
+ (let ((body (get-body "label" nil)))
+ (push (list (list-to-symbol body) *name-reference*
+ *file-name* *name-number*)
+ *label-list*)))
+
+(defun do-make ()
+ (let ((what (get-body "make" nil)))
+ (setf what (string-upcase
+ (list-to-string what)))
+ (setf what (intern what))
+ (cond ((member what '(manual article))
+ (setf *document-type* what))
+ (t
+ (format t "Unknown document type: ~A, assuming ARTICLE~%" what)
+ (setf *document-type* 'ARTICLE)))))
+
+(defun get-body (what spacesok)
+ (prog (tok body)
+loop
+ (setf tok (get-token))
+ (cond ((not (characterp tok))
+ (format t "expected characters in ~A: ~A\n" what tok))
+ ((paren-match tok)
+ (pop paren-stack)
+ (return (reverse body)))
+ ((and (not spacesok) (eql #\Space tok)))
+ ((null tok)
+ (format t "early end of file\n")
+ (break))
+ (t
+ (push tok body)))
+ (go loop)))
+
+
+(defun write-code ()
+ (if *omit* nil (format *outf* "<code>"))
+ (translate)
+ (if *omit* nil (format *outf* "</code>")))
+
+(defun write-codef ()
+ (progv '(*codef*) '(t) (write-code) (codef-complete)))
+
+(defun write-quotation ()
+ (format *outf* "<blockquote>")
+ (translate)
+ (format *outf* "</blockquote>"))
+
+(defun write-normal ()
+ (format *outf* "<span style=\"font-style:normal\">")
+ (translate)
+ (format *outf* "</span>"))
+
+(defun write-t ()
+ (let (paren)
+ (format *outf* "<tt>")
+ (translate)
+ (format *outf* "</tt>")))
+
+(defun list-to-string (body)
+ (let ((str ""))
+ (dolist (ch body)
+ (setf str (strcat str (string ch))))
+ str))
+
+(defun list-to-symbol (body)
+ (setf cmd (intern (string-upcase (list-to-string body)))))
+
+;; index-casify -- first letter upper, all others lower
+;;
+(defun index-casify (item)
+ (nstring-downcase item)
+ (nstring-upcase item :start 0 :end 1))
+
+(defun enter-index-item (item def-flag)
+ (setf item (index-casify item))
+ (setf *index-number* (1+ *index-number*))
+ (let ((entry (assoc item *index-list* :test #'equal))
+ (ref (list *file-name* *index-number*))
+ front)
+ (cond ((and entry def-flag)
+ ;; put new reference at beginning of list
+ (rplacd entry (cons ref (cdr entry))))
+ (entry
+ (nconc entry (list ref)))
+ (t
+ (push (list item ref) *index-list*)))
+ *index-number*))
+
+(defun write-index (&optional def-flag)
+ (let (body str n)
+ (setf body (get-body "index" t))
+ (setf str (list-to-string body))
+ (if *token-trace* (format t "Index item: ~A~%" str))
+ (setf n (enter-index-item str def-flag))
+ (format *outf* "<a name=\"index~A\">" n)))
+
+(defun index-sort-fn (a b)
+ (string< (car a) (car b)))
+
+(defun mysort (list)
+ (setf list (cons 'header list))
+ (prog (first ptr result)
+loop1
+ (cond ((null (cdr list))
+ (return result)))
+; (display "loop1" list result)
+ (setf first list)
+ (setf ptr (cdr first))
+loop
+ (cond ((null (cdr ptr))
+ (go gotone))
+ ((index-sort-fn (cadr first) (cadr ptr))
+ (setf first ptr)))
+ (setf ptr (cdr ptr))
+ (go loop)
+gotone
+ (push (cadr first) result)
+ (rplacd first (cddr first))
+ (go loop1)))
+
+(cond ((not (boundp '*bgcolorinfo*))
+ (setf *bgcolorinfo* " bgcolor=\"ffffff\"")))
+(cond ((not (boundp '*8.3*))
+ (setf *8.3* nil)))
+
+(defun html-file (namestring)
+ (cond (*8.3*
+ (setf namestring (string-upcase namestring))
+ (cond ((> (length namestring) 8)
+ (setf namestring (subseq namestring 0 8))))
+ (strcat namestring ".HTM"))
+ (t
+ (strcat namestring ".html"))))
+
+(defun generate-index-entry (entry target)
+ (let (n)
+ ;; if only one target for index entry, make the word be a link
+ (cond ((= 1 (length (cdr entry)))
+ (format *outf* "<a href=\"~A#index~A\"~A>~A</a><br>~%"
+ (caadr entry) (cadadr entry) target (car entry)))
+ (t
+ (setf n 1)
+ ; (car entry) may have formatting commands...
+ (format *outf* "~A" (car entry))
+ (dolist (ref (cdr entry))
+ (format *outf* " <a href = \"~A#index~A\"~A>~A</a> "
+ (car ref) (cadr ref) target n)
+ (setf n (1+ n)))
+ (format *outf* "<br>\n")))))
+
+;; HAS-ALPHA - trim non-alpha from beginning of key and capitalize
+;; returns: nil if no alpha chars, *rslt* = key without non-alpha prefix
+;;
+(defun has-alpha (key)
+ (while (and (> (length key) 0)
+ (not (both-case-p (char key 0))))
+ (setf key (subseq key 1)))
+ (setf *rslt* key)
+ ;(display "non-alpha" key)
+ (cond ((> (length key) 0)
+ (setf *rslt* (index-casify *rslt*))
+ t)
+ (t nil)))
+
+
+;; FIX-NON-ALPHA -- duplicate non-alpha entries that have an alpha char
+;; and make all entries have sort keys
+(defun fix-non-alpha (lis)
+ (let (rslt)
+ (dolist (entry lis)
+ (setf key (car entry))
+ (push (cons key entry) rslt)
+ (cond ((both-case-p (char key 0)) nil) ;; normal alpha key
+ ((has-alpha key)
+ (push (cons *rslt* entry) rslt))))
+ rslt))
+
+
+;; GENERATE-INDEX -- generate the index and write to outf
+;;
+;; if frame-flag is provided, it signals that the output goes
+;; to an already open file, which is in fact the value of frame-flag
+;; This would be the second time generate-index is called, so the
+;; preprocessing and sorting is not needed when frame-flag is a file
+;;
+(defun generate-index (&optional frame-flag)
+ (let (n target initial-char)
+ (setf *outf* (if frame-flag frame-flag
+ (open (strcat *dest-dir* (html-file "indx"))
+ :direction :output)))
+ (cond (frame-flag t)
+ (t
+ (incf *part-number*)
+ (display "generate-index top" *part-number*)
+ (write-chapter-links t t)
+ (setf *index-list* (fix-non-alpha *index-list*))
+ (setf *index-list* (mysort *index-list*))
+ (generate-index-chars)
+ (format *outf* "<html><head><title>Index</title></head>\n")
+ (format *outf* "<body~A>" *bgcolorinfo*)))
+ (setf initial-char (car *index-chars*))
+ (format *outf* "<h2>Index</h2>~%")
+ (setf target (if frame-flag " target=m" ""))
+ (format *outf* "<a name=\"index-~A\"><h2>~A</h2></a>~%"
+ initial-char initial-char)
+ (format *outf* "<a href=\"#top\">TOP</a><br>~%")
+ ;; generate all non-alpha entries
+ (dolist (entry *index-list*)
+ (cond ((both-case-p (char (car entry) 0)))
+ (t
+ (generate-index-entry (cdr entry) target))))
+ ;; generate A - Z
+ (dolist (entry *index-list*)
+ ;; put headings for every new starting character
+ (let ((c (char (car entry) 0)))
+ (cond ((not (both-case-p c)) nil) ; ignore non-alphas here
+ ((eql initial-char (char (car entry) 0))) ; no change
+ (t
+ (setf initial-char (char (car entry) 0))
+ (format *outf* "<a name=\"index-~A\"><h2>~A</h2></a>~%"
+ initial-char initial-char)
+ (format *outf* "<a href=\"#top\">TOP</a><br>~%")))
+ (if (both-case-p c)
+ (generate-index-entry (cdr entry) target))))
+ (cond (frame-flag t)
+ (t (display "generate-index bottom" *part-number*)
+ (write-chapter-links nil t)
+ (format t "closing indx.html\n")
+ (close *outf*)))))
+
+
+;; GENERATE-TOC-2 -- generate table of contents body
+;;
+;; if frame-flag is t, generate html for left frame
+;; output to *outf*
+;;
+(defun generate-toc-2 (lis &optional frame-flag)
+ (format *outf* "<ul>\n")
+ (dolist (lis1 lis)
+ (let (lis2 target)
+ (setf lis1 (reverse lis1))
+ (setf lis2 (car lis1))
+; (display "part1" lis2)
+ (if frame-flag (setf target " target=\"m\""))
+ (format *outf* "<li><a href = \"~A#~A\"~A>~A</a>\n"
+ ;filename ;ref-number ;target ;name
+ (car lis2) (cadr lis2) target (caddr lis2))
+ (setf lis2 (cdr lis1))
+; (display "part2" lis2)
+ (cond (lis2
+ (generate-toc-2 lis2 frame-flag)))))
+ (format *outf* "</ul>\n"))
+
+
+(defun generate-toc (&optional frame-flag)
+ (format *outf* "<a name = \"toc\">\n")
+ (format *outf* "<h2>Table of Contents</h2>\n")
+ (generate-toc-2 (reverse *chapter-list*) frame-flag)
+ (cond (frame-flag t)
+ (t
+ (format *outf* "<ul><li><a href = \"~A\">Index</a>\n</ul>"
+ (html-file "indx")))))
+
+
+(defun get-primary (str)
+ (get-string-after "primary" str))
+
+(defun get-secondary (str)
+ (get-string-after "secondary" str))
+
+(defun get-string-after (key str)
+ (let ((n (string-search key str))
+ m)
+ (cond ((null n)
+ (format t "get-string-after could not find ~A in ~A~%"
+ key str)
+ (break)))
+ (setf n (+ n (length key)))
+ (display "a" n)
+ (setf n (string-search "\"" str :start n))
+ (display "b" n)
+ (cond ((null n)
+ (format t "get-string-after: no quote after ~A in ~A~%"
+ key str)
+ (break)))
+ (setf n (1+ n))
+ (setf m (string-search "\"" str :start n))
+ (display "c" m)
+ (cond ((null m)
+ (format t
+ "get-string-after: no close quote after ~A in ~A~%"
+ key str)
+ (break)))
+ (subseq str n m)))
+
+(defun write-indexsecondary ()
+ (let (body str n)
+ (setf body (get-body "secondaryindex" t))
+ (setf str (list-to-string body))
+ (if *token-trace* (format t "SecondaryIndex item: ~A~%" str))
+ (setf str (strcat (get-primary str) ", " (get-secondary str)))
+ (setf n (enter-index-item str nil))
+ (format *outf* "<a name=\"~A~A\">" str n)))
+
+
+(defun read-begin-command ()
+ (let (cmd n
+ (body (get-body "begin" nil)))
+ (setf cmd (list-to-string body))
+ (setf n (string-search "," cmd))
+ (cond (n
+ (format t
+ "warning: dropping parameters after comma in @begin(~A)~%"
+ cmd)
+ (setf cmd (subseq cmd 0 n))))
+ (setf cmd (intern (string-upcase cmd)))
+ (push cmd paren-stack)
+ cmd))
+
+
+(defun read-end-command ()
+ (let (cmd
+ (body (get-body "end" nil)))
+ (setf cmd (list-to-symbol body))
+ (list 'end cmd)))
+
+(defun read-pragma-command ()
+ (let ((body (get-body "end" nil)) cmd)
+ (setf cmd (list-to-symbol body))
+ cmd))
+
+(defun write-style (style)
+ (format *outf* "<~A>" style)
+ (translate)
+ (format *outf* "</~A>" style))
+
+(defun write-bold-italic ()
+ (format *outf* "<b><i>")
+ (translate)
+ (format *outf* "</i></b>"))
+
+(defun write-superscript ()
+ (output-char #\^)
+ (output-char #\()
+ (translate)
+ (output-char #\)))
+
+(defun write-subscript ()
+; (output-char #\[)
+ (translate)
+; (output-char #\])
+ )
+
+(defun write-dd ()
+ (if (and *description* (not *omit*))
+ (format *outf* "<dd>")))
+
+(defun write-description ()
+ (format *outf* "<dl>\n<dt>")
+ (progv '(*description*) '(t)
+ (translate))
+ (format *outf* "</dl>"))
+
+(defun write-fdescription ()
+ (format *outf* "<dl>\n<dt>")
+ (progv '(*fdescription*) '(t)
+ (progv '(*codef*) '(t)
+ (translate)
+ (codef-complete)))
+ (format *outf* "</dl>"))
+
+(defun write-fgroup ()
+ (progv '(*fgroup*) '(t)
+; (format *outf* " enter fgroup ")
+ (translate)))
+; (format *outf* " exit fgroup ")
+
+(defun write-pdescription ()
+ (let ((pdesc *pdescription*))
+ (if pdesc (format *outf* "<dl>"))
+ (format *outf* "<dd>")
+ (setf *pdescription* t)
+ (codef-complete) ;; finish preceding function completion string
+ (progv '(*codef*) '(nil)
+ (translate))
+ (setf *codef* t) ;; turn back on for next definition
+ (if pdesc (format *outf* "</dl>"))
+ (setf *pdescription* pdesc)))
+
+(defun close-paren-p (tok)
+ (or (and (listp tok)
+ (eq (car tok) 'end))
+ (paren-match tok)))
+
+
+(defun paren-match (p2)
+ (let ((p1 (car paren-stack)))
+ (or (and (eql p2 #\))
+ (eql p1 #\())
+ (and (eql p2 #\])
+ (eql p1 #\[))
+ (and (eql p2 #\})
+ (eql p1 #\{))
+ (and (eql p2 #\>)
+ (eql p1 #\<))
+ (and (listp p2)
+ (eq (car p2) 'end)
+ (eq p1 (cadr p2))))))
+
+(defun skip-it ()
+ (let ((omit *omit*))
+ (setf *omit* t)
+ (translate)
+ (setf *omit* omit)))
+
+(defun write-titlepage ()
+ (translate))
+
+
+(defun write-titlebox ()
+ (translate))
+
+(defun write-majorheading ()
+ (format *outf* "<h1>")
+ (translate)
+ (format *outf* "</h1>"))
+
+(defun write-h2 ()
+ (format *outf* "<h2>")
+ (translate)
+ (format *outf* "</h2>"))
+
+(defun write-h3 ()
+ (format *outf* "<h3>")
+ (translate)
+ (format *outf* "</h3>"))
+
+(defun write-h4 ()
+ (format *outf* "<h4>")
+ (translate)
+ (format *outf* "</h4>"))
+
+(defun write-paragraph ()
+ (let ((body (get-body "paragraph" t)))
+ (setf body (list-to-string body))
+ (setf *name-reference* (format nil "\"~A\"" body))
+ (setf *name-number* (1+ *name-number*))
+ (push (list (list *file-name* *name-number* body)) *paragraph-list*)
+ (format *outf* "<a name = \"~A\"><h5>~A</h5></a>" *name-number* body)))
+
+(defun finish-subsection ()
+ (push *paragraph-list* *subsection-list*)
+ (setf *paragraph-list* nil))
+
+(defun write-subsection ()
+ (let ((body (get-body "subsection" t)))
+ (setf body (list-to-string body))
+ (setf *name-reference* (format nil "\"~A\"" body))
+ (setf *name-number* (1+ *name-number*))
+ (cond (*paragraph-list*
+ (finish-subsection)))
+ (setf *paragraph-list*
+ (list (list *file-name* *name-number* body)))
+ (format *outf* "<a name = \"~A\"><h4>~A</h4></a>" *name-number* body)))
+
+
+(defun finish-section ()
+ (cond (*paragraph-list*
+ (finish-subsection)))
+ (push *subsection-list* *section-list*)
+ (setf *subsection-list* nil))
+
+(defun write-section ()
+ (let ((body (get-body "section" t)))
+ (setf body (list-to-string body))
+ (setf *name-reference* (format nil "\"~A\"" body))
+ (setf *name-number* (1+ *name-number*))
+ (cond (*subsection-list*
+ (finish-section)))
+ (setf *subsection-list*
+ (list (list *file-name* *name-number* body)))
+ (format *outf* "<a name = \"~A\"><h3>~A</h3></a>" *name-number* body)))
+
+(defun previous-part-file-name ()
+ (cond ((> *part-number* 2)
+ (html-file (format nil "part~A" (- *part-number* 2))))
+ (t *dest*)))
+
+;; called when new chapter is encountered,
+;; lastflag = nil means write a Next Section link
+(defun finish-chapter ()
+ (cond (*subsection-list*
+ (finish-section)))
+ (push *section-list* *chapter-list*)
+ (setf *section-list* nil)
+ ; *dest* links get added after table of contents
+ (cond ((not (eq *outf* *rootf*))
+ (write-chapter-links)
+ (format *outf* "</body></html>\n") )))
+
+
+(defun write-title-page-links ()
+ (format *outf* "<hr>\n")
+ (let (name)
+ (setf name (html-file "part1"))
+ (format *outf* "<a href = \"~A\">Next Section</a> | " name))
+ (format *outf* "<a href = \"~A\">Index</a> | " (html-file "indx"))
+ (format *outf* "<hr>\n"))
+
+
+(defun write-chapter-links (&optional top-flag index-flag title-flag)
+ (display "write-chapter-links" *part-number* *previous-number-of-parts*)
+ (let ((lastflag (eql *part-number* *previous-number-of-parts*)))
+ (if top-flag t (format *outf* "<hr>\n"))
+ (cond ((not title-flag)
+ (format *outf* "<a href = \"~A\">Previous Section</a> | "
+ (previous-part-file-name))))
+ (cond (index-flag nil)
+ ((not lastflag)
+ (let (name)
+ (setf name (html-file (if title-flag "part1"
+ (format nil "part~A" *part-number*))))
+ (format *outf* "<a href = \"~A\">Next Section</a> | " name)))
+ (t
+ (format *outf* "<a href = \"~A\">Next Section (Index)</a> | "
+ (html-file "indx"))))
+ (format *outf* "<a href = \"~A#toc\">Table of Contents</a> | " *dest*)
+ (cond ((and (not lastflag) (not index-flag))
+ (format *outf* "<a href = \"~A\">Index</a> | " (html-file "indx"))))
+ (format *outf* "<a href = \"~A\">Title Page</a>\n" *dest*)
+ (if top-flag (format *outf* "<hr>\n"))))
+
+
+(defun set-html-title ()
+ (setf *title* (get-body "htmltitle" t))
+ (setf *title* (list-to-string *title*)))
+
+
+(defun write-chapter ()
+ (let ((body (get-body "chapter" t)))
+ ;(display "write-chapter" body)
+ (setf body (list-to-string body))
+ (setf *name-reference* (format nil "\"~A\"" body))
+ (setf *name-number* (1+ *name-number*))
+ (cond (*section-list*
+ (finish-chapter)))
+ (cond ((eq *outf* *rootf*))
+ (t
+ (format t "Closing ~A~%" *file-name*)
+ (close *outf*)))
+ (setf *file-name* (html-file (format nil "part~A" *part-number*)))
+ (setf *section-list*
+ (list (list *file-name* *name-number* body)))
+ (setf *outf* (open (strcat *dest-dir* *file-name*)
+ :direction :output))
+ (setf *part-number* (1+ *part-number*))
+ (format *outf* "<html><head><title>~A</title></head>\n<body~A>\n"
+ body *bgcolorinfo*)
+ (write-chapter-links t)
+ (format *outf* "<a name = \"~A\"><h2>~A</h2></a>" *name-number* body)))
+
+(defun write-detail ()
+ (format *outf* "<small>")
+ (translate)
+ (format *outf* "</small>\n"))
+
+(defun write-appendix ()
+ (let ((body (get-body "appendix" t)))
+ (setf body (list-to-string body))
+ (setf *name-reference* (format nil "\"~A\"" body))
+ (setf body (format nil "Appendix ~A: ~A" *appendix-number* body))
+ (setf *appendix-number* (1+ *appendix-number*))
+ (setf *name-number* (1+ *name-number*))
+ (cond (*section-list*
+ (finish-chapter)))
+ (cond ((eq *outf* *rootf*))
+ (t
+ (format t "Closing ~A~%" *file-name*)
+ (close *outf*)))
+ (setf *file-name* (html-file (format nil "part~A" *part-number*)))
+ (setf *section-list*
+ (list (list *file-name* *name-number* body)))
+ (setf *outf* (open (strcat *dest-dir* *file-name*)
+ :direction :output))
+ (setf *part-number* (1+ *part-number*))
+ (write-chapter-links t)
+ (format *outf* "<html><head><title>~A</title></head>\n" body)
+ (format *outf* "<a name = \"~A\"><h2>~A</h2></a>" *name-number* body)))
+
+
+(defun write-blankspace ()
+ (cond (*fdescription*
+ ; what we want is <br><br><dt> after pdescription environment
+ ; to set up the next fdescription, but we may have output one <br>
+ ; after the last pdescription. By using (linebreak) we avoid a
+ ; third <br> which would output too much space.
+ (linebreak)
+ (format *outf* "<br><dt>"))
+ (t
+ (paragraph)))
+ (get-body "blankspace" t))
+
+
+;(defun write-center ()
+; (linebreak)
+; (translate)
+; (linebreak))
+
+(defun write-newpage ()
+ (translate))
+
+; ignore multiple calls in sequence
+;
+(defun paragraph ()
+ (cond ((null *paragraph*)
+ (cond (*itemize*
+ (format *outf* "\n<li>"))
+ (*description*
+ (format *outf* "<br><br>\n<dt>"))
+ ((or *pdescription* *fgroup*)
+ (linebreak))
+ (*fdescription*) ; and not *pdescription*: no paragraph
+ (t
+ (format *outf* "\n<p>\n")))
+ (setf *paragraph* t))))
+
+(defun linebreak ()
+ (cond ((and (null *paragraph*)
+ (null *linebreak*))
+ (format *outf* "<br>\n")
+ (setf *linebreak* t))))
+
+(defun write-smallcaps ()
+ (let ((sc *smallcap*))
+ (setf *smallcap* t)
+ (translate)
+ (setf *smallcap* sc)))
+
+
+(defun write-cite ()
+ (let (body link)
+ (setf body (get-body "cite" nil))
+ (setf body (list-to-symbol body))
+ (format t "Citation: ~A ~%" body)
+ (setf link (assoc body *citations*))
+ (cond ((null link)
+ (format t "Undefined citation: ~A~%" body))
+ (t
+ (format *outf* " <a href = \"~A\">~A</a>"
+ (cadr link) (caddr link))))))
+
+
+(defun write-ref ()
+ (let ((body (get-body "ref" nil)) ref (file ""))
+ (cond (*startref*
+ (setf *startref* nil)
+ (setf *omit* nil)))
+ (setf body (list-to-symbol body))
+ (setf ref (assoc body *previous-label-list*))
+ (cond ((null ref)
+ (format t "warning: undefined label ~A~%" body))
+ (t
+ (cond ((not (equal (caddr ref) *file-name*))
+ (setf file (caddr ref))))
+ (format *outf* "<a href = \"~A#~A\">~A</a>"
+ file (cadddr ref) (cadr ref))))))
+
+(defun write-example ()
+ (format *outf* "<pre>")
+ (translate)
+ (format *outf* "</pre>\n"))
+
+(defun write-enumerate ()
+ (let ((itemize *itemize*))
+ (format *outf* "<ol>\n<li>")
+ (setf *itemize* t)
+ (translate)
+ (format *outf* "</ol>")
+ (setf *itemize* itemize)))
+
+(defun write-itemize ()
+ (let ((itemize *itemize*))
+ (format *outf* "<ul>\n<li>")
+ (setf *itemize* t)
+ (translate)
+ (format *outf* "</ul>")
+ (setf *itemize* itemize)))
+
+
+
+(defun write-format ()
+ (let ((display *display*))
+ ; hopefully, we'll get a linebreak to separate the text as does scribe
+ (setf *display* t)
+ (translate)
+ (format *outf* "<p>~%") ; separate the text from what follows
+ (setf *display* display)))
+
+(defun write-display ()
+ (let ((display *display*))
+ (format *outf* "<blockquote>")
+ (setf *display* t)
+ (setf *linebreak* t) ; it's automatic with blockquote,
+ ; so we do this to suppress an extra <br>
+ (translate)
+ (format *outf* "</blockquote>")
+ (setf *display* display)))
+
+
+(defun write-figure ()
+ (format *outf* "<hr>")
+ (translate)
+ (format *outf* "<hr>"))
+
+
+(defun write-dash ()
+ (get-body "dash" nil)
+ (output-char #\-))
+
+
+(defun write-html ()
+ (setf *html* t)
+ (translate)
+ (setf *html* nil))
+
+(defun write-foot ()
+ (let ((outf *outf*)
+ (name (html-file "foot")))
+ (format *outf* " <a href = \"~A#foot~A\">(Footnote ~A)</a> "
+ name *footnote-number* *footnote-number*)
+ (cond ((null *footnotefile*)
+ (setf *footnotefile* (open (strcat *dest-dir* name) :direction :output))
+ (format *footnotefile* "<html><head><title>Footnotes</title></head>\n")
+ (format *footnotefile* "<body~A>\n<h2>Footnotes</h2>\n" *bgcolorinfo*)
+ ))
+ (setf *outf* *footnotefile*)
+ (format *outf* "<a name = \"foot~A\"> ~A. </a>" *footnote-number* *footnote-number*)
+ (setf *footnote-number* (1+ *footnote-number*))
+ (translate)
+ (format *outf* "\n<P>\n")
+ (setf *outf* outf)))
+
+
+(defun write-fillcaption ()
+ (paragraph)
+ (format *outf* "<b>Figure ~A: </b>" *figure-number*)
+ (translate))
+
+
+(defun do-include ()
+ (setf *include* t))
+
+(defun write-include ()
+ (let ((body (get-body "include" nil))
+ file)
+ (cond (*include*
+ (setf *include* nil)
+ (setf body (list-to-string body))
+ (setf file *inf*)
+ (setf *inf* (open (strcat *include-prefix* body)))
+ (cond ((null *inf*)
+ (format t "Could not open include file ~A\n" body)
+ (break))
+ (t
+ (format t "Processing include file ~A\n" body)
+ (translate)
+ (format t "Closing include file ~A\n" body)
+ (close *inf*)
+ (setf *inf* file))) ))))
+
+(defun do-tag ()
+ (let ((body (get-body "tag" nil)))
+ (push (list (list-to-symbol body) (format nil "~A" *figure-number*)
+ *file-name* *name-number*)
+ *label-list*)
+ (setf *figure-number* (1+ *figure-number*)) ))
+
+
+(defun write-math ()
+ (translate))
+
+(defun write-underline ()
+ (format *outf* "<u>")
+ (translate)
+ (format *outf* "</u>\n"))
+
+; initiated by @startscribe()
+; and ended by @endscribe()
+;
+(defun do-startscribe ()
+ (setf *omit* t))
+
+(defun do-endscribe ()
+ (setf *omit* nil))
+
+(defun do-startref ()
+ (setf *omit* t)
+ (setf *startref* t))
+
+(defun write-title ()
+ (translate))
+
+
+(defun do-comment ()
+ ; skip everything until matching paren
+ (prog (tok)
+loop
+ (setf tok (get-comment-token))
+; (display "do-comment" tok paren-stack)
+ (cond ((and (close-paren-p tok)
+ (paren-match tok))
+; (display "do-comment" paren-stack)
+ (pop paren-stack)
+; (format t "do-comment done\n")
+ (return)))
+ (go loop)))
+
+
+(defun output-char (c)
+ (cond (*omit* t)
+ (t
+ (cond ((and *smallcap*
+ (alpha-char-p c))
+ (setf c (char-upcase c))))
+ ; (display "output-char" *display*)
+ (cond ((and *display* (eql c #\Newline))
+ (linebreak))
+ ((member c '(#\Space #\Newline)))
+ (t
+ (setf *paragraph* nil)
+ (setf *linebreak* nil)))
+ (cond (*html*) ; no translation if we're in an @html(...) section
+ ((eq c #\<)
+ (write-char #\& *outf*)
+ (write-char #\l *outf*)
+ (write-char #\t *outf*)
+ (setf c #\;))
+ ((eq c #\>)
+ (write-char #\& *outf*)
+ (write-char #\g *outf*)
+ (write-char #\t *outf*)
+ (setf c #\;))
+ ((eq c #\&)
+ (write-char #\& *outf*)
+ (write-char #\a *outf*)
+ (write-char #\m *outf*)
+ (write-char #\p *outf*)
+ (setf c #\;)))
+ ; (display "output-char" c)
+ (write-char c *outf*))))
+
+
+(setf *translate-depth* 0)
+
+(defun translate ()
+ (setf *translate-depth* (1+ *translate-depth*))
+ (if *token-trace* (format t "(~A " *translate-depth*))
+ (prog (tok)
+loop
+ (setf tok (get-token))
+ (cond ((and tok (symbolp tok) *token-trace*)
+ (format t "[~A]" tok)))
+ (cond ((null tok) (go ret))
+ ((close-paren-p tok)
+ (cond ((paren-match tok)
+ (pop paren-stack))
+ (t
+ (format t "unmatched end: ~A~%" tok)
+ (break)))
+ (go ret))
+ ((eq tok 'altdef)
+ (translate))
+ ((characterp tok)
+ ;; output completion hints file
+ (cond (*codef* (codef-char tok)))
+ (output-char tok))
+ ((eq tok 'label)
+ (write-label))
+ ((member tok '(code smallcode xlcode))
+ (write-code))
+ ((eq tok 'codef)
+ (write-codef))
+ ((eq tok 'index)
+ (write-index definition-flag)
+ (setf definition-flag nil))
+ ((eq tok 'indexsecondary)
+ (write-indexsecondary))
+ ((eq tok 'indexdef) ;; this is obsolete now
+ (write-index t))
+ ((eq tok 'r)
+ (write-normal))
+ ((eq tok 'i)
+ (write-style "i"))
+ ((eq tok 'b)
+ (write-style "b"))
+ ((eq tok 'titlepage)
+ (write-titlepage))
+ ((eq tok 'titlebox)
+ (write-titlebox))
+ ((member tok '(majorheading chapnum)) ; chapnum is for Tomayko
+ (write-majorheading))
+ ((member tok '(skip blankspace)) ; skip is for Tomayko
+ (write-blankspace))
+ ((member tok '(verse center))
+ (write-display)) ;; seems to be best substitute for center
+ ((eq tok 'format)
+ (write-format))
+ ((eq tok 'newpage)
+ (write-newpage))
+ ((eq tok 'c)
+ (write-smallcaps))
+ ((member tok '(text quotation))
+ (write-quotation))
+ ((eq tok 't)
+ (write-t))
+ ((eq tok 'title)
+ (write-title))
+ ((eq tok 'htmltitle)
+ (set-html-title))
+ ((member tok '(chapter unnumbered))
+ (write-chapter))
+ ((eq tok 'appendix)
+ (write-appendix))
+ ((eq tok 'detail)
+ (write-detail))
+ ((eq tok 'section)
+ (write-section))
+ ((eq tok 'heading)
+ (write-h3))
+ ((eq tok 'subsection)
+ (write-subsection))
+ ((eq tok 'subheading)
+ (write-h4))
+ ((eq tok 'paragraph)
+ (write-paragraph))
+ ((eq tok 'cite)
+ (write-cite))
+ ((member tok '(ref pageref))
+ (write-ref))
+ ((eq tok 'startref)
+ (do-startref))
+ ((eq tok 'p)
+ (write-bold-italic))
+ ((eq tok 'plus)
+ (write-superscript))
+ ((eq tok 'minus)
+ (write-subscript))
+ ((eq tok 'html) ; special way to insert html
+ (write-html))
+ ((member tok '(example programexample))
+ (write-example))
+ ((eq tok 'figure)
+ (write-figure))
+ ((eq tok 'fillcaption)
+ (write-fillcaption))
+ ((eq tok 'tag)
+ (do-tag))
+ ((eq tok 'doinclude)
+ (do-include))
+ ((eq tok 'include)
+ (write-include))
+ ((eq tok 'backslash)
+ (write-dd))
+ ((eq tok 'math)
+ (write-math))
+ ((member tok '(foot note)) ; note is for Tomayko
+ (codef-complete)
+ (setf *codef* nil)
+ (write-foot))
+ ((member tok '(description fndefs))
+ (write-description))
+ ((eq tok 'fdescription)
+ (write-fdescription))
+ ((eq tok 'pdescription)
+ (write-pdescription))
+ ((eq tok 'fgroup)
+ (write-fgroup))
+ ((eq tok 'itemize)
+ (write-itemize))
+ ((eq tok 'enumerate)
+ (write-enumerate))
+ ((eq tok 'display)
+ (write-display))
+ ((member tok '(subtract itemsep dash ndash))
+ (cond ((eq tok 'itemsep)
+ (codef-complete)
+ (setf *codef* nil))) ;; end completion string
+ (write-dash))
+ ((eq tok 'star)
+ (linebreak))
+ ((eq tok 'new-paragraph)
+ (paragraph))
+ ((member tok '(y value definefont))
+ (format t "warning: omitting @~A[] text\n" tok)
+ (skip-it))
+ ((member tok '(one colon shout slash bar bibliography))
+ (format t "ignoring ~A\n" tok))
+ ((eq tok 'make)
+ (do-make))
+ ((member tok '(device libraryfile style commandstring modify define use counter pageheading set graphic mult tabset tabclear textform part))
+ (skip-it))
+ ((eq tok 'comment)
+ (do-comment))
+ ((eq tok 'defn)
+ (setf definition-flag t))
+ ((eq tok 'startscribe)
+ (do-startscribe))
+ ((eq tok 'endscribe)
+ (do-endscribe))
+ ((eq tok 'endcodef)
+ (codef-complete))
+ ((eq tok 'stopcodef)
+ (setf *codef* nil))
+ ((eq tok 'startcodef)
+ (setf *codef* t))
+ ((member tok '(u ux))
+ (write-underline))
+ ((member tok '(group flushleft)) ; ignore it, flushleft is for Tomayko
+ (translate))
+ (t
+ (format t "unrecognized token: ~A~%" tok)
+ (break)))
+ (go loop)
+ret
+ (if *token-trace* (format t ")"))
+ (setf *translate-depth* (- *translate-depth* 1))
+
+ ))
+
+(defun manualp () (eq *document-type* 'manual))
+
+
+(format t "To run, call:\n")
+(format t " (g \"scribe source directory\" ; omit the trailing slash\n")
+(format t " \"scribe file\" ; omit the .mss suffix\n")
+(format t " \"html directory\" ; omit the trailing slash\n")
+(format t " \"html root file\" ; omit the .html suffix\n")
+(format t " [t]) ; optional flag generates html with frames\n")
+
+(defun g (sourcedir source destdir dest &optional frame-flag)
+ (setf *codef-capture* "")
+ (setf *codef-list* nil)
+ (setf *figure-number* 1)
+ (setf *index-number* 1)
+ (setf *appendix-number* 1)
+ (setf *footnotefile* nil)
+ (setf *footnote-number* 1)
+ (setf *name-number* 0)
+ (setf *name-reference* nil)
+ (setf *omit* nil)
+ (setf *html* nil) ; says we're in section to dump html literally
+ (setf *include* nil) ; process include or not?
+ (setf *next-tokens* nil)
+ (setf *smallcap* nil)
+ (setf *paragraph* t)
+ (setf *linebreak* t)
+ (setf *itemize* nil)
+ (setf *display* nil)
+ (setf *description* nil)
+ (setf *fdescription* nil)
+ (setf *fgroup* nil)
+ (setf *pdescription* nil)
+ (setf *codef* nil) ; says we're defining a function, add to completion list
+ ;; paragraph-list is initialized to:
+ ;; ((file number sectionname))
+ ;; and after each paragraph, expands, e.g.:
+ ;; ((file number paragraphname) (file number sectionname))
+ (setf *paragraph-list* nil)
+ ;; likewise, the subsection-list is initialized to:
+ ;; ((file number sectionname))
+ ;; and after each subsection, expands, e.g.:
+ ;; (((file number paragraphname) (file number subsectionname))
+ ;; (file number sectionname)))
+ (setf *subsection-list* nil)
+ ;; and so on...
+ (setf *section-list* nil)
+ (setf *chapter-list* nil)
+ ; *dest* is the root HTML file
+ (setf *dest* (if frame-flag
+ (html-file "title")
+ (html-file dest)))
+ ; *file-name* is the current HTML file
+ (setf *file-name* *dest*)
+ (format t "Destination HTML file: ~A~%" *file-name*)
+ (setf *part-number* 1)
+
+ ; *startref* is set when @startref() is encountered, at which
+ ; point text is omitted until a reference is encountered, at
+ ; which point text is resumed.
+ (setf *startref* nil)
+
+ ;; index-list shall look like this:
+ ;; (("key" "indexterm" (filename num) (filename num) ...)
+ ;; ("key" "indexterm" (filename num) (filename num) ...) ...)
+ ;; where key is the sortkey (usually indexterm) and indexterm is
+ ;; what gets printed. This allows non-alphabetic items to be sorted
+ ;; according to their first alphabetic character, e.g. *rslt* can
+ ;; be sorted as "rslt" as well as "*rslt*"
+ ;;
+ (setf *index-list* nil)
+
+ (setf paren-stack nil)
+
+ ;; run this twice to get labels right
+ ;; if *label-list* is NIL, it may be because we reloaded this file,
+ ;; in which case *previous-label-list* has already been copied from
+ ;; *label-list*
+ (cond (*label-list*
+ (setf *previous-label-list* *label-list*))
+ ((not (boundp '*previous-label-list*))
+ (setf *previous-label-list* nil)))
+ (cond (*number-of-parts*
+ (setf *previous-number-of-parts* *number-of-parts*)))
+ (cond ((not (boundp '*previous-number-of-parts*))
+ (setf *previous-number-of-parts* 0)))
+
+ (setf *inf* (open (strcat sourcedir "/" source ".mss")))
+; "test.mss"))
+; "/afs/cs/user/rbd/doc/man/nyquist/nyquistman.mss"))
+ (setf *include-prefix* (strcat sourcedir "/"))
+ (setf *dest-dir* (strcat destdir "/"))
+ (setf *outf* (open (strcat *dest-dir* *file-name*) :direction :output))
+ (setf *codef-file* (open (strcat *dest-dir* "NyquistWords.txt" )
+ :direction :output))
+ (setf *rootf* *outf*)
+ (display "g-before translate" *outf* *rootf* *inf*)
+ (translate)
+ (display "g-after translate" *outf* *rootf* *inf*)
+ (format t "g: closing *inf*\n")
+ (close *inf*)
+ (setf *inf* nil)
+ (format t "g: closing *outf*\n")
+ (finish-chapter)
+ (cond ((not (eq *outf* *rootf*))
+ (close *outf*)
+ (setf *outf* nil)))
+ (cond (*footnotefile*
+ (format *footnotefile* "</body></html>\n")
+ (close *footnotefile*)))
+ (setf *footnotefile* nil)
+ (setf *outf* *rootf*)
+ (display "g-before toc" *outf* *rootf* *inf*)
+ (setf *number-of-parts* *part-number*)
+ (cond ((manualp)
+ (setf *part-number* 1) ;; reset for title page
+ (write-title-page-links)
+ (generate-toc)
+ (write-chapter-links nil nil t)))
+ (format *rootf* "</body></html>\n")
+ (format t "g: closing *rootf*\n")
+ (close *rootf*)
+ (setf *outf* (setf *rootf* nil))
+ (cond ((manualp)
+ (setf *part-number* *number-of-parts*) ;; restore from above
+ (generate-index))
+ ; if this is not a manual, there are no chapters, so there are no
+ ; links between chapters or table of contents, so index cannot be
+ ; reached, so index is not generated. This is bad if there really
+ ; are index terms!!!!
+ (*index-list*
+ (format t "WARNING: NO INDEX IS BEING GENERATED, THIS IS A BUG~%")))
+ (cond (frame-flag
+ (if (not (manualp))
+ (error "frame option only works with manual document types"))
+ (generate-home *title* (strcat *dest-dir* (html-file dest)))
+ (generate-guide (strcat *dest-dir* (html-file "guide")))
+ ))
+ (codef-close)
+)
+
+
+(defun generate-home (title filename)
+ (let ((outf (open filename :direction :output)))
+ (format outf "<html><head><title>~A</title></head>~%" title)
+ (format outf "<frameset cols=\"1*, 2*\">~%")
+ (format outf "<frame scrolling=auto src=guide.html frameborder=0>~%")
+ (format outf
+ "<frame name=m scrolling=auto src=title.html frameborder=0>~%")
+ (format outf "<noframes><body><p>This browser does not support frames.~%")
+ (format outf "<p><a href=title.html>The no-frames version is here.</a>~%")
+ (format outf "</body></noframes></frameset></html>~%")
+ (close outf)))
+
+
+;; FIND-ALPHA-AND-NON-ALPHA -- sublist with only alpha chars
+;; return the range of the rest in *rslt*, e.g. "!-~"
+;;
+(defun find-alpha-and-non-alpha (lis)
+ (let (prev first last rslt)
+ (dolist (c lis)
+ (cond ((eql prev c))
+ (t
+ (setf prev c)
+ (cond ((both-case-p prev)
+ (push prev rslt))
+ ((null first)
+ (setf first prev)
+ (setf last prev))
+ (t
+ (setf last prev))))))
+ (setf *rslt* (strcat (string first) "-" (string last)))
+ rslt))
+
+
+(defun generate-index-chars ()
+ (let (term initial prev)
+ (setf *index-chars* nil)
+ ;; compute the list of characters for index
+ (dolist (entry *index-list*)
+ (setf term (car entry))
+ (setf initial (char term 0))
+ (cond ((eql prev (char term 0)))
+ (t
+ (setf prev initial)
+ (push prev *index-chars*))))
+ (setf *index-chars* (reverse *index-chars*))
+ (setf *index-chars* (find-alpha-and-non-alpha *index-chars*))
+ (setf *index-chars* (reverse *index-chars*))
+ (push *rslt* *index-chars*)))
+
+
+(defun generate-guide (dest)
+ (let (term initial prev index-chars non-alpha)
+ (setf *outf* (open dest :direction :output))
+ (format *outf* "<html><head><title>Links</title></head><body>~%")
+ (format *outf* "<h3><a name=top>~%")
+ (dotimes (n (length *index-chars*))
+ (setf c (nth n *index-chars*))
+ (format *outf* "<a href=\"#index-~A\">~A</a>~%" c c)
+ (if (zerop (rem (1+ n) 9))
+ (format *outf* "<br>~%")))
+ (format *outf* "</h3>~%")
+ (generate-toc t)
+ (generate-index *outf*)
+ (format *outf* "</body></html>~%")
+ (close *outf*)))
+
+
+(defun alpha-char-p (c)
+ (let ((cc (char-code c)))
+ (or (and (>= cc (char-code #\a))
+ (<= cc (char-code #\z)))
+ (and (>= cc (char-code #\A))
+ (<= cc (char-code #\Z))))))
+
+
+(defun process-comment-at ()
+ (let (c cmd)
+ (read-char *inf*) ; read the @
+ (setf c (peek-char nil *inf*))
+ (cond ((alpha-char-p c)
+ (setf cmd (read-command))
+ (cond ((eq cmd 'end)
+ (open-paren)
+ (read-end-command))
+ (t #\z))))))
+
+
+(defun process-at ()
+ (let (c cmd)
+ (read-char *inf*) ; read the @
+ (setf c (peek-char nil *inf*))
+ (cond ((eql c #\@) (read-char *inf*))
+ ((eql c #\\) (read-char *inf*) 'backslash)
+ ((eql c #\/) (read-char *inf*) 'slash)
+ ((eql c #\1) (read-char *inf*) 'one)
+ ((eql c #\+) (read-char *inf*)
+ (open-paren)
+ 'plus)
+ ((eql c #\*) (read-char *inf*) 'star)
+ ((eql c #\-) (read-char *inf*)
+ (open-paren)
+ 'minus)
+ ((eql c #\:) (read-char *inf*) 'colon)
+ ((eql c #\!) (read-char *inf*) 'shout)
+ ((eql c #\|) (read-char *inf*) 'bar)
+ ((alpha-char-p c)
+ (setf cmd (read-command))
+ (cond ((eq cmd 'begin)
+ (open-paren)
+ (read-begin-command))
+ ((eq cmd 'end)
+ (open-paren)
+ (read-end-command))
+ ((eq cmd 'pragma)
+ (open-paren)
+ (read-pragma-command))
+ (t
+ (open-paren)
+ cmd)))
+ (t (format t "unexpected char after @: ~A~%" c)
+ (break)))))
+
+
+(defun process-newline ()
+ (let (c)
+ (read-char *inf*) ; read the newline
+ (setf c (peek-char nil *inf*))
+ (cond ((eql c #\Newline)
+ (while (eql (peek-char nil *inf*) #\Newline)
+ (read-char *inf*))
+ 'new-paragraph)
+ (t #\Newline))))
+
+
+;; READ-COMMAND -- read command after an @
+;
+(defun read-command ()
+ (let ((command ""))
+ (while (alpha-char-p (peek-char nil *inf*))
+ (setf command
+ (strcat command (string (read-char *inf*)))))
+ (intern (string-upcase command))))
+
+
+
+;; (read-char *inf*))
+
+(defun get-token ()
+ (let ((c (peek-char nil *inf*))
+ result)
+
+ ;; allow others to force next token:
+ (cond (*next-tokens*
+ (setf result (car *next-tokens*))
+ (setf *next-tokens* (cdr *next-tokens*)))
+ (t
+ (setf result
+ (cond ((eql c #\@) (process-at))
+ ((eql c #\Newline) (process-newline))
+ ((eql c #\`) ;; double `` -> "
+ (read-char *inf*)
+ (setf c (peek-char nil *inf*))
+ (cond ((eql c #\`)
+ (read-char *inf*)
+ #\")
+ (t #\`)))
+ ((eql c #\') ;; double '' -> "
+ (read-char *inf*)
+ (setf c (peek-char nil *inf*))
+ (cond ((eql c #\')
+ (read-char *inf*)
+ #\")
+ (t #\')))
+ (t (read-char *inf*))))))
+ (if *token-trace* (format t "->~A " result))
+ result
+ ))
+
+
+(defun get-comment-token ()
+ (let ((c (peek-char nil *inf*))
+ result)
+ (setf result
+ (cond ((eql c #\@) (process-comment-at))
+ (t (read-char *inf*))))
+ (if *token-trace* (format t "->~A " result))
+ result
+ ))
+
+(defun codef-char (c)
+ (if (member c '(#\Newline #\Tab)) (setf c #\Space))
+ (setf *codef-capture* (strcat *codef-capture* (string c))))
+
+(defun codef-complete ()
+; (write-char #\) *codef-file*)
+ (let (index)
+ ;; remove [lisp] and [sal] and everything after it
+ (if (setf index (string-search "[lisp]" *codef-capture*))
+ (setf *codef-capture* (subseq *codef-capture* 0 index)))
+ (if (setf index (string-search "[sal]" *codef-capture*))
+ (setf *codef-capture* (subseq *codef-capture* 0 index)))
+ ;; trim extra blanks
+ (while (setf index (string-search " " *codef-capture*))
+ (setf *codef-capture* (strcat (subseq *codef-capture* 0 index)
+ (subseq *codef-capture* (1+ index)))))
+ ;; replace "expr..." with "expr ..." Want to replace all occurences,
+ ;; so scan string, starting at previous spot + 2 (to get beyond the
+ ;; inserted space character) until nothing is found
+ (setf index 0)
+ (while (and (< (+ index 2) (length *codef-capture*))
+ (setf index (string-search "..." *codef-capture*
+ :start (+ 2 index))))
+ (cond ((and index (> index 0)
+ (not (eq (char *codef-capture* (1- index)) #\Space)))
+ (setf *codef-capture*
+ (strcat (subseq *codef-capture* 0 index) " "
+ (subseq *codef-capture* index))))))
+ ;; trim blanks after open bracket/comma and before close paren
+ (while (setf index (string-search "[, " *codef-capture*))
+ (setf index (+ 2 index))
+ (setf *codef-capture* (strcat (subseq *codef-capture* 0 index)
+ (subseq *codef-capture* (1+ index)))))
+ (while (setf index (string-search " )" *codef-capture*))
+ (setf *codef-capture* (strcat (subseq *codef-capture* 0 index)
+ (subseq *codef-capture* (1+ index)))))
+ )
+
+ ;; trim blanks
+ (setf *codef-capture* (string-trim " " *codef-capture*))
+ ;; translate &key to example format
+ (cond ((or (string-search "&key" *codef-capture*)
+ (string-search "&optional" *codef-capture*))
+ (setf *codef-capture* (codef-expand *codef-capture*))))
+ (if (and (> (length *codef-capture*) 0) ; must be non-empty
+ (not (eq (char *codef-capture* 0) #\:))) ; ignore messages
+ (push (string-downcase
+ (convert-sal-to-lisp *codef-capture*))
+ *codef-list*))
+ ;; trim leading open paren
+ (if (and (> (length *codef-capture*) 0)
+ (eq (char *codef-capture* 0) #\())
+ (setf *codef-capture* (subseq *codef-capture* 1)))
+
+ (setf *codef-capture* ""))
+
+
+(defun convert-sal-to-lisp (codef)
+ ;(format *codef-file* "sal-to-lisp |~A|~%" codef)
+ ;; some of these strings are already lisp. The SAL strings have an
+ ;; open paren after the function call
+ (cond ((eq (char codef 0) #\()
+ (setf codef (subseq codef 1)))
+ ((string-search "(" codef)
+ (setf codef (do-convert-sal-to-lisp codef))))
+ codef)
+
+(defun do-convert-sal-to-lisp (codef)
+ ;; take out initial "(" and replace with space
+ ;; delete each subsequent comma
+ ;; for each colon, flip it to a keyword (key: -> :key)
+ (let ((p (string-search "(" codef)))
+ ;; replace "(" with " "
+ (setf codef (strcat (subseq codef 0 p) " " (subseq codef (1+ p))))
+ ;; delete commas:
+ (setf p (string-search "," codef))
+ (while p
+ (setf codef (strcat (subseq codef 0 p) (subseq codef (1+ p))))
+ (setf p (string-search "," codef)))
+ ;; for each colon, flip it to a keyword
+ (setf p (string-search ":" codef))
+ (while p
+ ;; back up
+ (setf q (1- p))
+ (while (not (member (char codef q) '(#\Space #\[)))
+ (setf q (1- q)))
+ (incf q)
+ (setf codef (strcat (subseq codef 0 q) ":"
+ (subseq codef q p) (subseq codef (1+ p))))
+ (setf p (string-search ":" codef :start (1+ p)))
+ '(display "do-cstl" p codef))
+ codef))
+
+
+(defun split (s)
+ (let (rslt (token "") c)
+ (dotimes (i (length s))
+ (setf c (char s i))
+ (cond ((eq c #\Space)
+ (cond ((> (length token) 0)
+ (push token rslt)
+ (setf token ""))))
+ ((member c '(#\( #\)))
+ (cond ((> (length token) 0)
+ (push token rslt)
+ (setf token "")))
+ (push (string c) rslt))
+ (t
+ (setf token (strcat token (string c))))))
+ (cond ((> (length token) 0)
+ (push token rslt)))
+ (reverse rslt)))
+
+
+(defun colonize (word)
+ (if (eq (char word 0) #\:)
+ word
+ (strcat ":" word)))
+
+(defun uncolonize (word)
+ (if (eq (char word 0) #\:)
+ (subseq word 1)
+ word))
+
+
+(defun codef-expand (s)
+ (let (words (r "") mode (space ""))
+ (setf words (split s))
+ (dolist (word words)
+ (cond ((equal word "&key")
+ (setf mode :key))
+ ((equal word "&optional")
+ (setf mode :optional))
+ ((equal word "(")
+ (setf r (strcat r space word))
+ (setf space ""))
+ ((equal word ")")
+ (setf r (strcat r word))
+ (setf space " "))
+ ((eq mode :key)
+ (setf r (strcat r space "[" (colonize word) " "
+ (uncolonize word) "]"))
+ (setf space " "))
+ ((eq mode :optional)
+ (setf r (strcat r space "[" word "]"))
+ (setf space " "))
+ (t
+ (setf r (strcat r space word))
+ (setf space " "))))
+ r))
+
+(defun find-url-for (item)
+ (let (i entry)
+ ;; first, extract the initial symbol from item
+ (setf i (string-search " " item))
+ (cond (i (setf item (subseq item 0 i))))
+ ;; trim trailing (or any) close parenthesis
+ (setf i (string-search ")" item))
+ (cond (i (setf item (subseq item 0 i))))
+ ;; fix the case/capitalization to match what's in *index-list*
+ (setf item (index-casify item))
+ ;; look it up
+ (setf entry (assoc item *index-list* :test #'equal))
+ ;; return the URL
+ (cond (entry
+ ;; entry has (sort-key, name, ref1, ref2, ...)
+ (setf entry (third entry)) ;; get first reference
+ (format nil "~A#index~A" (first entry) (second entry)))
+ (t
+ (format t "WARNING: ~A IS NOT IN INDEX~%" item)
+ "home.htm"))))
+
+
+(defun codef-close () ;; called to close file
+ ;; nothing written yet
+ (let (url)
+ (setf *codef-list* (sort *codef-list* #'string<))
+ (dolist (item *codef-list*)
+ (setf url (find-url-for item))
+ (format *codef-file* "~A~%~A~%" item url))
+ (close *codef-file*)))