~%"))
(P s0)]
[(#\&) (P sampersand ())]
[(eof)
(close-input-port ip)
(if (null? ips)
(void)
(P (car eofconts)
([ip (car ips)]
[ips (cdr ips)]
[ifiles (if (eq? ip (car ifiles)) (pop-ifile ifiles) ifiles)]
[eofconts (cdr eofconts)])))]
[else (write-char c op) (P s0)])))
;-----------------------------------------------------------------------
; rudimentary table support
(define-record table (col-format border?))
(define silenced? #f)
(define parse-col-format
(lambda (s)
(let ([ip (open-input-string s)])
(let loop ([ls '()] [border? #f])
(state-case (c (read-char ip))
[(#\|)
(unless silenced?
(set! silenced? #t)
(warningf 'tabular "support for rules in HTML tables is imprecise"))
(loop ls #t)]
[(#\c) (loop (cons " align=\"center\"" ls) border?)]
[(#\l) (loop (cons " align=\"left\"" ls) border?)]
[(#\r) (loop (cons " align=\"right\"" ls) border?)]
[(#\@)
(warningf 'tabular "ignoring @{~a} for now" (read-bracketed-text ip))
(loop ls border?)]
[(eof) (make-table (list->vector (reverse ls)) border?)]
[else (input-error (format "unexpected column format specifier ~a" c))])))))
(define emit-td
(P lambda (k)
(fprintf (car ops) "
" (car ops))
(P s0 ([column 0]))))]
[else
(display "
\n" op)
(P s0)])))
;-----------------------------------------------------------------------
(define header-stuff (make-parameter #f))
(define style-sheet (make-parameter #f))
(define current-ofile (make-parameter #f)) ; for slabel
(define current-ref-label (make-parameter #f))
(define document-title (make-parameter #f))
(define index-entries (make-parameter #f))
(define latex-cache (make-parameter #f))
(define output-file-counters (make-parameter #f))
(define haux-op (make-parameter #f))
(define jobname (make-parameter #f))
(define go
(lambda (fn)
(define bit-sink
(let ()
(define make-bit-sink-port
(lambda ()
(define handler
(lambda (msg . args)
(record-case (cons msg args)
[block-write (p s n) (void)]
[clear-output-port (p) (set-port-output-index! p 0)]
[close-port (p)
(set-port-output-size! p 0)
(mark-port-closed! p)]
[flush-output-port (p) (set-port-output-index! p 0)]
[port-name (p) "bit-sink port"]
[write-char (c p) (set-port-output-index! p 0)]
[else (errorf 'bit-sink-port "operation ~s not handled"
msg)])))
(let ([len 1024])
(let ([p (make-output-port handler (make-string len))])
p))))
(make-bit-sink-port)))
(jobname fn)
(let ([ip (open-input-file (tex-file-name fn))])
; preplib parameters
(parameterize ([current-ifile #f]
[genlab-prefix "h"]
[genlab-counters '()])
; local parameters
(parameterize ([header-stuff #f]
[style-sheet #f]
[current-ofile #f]
[current-ref-label #f]
[document-title "Untitled Document"]
[index-entries '()]
[latex-cache '()]
[output-file-counters '()]
[haux-op bit-sink])
(P s0
([ip ip]
[op bit-sink]
[def-env '()]
[pending '(top)]
[groups '(top)]
[ips '()]
[ops '()]
[ifiles (push-ifile ip '())]
[ofiles '()]
[rawfiles '()]
[hard-spaces #f]
[eofconts (list s0)]
[undos (list '())]
[column #f] ; need flow-sensitive static analysis
[columns '()]
[colfmt #f] ; need flow-sensitive static analysis
[colfmts '()]
[convert-quotes #t])))))))
(global-def def
(P lambda ()
(let* ([cmd (state-case (c (read-char ip))
[(#\\) (read-command ip)]
[else (input-error "invalid \\def syntax")])]
[pattern (read-def-pattern ip)]
[template (read-bracketed-text ip)])
(set-def! cmd def-env #f
(P lambda ()
(P s0
([ip (open-input-string
(expand-template template
(read-args ip pattern cmd) cmd))]
[ips (cons ip ips)]
[eofconts (cons s0 eofconts)]))))
(P s0))))
;\let\foo=
(global-def let
(P lambda ()
(let* ([cmd (state-case (c (read-char ip))
[(#\\) (read-command ip)]
[else (input-error "invalid \\let syntax")])]
[rhs (state-case (c (read-char ip))
[(#\=) (state-case (c (read-char ip))
[(#\\) (read-command ip)]
[else (input-error "invalid \\let right-hand side")])]
[else (input-error "expected = after \\let")])])
(set-def! cmd def-env #f (get-def rhs def-env))
(P s0))))
(global-def edef
(P lambda ()
(let* ([cmd (state-case (c (read-char ip))
[(#\\) (read-command ip)]
[else (input-error "invalid \\def syntax")])]
[pattern (read-def-pattern ip)]
[template (read-bracketed-text ip)])
(P process-string () template
(P lambda (template)
(set-def! cmd def-env #f
(P lambda ()
(P s0
([ip (open-input-string
(expand-template template
(read-args ip pattern cmd) cmd))]
[ips (cons ip ips)]
[eofconts (cons s0 eofconts)]))))
(P s0))))))
(global-def newcommand
(P lambda ()
(read-open-brace ip)
(read-back-slash ip)
(let ([cmd (read-command ip)])
(read-close-brace ip)
(when (get-def cmd def-env)
(input-error "\\newcommand: \\~a already defined" cmd))
(P snewcommand () cmd))))
(global-def renewcommand
(P lambda ()
(read-open-brace ip)
(read-back-slash ip)
(let ([cmd (read-command ip)])
(read-close-brace ip)
(unless (get-def cmd def-env)
(input-error "\\renewcommand: \\~a undefined" cmd))
(P snewcommand () cmd))))
(global-def newenvironment
(P lambda ()
(let ([cmd (string->symbol (read-bracketed-text ip))])
(when (get-def cmd def-env)
(input-error "\\newenvironment: \\~a already defined" cmd))
(P snewenvironment () cmd))))
(global-def renewenvironment
(P lambda ()
(let ([cmd (string->symbol (read-bracketed-text ip))])
(unless (get-def cmd def-env)
(input-error "\\renewenvironment: \\~a undefined" cmd))
(P snewenvironment () cmd))))
(global-def begin
(P lambda ()
(let ([cmd (string->symbol (read-bracketed-text ip))])
(cond
[(get-def cmd def-env) => (lambda (proc) (P proc))]
[else (input-error "undefined command \\begin{~a}" cmd)]))))
(global-def end
(P lambda ()
(let* ([cmd (string->symbol (read-bracketed-text ip))]
[endcmd (string->symbol (format "end~a" cmd))])
(cond
[(get-def endcmd def-env) => (lambda (proc) (P proc))]
[else (input-error "undefined command \\end{~a}" cmd)]))))
(global-def eqnarray* ; no endeqnarray*---we finish the job here
(P lambda ()
(fprintf op "~%")
(seqnarray* ip op)
(fprintf op "
~%")
(P s0 ())))
(global-def divertoutput
(P lambda ()
(let* ([level-str (or (read-optional-arg ip) "0")]
[level (let ([i (string->number level-str)])
(and (fixnum? i)
(let ([n (length ofiles)])
(and (fixnum? i)
(if (fx< -1 i n)
(fx- n i 1)
(and (fx<= (- n) i -1)
(fx- -1 i)))))))])
(cond
[level (P s0 ([op (list-ref ofiles level)] [ops (cons op ops)]))]
[(assoc level-str rawfiles) =>
(lambda (a)
(P s0 ([op (cdr a)] [ops (cons op ops)])))]
[else (input-error (format "invalid divertoutput file ~a" level-str))]))))
(global-def enddivertoutput
(P lambda ()
(P s0 ([op (car ops)] [ops (cdr ops)]))))
(global-def begingroup
(P lambda ()
(P sbegingroup () 'begingroup)))
(global-def endgroup
(P lambda ()
(P sendgroup () 'begingroup)))
(global-def bgroup
(P lambda ()
(P sbegingroup () 'bgroup)))
(global-def egroup
(P lambda ()
(P sendgroup () 'bgroup)))
(global-def |[| ;]
(P lambda ()
(fprintf op "
~%")
(smathdisplay ip op)
(fprintf op "
~%")
(P s0)))
(global-def raw
(P lambda ()
(sraw (open-input-string (read-bracketed-text ip)) op)
(P s0)))
(global-def jobname
(P lambda ()
(display (jobname) op)
(P s0)))
(global-def newif
(P lambda ()
(snewif ip def-env)
(P s0)))
(numbering-command arabic (lambda (n) n))
(numbering-command alph
(lambda (n)
(when (> n 26)
(input-error "counter value ~a too large for \\alph" n))
(string-ref "abcdefghijklmnopqrstuvwxyz" (- n 1))))
(numbering-command Alph
(lambda (n)
(when (> n 26)
(input-error "counter value ~a too large for \\Alph" n))
(string-ref "ABCDEFGHIJKLMNOPQRSTUVWXYZ" (- n 1))))
(global-def newcounter
(P lambda ()
(let* ([name-str (read-bracketed-text ip)]
[counter (string->symbol name-str)]
[within (read-optional-arg ip)])
(when (get-counter-value counter)
(input-error "newcounter of existing counter ~a" counter))
(when within
(let ([within (string->symbol within)])
(unless (get-counter-value within)
(input-error "newcounter of ~a within unknown counter ~a"
counter within))
(add-subcounter! within counter)))
(set-counter-value! counter 0)
(set-def! (string->symbol (string-append "the" name-str)) def-env #f
(P lambda ()
(display (get-counter-value counter) op)
(P s0))))
(P s0)))
(global-def setcounter
(P lambda ()
(let* ([counter (string->symbol (read-bracketed-text ip))]
[num-str (read-bracketed-text ip)]
[old-value (get-counter-value counter)]
[new-value (string->number num-str)])
(unless old-value
(input-error "setcounter of unknown counter ~a" counter))
(unless new-value
(input-error "invalid setcounter value ~a" num-str))
(set-counter-value! counter new-value))
(P s0)))
(global-def addtocounter
(P lambda ()
(let* ([counter (string->symbol (read-bracketed-text ip))]
[num-str (read-bracketed-text ip)]
[old-value (get-counter-value counter)]
[incr (string->number num-str)])
(unless old-value
(input-error "addtocounter of unknown counter ~a" counter))
(unless incr
(input-error "invalid addtocounter increment ~a" num-str))
(set-counter-value! counter (+ old-value incr)))
(P s0)))
(global-def stepcounter
(P lambda ()
(let* ([counter (string->symbol (read-bracketed-text ip))]
[old-value (get-counter-value counter)])
(unless old-value
(input-error "\\stepcounter of unknown counter ~a" counter))
(set-counter-value! counter (+ old-value 1))
(for-each
(lambda (x) (set-counter-value! x 0))
(subcounters counter)))
(P s0)))
(global-def refstepcounter
(P lambda ()
(let* ([counter (string->symbol (read-bracketed-text ip))]
[old-value (get-counter-value counter)])
(unless old-value
(input-error "\\refstepcounter of unknown counter ~a" counter))
(set-counter-value! counter (+ old-value 1))
(for-each
(lambda (x) (set-counter-value! x 0))
(subcounters counter))
(P process-string () (format "\\the~a" counter)
(P lambda (s)
(let ([tag (gensym)])
(current-ref-label
(cons s (format "~a#~a" (current-ofile-name) tag)))
(fprintf op "" tag))
(P s0))))))
(global-def pagebreak
(P lambda ()
(read-optional-arg ip) ; ignore [...]
(P s0)))
(global-def verbatim ; no endverbatim---we finish the job here
(P lambda ()
(define escape-char
(lambda (c)
(case c
[(#\space #\tab #\newline #\return) (write-char c op)]
[(#\<) (fprintf op "<")]
[(#\>) (fprintf op ">")]
[(#\&) (fprintf op "&")]
[else (write-char c op)])))
(display "
" op)
(let loop ()
(state-case (c (read-char ip))
[(#\\)
(let ([cmd (read-command ip)])
(case cmd
[(end)
(state-case (c (read-char ip))
[(#\{)
(let ([what (read-alpha-command ip)])
(if (and (eq? what 'verbatim) (eqv? (peek-char ip) #\}))
(read-char ip)
(begin
(fprintf op "\\end{~a" what)
(loop))))]
[(eof) (unexpected-eof "within verbatim environment")]
[else (fprintf op "\\end") (escape-char c) (loop)])]
[else (fprintf op "\\~a" cmd) (loop)]))]
[(eof) (unexpected-eof "within verbatim environment")]
[else (escape-char c) (loop)]))
(fprintf op "
~%")
(P s0 ())))
(global-def |'|
(P lambda ()
(state-case (c (read-char ip))
[(#\e) (fprintf op "é")]
[(#\o) (fprintf op "ó")]
[else (input-error "invalid \\' command \\'~a" c)])
(P s0)))
(global-def |"| ; \"{}
(P lambda ()
(let ([arg (read-bracketed-text ip)])
(unless (= (string-length arg) 1)
(input-error "invalid \\\" argument ~s" arg))
(let ([c (string-ref arg 0)])
(case c
[(#\a #\e #\i #\o #\u #\y #\A #\E #\I #\O #\U)
(fprintf op "&~auml;" c)]
[else (input-error "invalid \\\" command \\\"{~a}" c)])))
(P s0)))
(global-def |c| ; \c{}
(P lambda ()
(let ([arg (read-bracketed-text ip)])
(unless (= (string-length arg) 1)
(input-error "invalid \\c argument ~s" arg))
(let ([c (string-ref arg 0)])
(case c
[(#\c #\C) (fprintf op "&~acedil;" c)]
[else (input-error "invalid \\c command \\c{~a}" c)])))
(P s0)))
(global-def ss
(P lambda ()
(fprintf op "ß")
(P s0)))
(global-def vskip
(P lambda ()
; it's a pain to parse tex amounts, so we choose to ignore
; everything up to the next line break instead...watch out!
(let ([op (open-output-string)])
(let f ()
(state-case (c (read-char ip))
[(#\newline eof)
(warningf 'vskip "discarded text: ~a" (get-output-string op))
(P s0)]
[else (write-char c op) (f)])))))
(global-def large
(P lambda ()
(fprintf op "")
(P s0
([undos (push-undo
(P lambda (next) (fprintf op "") (P next))
undos)]))))
(global-def Large
(P lambda ()
(fprintf op "")
(P s0
([undos (push-undo
(P lambda (next) (fprintf op "") (P next))
undos)]))))
(global-def LARGE
(P lambda ()
(fprintf op "")
(P s0
([undos (push-undo
(P lambda (next) (fprintf op "") (P next))
undos)]))))
(global-def small
(P lambda ()
(fprintf op "")
(P s0
([undos (push-undo
(P lambda (next) (fprintf op "") (P next))
undos)]))))
(global-def footnotesize
(P lambda ()
(fprintf op "")
(P s0
([undos (push-undo
(P lambda (next) (fprintf op "") (P next))
undos)]))))
(global-def tiny
(P lambda ()
(fprintf op "")
(P s0
([undos (push-undo
(P lambda (next) (fprintf op "") (P next))
undos)]))))
(global-def normalsize
(P lambda ()
(fprintf op "")
(P s0
([undos (push-undo
(P lambda (next) (fprintf op "") (P next))
undos)]))))
(global-def tt
(P lambda ()
(fprintf op "")
(P s0
([convert-quotes #f]
[undos (push-undo
(P lambda (next)
(fprintf op "")
(P next ([convert-quotes #t])))
undos)]))))
(global-def bf
(P lambda ()
(fprintf op "")
(P s0
([undos (push-undo
(P lambda (next) (fprintf op "") (P next))
undos)]))))
(global-def it
(P lambda ()
(fprintf op "")
(P s0
([undos (push-undo
(P lambda (next) (fprintf op "") (P next))
undos)]))))
(global-def hardspaces
(P lambda ()
(let ([old-hs hard-spaces])
(P s0
([hard-spaces #t]
[undos (push-undo
(P lambda (next) (P next ([hard-spaces old-hs])))
undos)])))))
(global-def include
(P lambda ()
(P process-string () (read-bracketed-text ip)
(P lambda (fn)
(P sinclude () (format "~a.tex" fn))))))
(global-def input
(P lambda ()
(P process-string () (read-bracketed-text ip)
(P lambda (fn)
(P sinclude () (tex-file-name fn))))))
(global-def rawinput
(P lambda ()
(P process-string () (read-bracketed-text ip)
(P lambda (fn)
(call-with-port (guard (c [else (warningf #f "cannot open ~a" fn) #f])
(open-input-file fn))
(lambda (raw-ip)
(let loop ()
(let ([c (read-char raw-ip)])
(unless (eof-object? c)
(write-char c op)
(loop))))))
(P s0)))))
(global-def label
(P lambda ()
(P process-string () (read-bracketed-text ip)
(P lambda (s)
(display (slabel (string->symbol s) "" s) op)
(P s0)))))
(global-def href
(P lambda ()
(let ([class (read-optional-arg ip)])
(P process-string () (read-bracketed-text ip)
(P lambda (lab)
(P process-string () (read-bracketed-text ip)
(P lambda (text)
(let ([name (string->symbol lab)])
(fprintf op "~a"
class
(get-label name 'ref-url)
text)
(P s0)))))))))
(global-def hpageref
(P lambda ()
(let ([class (read-optional-arg ip)])
(P process-string () (read-bracketed-text ip)
(P lambda (lab)
(P process-string () (read-bracketed-text ip)
(P lambda (text)
(let ([name (string->symbol lab)])
(fprintf op "~a"
class
(get-label name 'pageref-url)
text)
(P s0)))))))))
(global-def ref
(P lambda ()
(let ([class (read-optional-arg ip)])
(P process-string () (read-bracketed-text ip)
(P lambda (s)
(let ([name (string->symbol s)])
(fprintf op "~a"
class
(get-label name 'ref-url)
(get-label name 'ref)))
(P s0))))))
(global-def pageref
(P lambda ()
(let ([class (read-optional-arg ip)])
(P process-string () (read-bracketed-text ip)
(P lambda (s)
(let ([name (string->symbol s)])
(fprintf op "~a"
class
(get-label name 'pageref-url)
(get-label name 'pageref)))
(P s0))))))
(global-def cite
(P lambda ()
(write-char #\[ op)
(let ([keys (let ([sip (open-input-string (read-bracketed-text ip))]
[buf (open-output-string)])
(let loop ()
(state-case (c (read-char sip))
[(#\,)
(let ([key (get-output-string buf)])
(cons key (loop)))]
[(eof)
(list (get-output-string buf))]
[else
(write-char c buf)
(loop)])))])
(do ([keys keys (cdr keys)] [sep "" ","])
((null? keys) (write-char #\] op))
(let ([key (string->symbol (car keys))])
(fprintf op "~a~a"
sep (get-label key 'pageref-url) (get-cite key)))))
(P s0)))
(global-def epsfbox
(P lambda ()
(fprintf op "~%")
(punt-to-latex (format "\\input{epsf.sty}\\epsfbox{~a}" (read-bracketed-text ip)) op)
(fprintf op "
~%")
(P s0)))
(global-def bibitem
(P lambda ()
(let ([key (string->symbol (read-bracketed-text ip))])
(fprintf op "
[~a] " (slabel key (get-cite key))))
(P s0)))
(global-def openhtmlfile
(P lambda ()
(P process-string () (read-bracketed-text ip)
(P lambda (title)
(let ([new-op (open-html-file (car ifiles) title)])
(P s0
([op new-op]
[ops (cons op ops)]
[ofiles (push-ofile new-op ofiles)])))))))
(global-def closehtmlfile
(P lambda ()
(unless (and (not (null? ofiles)) (eq? op (car ofiles)))
(input-error "invalid context for \\closehtmlfile"))
(close-html-port op)
(P s0 ([op (car ops)] [ops (cdr ops)] [ofiles (pop-ofile ofiles)]))))
(global-def openrawfile
(P lambda ()
(let ([name (read-bracketed-text ip)])
(P process-string () (read-bracketed-text ip)
(P lambda (path)
(P s0 ([rawfiles (cons (cons name (open-output-file path 'replace))
rawfiles)])))))))
(global-def closerawfile
(P lambda ()
(let ([name (read-bracketed-text ip)])
(cond
[(assoc name rawfiles) =>
(lambda (a)
(close-output-port (cdr a))
(P s0 ([rawfiles (remq a rawfiles)])))]
[else (input-error "unrecognized raw file" name)]))))
(global-def genlab
(P lambda ()
(display (genlab) op)
(P s0)))
(global-def hindex
(P lambda ()
(P process-string () (read-bracketed-text ip)
(P lambda (s)
(read-open-brace ip)
(sindex ip op (string->symbol s))
(P s0)))))
(global-def index
(P lambda ()
(let ([lab (genlab)])
(display (slabel lab "") op)
(read-open-brace ip)
(sindex ip op lab)
(P s0))))
(global-def makeindex
(P lambda ()
(let ([buf (open-output-string)])
(smakeindex buf)
(P s0 ([ip (open-input-string (get-output-string buf))]
[ips (cons ip ips)]
[eofconts (cons s0 eofconts)])))))
(global-def documentclass
(P lambda ()
(read-optional-arg ip)
(P sinclude ()
(with-source-path 'documentclass
(format "~a.hcls" (read-bracketed-text ip))
(lambda (x)
(printf "using ~a~%" x)
x)))))
(global-def document
(P lambda ()
(let ([root (path-root (port-name (car ifiles)))])
(let ([auxfn (format "~a.aux" root)] [hauxfn (format "~a.haux" root)])
(guard (c [else (warningf #f "missing or incomplete aux file")])
(read-aux-file (format "~a.aux" root)))
(guard (c [else (warningf #f "missing or incomplete haux file")])
(load hauxfn))
(haux-op (open-output-file hauxfn 'replace))))
(P s0
([ip (open-input-string
(format "\\openhtmlfile{\\raw{~a}}" (document-title)))]
[ips (cons ip ips)]
[eofconts (cons s0 eofconts)]))))
(global-def enddocument
(P lambda ()
(for-each close-output-port (map cdr rawfiles))
(P s0
([ip (open-input-string "\\closehtmlfile")]
[ips (cons ip ips)]
[eofconts (cons s0 eofconts)]))))
(global-def headerstuff
(P lambda ()
(header-stuff (read-bracketed-text ip))
(P s0)))
(global-def documenttitle
(P lambda ()
(let ([fmt (read-optional-arg ip)])
(P process-string () (read-bracketed-text ip)
(P lambda (title)
(global-def thetitle (P lambda () (display title op) (P s0)))
(style-sheet fmt)
(document-title title)
(P s0))))))
(global-def |{|
(P lambda ()
(display "{" op)
(P s0)))
(global-def |}|
(P lambda ()
(display "}" op)
(P s0)))
(global-def | |
(P lambda ()
(display (if hard-spaces " " #\space) op)
(P s0)))
(global-def |\| scr)
(global-def usepackage
(P lambda ()
(let ([filename (string-append (read-bracketed-text ip) ".hsty")])
(P sinclude ()
(or (ormap
(lambda (p)
(let ([path (string-append p "/" filename)])
(and (file-exists? path) path)))
(source-directories))
(input-error
(format "hprep style file ~s not found in TEXINPUTS"
filename)))))))
(global-def year
(P lambda ()
(let* ([s (date-and-time)] [len (string-length s)])
(display (substring s (- len 4) len) op))
(P s0)))
(global-def url
(P lambda ()
(define display-url
(lambda (s op)
(let ([n (string-length s)])
(let loop ([i 0] [escape? #f])
(unless (fx= i n)
(loop (fx+ i 1)
(let ([c (string-ref s i)])
(or (and (not escape?) (char=? c #\\))
(begin (write-char c op) #f)))))))))
(display-url (read-bracketed-text ip) op)
(P s0)))
(let ()
(global-def tabular
(P lambda ()
(let ([s (read-bracketed-text ip)])
(let ([col-format (parse-col-format s)])
(display
(if (table-border? col-format)
"
"
"")
op)
(P s0 ([op (open-output-string)]
[ops (cons op ops)]
[column 0] ; could collapse these
[columns (cons column columns)]
[colfmt col-format]
[colfmts (cons colfmt colfmts)]
[pending (cons 'tabular pending)]))))))
(global-def endtabular
(P lambda ()
(P emit-td ()
(P lambda ()
(check-pending (car pending) 'tabular)
(display "
" (car ops))
(P s0 ([op (car ops)]
[ops (cdr ops)]
[column (car columns)]
[columns (cdr columns)]
[colfmt (car colfmts)]
[colfmts (cdr colfmts)]
[pending (cdr pending)]))))))
(global-def multicolumn
(P lambda ()
(let ([span
(or (string->number (read-bracketed-text ip))
(input-error "number expected"))]
[v (table-col-format colfmt)])
(unless (integer? span)
(input-error "invalid \\multicolumn span"))
(unless (<= 1 span (- (vector-length v) column))
(input-error
(format "\\multicolumn span ~s out of range for ~s column table"
span (vector-length v))))
(let* ([s (read-bracketed-text ip)]
[fmt (parse-col-format s)])
(unless (= 1 (vector-length (table-col-format fmt)))
(input-error (format "invalid \\multicolumn format ~a" s)))
(P s0 ([ip (open-input-string (read-bracketed-text ip))]
[ips (cons ip ips)]
[colfmt
(let ([newsize (- (vector-length v) span -1)])
(let ([new (make-vector newsize)])
(do ([i 0 (+ i 1)])
((= i newsize) (make-table new (table-border? colfmt)))
(vector-set! new i
(cond
[(< i column) (vector-ref v i)]
[(= i column)
(format " colspan=\"~a\"~a" span
(vector-ref (table-col-format fmt) 0))]
[else (vector-ref v (+ i span -1))])))))]
[colfmts (cons colfmt colfmts)]
[pending (cons 'multicolumn pending)]
[eofconts (cons s0 eofconts)]))))))
)
(populate-source-directories)
(command-line-case (command-line)
[((keyword --help)) (usage)]
[((flags [--mathdir mathdir $ (math-directory mathdir)])
filename* ...)
(for-each go
(let ([found (find-filename "html-prep.tex")])
(if found
(cons found filename*)
filename*)))])