~ chicken-core (chicken-5) c6d2abc010fa4e853c6ceb3ed94eca9563555c42
commit c6d2abc010fa4e853c6ceb3ed94eca9563555c42
Author: felix <felix@call-with-current-continuation.org>
AuthorDate: Thu Dec 24 00:26:14 2009 +0100
Commit: felix <felix@call-with-current-continuation.org>
CommitDate: Thu Dec 24 00:26:14 2009 +0100
added slatex to test suite
diff --git a/distribution/manifest b/distribution/manifest
index a17e8a44..961d4d4b 100644
--- a/distribution/manifest
+++ b/distribution/manifest
@@ -205,6 +205,9 @@ tests/feeley-dynwind.scm
tests/compiler-syntax-tests.scm
tests/compiler.scm
tests/fft.scm
+tests/slatex.scm
+tests/test.tex
+tests/slatex.sty
tweaks.scm
utils.scm
apply-hack.x86.S
diff --git a/tests/library-tests.scm b/tests/library-tests.scm
index 38d7e34f..4c5509fa 100644
--- a/tests/library-tests.scm
+++ b/tests/library-tests.scm
@@ -41,3 +41,6 @@
(assert (= -43.0 (fpfloor -42.5)))
(assert (= 43.0 (fpceiling 42.5)))
(assert (= -42.0 (fpceiling -42.2)))
+(assert (not (fpinteger? 2.3)))
+(assert (fpinteger? 1.0))
+
diff --git a/tests/runtests.sh b/tests/runtests.sh
index 68512d1b..cbdceceb 100644
--- a/tests/runtests.sh
+++ b/tests/runtests.sh
@@ -215,6 +215,12 @@ time $compile compiler.scm -O5 -debug pb -v
echo "executing ..."
time ./a.out
+echo "======================================== running slatex ..."
+$compile slatex.scm -O5
+mkdir -p slatexdir
+rm slatexdir/*
+time ./a.out
+
echo "======================================== running floating-point benchmark ..."
echo "boxed:"
$compile fft.scm -O5
diff --git a/tests/slatex.scm b/tests/slatex.scm
new file mode 100644
index 00000000..4c53a1a3
--- /dev/null
+++ b/tests/slatex.scm
@@ -0,0 +1,2373 @@
+(declare (standard-bindings) (extended-bindings)
+ (fixnum) (not safe) (block))
+
+(define slatex-iters 20)
+
+(define (fatal-error . args)
+ (for-each display args)
+ (newline)
+ (exit 1))
+
+ (define (call-with-output-file/truncate filename proc)
+ (call-with-output-file filename proc))
+
+(define (run-bench name count ok? run)
+ (let loop ((i count) (result '(undefined)))
+ (if (< 0 i)
+ (loop (- i 1) (run))
+ result)))
+
+(define (run-benchmark name count ok? run-maker . args)
+ (newline)
+ (let* ((run (apply run-maker args))
+ (result (run-bench name count ok? run)))
+ (if (not (ok? result))
+ (begin
+ (display "*** wrong result ***")
+ (newline)
+ (display "*** got: ")
+ (pp result)
+ (newline))))
+ (exit 0))
+
+;;; SLATEX -- Scheme to Latex processor.
+
+;slatex.scm file generated using config.scm
+;This file is compatible for the dialect other
+;(c) Dorai Sitaram, Rice U., 1991, 1994
+
+(define *op-sys* 'unix)
+
+(define slatex.ormap
+ (lambda (f l)
+ (let loop ((l l)) (if (null? l) #f (or (f (car l)) (loop (cdr l)))))))
+
+(define slatex.ormapcdr
+ (lambda (f l)
+ (let loop ((l l)) (if (null? l) #f (or (f l) (loop (cdr l)))))))
+
+(define slatex.append!
+ (lambda (l1 l2)
+ (cond ((null? l1) l2)
+ ((null? l2) l1)
+ (else
+ (let loop ((l1 l1))
+ (if (null? (cdr l1)) (set-cdr! l1 l2) (loop (cdr l1))))
+ l1))))
+
+(define slatex.append-map!
+ (lambda (f l)
+ (let loop ((l l))
+ (if (null? l) '() (slatex.append! (f (car l)) (loop (cdr l)))))))
+
+(define slatex.remove-if!
+ (lambda (p s)
+ (let loop ((s s))
+ (cond ((null? s) '())
+ ((p (car s)) (loop (cdr s)))
+ (else (let ((r (loop (cdr s)))) (set-cdr! s r) s))))))
+
+(define slatex.reverse!
+ (lambda (s)
+ (let loop ((s s) (r '()))
+ (if (null? s) r (let ((d (cdr s))) (set-cdr! s r) (loop d s))))))
+
+(define slatex.list-set!
+ (lambda (l i v)
+ (let loop ((l l) (i i))
+ (cond ((null? l) (slatex.error 'slatex.list-set! 'list-too-small))
+ ((= i 0) (set-car! l v))
+ (else (loop (cdr l) (- i 1)))))))
+
+(define slatex.list-prefix?
+ (lambda (pfx l)
+ (cond ((null? pfx) #t)
+ ((null? l) #f)
+ ((eqv? (car pfx) (car l)) (slatex.list-prefix? (cdr pfx) (cdr l)))
+ (else #f))))
+
+(define slatex.string-prefix?
+ (lambda (pfx s)
+ (let ((pfx-len (string-length pfx)) (s-len (string-length s)))
+ (if (> pfx-len s-len)
+ #f
+ (let loop ((i 0))
+ (if (>= i pfx-len)
+ #t
+ (and (char=? (string-ref pfx i) (string-ref s i))
+ (loop (+ i 1)))))))))
+
+(define slatex.string-suffix?
+ (lambda (sfx s)
+ (let ((sfx-len (string-length sfx)) (s-len (string-length s)))
+ (if (> sfx-len s-len)
+ #f
+ (let loop ((i (- sfx-len 1)) (j (- s-len 1)))
+ (if (< i 0)
+ #t
+ (and (char=? (string-ref sfx i) (string-ref s j))
+ (loop (- i 1) (- j 1)))))))))
+
+(define slatex.member-string member)
+
+(define slatex.adjoin-string
+ (lambda (s l) (if (slatex.member-string s l) l (cons s l))))
+
+(define slatex.remove-string!
+ (lambda (s l) (slatex.remove-if! (lambda (l_i) (string=? l_i s)) l)))
+
+(define slatex.adjoin-char (lambda (c l) (if (memv c l) l (cons c l))))
+
+(define slatex.remove-char!
+ (lambda (c l) (slatex.remove-if! (lambda (l_i) (char=? l_i c)) l)))
+
+(define slatex.sublist
+ (lambda (l i f)
+ (let loop ((l (list-tail l i)) (k i) (r '()))
+ (cond ((>= k f) (slatex.reverse! r))
+ ((null? l) (slatex.error 'slatex.sublist 'list-too-small))
+ (else (loop (cdr l) (+ k 1) (cons (car l) r)))))))
+
+(define slatex.position-char
+ (lambda (c l)
+ (let loop ((l l) (i 0))
+ (cond ((null? l) #f)
+ ((char=? (car l) c) i)
+ (else (loop (cdr l) (+ i 1)))))))
+
+(define slatex.string-position-right
+ (lambda (c s)
+ (let ((n (string-length s)))
+ (let loop ((i (- n 1)))
+ (cond ((< i 0) #f)
+ ((char=? (string-ref s i) c) i)
+ (else (loop (- i 1))))))))
+
+(define slatex.token=?
+ (lambda (t1 t2)
+ ((if slatex.*slatex-case-sensitive?* string=? string-ci=?) t1 t2)))
+
+(define slatex.assoc-token
+ (lambda (x s)
+ (slatex.ormap (lambda (s_i) (if (slatex.token=? (car s_i) x) s_i #f)) s)))
+
+(define slatex.member-token
+ (lambda (x s)
+ (slatex.ormapcdr
+ (lambda (s_i..) (if (slatex.token=? (car s_i..) x) s_i.. #f))
+ s)))
+
+(define slatex.remove-token!
+ (lambda (x s) (slatex.remove-if! (lambda (s_i) (slatex.token=? s_i x)) s)))
+
+(define slatex.file-exists? (lambda (f) #t))
+
+(define slatex.delete-file (lambda (f) 'assume-file-deleted))
+
+(define slatex.force-output (lambda z 'assume-output-forced))
+
+(define slatex.*return* (integer->char 13))
+
+(define slatex.*tab* (integer->char 9))
+
+(define slatex.error
+ (lambda (error-type error-values)
+ (display "Error: ")
+ (display error-type)
+ (display ": ")
+ (newline)
+ (for-each (lambda (x) (write x) (newline)) error-values)
+ (fatal-error "")))
+
+(define slatex.keyword-tokens
+ (map symbol->string
+ '(=> %
+ abort
+ and
+ begin
+ begin0
+ case
+ case-lambda
+ cond
+ define
+ define!
+ define-macro!
+ define-syntax
+ defrec!
+ delay
+ do
+ else
+ extend-syntax
+ fluid-let
+ if
+ lambda
+ let
+ let*
+ letrec
+ let-syntax
+ letrec-syntax
+ or
+ quasiquote
+ quote
+ rec
+ record-case
+ record-evcase
+ recur
+ set!
+ sigma
+ struct
+ syntax
+ syntax-rules
+ trace
+ trace-lambda
+ trace-let
+ trace-recur
+ unless
+ unquote
+ unquote-splicing
+ untrace
+ when
+ with)))
+
+(define slatex.variable-tokens '())
+
+(define slatex.constant-tokens '())
+
+(define slatex.special-symbols
+ (list (cons "." ".")
+ (cons "..." "{\\dots}")
+ (cons "-" "$-$")
+ (cons "1-" "\\va{1$-$}")
+ (cons "-1+" "\\va{$-$1$+$}")))
+
+(define slatex.macro-definers
+ '("define-syntax" "syntax-rules" "defmacro" "extend-syntax" "define-macro!"))
+
+(define slatex.case-and-ilk '("case" "record-case"))
+
+(define slatex.tex-analog
+ (lambda (c)
+ (cond ((memv c '(#\$ #\& #\% #\# #\_)) (string #\\ c))
+ ((memv c '(#\{ #\})) (string #\$ #\\ c #\$))
+ ((char=? c #\\) "$\\backslash$")
+ ((char=? c #\+) "$+$")
+ ((char=? c #\=) "$=$")
+ ((char=? c #\<) "$\\lt$")
+ ((char=? c #\>) "$\\gt$")
+ ((char=? c #\^) "\\^{}")
+ ((char=? c #\|) "$\\vert$")
+ ((char=? c #\~) "\\~{}")
+ ((char=? c #\@) "{\\atsign}")
+ ((char=? c #\") "{\\tt\\dq}")
+ (else (string c)))))
+
+(define slatex.*slatex-case-sensitive?* #t)
+
+(define slatex.*slatex-enabled?* #t)
+
+(define slatex.*slatex-reenabler* "UNDEFINED")
+
+(define slatex.*intext-triggerers* (list "scheme"))
+
+(define slatex.*resultintext-triggerers* (list "schemeresult"))
+
+(define slatex.*display-triggerers* (list "schemedisplay"))
+
+(define slatex.*box-triggerers* (list "schemebox"))
+
+(define slatex.*input-triggerers* (list "schemeinput"))
+
+(define slatex.*region-triggerers* (list "schemeregion"))
+
+(define slatex.*math-triggerers* '())
+
+(define slatex.*slatex-in-protected-region?* #f)
+
+(define slatex.*protected-files* '())
+
+(define slatex.*include-onlys* 'all)
+
+(define slatex.*latex?* #t)
+
+(define slatex.*slatex-separate-includes?* #f)
+
+(define slatex.set-keyword
+ (lambda (x)
+ (if (slatex.member-token x slatex.keyword-tokens)
+ 'skip
+ (begin
+ (set! slatex.constant-tokens
+ (slatex.remove-token! x slatex.constant-tokens))
+ (set! slatex.variable-tokens
+ (slatex.remove-token! x slatex.variable-tokens))
+ (set! slatex.keyword-tokens (cons x slatex.keyword-tokens))))))
+
+(define slatex.set-constant
+ (lambda (x)
+ (if (slatex.member-token x slatex.constant-tokens)
+ 'skip
+ (begin
+ (set! slatex.keyword-tokens
+ (slatex.remove-token! x slatex.keyword-tokens))
+ (set! slatex.variable-tokens
+ (slatex.remove-token! x slatex.variable-tokens))
+ (set! slatex.constant-tokens (cons x slatex.constant-tokens))))))
+
+(define slatex.set-variable
+ (lambda (x)
+ (if (slatex.member-token x slatex.variable-tokens)
+ 'skip
+ (begin
+ (set! slatex.keyword-tokens
+ (slatex.remove-token! x slatex.keyword-tokens))
+ (set! slatex.constant-tokens
+ (slatex.remove-token! x slatex.constant-tokens))
+ (set! slatex.variable-tokens (cons x slatex.variable-tokens))))))
+
+(define slatex.set-special-symbol
+ (lambda (x transl)
+ (let ((c (slatex.assoc-token x slatex.special-symbols)))
+ (if c
+ (set-cdr! c transl)
+ (set! slatex.special-symbols
+ (cons (cons x transl) slatex.special-symbols))))))
+
+(define slatex.unset-special-symbol
+ (lambda (x)
+ (set! slatex.special-symbols
+ (slatex.remove-if!
+ (lambda (c) (slatex.token=? (car c) x))
+ slatex.special-symbols))))
+
+(define slatex.texify (lambda (s) (list->string (slatex.texify-aux s))))
+
+(define slatex.texify-data
+ (lambda (s)
+ (let loop ((l (slatex.texify-aux s)) (r '()))
+ (if (null? l)
+ (list->string (slatex.reverse! r))
+ (let ((c (car l)))
+ (loop (cdr l)
+ (if (char=? c #\-)
+ (slatex.append! (list #\$ c #\$) r)
+ (cons c r))))))))
+
+(define slatex.texify-aux
+ (let* ((arrow (string->list "-$>$")) (arrow-lh (length arrow)))
+ (lambda (s)
+ (let* ((sl (string->list s))
+ (texified-sl
+ (slatex.append-map!
+ (lambda (c) (string->list (slatex.tex-analog c)))
+ sl)))
+ (slatex.ormapcdr
+ (lambda (d)
+ (if (slatex.list-prefix? arrow d)
+ (let ((to (string->list "$\\to$")))
+ (set-car! d (car to))
+ (set-cdr! d (append (cdr to) (list-tail d arrow-lh)))))
+ #f)
+ texified-sl)
+ texified-sl))))
+
+(define slatex.display-begin-sequence
+ (lambda (out)
+ (if (or slatex.*intext?* (not slatex.*latex?*))
+ (begin
+ (display "\\" out)
+ (display slatex.*code-env-spec* out)
+ (newline out))
+ (begin
+ (display "\\begin{" out)
+ (display slatex.*code-env-spec* out)
+ (display "}" out)
+ (newline out)))))
+
+(define slatex.display-end-sequence
+ (lambda (out)
+ (if (or slatex.*intext?* (not slatex.*latex?*))
+ (begin
+ (display "\\end" out)
+ (display slatex.*code-env-spec* out)
+ (newline out))
+ (begin
+ (display "\\end{" out)
+ (display slatex.*code-env-spec* out)
+ (display "}" out)
+ (newline out)))))
+
+(define slatex.display-tex-char
+ (lambda (c p) (display (if (char? c) (slatex.tex-analog c) c) p)))
+
+(define slatex.display-token
+ (lambda (s typ p)
+ (cond ((eq? typ 'syntax)
+ (display "\\sy{" p)
+ (display (slatex.texify s) p)
+ (display "}" p))
+ ((eq? typ 'variable)
+ (display "\\va{" p)
+ (display (slatex.texify s) p)
+ (display "}" p))
+ ((eq? typ 'constant)
+ (display "\\cn{" p)
+ (display (slatex.texify s) p)
+ (display "}" p))
+ ((eq? typ 'data)
+ (display "\\dt{" p)
+ (display (slatex.texify-data s) p)
+ (display "}" p))
+ (else (slatex.error 'slatex.display-token typ)))))
+
+(define slatex.*max-line-length* 200)
+
+(begin
+ (define slatex.&inner-space (integer->char 7))
+ (define slatex."e-space (integer->char 6))
+ (define slatex.&bracket-space (integer->char 5))
+ (define slatex.&paren-space (integer->char 4))
+ (define slatex.&init-plain-space (integer->char 3))
+ (define slatex.&init-space (integer->char 2))
+ (define slatex.&plain-space (integer->char 1))
+ (define slatex.&void-space (integer->char 0)))
+
+(begin
+ (define slatex.&plain-crg-ret (integer->char 4))
+ (define slatex.&tabbed-crg-ret (integer->char 3))
+ (define slatex.&move-tab (integer->char 2))
+ (define slatex.&set-tab (integer->char 1))
+ (define slatex.&void-tab (integer->char 0)))
+
+(begin
+ (define slatex.&end-math (integer->char 8))
+ (define slatex.&mid-math (integer->char 7))
+ (define slatex.&begin-math (integer->char 6))
+ (define slatex.&end-string (integer->char 5))
+ (define slatex.&mid-string (integer->char 4))
+ (define slatex.&begin-string (integer->char 3))
+ (define slatex.&mid-comment (integer->char 2))
+ (define slatex.&begin-comment (integer->char 1))
+ (define slatex.&void-notab (integer->char 0)))
+
+(begin
+ (define slatex.make-raw-line (lambda () (make-vector 5)))
+ (define slatex.=notab 4)
+ (define slatex.=tab 3)
+ (define slatex.=space 2)
+ (define slatex.=char 1)
+ (define slatex.=rtedge 0))
+
+(define slatex.make-line
+ (lambda ()
+ (let ((l (slatex.make-raw-line)))
+ (vector-set! l slatex.=rtedge 0)
+ (vector-set!
+ l
+ slatex.=char
+ (make-string slatex.*max-line-length* #\space))
+ (vector-set!
+ l
+ slatex.=space
+ (make-string slatex.*max-line-length* slatex.&void-space))
+ (vector-set!
+ l
+ slatex.=tab
+ (make-string slatex.*max-line-length* slatex.&void-tab))
+ (vector-set!
+ l
+ slatex.=notab
+ (make-string slatex.*max-line-length* slatex.&void-notab))
+ l)))
+
+(define slatex.*line1* (slatex.make-line))
+
+(define slatex.*line2* (slatex.make-line))
+
+(begin
+ (define slatex.make-case-frame (lambda () (make-vector 3)))
+ (define slatex.=in-case-exp 2)
+ (define slatex.=in-bktd-ctag-exp 1)
+ (define =in-ctag-tkn 0))
+
+(begin
+ (define slatex.make-bq-frame (lambda () (make-vector 3)))
+ (define slatex.=in-bktd-bq-exp 2)
+ (define slatex.=in-bq-tkn 1)
+ (define slatex.=in-comma 0))
+
+(define slatex.*latex-paragraph-mode?* 'fwd1)
+
+(define slatex.*intext?* 'fwd2)
+
+(define slatex.*code-env-spec* "UNDEFINED")
+
+(define slatex.*in* 'fwd3)
+
+(define slatex.*out* 'fwd4)
+
+(define slatex.*in-qtd-tkn* 'fwd5)
+
+(define slatex.*in-bktd-qtd-exp* 'fwd6)
+
+(define slatex.*in-mac-tkn* 'fwd7)
+
+(define slatex.*in-bktd-mac-exp* 'fwd8)
+
+(define slatex.*case-stack* 'fwd9)
+
+(define slatex.*bq-stack* 'fwd10)
+
+(define slatex.display-space
+ (lambda (s p)
+ (cond ((eq? s slatex.&plain-space) (display #\space p))
+ ((eq? s slatex.&init-plain-space) (display #\space p))
+ ((eq? s slatex.&init-space) (display "\\HL " p))
+ ((eq? s slatex.&paren-space) (display "\\PRN " p))
+ ((eq? s slatex.&bracket-space) (display "\\BKT " p))
+ ((eq? s slatex."e-space) (display "\\QUO " p))
+ ((eq? s slatex.&inner-space) (display "\\ " p)))))
+
+(define slatex.display-tab
+ (lambda (tab p)
+ (cond ((eq? tab slatex.&set-tab) (display "\\=" p))
+ ((eq? tab slatex.&move-tab) (display "\\>" p)))))
+
+(define slatex.display-notab
+ (lambda (notab p)
+ (cond ((eq? notab slatex.&begin-string) (display "\\dt{" p))
+ ((eq? notab slatex.&end-string) (display "}" p)))))
+
+(define slatex.get-line
+ (let ((curr-notab slatex.&void-notab))
+ (lambda (line)
+ (let ((graphic-char-seen? #f))
+ (let loop ((i 0))
+ (let ((c (read-char slatex.*in*)))
+ (cond (graphic-char-seen? 'already-seen)
+ ((or (eof-object? c)
+ (char=? c slatex.*return*)
+ (char=? c #\newline)
+ (char=? c #\space)
+ (char=? c slatex.*tab*))
+ 'not-yet)
+ (else (set! graphic-char-seen? #t)))
+ (cond ((eof-object? c)
+ (cond ((eq? curr-notab slatex.&mid-string)
+ (if (> i 0)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ (- i 1)
+ slatex.&end-string)))
+ ((eq? curr-notab slatex.&mid-comment)
+ (set! curr-notab slatex.&void-notab))
+ ((eq? curr-notab slatex.&mid-math)
+ (slatex.error
+ 'slatex.get-line
+ 'runaway-math-subformula)))
+ (string-set! (vector-ref line slatex.=char) i #\newline)
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ slatex.&void-space)
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i
+ slatex.&void-tab)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ i
+ slatex.&void-notab)
+ (vector-set! line slatex.=rtedge i)
+ (if (eq? (string-ref (vector-ref line slatex.=notab) 0)
+ slatex.&mid-string)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ 0
+ slatex.&begin-string))
+ (if (= i 0) #f #t))
+ ((or (char=? c slatex.*return*) (char=? c #\newline))
+ (if (and (eq? *op-sys* 'dos) (char=? c slatex.*return*))
+ (if (char=? (peek-char slatex.*in*) #\newline)
+ (read-char slatex.*in*)))
+ (cond ((eq? curr-notab slatex.&mid-string)
+ (if (> i 0)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ (- i 1)
+ slatex.&end-string)))
+ ((eq? curr-notab slatex.&mid-comment)
+ (set! curr-notab slatex.&void-notab))
+ ((eq? curr-notab slatex.&mid-math)
+ (slatex.error
+ 'slatex.get-line
+ 'runaway-math-subformula)))
+ (string-set! (vector-ref line slatex.=char) i #\newline)
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ slatex.&void-space)
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i
+ (cond ((eof-object? (peek-char slatex.*in*))
+ slatex.&plain-crg-ret)
+ (slatex.*intext?* slatex.&plain-crg-ret)
+ (else slatex.&tabbed-crg-ret)))
+ (string-set!
+ (vector-ref line slatex.=notab)
+ i
+ slatex.&void-notab)
+ (vector-set! line slatex.=rtedge i)
+ (if (eq? (string-ref (vector-ref line slatex.=notab) 0)
+ slatex.&mid-string)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ 0
+ slatex.&begin-string))
+ #t)
+ ((eq? curr-notab slatex.&mid-comment)
+ (string-set! (vector-ref line slatex.=char) i c)
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ (cond ((char=? c #\space) slatex.&plain-space)
+ ((char=? c slatex.*tab*) slatex.&plain-space)
+ (else slatex.&void-space)))
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i
+ slatex.&void-tab)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ i
+ slatex.&mid-comment)
+ (loop (+ i 1)))
+ ((char=? c #\\)
+ (string-set! (vector-ref line slatex.=char) i c)
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ slatex.&void-space)
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i
+ slatex.&void-tab)
+ (string-set! (vector-ref line slatex.=notab) i curr-notab)
+ (let ((i+1 (+ i 1)) (c+1 (read-char slatex.*in*)))
+ (if (char=? c+1 slatex.*tab*) (set! c+1 #\space))
+ (string-set! (vector-ref line slatex.=char) i+1 c+1)
+ (string-set!
+ (vector-ref line slatex.=space)
+ i+1
+ (if (char=? c+1 #\space)
+ slatex.&plain-space
+ slatex.&void-space))
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i+1
+ slatex.&void-tab)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ i+1
+ curr-notab)
+ (loop (+ i+1 1))))
+ ((eq? curr-notab slatex.&mid-math)
+ (if (char=? c slatex.*tab*) (set! c #\space))
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ (if (char=? c #\space)
+ slatex.&plain-space
+ slatex.&void-space))
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i
+ slatex.&void-tab)
+ (cond ((memv c slatex.*math-triggerers*)
+ (string-set! (vector-ref line slatex.=char) i #\$)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ i
+ slatex.&end-math)
+ (set! curr-notab slatex.&void-notab))
+ (else
+ (string-set! (vector-ref line slatex.=char) i c)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ i
+ slatex.&mid-math)))
+ (loop (+ i 1)))
+ ((eq? curr-notab slatex.&mid-string)
+ (if (char=? c slatex.*tab*) (set! c #\space))
+ (string-set! (vector-ref line slatex.=char) i c)
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ (if (char=? c #\space)
+ slatex.&inner-space
+ slatex.&void-space))
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i
+ slatex.&void-tab)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ i
+ (cond ((char=? c #\")
+ (set! curr-notab slatex.&void-notab)
+ slatex.&end-string)
+ (else slatex.&mid-string)))
+ (loop (+ i 1)))
+ ((char=? c #\space)
+ (string-set! (vector-ref line slatex.=char) i c)
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ (cond (slatex.*intext?* slatex.&plain-space)
+ (graphic-char-seen? slatex.&inner-space)
+ (else slatex.&init-space)))
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i
+ slatex.&void-tab)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ i
+ slatex.&void-notab)
+ (loop (+ i 1)))
+ ((char=? c slatex.*tab*)
+ (let loop2 ((i i) (j 0))
+ (if (< j 8)
+ (begin
+ (string-set! (vector-ref line slatex.=char) i #\space)
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ (cond (slatex.*intext?* slatex.&plain-space)
+ (graphic-char-seen? slatex.&inner-space)
+ (else slatex.&init-space)))
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i
+ slatex.&void-tab)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ i
+ slatex.&void-notab)
+ (loop2 (+ i 1) (+ j 1)))))
+ (loop (+ i 8)))
+ ((char=? c #\")
+ (string-set! (vector-ref line slatex.=char) i c)
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ slatex.&void-space)
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i
+ slatex.&void-tab)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ i
+ slatex.&begin-string)
+ (set! curr-notab slatex.&mid-string)
+ (loop (+ i 1)))
+ ((char=? c #\;)
+ (string-set! (vector-ref line slatex.=char) i c)
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ slatex.&void-space)
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i
+ slatex.&void-tab)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ i
+ slatex.&begin-comment)
+ (set! curr-notab slatex.&mid-comment)
+ (loop (+ i 1)))
+ ((memv c slatex.*math-triggerers*)
+ (string-set! (vector-ref line slatex.=char) i #\$)
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ slatex.&void-space)
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i
+ slatex.&void-tab)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ i
+ slatex.&begin-math)
+ (set! curr-notab slatex.&mid-math)
+ (loop (+ i 1)))
+ (else
+ (string-set! (vector-ref line slatex.=char) i c)
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ slatex.&void-space)
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i
+ slatex.&void-tab)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ i
+ slatex.&void-notab)
+ (loop (+ i 1))))))))))
+
+(define slatex.peephole-adjust
+ (lambda (curr prev)
+ (if (or (slatex.blank-line? curr) (slatex.flush-comment-line? curr))
+ (if slatex.*latex-paragraph-mode?*
+ 'skip
+ (begin
+ (set! slatex.*latex-paragraph-mode?* #t)
+ (if slatex.*intext?*
+ 'skip
+ (begin
+ (slatex.remove-some-tabs prev 0)
+ (let ((prev-rtedge (vector-ref prev slatex.=rtedge)))
+ (if (eq? (string-ref (vector-ref prev slatex.=tab) prev-rtedge)
+ slatex.&tabbed-crg-ret)
+ (string-set!
+ (vector-ref prev slatex.=tab)
+ (vector-ref prev slatex.=rtedge)
+ slatex.&plain-crg-ret)))))))
+ (begin
+ (if slatex.*latex-paragraph-mode?*
+ (set! slatex.*latex-paragraph-mode?* #f)
+ (if slatex.*intext?*
+ 'skip
+ (let ((remove-tabs-from #f))
+ (let loop ((i 0))
+ (cond ((char=? (string-ref (vector-ref curr slatex.=char) i)
+ #\newline)
+ (set! remove-tabs-from i))
+ ((char=? (string-ref (vector-ref prev slatex.=char) i)
+ #\newline)
+ (set! remove-tabs-from #f))
+ ((eq? (string-ref (vector-ref curr slatex.=space) i)
+ slatex.&init-space)
+ (if (eq? (string-ref (vector-ref prev slatex.=notab) i)
+ slatex.&void-notab)
+ (begin
+ (cond ((or (char=? (string-ref
+ (vector-ref prev slatex.=char)
+ i)
+ #\()
+ (eq? (string-ref
+ (vector-ref prev slatex.=space)
+ i)
+ slatex.&paren-space))
+ (string-set!
+ (vector-ref curr slatex.=space)
+ i
+ slatex.&paren-space))
+ ((or (char=? (string-ref
+ (vector-ref prev slatex.=char)
+ i)
+ #\[)
+ (eq? (string-ref
+ (vector-ref prev slatex.=space)
+ i)
+ slatex.&bracket-space))
+ (string-set!
+ (vector-ref curr slatex.=space)
+ i
+ slatex.&bracket-space))
+ ((or (memv (string-ref
+ (vector-ref prev slatex.=char)
+ i)
+ '(#\' #\` #\,))
+ (eq? (string-ref
+ (vector-ref prev slatex.=space)
+ i)
+ slatex."e-space))
+ (string-set!
+ (vector-ref curr slatex.=space)
+ i
+ slatex."e-space)))
+ (if (memq (string-ref
+ (vector-ref prev slatex.=tab)
+ i)
+ (list slatex.&set-tab slatex.&move-tab))
+ (string-set!
+ (vector-ref curr slatex.=tab)
+ i
+ slatex.&move-tab))))
+ (loop (+ i 1)))
+ ((= i 0) (set! remove-tabs-from 0))
+ ((not (eq? (string-ref (vector-ref prev slatex.=tab) i)
+ slatex.&void-tab))
+ (set! remove-tabs-from (+ i 1))
+ (if (memq (string-ref (vector-ref prev slatex.=tab) i)
+ (list slatex.&set-tab slatex.&move-tab))
+ (string-set!
+ (vector-ref curr slatex.=tab)
+ i
+ slatex.&move-tab)))
+ ((memq (string-ref (vector-ref prev slatex.=space) i)
+ (list slatex.&init-space
+ slatex.&init-plain-space
+ slatex.&paren-space
+ slatex.&bracket-space
+ slatex."e-space))
+ (set! remove-tabs-from (+ i 1)))
+ ((and (char=? (string-ref
+ (vector-ref prev slatex.=char)
+ (- i 1))
+ #\space)
+ (eq? (string-ref
+ (vector-ref prev slatex.=notab)
+ (- i 1))
+ slatex.&void-notab))
+ (set! remove-tabs-from (+ i 1))
+ (string-set!
+ (vector-ref prev slatex.=tab)
+ i
+ slatex.&set-tab)
+ (string-set!
+ (vector-ref curr slatex.=tab)
+ i
+ slatex.&move-tab))
+ (else
+ (set! remove-tabs-from (+ i 1))
+ (let loop1 ((j (- i 1)))
+ (cond ((<= j 0) 'exit-loop1)
+ ((not (eq? (string-ref
+ (vector-ref curr slatex.=tab)
+ j)
+ slatex.&void-tab))
+ 'exit-loop1)
+ ((memq (string-ref
+ (vector-ref curr slatex.=space)
+ j)
+ (list slatex.&paren-space
+ slatex.&bracket-space
+ slatex."e-space))
+ (loop1 (- j 1)))
+ ((or (not (eq? (string-ref
+ (vector-ref prev slatex.=notab)
+ j)
+ slatex.&void-notab))
+ (char=? (string-ref
+ (vector-ref prev slatex.=char)
+ j)
+ #\space))
+ (let ((k (+ j 1)))
+ (if (memq (string-ref
+ (vector-ref prev slatex.=notab)
+ k)
+ (list slatex.&mid-comment
+ slatex.&mid-math
+ slatex.&end-math
+ slatex.&mid-string
+ slatex.&end-string))
+ 'skip
+ (begin
+ (if (eq? (string-ref
+ (vector-ref prev slatex.=tab)
+ k)
+ slatex.&void-tab)
+ (string-set!
+ (vector-ref prev slatex.=tab)
+ k
+ slatex.&set-tab))
+ (string-set!
+ (vector-ref curr slatex.=tab)
+ k
+ slatex.&move-tab)))))
+ (else 'anything-else?))))))
+ (slatex.remove-some-tabs prev remove-tabs-from))))
+ (if slatex.*intext?* 'skip (slatex.add-some-tabs curr))
+ (slatex.clean-init-spaces curr)
+ (slatex.clean-inner-spaces curr)))))
+
+(define slatex.add-some-tabs
+ (lambda (line)
+ (let loop ((i 1) (succ-parens? #f))
+ (let ((c (string-ref (vector-ref line slatex.=char) i)))
+ (cond ((char=? c #\newline) 'exit-loop)
+ ((not (eq? (string-ref (vector-ref line slatex.=notab) i)
+ slatex.&void-notab))
+ (loop (+ i 1) #f))
+ ((char=? c #\[)
+ (if (eq? (string-ref (vector-ref line slatex.=tab) i)
+ slatex.&void-tab)
+ (string-set! (vector-ref line slatex.=tab) i slatex.&set-tab))
+ (loop (+ i 1) #f))
+ ((char=? c #\()
+ (if (eq? (string-ref (vector-ref line slatex.=tab) i)
+ slatex.&void-tab)
+ (if succ-parens?
+ 'skip
+ (string-set!
+ (vector-ref line slatex.=tab)
+ i
+ slatex.&set-tab)))
+ (loop (+ i 1) #t))
+ (else (loop (+ i 1) #f)))))))
+
+(define slatex.remove-some-tabs
+ (lambda (line i)
+ (if i
+ (let loop ((i i))
+ (cond ((char=? (string-ref (vector-ref line slatex.=char) i) #\newline)
+ 'exit)
+ ((eq? (string-ref (vector-ref line slatex.=tab) i)
+ slatex.&set-tab)
+ (string-set! (vector-ref line slatex.=tab) i slatex.&void-tab)
+ (loop (+ i 1)))
+ (else (loop (+ i 1))))))))
+
+(define slatex.clean-init-spaces
+ (lambda (line)
+ (let loop ((i (vector-ref line slatex.=rtedge)))
+ (cond ((< i 0) 'exit-loop)
+ ((eq? (string-ref (vector-ref line slatex.=tab) i)
+ slatex.&move-tab)
+ (let loop2 ((i (- i 1)))
+ (cond ((< i 0) 'exit-loop2)
+ ((memq (string-ref (vector-ref line slatex.=space) i)
+ (list slatex.&init-space
+ slatex.&paren-space
+ slatex.&bracket-space
+ slatex."e-space))
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ slatex.&init-plain-space)
+ (loop2 (- i 1)))
+ (else (loop2 (- i 1))))))
+ (else (loop (- i 1)))))))
+
+(define slatex.clean-inner-spaces
+ (lambda (line)
+ (let loop ((i 0) (succ-inner-spaces? #f))
+ (cond ((char=? (string-ref (vector-ref line slatex.=char) i) #\newline)
+ 'exit-loop)
+ ((eq? (string-ref (vector-ref line slatex.=space) i)
+ slatex.&inner-space)
+ (if succ-inner-spaces?
+ 'skip
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ slatex.&plain-space))
+ (loop (+ i 1) #t))
+ (else (loop (+ i 1) #f))))))
+
+(define slatex.blank-line?
+ (lambda (line)
+ (let loop ((i 0))
+ (let ((c (string-ref (vector-ref line slatex.=char) i)))
+ (cond ((char=? c #\space)
+ (if (eq? (string-ref (vector-ref line slatex.=notab) i)
+ slatex.&void-notab)
+ (loop (+ i 1))
+ #f))
+ ((char=? c #\newline)
+ (let loop2 ((j (- i 1)))
+ (if (<= j 0)
+ 'skip
+ (begin
+ (string-set!
+ (vector-ref line slatex.=space)
+ i
+ slatex.&void-space)
+ (loop2 (- j 1)))))
+ #t)
+ (else #f))))))
+
+(define slatex.flush-comment-line?
+ (lambda (line)
+ (and (char=? (string-ref (vector-ref line slatex.=char) 0) #\;)
+ (eq? (string-ref (vector-ref line slatex.=notab) 0)
+ slatex.&begin-comment)
+ (not (char=? (string-ref (vector-ref line slatex.=char) 1) #\;)))))
+
+(define slatex.do-all-lines
+ (lambda ()
+ (let loop ((line1 slatex.*line1*) (line2 slatex.*line2*))
+ (let* ((line2-paragraph? slatex.*latex-paragraph-mode?*)
+ (more? (slatex.get-line line1)))
+ (slatex.peephole-adjust line1 line2)
+ ((if line2-paragraph? slatex.display-tex-line slatex.display-scm-line)
+ line2)
+ (if (eq? line2-paragraph? slatex.*latex-paragraph-mode?*)
+ 'else
+ ((if slatex.*latex-paragraph-mode?*
+ slatex.display-end-sequence
+ slatex.display-begin-sequence)
+ slatex.*out*))
+ (if more? (loop line2 line1))))))
+
+(define scheme2tex
+ (lambda (inport outport)
+ (set! slatex.*in* inport)
+ (set! slatex.*out* outport)
+ (set! slatex.*latex-paragraph-mode?* #t)
+ (set! slatex.*in-qtd-tkn* #f)
+ (set! slatex.*in-bktd-qtd-exp* 0)
+ (set! slatex.*in-mac-tkn* #f)
+ (set! slatex.*in-bktd-mac-exp* 0)
+ (set! slatex.*case-stack* '())
+ (set! slatex.*bq-stack* '())
+ (let ((flush-line
+ (lambda (line)
+ (vector-set! line slatex.=rtedge 0)
+ (string-set! (vector-ref line slatex.=char) 0 #\newline)
+ (string-set!
+ (vector-ref line slatex.=space)
+ 0
+ slatex.&void-space)
+ (string-set! (vector-ref line slatex.=tab) 0 slatex.&void-tab)
+ (string-set!
+ (vector-ref line slatex.=notab)
+ 0
+ slatex.&void-notab))))
+ (flush-line slatex.*line1*)
+ (flush-line slatex.*line2*))
+ (slatex.do-all-lines)))
+
+(define slatex.display-tex-line
+ (lambda (line)
+ (cond (else
+ (let loop ((i (if (slatex.flush-comment-line? line) 1 0)))
+ (let ((c (string-ref (vector-ref line slatex.=char) i)))
+ (if (char=? c #\newline)
+ (if (eq? (string-ref (vector-ref line slatex.=tab) i)
+ slatex.&void-tab)
+ 'skip
+ (newline slatex.*out*))
+ (begin (display c slatex.*out*) (loop (+ i 1))))))))))
+
+(define slatex.display-scm-line
+ (lambda (line)
+ (let loop ((i 0))
+ (let ((c (string-ref (vector-ref line slatex.=char) i)))
+ (cond ((char=? c #\newline)
+ (let ((tab (string-ref (vector-ref line slatex.=tab) i)))
+ (cond ((eq? tab slatex.&tabbed-crg-ret)
+ (display "\\\\" slatex.*out*)
+ (newline slatex.*out*))
+ ((eq? tab slatex.&plain-crg-ret) (newline slatex.*out*))
+ ((eq? tab slatex.&void-tab)
+ (display #\% slatex.*out*)
+ (newline slatex.*out*)))))
+ ((eq? (string-ref (vector-ref line slatex.=notab) i)
+ slatex.&begin-comment)
+ (slatex.display-tab
+ (string-ref (vector-ref line slatex.=tab) i)
+ slatex.*out*)
+ (display c slatex.*out*)
+ (loop (+ i 1)))
+ ((eq? (string-ref (vector-ref line slatex.=notab) i)
+ slatex.&mid-comment)
+ (display c slatex.*out*)
+ (loop (+ i 1)))
+ ((eq? (string-ref (vector-ref line slatex.=notab) i)
+ slatex.&begin-string)
+ (slatex.display-tab
+ (string-ref (vector-ref line slatex.=tab) i)
+ slatex.*out*)
+ (display "\\dt{" slatex.*out*)
+ (if (char=? c #\space)
+ (slatex.display-space
+ (string-ref (vector-ref line slatex.=space) i)
+ slatex.*out*)
+ (slatex.display-tex-char c slatex.*out*))
+ (loop (+ i 1)))
+ ((eq? (string-ref (vector-ref line slatex.=notab) i)
+ slatex.&mid-string)
+ (if (char=? c #\space)
+ (slatex.display-space
+ (string-ref (vector-ref line slatex.=space) i)
+ slatex.*out*)
+ (slatex.display-tex-char c slatex.*out*))
+ (loop (+ i 1)))
+ ((eq? (string-ref (vector-ref line slatex.=notab) i)
+ slatex.&end-string)
+ (if (char=? c #\space)
+ (slatex.display-space
+ (string-ref (vector-ref line slatex.=space) i)
+ slatex.*out*)
+ (slatex.display-tex-char c slatex.*out*))
+ (display "}" slatex.*out*)
+ (loop (+ i 1)))
+ ((eq? (string-ref (vector-ref line slatex.=notab) i)
+ slatex.&begin-math)
+ (slatex.display-tab
+ (string-ref (vector-ref line slatex.=tab) i)
+ slatex.*out*)
+ (display c slatex.*out*)
+ (loop (+ i 1)))
+ ((memq (string-ref (vector-ref line slatex.=notab) i)
+ (list slatex.&mid-math slatex.&end-math))
+ (display c slatex.*out*)
+ (loop (+ i 1)))
+ ((char=? c #\space)
+ (slatex.display-tab
+ (string-ref (vector-ref line slatex.=tab) i)
+ slatex.*out*)
+ (slatex.display-space
+ (string-ref (vector-ref line slatex.=space) i)
+ slatex.*out*)
+ (loop (+ i 1)))
+ ((char=? c #\')
+ (slatex.display-tab
+ (string-ref (vector-ref line slatex.=tab) i)
+ slatex.*out*)
+ (display c slatex.*out*)
+ (if (or slatex.*in-qtd-tkn* (> slatex.*in-bktd-qtd-exp* 0))
+ 'skip
+ (set! slatex.*in-qtd-tkn* #t))
+ (loop (+ i 1)))
+ ((char=? c #\`)
+ (slatex.display-tab
+ (string-ref (vector-ref line slatex.=tab) i)
+ slatex.*out*)
+ (display c slatex.*out*)
+ (if (or (null? slatex.*bq-stack*)
+ (vector-ref (car slatex.*bq-stack*) slatex.=in-comma))
+ (set! slatex.*bq-stack*
+ (cons (let ((f (slatex.make-bq-frame)))
+ (vector-set! f slatex.=in-comma #f)
+ (vector-set! f slatex.=in-bq-tkn #t)
+ (vector-set! f slatex.=in-bktd-bq-exp 0)
+ f)
+ slatex.*bq-stack*)))
+ (loop (+ i 1)))
+ ((char=? c #\,)
+ (slatex.display-tab
+ (string-ref (vector-ref line slatex.=tab) i)
+ slatex.*out*)
+ (display c slatex.*out*)
+ (if (or (null? slatex.*bq-stack*)
+ (vector-ref (car slatex.*bq-stack*) slatex.=in-comma))
+ 'skip
+ (set! slatex.*bq-stack*
+ (cons (let ((f (slatex.make-bq-frame)))
+ (vector-set! f slatex.=in-comma #t)
+ (vector-set! f slatex.=in-bq-tkn #t)
+ (vector-set! f slatex.=in-bktd-bq-exp 0)
+ f)
+ slatex.*bq-stack*)))
+ (if (char=? (string-ref (vector-ref line slatex.=char) (+ i 1))
+ #\@)
+ (begin
+ (slatex.display-tex-char #\@ slatex.*out*)
+ (loop (+ 2 i)))
+ (loop (+ i 1))))
+ ((memv c '(#\( #\[))
+ (slatex.display-tab
+ (string-ref (vector-ref line slatex.=tab) i)
+ slatex.*out*)
+ (display c slatex.*out*)
+ (cond (slatex.*in-qtd-tkn*
+ (set! slatex.*in-qtd-tkn* #f)
+ (set! slatex.*in-bktd-qtd-exp* 1))
+ ((> slatex.*in-bktd-qtd-exp* 0)
+ (set! slatex.*in-bktd-qtd-exp*
+ (+ slatex.*in-bktd-qtd-exp* 1))))
+ (cond (slatex.*in-mac-tkn*
+ (set! slatex.*in-mac-tkn* #f)
+ (set! slatex.*in-bktd-mac-exp* 1))
+ ((> slatex.*in-bktd-mac-exp* 0)
+ (set! slatex.*in-bktd-mac-exp*
+ (+ slatex.*in-bktd-mac-exp* 1))))
+ (if (null? slatex.*bq-stack*)
+ 'skip
+ (let ((top (car slatex.*bq-stack*)))
+ (cond ((vector-ref top slatex.=in-bq-tkn)
+ (vector-set! top slatex.=in-bq-tkn #f)
+ (vector-set! top slatex.=in-bktd-bq-exp 1))
+ ((> (vector-ref top slatex.=in-bktd-bq-exp) 0)
+ (vector-set!
+ top
+ slatex.=in-bktd-bq-exp
+ (+ (vector-ref top slatex.=in-bktd-bq-exp) 1))))))
+ (if (null? slatex.*case-stack*)
+ 'skip
+ (let ((top (car slatex.*case-stack*)))
+ (cond ((vector-ref top =in-ctag-tkn)
+ (vector-set! top =in-ctag-tkn #f)
+ (vector-set! top slatex.=in-bktd-ctag-exp 1))
+ ((> (vector-ref top slatex.=in-bktd-ctag-exp) 0)
+ (vector-set!
+ top
+ slatex.=in-bktd-ctag-exp
+ (+ (vector-ref top slatex.=in-bktd-ctag-exp) 1)))
+ ((> (vector-ref top slatex.=in-case-exp) 0)
+ (vector-set!
+ top
+ slatex.=in-case-exp
+ (+ (vector-ref top slatex.=in-case-exp) 1))
+ (if (= (vector-ref top slatex.=in-case-exp) 2)
+ (set! slatex.*in-qtd-tkn* #t))))))
+ (loop (+ i 1)))
+ ((memv c '(#\) #\]))
+ (slatex.display-tab
+ (string-ref (vector-ref line slatex.=tab) i)
+ slatex.*out*)
+ (display c slatex.*out*)
+ (if (> slatex.*in-bktd-qtd-exp* 0)
+ (set! slatex.*in-bktd-qtd-exp*
+ (- slatex.*in-bktd-qtd-exp* 1)))
+ (if (> slatex.*in-bktd-mac-exp* 0)
+ (set! slatex.*in-bktd-mac-exp*
+ (- slatex.*in-bktd-mac-exp* 1)))
+ (if (null? slatex.*bq-stack*)
+ 'skip
+ (let ((top (car slatex.*bq-stack*)))
+ (if (> (vector-ref top slatex.=in-bktd-bq-exp) 0)
+ (begin
+ (vector-set!
+ top
+ slatex.=in-bktd-bq-exp
+ (- (vector-ref top slatex.=in-bktd-bq-exp) 1))
+ (if (= (vector-ref top slatex.=in-bktd-bq-exp) 0)
+ (set! slatex.*bq-stack* (cdr slatex.*bq-stack*)))))))
+ (let loop ()
+ (if (null? slatex.*case-stack*)
+ 'skip
+ (let ((top (car slatex.*case-stack*)))
+ (cond ((> (vector-ref top slatex.=in-bktd-ctag-exp) 0)
+ (vector-set!
+ top
+ slatex.=in-bktd-ctag-exp
+ (- (vector-ref top slatex.=in-bktd-ctag-exp) 1))
+ (if (= (vector-ref top slatex.=in-bktd-ctag-exp) 0)
+ (vector-set! top slatex.=in-case-exp 1)))
+ ((> (vector-ref top slatex.=in-case-exp) 0)
+ (vector-set!
+ top
+ slatex.=in-case-exp
+ (- (vector-ref top slatex.=in-case-exp) 1))
+ (if (= (vector-ref top slatex.=in-case-exp) 0)
+ (begin
+ (set! slatex.*case-stack*
+ (cdr slatex.*case-stack*))
+ (loop))))))))
+ (loop (+ i 1)))
+ (else
+ (slatex.display-tab
+ (string-ref (vector-ref line slatex.=tab) i)
+ slatex.*out*)
+ (loop (slatex.do-token line i))))))))
+
+(define slatex.do-token
+ (let ((token-delims
+ (list #\(
+ #\)
+ #\[
+ #\]
+ #\space
+ slatex.*return*
+ #\newline
+ #\,
+ #\@
+ #\;)))
+ (lambda (line i)
+ (let loop ((buf '()) (i i))
+ (let ((c (string-ref (vector-ref line slatex.=char) i)))
+ (cond ((char=? c #\\)
+ (loop (cons (string-ref
+ (vector-ref line slatex.=char)
+ (+ i 1))
+ (cons c buf))
+ (+ i 2)))
+ ((or (memv c token-delims) (memv c slatex.*math-triggerers*))
+ (slatex.output-token (list->string (slatex.reverse! buf)))
+ i)
+ ((char? c)
+ (loop (cons (string-ref (vector-ref line slatex.=char) i) buf)
+ (+ i 1)))
+ (else (slatex.error 'slatex.do-token 1))))))))
+
+(define slatex.output-token
+ (lambda (token)
+ (if (null? slatex.*case-stack*)
+ 'skip
+ (let ((top (car slatex.*case-stack*)))
+ (if (vector-ref top =in-ctag-tkn)
+ (begin
+ (vector-set! top =in-ctag-tkn #f)
+ (vector-set! top slatex.=in-case-exp 1)))))
+ (if (slatex.assoc-token token slatex.special-symbols)
+ (display (cdr (slatex.assoc-token token slatex.special-symbols))
+ slatex.*out*)
+ (slatex.display-token
+ token
+ (cond (slatex.*in-qtd-tkn*
+ (set! slatex.*in-qtd-tkn* #f)
+ (cond ((equal? token "else") 'syntax)
+ ((slatex.data-token? token) 'data)
+ (else 'constant)))
+ ((slatex.data-token? token) 'data)
+ ((> slatex.*in-bktd-qtd-exp* 0) 'constant)
+ ((and (not (null? slatex.*bq-stack*))
+ (not (vector-ref
+ (car slatex.*bq-stack*)
+ slatex.=in-comma)))
+ 'constant)
+ (slatex.*in-mac-tkn*
+ (set! slatex.*in-mac-tkn* #f)
+ (slatex.set-keyword token)
+ 'syntax)
+ ((> slatex.*in-bktd-mac-exp* 0)
+ (slatex.set-keyword token)
+ 'syntax)
+ ((slatex.member-token token slatex.constant-tokens) 'constant)
+ ((slatex.member-token token slatex.variable-tokens) 'variable)
+ ((slatex.member-token token slatex.keyword-tokens)
+ (cond ((slatex.token=? token "quote")
+ (set! slatex.*in-qtd-tkn* #t))
+ ((slatex.member-token token slatex.macro-definers)
+ (set! slatex.*in-mac-tkn* #t))
+ ((slatex.member-token token slatex.case-and-ilk)
+ (set! slatex.*case-stack*
+ (cons (let ((f (slatex.make-case-frame)))
+ (vector-set! f =in-ctag-tkn #t)
+ (vector-set! f slatex.=in-bktd-ctag-exp 0)
+ (vector-set! f slatex.=in-case-exp 0)
+ f)
+ slatex.*case-stack*))))
+ 'syntax)
+ (else 'variable))
+ slatex.*out*))
+ (if (and (not (null? slatex.*bq-stack*))
+ (vector-ref (car slatex.*bq-stack*) slatex.=in-bq-tkn))
+ (set! slatex.*bq-stack* (cdr slatex.*bq-stack*)))))
+
+(define slatex.data-token?
+ (lambda (token)
+ (or (char=? (string-ref token 0) #\#) (string->number token))))
+
+(define slatex.*texinputs* "")
+
+(define slatex.*texinputs-list* '())
+
+(define slatex.*path-separator*
+ (cond ((eq? *op-sys* 'unix) #\:)
+ ((eq? *op-sys* 'dos) #\;)
+ (else (slatex.error 'slatex.*path-separator* 'cant-determine))))
+
+(define slatex.*directory-mark*
+ (cond ((eq? *op-sys* 'unix) "/")
+ ((eq? *op-sys* 'dos) "\\")
+ (else (slatex.error 'slatex.*directory-mark* 'cant-determine))))
+
+(define slatex.*file-hider*
+ (cond ((eq? *op-sys* 'unix) "") ((eq? *op-sys* 'dos) "x") (else ".")))
+
+(define slatex.path->list
+ (lambda (p)
+ (let loop ((p (string->list p)) (r (list "")))
+ (let ((separator-pos (slatex.position-char slatex.*path-separator* p)))
+ (if separator-pos
+ (loop (list-tail p (+ separator-pos 1))
+ (cons (list->string (slatex.sublist p 0 separator-pos)) r))
+ (slatex.reverse! (cons (list->string p) r)))))))
+
+(define slatex.find-some-file
+ (lambda (path . files)
+ (let loop ((path path))
+ (if (null? path)
+ #f
+ (let ((dir (car path)))
+ (let loop2 ((files (if (or (string=? dir "") (string=? dir "."))
+ files
+ (map (lambda (file)
+ (string-append
+ dir
+ slatex.*directory-mark*
+ file))
+ files))))
+ (if (null? files)
+ (loop (cdr path))
+ (let ((file (car files)))
+ (if (slatex.file-exists? file)
+ file
+ (loop2 (cdr files)))))))))))
+
+(define slatex.file-extension
+ (lambda (filename)
+ (let ((i (slatex.string-position-right #\. filename)))
+ (if i (substring filename i (string-length filename)) #f))))
+
+(define slatex.basename
+ (lambda (filename ext)
+ (let* ((filename-len (string-length filename))
+ (ext-len (string-length ext))
+ (len-diff (- filename-len ext-len)))
+ (cond ((> ext-len filename-len) filename)
+ ((equal? ext (substring filename len-diff filename-len))
+ (substring filename 0 len-diff))
+ (else filename)))))
+
+(define slatex.full-texfile-name
+ (lambda (filename)
+ (let ((extn (slatex.file-extension filename)))
+ (if (and extn (or (string=? extn ".sty") (string=? extn ".tex")))
+ (slatex.find-some-file slatex.*texinputs-list* filename)
+ (slatex.find-some-file
+ slatex.*texinputs-list*
+ (string-append filename ".tex")
+ filename)))))
+
+(define slatex.full-scmfile-name
+ (lambda (filename)
+ (apply slatex.find-some-file
+ slatex.*texinputs-list*
+ filename
+ (map (lambda (extn) (string-append filename extn))
+ '(".scm" ".ss" ".s")))))
+
+(define slatex.new-aux-file
+ (lambda e
+ (apply (if slatex.*slatex-in-protected-region?*
+ slatex.new-secondary-aux-file
+ slatex.new-primary-aux-file)
+ e)))
+
+(define slatex.subjobname 'fwd)
+
+(define primary-aux-file-count -1)
+
+(define slatex.new-primary-aux-file
+ (lambda e
+ (set! primary-aux-file-count (+ primary-aux-file-count 1))
+ (apply string-append
+ slatex.*file-hider*
+ "slatexdir/z"
+ (number->string primary-aux-file-count)
+; slatex.subjobname
+ e)))
+
+(define slatex.new-secondary-aux-file
+ (let ((n -1))
+ (lambda e
+ (set! n (+ n 1))
+ (apply string-append
+ slatex.*file-hider*
+ "slatexdir/zz"
+ (number->string n)
+; slatex.subjobname
+ e))))
+
+(define slatex.eat-till-newline
+ (lambda (in)
+ (let loop ()
+ (let ((c (read-char in)))
+ (cond ((eof-object? c) 'done)
+ ((char=? c #\newline) 'done)
+ (else (loop)))))))
+
+(define slatex.read-ctrl-seq
+ (lambda (in)
+ (let ((c (read-char in)))
+ (if (eof-object? c) (slatex.error 'read-ctrl-exp 1))
+ (if (char-alphabetic? c)
+ (list->string
+ (slatex.reverse!
+ (let loop ((s (list c)))
+ (let ((c (peek-char in)))
+ (cond ((eof-object? c) s)
+ ((char-alphabetic? c) (read-char in) (loop (cons c s)))
+ ((char=? c #\%) (slatex.eat-till-newline in) (loop s))
+ (else s))))))
+ (string c)))))
+
+(define slatex.eat-tabspace
+ (lambda (in)
+ (let loop ()
+ (let ((c (peek-char in)))
+ (cond ((eof-object? c) 'done)
+ ((or (char=? c #\space) (char=? c slatex.*tab*))
+ (read-char in)
+ (loop))
+ (else 'done))))))
+
+(define slatex.eat-whitespace
+ (lambda (in)
+ (let loop ()
+ (let ((c (peek-char in)))
+ (cond ((eof-object? c) 'done)
+ ((char-whitespace? c) (read-char in) (loop))
+ (else 'done))))))
+
+(define slatex.eat-latex-whitespace
+ (lambda (in)
+ (let loop ()
+ (let ((c (peek-char in)))
+ (cond ((eof-object? c) 'done)
+ ((char-whitespace? c) (read-char in) (loop))
+ ((char=? c #\%) (slatex.eat-till-newline in))
+ (else 'done))))))
+
+(define slatex.chop-off-whitespace
+ (lambda (l)
+ (slatex.ormapcdr (lambda (d) (if (char-whitespace? (car d)) #f d)) l)))
+
+(define slatex.read-grouped-latexexp
+ (lambda (in)
+ (slatex.eat-latex-whitespace in)
+ (let ((c (read-char in)))
+ (if (eof-object? c) (slatex.error 'slatex.read-grouped-latexexp 1))
+ (if (char=? c #\{) 'ok (slatex.error 'slatex.read-grouped-latexexp 2))
+ (slatex.eat-latex-whitespace in)
+ (list->string
+ (slatex.reverse!
+ (slatex.chop-off-whitespace
+ (let loop ((s '()) (nesting 0) (escape? #f))
+ (let ((c (read-char in)))
+ (if (eof-object? c)
+ (slatex.error 'slatex.read-grouped-latexexp 3))
+ (cond (escape? (loop (cons c s) nesting #f))
+ ((char=? c #\\) (loop (cons c s) nesting #t))
+ ((char=? c #\%)
+ (slatex.eat-till-newline in)
+ (loop s nesting #f))
+ ((char=? c #\{) (loop (cons c s) (+ nesting 1) #f))
+ ((char=? c #\})
+ (if (= nesting 0) s (loop (cons c s) (- nesting 1) #f)))
+ (else (loop (cons c s) nesting #f)))))))))))
+
+(define slatex.read-filename
+ (let ((filename-delims
+ (list #\{
+ #\}
+ #\[
+ #\]
+ #\(
+ #\)
+ #\#
+ #\%
+ #\\
+ #\,
+ #\space
+ slatex.*return*
+ #\newline
+ slatex.*tab*)))
+ (lambda (in)
+ (slatex.eat-latex-whitespace in)
+ (let ((c (peek-char in)))
+ (if (eof-object? c) (slatex.error 'slatex.read-filename 1))
+ (if (char=? c #\{)
+ (slatex.read-grouped-latexexp in)
+ (list->string
+ (slatex.reverse!
+ (let loop ((s '()) (escape? #f))
+ (let ((c (peek-char in)))
+ (cond ((eof-object? c)
+ (if escape? (slatex.error 'slatex.read-filename 2) s))
+ (escape? (read-char in) (loop (cons c s) #f))
+ ((char=? c #\\) (read-char in) (loop (cons c s) #t))
+ ((memv c filename-delims) s)
+ (else (read-char in) (loop (cons c s) #f))))))))))))
+
+(define slatex.read-schemeid
+ (let ((schemeid-delims
+ (list #\{
+ #\}
+ #\[
+ #\]
+ #\(
+ #\)
+ #\space
+ slatex.*return*
+ #\newline
+ slatex.*tab*)))
+ (lambda (in)
+ (slatex.eat-whitespace in)
+ (list->string
+ (slatex.reverse!
+ (let loop ((s '()) (escape? #f))
+ (let ((c (peek-char in)))
+ (cond ((eof-object? c) s)
+ (escape? (read-char in) (loop (cons c s) #f))
+ ((char=? c #\\) (read-char in) (loop (cons c s) #t))
+ ((memv c schemeid-delims) s)
+ (else (read-char in) (loop (cons c s) #f))))))))))
+
+(define slatex.read-delimed-commaed-filenames
+ (lambda (in lft-delim rt-delim)
+ (slatex.eat-latex-whitespace in)
+ (let ((c (read-char in)))
+ (if (eof-object? c)
+ (slatex.error 'slatex.read-delimed-commaed-filenames 1))
+ (if (char=? c lft-delim)
+ 'ok
+ (slatex.error 'slatex.read-delimed-commaed-filenames 2))
+ (let loop ((s '()))
+ (slatex.eat-latex-whitespace in)
+ (let ((c (peek-char in)))
+ (if (eof-object? c)
+ (slatex.error 'slatex.read-delimed-commaed-filenames 3))
+ (if (char=? c rt-delim)
+ (begin (read-char in) (slatex.reverse! s))
+ (let ((s (cons (slatex.read-filename in) s)))
+ (slatex.eat-latex-whitespace in)
+ (let ((c (peek-char in)))
+ (if (eof-object? c)
+ (slatex.error 'slatex.read-delimed-commaed-filenames 4))
+ (cond ((char=? c #\,) (read-char in))
+ ((char=? c rt-delim) 'void)
+ (else
+ (slatex.error
+ 'slatex.read-delimed-commaed-filenames
+ 5)))
+ (loop s)))))))))
+
+(define slatex.read-grouped-commaed-filenames
+ (lambda (in) (slatex.read-delimed-commaed-filenames in #\{ #\})))
+
+(define slatex.read-bktd-commaed-filenames
+ (lambda (in) (slatex.read-delimed-commaed-filenames in #\[ #\])))
+
+(define slatex.read-grouped-schemeids
+ (lambda (in)
+ (slatex.eat-latex-whitespace in)
+ (let ((c (read-char in)))
+ (if (eof-object? c) (slatex.error 'slatex.read-grouped-schemeids 1))
+ (if (char=? c #\{) 'ok (slatex.error 'slatex.read-grouped-schemeids 2))
+ (let loop ((s '()))
+ (slatex.eat-whitespace in)
+ (let ((c (peek-char in)))
+ (if (eof-object? c) (slatex.error 'slatex.read-grouped-schemeids 3))
+ (if (char=? c #\})
+ (begin (read-char in) (slatex.reverse! s))
+ (loop (cons (slatex.read-schemeid in) s))))))))
+
+(define slatex.disable-slatex-temply
+ (lambda (in)
+ (set! slatex.*slatex-enabled?* #f)
+ (set! slatex.*slatex-reenabler* (slatex.read-grouped-latexexp in))))
+
+(define slatex.enable-slatex-again
+ (lambda ()
+ (set! slatex.*slatex-enabled?* #t)
+ (set! slatex.*slatex-reenabler* "UNDEFINED")))
+
+(define slatex.ignore2 (lambda (i ii) 'void))
+
+(define slatex.add-to-slatex-db
+ (lambda (in categ)
+ (if (memq categ '(keyword constant variable))
+ (slatex.add-to-slatex-db-basic in categ)
+ (slatex.add-to-slatex-db-special in categ))))
+
+(define slatex.add-to-slatex-db-basic
+ (lambda (in categ)
+ (let ((setter (cond ((eq? categ 'keyword) slatex.set-keyword)
+ ((eq? categ 'constant) slatex.set-constant)
+ ((eq? categ 'variable) slatex.set-variable)
+ (else
+ (slatex.error 'slatex.add-to-slatex-db-basic 1))))
+ (ids (slatex.read-grouped-schemeids in)))
+ (for-each setter ids))))
+
+(define slatex.add-to-slatex-db-special
+ (lambda (in what)
+ (let ((ids (slatex.read-grouped-schemeids in)))
+ (cond ((eq? what 'unsetspecialsymbol)
+ (for-each slatex.unset-special-symbol ids))
+ ((eq? what 'setspecialsymbol)
+ (if (= (length ids) 1)
+ 'ok
+ (slatex.error
+ 'slatex.add-to-slatex-db-special
+ 'setspecialsymbol-takes-one-arg-only))
+ (let ((transl (slatex.read-grouped-latexexp in)))
+ (slatex.set-special-symbol (car ids) transl)))
+ (else (slatex.error 'slatex.add-to-slatex-db-special 2))))))
+
+(define slatex.process-slatex-alias
+ (lambda (in what which)
+ (let ((triggerer (slatex.read-grouped-latexexp in)))
+ (cond ((eq? which 'intext)
+ (set! slatex.*intext-triggerers*
+ (what triggerer slatex.*intext-triggerers*)))
+ ((eq? which 'resultintext)
+ (set! slatex.*resultintext-triggerers*
+ (what triggerer slatex.*resultintext-triggerers*)))
+ ((eq? which 'display)
+ (set! slatex.*display-triggerers*
+ (what triggerer slatex.*display-triggerers*)))
+ ((eq? which 'box)
+ (set! slatex.*box-triggerers*
+ (what triggerer slatex.*box-triggerers*)))
+ ((eq? which 'input)
+ (set! slatex.*input-triggerers*
+ (what triggerer slatex.*input-triggerers*)))
+ ((eq? which 'region)
+ (set! slatex.*region-triggerers*
+ (what triggerer slatex.*region-triggerers*)))
+ ((eq? which 'mathescape)
+ (if (= (string-length triggerer) 1)
+ 'ok
+ (slatex.error
+ 'slatex.process-slatex-alias
+ 'math-escape-should-be-character))
+ (set! slatex.*math-triggerers*
+ (what (string-ref triggerer 0) slatex.*math-triggerers*)))
+ (else (slatex.error 'slatex.process-slatex-alias 2))))))
+
+(define slatex.decide-latex-or-tex
+ (lambda (latex?)
+ (set! slatex.*latex?* latex?)
+ (let ((pltexchk.jnk "pltexchk.jnk"))
+ (if (slatex.file-exists? pltexchk.jnk) (slatex.delete-file pltexchk.jnk))
+ (if (not slatex.*latex?*)
+ (call-with-output-file/truncate
+ pltexchk.jnk
+ (lambda (outp) (display 'junk outp) (newline outp)))))))
+
+(define slatex.process-include-only
+ (lambda (in)
+ (set! slatex.*include-onlys* '())
+ (for-each
+ (lambda (filename)
+ (let ((filename (slatex.full-texfile-name filename)))
+ (if filename
+ (set! slatex.*include-onlys*
+ (slatex.adjoin-string filename slatex.*include-onlys*)))))
+ (slatex.read-grouped-commaed-filenames in))))
+
+(define slatex.process-documentstyle
+ (lambda (in)
+ (slatex.eat-latex-whitespace in)
+ (if (char=? (peek-char in) #\[)
+ (for-each
+ (lambda (filename)
+ (let ((%:g0% slatex.*slatex-in-protected-region?*))
+ (set! slatex.*slatex-in-protected-region?* #f)
+ (let ((%temp% (begin
+ (slatex.process-tex-file
+ (string-append filename ".sty")))))
+ (set! slatex.*slatex-in-protected-region?* %:g0%)
+ %temp%)))
+ (slatex.read-bktd-commaed-filenames in)))))
+
+(define slatex.process-case-info
+ (lambda (in)
+ (let ((bool (slatex.read-grouped-latexexp in)))
+ (set! slatex.*slatex-case-sensitive?*
+ (cond ((string-ci=? bool "true") #t)
+ ((string-ci=? bool "false") #f)
+ (else
+ (slatex.error
+ 'slatex.process-case-info
+ 'bad-schemecasesensitive-arg)))))))
+
+(define slatex.seen-first-command? #f)
+
+(define slatex.process-main-tex-file
+ (lambda (filename)
+; (display "SLaTeX v. 2.2")
+; (newline)
+ (set! slatex.*texinputs-list* (slatex.path->list slatex.*texinputs*))
+ (let ((file-hide-file "xZfilhid.tex"))
+ (if (slatex.file-exists? file-hide-file)
+ (slatex.delete-file file-hide-file))
+ (if (eq? *op-sys* 'dos)
+ (call-with-output-file/truncate
+ file-hide-file
+ (lambda (out) (display "\\def\\filehider{x}" out) (newline out)))))
+; (display "typesetting code")
+ (set! slatex.subjobname (slatex.basename filename ".tex"))
+ (set! slatex.seen-first-command? #f)
+ (slatex.process-tex-file filename)
+; (display 'done)
+; (newline)
+))
+
+(define slatex.dump-intext
+ (lambda (in out)
+ (let* ((display (if out display slatex.ignore2))
+ (delim-char (begin (slatex.eat-whitespace in) (read-char in)))
+ (delim-char (cond ((char=? delim-char #\{) #\}) (else delim-char))))
+ (if (eof-object? delim-char) (slatex.error 'slatex.dump-intext 1))
+ (let loop ()
+ (let ((c (read-char in)))
+ (if (eof-object? c) (slatex.error 'slatex.dump-intext 2))
+ (if (char=? c delim-char) 'done (begin (display c out) (loop))))))))
+
+(define slatex.dump-display
+ (lambda (in out ender)
+ (slatex.eat-tabspace in)
+ (let ((display (if out display slatex.ignore2))
+ (ender-lh (string-length ender))
+ (c (peek-char in)))
+ (if (eof-object? c) (slatex.error 'slatex.dump-display 1))
+ (if (char=? c #\newline) (read-char in))
+ (let loop ((buf ""))
+ (let ((c (read-char in)))
+ (if (eof-object? c) (slatex.error 'slatex.dump-display 2))
+ (let ((buf (string-append buf (string c))))
+ (if (slatex.string-prefix? buf ender)
+ (if (= (string-length buf) ender-lh) 'done (loop buf))
+ (begin (display buf out) (loop "")))))))))
+
+(define slatex.debug? #f)
+
+(define slatex.process-tex-file
+ (lambda (raw-filename)
+ (if slatex.debug?
+ (begin (display "begin ") (display raw-filename) (newline)))
+ (let ((filename (slatex.full-texfile-name raw-filename)))
+ (if (not filename)
+ (begin
+ (display "[")
+ (display raw-filename)
+ (display "]")
+ (slatex.force-output))
+ (call-with-input-file
+ filename
+ (lambda (in)
+ (let ((done? #f))
+ (let loop ()
+ (if done?
+ 'exit-loop
+ (begin
+ (let ((c (read-char in)))
+ (cond ((eof-object? c) (set! done? #t))
+ ((char=? c #\%) (slatex.eat-till-newline in))
+ ((char=? c #\\)
+ (let ((cs (slatex.read-ctrl-seq in)))
+ (if slatex.seen-first-command?
+ 'skip
+ (begin
+ (set! slatex.seen-first-command? #t)
+ (slatex.decide-latex-or-tex
+ (string=? cs "documentstyle"))))
+ (cond ((not slatex.*slatex-enabled?*)
+ (if (string=?
+ cs
+ slatex.*slatex-reenabler*)
+ (slatex.enable-slatex-again)))
+ ((string=? cs "slatexignorecurrentfile")
+ (set! done? #t))
+ ((string=? cs "slatexseparateincludes")
+ (if slatex.*latex?*
+ (set! slatex.*slatex-separate-includes?*
+ #t)))
+ ((string=? cs "slatexdisable")
+ (slatex.disable-slatex-temply in))
+ ((string=? cs "begin")
+ (let ((cs (slatex.read-grouped-latexexp
+ in)))
+ (cond ((member cs
+ slatex.*display-triggerers*)
+ (slatex.trigger-scheme2tex
+ 'envdisplay
+ in
+ cs))
+ ((member cs
+ slatex.*box-triggerers*)
+ (slatex.trigger-scheme2tex
+ 'envbox
+ in
+ cs))
+ ((member cs
+ slatex.*region-triggerers*)
+ (slatex.trigger-region
+ 'envregion
+ in
+ cs)))))
+ ((member cs slatex.*intext-triggerers*)
+ (slatex.trigger-scheme2tex
+ 'intext
+ in
+ #f))
+ ((member cs
+ slatex.*resultintext-triggerers*)
+ (slatex.trigger-scheme2tex
+ 'resultintext
+ in
+ #f))
+ ((member cs slatex.*display-triggerers*)
+ (slatex.trigger-scheme2tex
+ 'plaindisplay
+ in
+ cs))
+ ((member cs slatex.*box-triggerers*)
+ (slatex.trigger-scheme2tex
+ 'plainbox
+ in
+ cs))
+ ((member cs slatex.*region-triggerers*)
+ (slatex.trigger-region
+ 'plainregion
+ in
+ cs))
+ ((member cs slatex.*input-triggerers*)
+ (slatex.process-scheme-file
+ (slatex.read-filename in)))
+ ((string=? cs "input")
+ (let ((%:g1% slatex.*slatex-in-protected-region?*))
+ (set! slatex.*slatex-in-protected-region?*
+ #f)
+ (let ((%temp% (begin
+ (slatex.process-tex-file
+ (slatex.read-filename
+ in)))))
+ (set! slatex.*slatex-in-protected-region?*
+ %:g1%)
+ %temp%)))
+ ((string=? cs "include")
+ (if slatex.*latex?*
+ (let ((f (slatex.full-texfile-name
+ (slatex.read-filename in))))
+ (if (and f
+ (or (eq? slatex.*include-onlys*
+ 'all)
+ (member f
+ slatex.*include-onlys*)))
+ (let ((%:g2% slatex.*slatex-in-protected-region?*)
+ (%:g3% slatex.subjobname)
+ (%:g4% primary-aux-file-count))
+ (set! slatex.*slatex-in-protected-region?*
+ #f)
+ (set! slatex.subjobname
+ slatex.subjobname)
+ (set! primary-aux-file-count
+ primary-aux-file-count)
+ (let ((%temp% (begin
+ (if slatex.*slatex-separate-includes?*
+ (begin
+ (set! slatex.subjobname
+ (slatex.basename
+ f
+ ".tex"))
+ (set! primary-aux-file-count
+ -1)))
+ (slatex.process-tex-file
+ f))))
+ (set! slatex.*slatex-in-protected-region?*
+ %:g2%)
+ (set! slatex.subjobname %:g3%)
+ (set! primary-aux-file-count
+ %:g4%)
+ %temp%))))))
+ ((string=? cs "includeonly")
+ (if slatex.*latex?*
+ (slatex.process-include-only in)))
+ ((string=? cs "documentstyle")
+ (if slatex.*latex?*
+ (slatex.process-documentstyle in)))
+ ((string=? cs "schemecasesensitive")
+ (slatex.process-case-info in))
+ ((string=? cs "defschemetoken")
+ (slatex.process-slatex-alias
+ in
+ slatex.adjoin-string
+ 'intext))
+ ((string=? cs "undefschemetoken")
+ (slatex.process-slatex-alias
+ in
+ slatex.remove-string!
+ 'intext))
+ ((string=? cs "defschemeresulttoken")
+ (slatex.process-slatex-alias
+ in
+ slatex.adjoin-string
+ 'resultintext))
+ ((string=? cs "undefschemeresulttoken")
+ (slatex.process-slatex-alias
+ in
+ slatex.remove-string!
+ 'resultintext))
+ ((string=? cs "defschemedisplaytoken")
+ (slatex.process-slatex-alias
+ in
+ slatex.adjoin-string
+ 'display))
+ ((string=? cs "undefschemedisplaytoken")
+ (slatex.process-slatex-alias
+ in
+ slatex.remove-string!
+ 'display))
+ ((string=? cs "defschemeboxtoken")
+ (slatex.process-slatex-alias
+ in
+ slatex.adjoin-string
+ 'box))
+ ((string=? cs "undefschemeboxtoken")
+ (slatex.process-slatex-alias
+ in
+ slatex.remove-string!
+ 'box))
+ ((string=? cs "defschemeinputtoken")
+ (slatex.process-slatex-alias
+ in
+ slatex.adjoin-string
+ 'input))
+ ((string=? cs "undefschemeinputtoken")
+ (slatex.process-slatex-alias
+ in
+ slatex.remove-string!
+ 'input))
+ ((string=? cs "defschemeregiontoken")
+ (slatex.process-slatex-alias
+ in
+ slatex.adjoin-string
+ 'region))
+ ((string=? cs "undefschemeregiontoken")
+ (slatex.process-slatex-alias
+ in
+ slatex.remove-string!
+ 'region))
+ ((string=? cs "defschememathescape")
+ (slatex.process-slatex-alias
+ in
+ slatex.adjoin-char
+ 'mathescape))
+ ((string=? cs "undefschememathescape")
+ (slatex.process-slatex-alias
+ in
+ slatex.remove-char!
+ 'mathescape))
+ ((string=? cs "setkeyword")
+ (slatex.add-to-slatex-db in 'keyword))
+ ((string=? cs "setconstant")
+ (slatex.add-to-slatex-db in 'constant))
+ ((string=? cs "setvariable")
+ (slatex.add-to-slatex-db in 'variable))
+ ((string=? cs "setspecialsymbol")
+ (slatex.add-to-slatex-db
+ in
+ 'setspecialsymbol))
+ ((string=? cs "unsetspecialsymbol")
+ (slatex.add-to-slatex-db
+ in
+ 'unsetspecialsymbol)))))))
+ (loop)))))))))
+ (if slatex.debug?
+ (begin (display "end ") (display raw-filename) (newline)))))
+
+(define slatex.process-scheme-file
+ (lambda (raw-filename)
+ (let ((filename (slatex.full-scmfile-name raw-filename)))
+ (if (not filename)
+ (begin
+ (display "process-scheme-file: ")
+ (display raw-filename)
+ (display " doesn't exist")
+ (newline))
+ (let ((aux.tex (slatex.new-aux-file ".tex")))
+ ;(display ".")
+ (slatex.force-output)
+ (if (slatex.file-exists? aux.tex) (slatex.delete-file aux.tex))
+ (call-with-input-file
+ filename
+ (lambda (in)
+ (call-with-output-file/truncate
+ aux.tex
+ (lambda (out)
+ (let ((%:g5% slatex.*intext?*)
+ (%:g6% slatex.*code-env-spec*))
+ (set! slatex.*intext?* #f)
+ (set! slatex.*code-env-spec* "ZZZZschemedisplay")
+ (let ((%temp% (begin (scheme2tex in out))))
+ (set! slatex.*intext?* %:g5%)
+ (set! slatex.*code-env-spec* %:g6%)
+ %temp%))))))
+ (if slatex.*slatex-in-protected-region?*
+ (set! slatex.*protected-files*
+ (cons aux.tex slatex.*protected-files*)))
+ (slatex.process-tex-file filename))))))
+
+(define slatex.trigger-scheme2tex
+ (lambda (typ in env)
+ (let* ((aux (slatex.new-aux-file))
+ (aux.scm (string-append aux ".scm"))
+ (aux.tex (string-append aux ".tex")))
+ (if (slatex.file-exists? aux.scm) (slatex.delete-file aux.scm))
+ (if (slatex.file-exists? aux.tex) (slatex.delete-file aux.tex))
+; (display ".")
+ (slatex.force-output)
+ (call-with-output-file/truncate
+ aux.scm
+ (lambda (out)
+ (cond ((memq typ '(intext resultintext)) (slatex.dump-intext in out))
+ ((memq typ '(envdisplay envbox))
+ (slatex.dump-display in out (string-append "\\end{" env "}")))
+ ((memq typ '(plaindisplay plainbox))
+ (slatex.dump-display in out (string-append "\\end" env)))
+ (else (slatex.error 'slatex.trigger-scheme2tex 1)))))
+ (call-with-input-file
+ aux.scm
+ (lambda (in)
+ (call-with-output-file/truncate
+ aux.tex
+ (lambda (out)
+ (let ((%:g7% slatex.*intext?*) (%:g8% slatex.*code-env-spec*))
+ (set! slatex.*intext?* (memq typ '(intext resultintext)))
+ (set! slatex.*code-env-spec*
+ (cond ((eq? typ 'intext) "ZZZZschemecodeintext")
+ ((eq? typ 'resultintext) "ZZZZschemeresultintext")
+ ((memq typ '(envdisplay plaindisplay))
+ "ZZZZschemedisplay")
+ ((memq typ '(envbox plainbox)) "ZZZZschemebox")
+ (else (slatex.error 'slatex.trigger-scheme2tex 2))))
+ (let ((%temp% (begin (scheme2tex in out))))
+ (set! slatex.*intext?* %:g7%)
+ (set! slatex.*code-env-spec* %:g8%)
+ %temp%))))))
+ (if slatex.*slatex-in-protected-region?*
+ (set! slatex.*protected-files*
+ (cons aux.tex slatex.*protected-files*)))
+ (if (memq typ '(envdisplay plaindisplay envbox plainbox))
+ (slatex.process-tex-file aux.tex))
+ (slatex.delete-file aux.scm))))
+
+(define slatex.trigger-region
+ (lambda (typ in env)
+ (let ((aux.tex (slatex.new-primary-aux-file ".tex"))
+ (aux2.tex (slatex.new-secondary-aux-file ".tex")))
+ (if (slatex.file-exists? aux2.tex) (slatex.delete-file aux2.tex))
+ (if (slatex.file-exists? aux.tex) (slatex.delete-file aux.tex))
+; (display ".")
+ (slatex.force-output)
+ (let ((%:g9% slatex.*slatex-in-protected-region?*)
+ (%:g10% slatex.*protected-files*))
+ (set! slatex.*slatex-in-protected-region?* #t)
+ (set! slatex.*protected-files* '())
+ (let ((%temp% (begin
+ (call-with-output-file/truncate
+ aux2.tex
+ (lambda (out)
+ (cond ((eq? typ 'envregion)
+ (slatex.dump-display
+ in
+ out
+ (string-append "\\end{" env "}")))
+ ((eq? typ 'plainregion)
+ (slatex.dump-display
+ in
+ out
+ (string-append "\\end" env)))
+ (else
+ (slatex.error 'slatex.trigger-region 1)))))
+ (slatex.process-tex-file aux2.tex)
+ (set! slatex.*protected-files*
+ (slatex.reverse! slatex.*protected-files*))
+ (call-with-input-file
+ aux2.tex
+ (lambda (in)
+ (call-with-output-file/truncate
+ aux.tex
+ (lambda (out)
+ (slatex.inline-protected-files in out)))))
+ (slatex.delete-file aux2.tex))))
+ (set! slatex.*slatex-in-protected-region?* %:g9%)
+ (set! slatex.*protected-files* %:g10%)
+ %temp%)))))
+
+(define slatex.inline-protected-files
+ (lambda (in out)
+ (let ((done? #f))
+ (let loop ()
+ (if done?
+ 'exit-loop
+ (begin
+ (let ((c (read-char in)))
+ (cond ((eof-object? c) (display "{}" out) (set! done? #t))
+ ((char=? c #\%) (slatex.eat-till-newline in))
+ ((char=? c #\\)
+ (let ((cs (slatex.read-ctrl-seq in)))
+ (cond ((string=? cs "begin")
+ (let ((cs (slatex.read-grouped-latexexp in)))
+ (cond ((member cs slatex.*display-triggerers*)
+ (slatex.inline-protected
+ 'envdisplay
+ in
+ out
+ cs))
+ ((member cs slatex.*box-triggerers*)
+ (slatex.inline-protected
+ 'envbox
+ in
+ out
+ cs))
+ ((member cs slatex.*region-triggerers*)
+ (slatex.inline-protected
+ 'envregion
+ in
+ out
+ cs))
+ (else
+ (display "\\begin{" out)
+ (display cs out)
+ (display "}" out)))))
+ ((member cs slatex.*intext-triggerers*)
+ (slatex.inline-protected 'intext in out #f))
+ ((member cs slatex.*resultintext-triggerers*)
+ (slatex.inline-protected
+ 'resultintext
+ in
+ out
+ #f))
+ ((member cs slatex.*display-triggerers*)
+ (slatex.inline-protected
+ 'plaindisplay
+ in
+ out
+ cs))
+ ((member cs slatex.*box-triggerers*)
+ (slatex.inline-protected 'plainbox in out cs))
+ ((member cs slatex.*region-triggerers*)
+ (slatex.inline-protected 'plainregion in out cs))
+ ((member cs slatex.*input-triggerers*)
+ (slatex.inline-protected 'input in out cs))
+ (else (display "\\" out) (display cs out)))))
+ (else (display c out))))
+ (loop)))))))
+
+(define slatex.inline-protected
+ (lambda (typ in out env)
+ (cond ((eq? typ 'envregion)
+ (display "\\begin{" out)
+ (display env out)
+ (display "}" out)
+ (slatex.dump-display in out (string-append "\\end{" env "}"))
+ (display "\\end{" out)
+ (display env out)
+ (display "}" out))
+ ((eq? typ 'plainregion)
+ (display "\\" out)
+ (display env out)
+ (slatex.dump-display in out (string-append "\\end" env))
+ (display "\\end" out)
+ (display env out))
+ (else
+ (let ((f (car slatex.*protected-files*)))
+ (set! slatex.*protected-files* (cdr slatex.*protected-files*))
+ (call-with-input-file
+ f
+ (lambda (in) (slatex.inline-protected-files in out)))
+ (slatex.delete-file f))
+ (cond ((memq typ '(intext resultintext)) (slatex.dump-intext in #f))
+ ((memq typ '(envdisplay envbox))
+ (slatex.dump-display in #f (string-append "\\end{" env "}")))
+ ((memq typ '(plaindisplay plainbox))
+ (slatex.dump-display in #f (string-append "\\end" env)))
+ ((eq? typ 'input) (slatex.read-filename in))
+ (else (slatex.error 'slatex.inline-protected 1)))))))
+
+(define (main . args)
+ (run-benchmark
+ "slatex"
+ slatex-iters
+ (lambda (result) #t)
+ (lambda (filename) (lambda () (slatex.process-main-tex-file filename)))
+ "test"))
+
+(main)
diff --git a/tests/slatex.sty b/tests/slatex.sty
new file mode 100644
index 00000000..15a3f203
--- /dev/null
+++ b/tests/slatex.sty
@@ -0,0 +1,547 @@
+% slatex.sty
+% SLaTeX v. 2.2
+% style file to be used in (La)TeX when using SLaTeX
+% (c) Dorai Sitaram, Rice U., 1991, 1994
+
+% This file (or a soft link to it) should be in some
+% directory in your TEXINPUTS path (i.e., the one
+% (La)TeX scours for \input or \documentstyle option
+% files).
+
+% Do not attempt to debug this file, since the results
+% are not transparent just to (La)TeX. The Scheme part
+% of SLaTeX depends on information laid out here -- so
+% (La)TeX-minded debugging of this file will almost
+% inevitably sabotage SLaTeX.
+
+% It's possible you don't find the default style set
+% out here appealing: e.g., you may want to change the
+% positioning of displayed code; change the fonts for
+% keywords, constants, and variables; add new keywords,
+% constants, and variables; use your names instead of
+% the provided \scheme, [\begin|\end]{schemedisplay},
+% [\begin|\end]{schemebox}, (or \[end]schemedisplay,
+% \[end]schemebox for TeX), which might be seem too
+% long or unmnemonic, and many other things. The clean
+% way to do these things is outlined in the
+% accompanying manual, slatex-d.tex. This way is both
+% easier than messing with this .sty file, and safer
+% since you will not unwittingly break SLaTeX.
+
+%%%
+
+% to prevent loading slatex.sty more than once
+
+\ifx\slatexignorecurrentfile\UNDEFINED
+\else\endinput\fi
+
+% use \slatexignorecurrentfile to disable slatex for
+% the current file. (Unstrangely, the very definition
+% disables slatex for the rest of _this_ file, slatex.sty.)
+
+\def\slatexignorecurrentfile{}
+
+% checking whether we're using LaTeX or TeX?
+
+\newif\ifusinglatex
+\ifx\newenvironment\UNDEFINED\usinglatexfalse\else\usinglatextrue\fi
+
+% make @ a letter for TeX
+\ifusinglatex\relax\else
+\edef\atcatcodebeforeslatex{\the\catcode`@}
+\catcode`@11
+\fi
+
+% identification of TeX/LaTeX style for schemedisplay.
+% Do \defslatexenvstyle{tex} to get TeX environment
+% style in LaTeX
+\def\defslatexenvstyle#1{\gdef\slatexenvstyle{#1}}
+
+\ifusinglatex\defslatexenvstyle{latex}\else\defslatexenvstyle{tex}\fi
+
+% TeX doesn't have sans-serif; use roman instead
+\ifx\sf\UNDEFINED\def\sf{\rm}\fi
+
+% tabbing from plain TeX
+%
+\newif\ifus@ \newif\if@cr
+\newbox\tabs \newbox\tabsyet \newbox\tabsdone
+%
+\def\cleartabs{\global\setbox\tabsyet\null \setbox\tabs\null}
+\def\settabs{\setbox\tabs\null \futurelet\next\sett@b}
+\let\+=\relax % in case this file is being read in twice
+\def\sett@b{\ifx\next\+\let\next\relax
+ \def\next{\afterassignment\s@tt@b\let\next}%
+\else\let\next\s@tcols\fi\next}
+\def\s@tt@b{\let\next\relax\us@false\m@ketabbox}
+\def\tabalign{\us@true\m@ketabbox} % non-\outer version of \+
+\outer\def\+{\tabalign}
+\def\s@tcols#1\columns{\count@#1 \dimen@\hsize
+ \loop\ifnum\count@>\z@ \@nother \repeat}
+\def\@nother{\dimen@ii\dimen@ \divide\dimen@ii\count@
+ \setbox\tabs\hbox{\hbox to\dimen@ii{}\unhbox\tabs}%
+ \advance\dimen@-\dimen@ii \advance\count@\m@ne}
+%
+\def\m@ketabbox{\begingroup
+ \global\setbox\tabsyet\copy\tabs
+ \global\setbox\tabsdone\null
+ \def\cr{\@crtrue\crcr\egroup\egroup
+ \ifus@\unvbox\z@\lastbox\fi\endgroup
+ \setbox\tabs\hbox{\unhbox\tabsyet\unhbox\tabsdone}}%
+ \setbox\z@\vbox\bgroup\@crfalse
+ \ialign\bgroup&\t@bbox##\t@bb@x\crcr}
+%
+\def\t@bbox{\setbox\z@\hbox\bgroup}
+\def\t@bb@x{\if@cr\egroup % now \box\z@ holds the column
+ \else\hss\egroup \global\setbox\tabsyet\hbox{\unhbox\tabsyet
+ \global\setbox\@ne\lastbox}% now \box\@ne holds its size
+ \ifvoid\@ne\global\setbox\@ne\hbox to\wd\z@{}%
+ \else\setbox\z@\hbox to\wd\@ne{\unhbox\z@}\fi
+ \global\setbox\tabsdone\hbox{\box\@ne\unhbox\tabsdone}\fi
+ \box\z@}
+% finished (re)defining TeX's tabbing macros
+
+% above from plain.tex; was disabled in lplain.tex. Do
+% not modify above unless you really know what you're
+% up to. Make all changes you want to following code.
+% The new env is preferable to LaTeX's tabbing env
+% since latter accepts only a small number of tabs
+
+% following retrieves something like LaTeX's tabbing
+% env without the above problem (it also creates a box
+% for easy manipulation!)
+
+\def\lat@xtabbing{\leavevmode\hbox\bgroup\vbox\bgroup
+ \def\={\cleartabs&} \def\>{&} \def\\{\cr\tabalign} \tabalign}
+\def\endlat@xtabbing{\cr\egroup\egroup}
+
+%new
+
+\def\lat@xtabbing{\begingroup
+\def\={\cleartabs&} \def\>{&}%
+\def\\{\cr\tabalign\lat@xtabbingleftmost}%
+\tabalign\lat@xtabbingleftmost}
+\def\endlat@xtabbing{\cr\endgroup}
+\let\lat@xtabbingleftmost\relax
+
+% stuff for formating Scheme code
+
+\newskip\par@nlen \newskip\brack@tlen \newskip\quot@len
+\newskip\h@lflambda
+
+\newbox\garb@ge
+\def\s@ttowidth#1#2{\setbox\garb@ge\hbox{#2}#1\wd\garb@ge\relax}
+
+\s@ttowidth\par@nlen{$($} % size of paren
+\s@ttowidth\brack@tlen{$[$} % size of bracket
+\s@ttowidth\quot@len{'} % size of quote indentation
+\s@ttowidth\h@lflambda{ii} % size of half of lambda indentation
+
+\def\PRN{\hskip\par@nlen} % these are used by SLaTeX's codesetter
+\def\BKT{\hskip\brack@tlen}
+\def\QUO{\hskip\quot@len}
+\def\HL{\hskip\h@lflambda}
+
+\newskip\abovecodeskip \newskip\belowcodeskip
+\newskip\leftcodeskip \newskip\rightcodeskip
+
+% the following default assignments give a flushleft
+% display
+
+\abovecodeskip=\medskipamount \belowcodeskip=\medskipamount
+\leftcodeskip=0pt \rightcodeskip=0pt
+
+% adjust above,below,left,right codeskip's to personal
+% taste
+
+% for centered displays
+%
+% \leftcodeskip=0pt plus 1fil
+% \rightcodeskip=0pt plus 1fil
+%
+% if \rightcodeskip != 0pt, pagebreaks within Scheme
+% blocks in {schemedisplay} are disabled
+
+\def\checkfollpar{\futurelet\next\checkfollparII}
+\def\checkfollparII{\ifx\next\par\let\next\relax
+\else\par\noindent\let\next\ignorespaces\fi\next}
+
+% the following are the default font assignments for
+% words in code. Change them to suit personal taste
+
+\def\keywordfont#1{{\bf #1}}
+\def\variablefont#1{{\it #1\/}}
+\def\constantfont#1{{\sf #1}}
+\def\datafont#1{\constantfont{#1}}
+
+\def\schemecodehook{}
+
+%program listings that allow page breaks but
+%can't be centered
+
+\def\ZZZZschemedisplay{\edef\thez@skip{\the\z@skip}%
+\edef\@tempa{\the\rightcodeskip}%
+\ifx\@tempa\thez@skip\let\next\ZZZZschemeprogram
+\else\let\next\ZZZZschemeprogramII\fi\next}
+
+\def\endZZZZschemedisplay{\edef\thez@skip{\the\z@skip}%
+\edef\@tempa{\the\rightcodeskip}%
+\ifx\@tempa\thez@skip\let\next\endZZZZschemeprogram
+\else\let\next\endZZZZschemeprogramII\fi\next}
+
+\def\ZZZZschemeprogram{\vskip\abovecodeskip
+\begingroup
+\schemecodehook
+\let\sy=\keywordfont \let\cn=\constantfont
+\let\va=\variablefont \let\dt=\datafont
+\def\lat@xtabbingleftmost{\hskip\leftcodeskip\relax}%
+\lat@xtabbing}
+
+\def\endZZZZschemeprogram{\endlat@xtabbing
+\endgroup
+\vskip\belowcodeskip
+\ifusinglatex\let\next\@endparenv
+\else\let\next\checkfollpar\fi\next}
+
+\def\ZZZZschemeprogramII{\vskip\abovecodeskip
+\begingroup
+\noindent
+%\schemecodehook %\ZZZZschemebox already has it
+\hskip\leftcodeskip
+\ZZZZschemebox}
+
+\def\endZZZZschemeprogramII{\endZZZZschemebox
+\hskip\rightcodeskip
+\endgroup
+\vskip\belowcodeskip
+\ifusinglatex\let\next\@endparenv
+\else\let\next\checkfollpar\fi\next}
+
+%
+
+\def\ZZZZschemebox{%
+\leavevmode\hbox\bgroup\vbox\bgroup
+\schemecodehook
+\let\sy=\keywordfont \let\cn=\constantfont
+\let\va=\variablefont \let\dt=\datafont
+\lat@xtabbing}
+\def\endZZZZschemebox{\endlat@xtabbing
+\egroup\egroup\ignorespaces}
+
+%in-text
+
+\def\ZZZZschemecodeintext{\begingroup
+ \let\sy\keywordfont \let\cn\constantfont
+ \let\va\variablefont \let\dt\datafont}
+
+\def\endZZZZschemecodeintext{\endgroup\ignorespaces}
+
+\def\ZZZZschemeresultintext{\begingroup
+ \let\sy\datafont \let\cn\constantfont
+ \let\va\datafont \let\dt\datafont}
+
+\def\endZZZZschemeresultintext{\endgroup\ignorespaces}
+
+% \comm@nt<some-char>...text...<same-char> comments out
+% TeX source analogous to
+% \verb<some-char>...text...<same-char>. Sp. case:
+% \comm@nt{...text...} == \comm@nt}...text...}
+
+\def\@makeother#1{\catcode`#112\relax}
+
+\def\comm@nt{%
+ \begingroup
+ \let\do\@makeother \dospecials
+ \@comm}
+
+\begingroup\catcode`\<1\catcode`\>2
+\catcode`\{12\catcode`\}12
+\long\gdef\@comm#1<%
+ \if#1{\long\def\@tempa ##1}<\endgroup>\else
+ \long\def\@tempa ##1#1<\endgroup>\fi
+ \@tempa>
+\endgroup
+
+% input file if possible, else relax
+
+\def\inputifpossible#1{%
+ \immediate\openin0=#1\relax%
+ \ifeof0\relax\else\input#1\relax\fi%
+ \immediate\closein0}
+
+\def\ZZZZinput#1{\input#1\relax}
+
+% you may replace the above by
+%
+% \def\ZZZZinput#1{\inputifpossible{#1}}
+%
+% if you just want to call (La)TeX on your text
+% ignoring the portions that need to be SLaTeX'ed
+
+%use \subjobname rather than \jobname to generate
+%slatex's temp files --- this allows us to change
+%\subjobname for more control, if necessary.
+
+\let\subjobname\jobname
+
+% counter for generating temp file names
+
+\newcount\sch@mefilenamecount
+\sch@mefilenamecount=-1
+
+% To produce displayed Scheme code:
+% in LaTeX:
+% \begin{schemedisplay}
+% ... indented program (with sev'l lines) ...
+% \end{schemedisplay}
+%
+% in TeX:
+% \schemedisplay
+% ... indented program (with sev'l lines) ...
+% \endschemedisplay
+
+\begingroup\catcode`\|=0\catcode`\[=1\catcode`\]=2%
+\catcode`\{=12\catcode`\}=12\catcode`\\=12%
+|gdef|defschemedisplaytoken#1[%
+ |long|expandafter|gdef|csname ZZZZcomment#1|endcsname[%
+ |begingroup
+ |let|do|@makeother |dospecials
+ |csname ZZZZcomment|slatexenvstyle II#1|endcsname]%
+ |long|expandafter|gdef|csname ZZZZcommentlatexII#1|endcsname##1\end{#1}[%
+ |endgroup|end[#1]]%
+ |long|expandafter|gdef|csname ZZZZcommenttexII#1|endcsname##1\end#1[%
+ |endgroup|csname end#1|endcsname]%
+ |long|expandafter|gdef|csname #1|endcsname[%
+ |global|advance|sch@mefilenamecount by 1|relax%
+ |ZZZZinput[|filehider Z|number|sch@mefilenamecount|subjobname.tex]%
+ |csname ZZZZcomment#1|endcsname]%
+ |long|expandafter|gdef|csname end#1|endcsname[]]%
+|endgroup
+
+\defschemedisplaytoken{schemedisplay}
+
+\def\undefschemedisplaytoken#1{%
+ \expandafter\gdef\csname#1\endcsname{\UNDEFINED}}
+
+% \scheme|...program fragment...| produces Scheme code
+% in-text. Sp. case: \scheme{...} == \scheme}...}
+
+\def\defschemetoken#1{%
+ \long\expandafter\def\csname#1\endcsname{%
+ \global\advance\sch@mefilenamecount by 1\relax%
+ \ZZZZinput{\filehider Z\number\sch@mefilenamecount\subjobname.tex}%
+ \comm@nt}}
+\defschemetoken{scheme}
+
+\def\undefschemetoken#1{%
+ \expandafter\gdef\csname#1\endcsname{\UNDEFINED}}
+
+% \schemeresult|...program fragment...| produces a
+% Scheme code result in-text: i.e. keyword or variable
+% fonts are replaced by the data font. Sp. case:
+% \schemeresult{...} == \schemeresult}...}
+
+\def\defschemeresulttoken#1{%
+ \long\expandafter\def\csname#1\endcsname{%
+ \global\advance\sch@mefilenamecount by 1\relax%
+ \ZZZZinput{\filehider Z\number\sch@mefilenamecount\subjobname.tex}%
+ \comm@nt}}
+\defschemeresulttoken{schemeresult}
+
+\def\undefschemeresulttoken#1{%
+ \expandafter\gdef\csname#1\endcsname{\UNDEFINED}}
+
+% To produce a box of Scheme code:
+% in LaTeX:
+% \begin{schemebox}
+% ... indented program (with sev'l lines) ...
+% \end{schemebox}
+%
+% in TeX:
+% \schemebox
+% ... indented program (with sev'l lines) ...
+% \endschemebox
+
+\begingroup\catcode`\|=0\catcode`\[=1\catcode`\]=2%
+\catcode`\{=12\catcode`\}=12\catcode`\\=12%
+|gdef|defschemeboxtoken#1[%
+ |long|expandafter|gdef|csname ZZZZcomment#1|endcsname[%
+ |begingroup
+ |let|do|@makeother |dospecials
+ |csname ZZZZcomment|slatexenvstyle II#1|endcsname]%
+ |long|expandafter|gdef|csname ZZZZcommentlatexII#1|endcsname##1\end{#1}[%
+ |endgroup|end[#1]]%
+ |long|expandafter|gdef|csname ZZZZcommenttexII#1|endcsname##1\end#1[%
+ |endgroup|csname end#1|endcsname]%
+ |long|expandafter|gdef|csname #1|endcsname[%
+ |global|advance|sch@mefilenamecount by 1|relax%
+ |ZZZZinput[|filehider Z|number|sch@mefilenamecount|subjobname.tex]%
+ |csname ZZZZcomment#1|endcsname]%
+ |long|expandafter|gdef|csname end#1|endcsname[]]%
+|endgroup
+
+\defschemeboxtoken{schemebox}
+
+\def\undefschemeboxtoken#1{%
+ \expandafter\gdef\csname#1\endcsname{\UNDEFINED}}
+
+% for wholesale dumping of all-Scheme files into TeX (converting
+% .scm files to .tex),
+% use
+% \schemeinput{<filename>}
+% .scm, .ss, .s extensions optional
+
+\def\defschemeinputtoken#1{%
+ \long\expandafter\gdef\csname#1\endcsname##1{%
+ \global\advance\sch@mefilenamecount by 1\relax%
+ \ZZZZinput{\filehider Z\number\sch@mefilenamecount\subjobname.tex}}}
+\defschemeinputtoken{schemeinput}
+
+\def\undefschemeinputtoken#1{%
+ \expandafter\gdef\csname#1\endcsname{\UNDEFINED}}
+
+% delineating a region that features typeset code
+% not usually needed, except when using \scheme and schemedisplay
+% inside macro-args and macro-definition-bodies
+% in LaTeX:
+% \begin{schemeregion}
+% ...
+% \end{schemeregion}
+%
+% in TeX:
+% \schemeregion
+% ...
+% \endschemeregion
+
+\begingroup\catcode`\|=0\catcode`\[=1\catcode`\]=2%
+\catcode`\{=12\catcode`\}=12\catcode`\\=12%
+|gdef|defschemeregiontoken#1[%
+ |long|expandafter|gdef|csname ZZZZcomment#1|endcsname[%
+ |begingroup
+ |let|do|@makeother |dospecials
+ |csname ZZZZcomment|slatexenvstyle II#1|endcsname]%
+ |long|expandafter|gdef|csname ZZZZcommentlatexII#1|endcsname##1\end{#1}[%
+ |endgroup|end[#1]]%
+ |long|expandafter|gdef|csname ZZZZcommenttexII#1|endcsname##1\end#1[%
+ |endgroup|csname end#1|endcsname]%
+ |long|expandafter|gdef|csname #1|endcsname[%
+ |global|advance|sch@mefilenamecount by 1|relax%
+ |ZZZZinput[|filehider Z|number|sch@mefilenamecount|subjobname.tex]%
+ |csname ZZZZcomment#1|endcsname]%
+ |long|expandafter|gdef|csname end#1|endcsname[]]%
+|endgroup
+
+\defschemeregiontoken{schemeregion}
+
+\def\undefschemeregiontoken#1{%
+ \expandafter\gdef\csname#1\endcsname{\UNDEFINED}}
+
+% introducing new code-tokens to the keyword, variable and constant
+% categories
+
+\def\comm@ntII{%
+ \begingroup
+ \let\do\@makeother \dospecials
+ \@commII}
+
+\begingroup\catcode`\[1\catcode`\]2
+\catcode`\{12\catcode`\}12
+\long\gdef\@commII{[%
+ \long\def\@tempa ##1}[\endgroup]\@tempa]%
+\endgroup
+
+\let\setkeyword\comm@ntII
+\let\setvariable\comm@ntII
+\let\setconstant\comm@ntII
+
+% \defschememathescape makes the succeeding grouped character an
+% escape into latex math from within Scheme code;
+% this character can't be }
+
+\let\defschememathescape\comm@ntII
+\let\undefschememathescape\comm@ntII
+
+% telling SLaTeX that a certain Scheme identifier is to
+% be replaced by the specified LaTeX expression.
+% Useful for generating ``mathematical''-looking
+% typeset code even though the corresponding Scheme
+% code is ascii as usual and doesn't violate
+% identifier-naming rules
+
+\def\setspecialsymbol{%
+ \begingroup
+ \let\do\@makeother \dospecials
+ \@commIII}
+
+\begingroup\catcode`\[1\catcode`\]2
+\catcode`\{12\catcode`\}12
+\long\gdef\@commIII{[%
+ \long\def\@tempa ##1}[\endgroup\@gobbleI]\@tempa]%
+\endgroup
+
+\def\@gobbleI#1{}
+
+% \unsetspecialsymbol strips Scheme identifier(s) of
+% any ``mathematical'' look lent by the above
+
+\let\unsetspecialsymbol\comm@ntII
+
+% enabling/disabling slatex
+
+\def\slatexdisable#1{\expandafter\gdef\csname#1\endcsname{}}
+
+% \schemecasesensitive takes either true or false as
+% argument
+
+\def\schemecasesensitive#1{}
+
+%for latex only: use \slatexseparateincludes before the
+%occurrence of any Scheme code in your file, if you
+%want the various \include'd files to have their own
+%pool of temporary slatex files. This lets you juggle
+%your \include's in successive runs of LaTeX without
+%having to worry that the temp. files may interfere.
+%By default, only a single pool of temp files is used.
+%Warning: On DOS, if your \include'd files have fairly
+%similar names, avoid \slatexseparateincludes since the
+%short filenames on DOS will likely confuse the temp
+%file pools of different \include files.
+
+\def\slatexseparateincludes{%
+\gdef\include##1{{\def\subjobname{##1}%
+\sch@mefilenamecount=-1%
+\@include##1 }}}
+
+% convenient abbreviations for characters
+
+\begingroup
+\catcode`\|=0
+|catcode`|\=12
+|gdef|ttbackslash{{|tt|catcode`|\=12\}}
+|endgroup
+\mathchardef\lt="313C
+\mathchardef\gt="313E
+\begingroup
+ \catcode`\@12%
+ \global\let\atsign@%
+\endgroup
+\chardef\dq=`\"
+
+% leading character of slatex filenames: . for unix to
+% keep them out of the way
+
+\def\filehider{.}
+
+% since the above doesn't work of dos, slatex on dos
+% will use a different character, and make the
+% redefinition available through the following
+
+\inputifpossible{xZfilhid.tex}
+
+% @ is no longer a letter for TeX
+
+\ifusinglatex\relax\else
+\catcode`@\atcatcodebeforeslatex
+\fi
+
+\message{*** Check: Are you sure you called SLaTeX? ***}
diff --git a/tests/test.tex b/tests/test.tex
new file mode 100644
index 00000000..4826a1e0
--- /dev/null
+++ b/tests/test.tex
@@ -0,0 +1,1658 @@
+%slatex-d.tex
+%SLaTeX Version 2
+%Documentation for SLaTeX
+%(c) Dorai Sitaram, 1991, 1994
+%dorai@cs.rice.edu
+
+\documentstyle[slatex]{article}
+
+\slatexdisable{enableslatex}
+
+\edef\atcatcodebeforepreamble{\the\catcode`@}
+\catcode`@11
+
+\inputifpossible{multicol.sty}
+
+%if Frank Mittelbach's multicol.sty is not
+%available, the index will simply waste some paper
+
+%latex wastes too much paper, so...
+
+\textheight 11in
+\textwidth 8.5in
+\oddsidemargin 1.25in
+\advance\textheight -2\oddsidemargin
+\advance\textwidth -2\oddsidemargin
+\advance\oddsidemargin -1in
+\evensidemargin\oddsidemargin
+\topmargin\oddsidemargin
+\advance\topmargin -\headheight
+\advance\topmargin -\headsep
+
+%latex's section headings are way too obnoxiously
+%large, so...
+
+\def\nolargefonts{\let\large\normalsize
+\let\Large\normalsize
+\let\LARGE\normalsize
+\let\huge\normalsize
+\let\Huge\normalsize}
+
+%mini headers for introducing paragraphs
+
+\def\re{\medbreak\parindent0pt%
+\aftergroup\smallskip\obeylines
+\llap{$\searrow$\enspace\enspace}}
+
+%a wide line
+
+\def\wideline{\centerline{\hrulefill}}
+
+%smart italics
+
+\def\italicsbegin{\begingroup\it}
+\def\italicsend{\endgroup\futurelet\next\italiccorrection}
+\def\italiccorrection{\ifx\next,\else\ifx\next.\else\/\fi\fi}
+\def\italicstoggle{\italicsbegin\let\italicstoggle\italicsend}
+\catcode`\_\active
+\def_{\ifmmode\sb\else\expandafter\italicstoggle\fi}
+
+%quote.tex, by Hunter Goatley
+
+{\catcode`\"\active
+%
+\gdef\begindoublequotes{\global\catcode`\"\active
+\global\let\dblqu@te=L}
+%
+\gdef"{\ifinner\else\ifvmode\let\dblqu@te=L\fi\fi
+\if L\dblqu@te``\global\let\dblqu@te=R\else
+\let\xxx=\spacefactor
+''\global\let\dblqu@te=L%
+\spacefactor\xxx
+\fi}}
+
+\def\enddoublequotes{\catcode`\"=12}
+
+%nicer \verb
+
+\begingroup\catcode`[1\catcode`]2\catcode`\{12\catcode`\}12%
+\gdef\@sverb#1[\if#1{\def\@tempa##1}[\leavevmode\null##1\endgroup]\else
+\def\@tempa##1#1[\leavevmode\null##1\endgroup]\fi\@tempa]%
+\endgroup
+
+%nicer \footnote
+
+\let\latexfootnote\footnote
+\def\footnote{\unskip\latexfootnote\bgroup\let\dummy=}
+
+%item
+
+\let\o\item
+
+%index environment that exploits multicol.sty if
+%available...
+
+\renewenvironment{theindex}%
+{\parindent0pt%
+\let\item\@idxitem
+\section*{Index}%
+\ifx\multicols\undefined\else
+\begin{multicols}{2}\fi}%
+{\ifx\multicols\undefined\else
+\end{multicols}\fi}
+
+\catcode`@\atcatcodebeforepreamble
+
+\begindoublequotes
+\makeindex
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\title{How to Use SLaTeX}
+
+\author{Dorai Sitaram\\
+{\tt dorai@cs.rice.edu}\\
+Department of Computer Science\\
+Rice University\\
+Houston, TX 77251--1892}
+
+\date{Gestated 1990\\
+First public release, Mar. 1991\\
+First major update, Dec. 1991\\
+Current update, Jan. 1994}
+
+\begin{document}
+\maketitle
+\nolargefonts
+
+\section{Introduction}
+
+SLaTeX\index{introduction} is a Scheme program
+that allows you to write programs or program fragments
+"as is" in your TeX or LaTeX source. SLaTeX is
+particularly geared to the programming languages Scheme
+and other Lisps, e.g., Common Lisp. The formatting of
+the code includes assigning appropriate fonts to the
+various tokens in the code (keywords, variables,
+constants, data), at the same time retaining the proper
+indentation when going to the non-monospace
+(non-typewriter) fonts provided by TeX. SLaTeX comes
+with two databases that recognize the identifier
+conventions of Scheme and Common Lisp respectively.
+These can be modified by the user using easy TeX
+commands. In addition, the user can inform SLaTeX to
+typeset certain identifiers as specially suited LaTeX
+expressions (i.e., beyond just fonting them). All this
+is done without interfering with the identifier
+conventions of the language of the programming code at
+all. In sum, no change need be made to your
+(presumably running) program code in order to get a
+typeset version suited to the particular need: you can
+get a spectrum of styles ranging from _no_ fonting
+through basic default fonting to various
+"mathematical"-looking output for pedagogic or other
+reasons.
+
+\enableslatex
+Other packages~\cite{schemeweb,lisp2tex} for
+typesetting code fragments use a \verb{verbatim}
+environment where all the characters are in a
+\verb{monospace typewriter font}. This \verb{monospace}
+ensures that the indentation is not affected. However,
+the resulting output fails to distinguish between the
+various tokens used in the code, e.g., boldface for
+keywords like
+\scheme{define} and \scheme{lambda}, sans-serif for
+constants like \scheme{#t} and \scheme{42}, and italics
+for variables such as \scheme{x} and
+\scheme{y} in \scheme{(lambda (x y) (cons x (cons y
+'())))}.
+\slatexdisable{enableslatex}
+
+The program SLaTeX provides a convenient way of
+capturing the indentation information as well as
+assigning distinguishing fonts to code tokens without
+requiring the user to worry about fonting and spacing.
+It uses temporary files to store its typeset version of
+the user's code fragments and then calls TeX or LaTeX
+on the user's TeX files as well as these temporaries.
+
+The following section will introduce you to the basic
+use of SLaTeX with a small example.
+Section~\ref{slatex.sty} introduces the SLaTeX style
+files. Section~\ref{glossary} gives a complete
+description of all the SLaTeX control sequences. These
+include commands for manipulating output positioning,
+enhancing the database, changing the fonting defaults,
+adding special symbols, and selective disabling of
+SLaTeX. Section~\ref{preamble} desribes how to set up
+a preamble that reflects your typesetting taste.
+Section~\ref{ftp} contains information on obtaining and
+installing SLaTeX.
+
+\section{A quick illustration of using SLaTeX}
+\label{quick}
+\index{quick illustration}
+
+This section presents a short example of SLaTeX use.
+We first look at a LaTeX file using SLaTeX commands,
+and then give a plain TeX version of the same file. We
+will see that there are minor differences between the
+ways SLaTeX is used with plain TeX and LaTeX (but see
+\verb{\defslatexenvstyle} for a way to use the
+plain-TeX style with the LaTeX format, and conversely,
+the LaTeX style with the plain format).
+
+\subsection{For LaTeX users}
+\index{LaTeX}
+\index{scheme@\verb{\scheme}}
+\index{schemedisplay@\verb{schemedisplay}!in LaTeX}
+\index{in-text Scheme code}
+\index{displayed Scheme code}
+\index{slatex.sty@\verb{slatex.sty}}
+\index{slatex.sty@\verb{slatex.sty}!as document style}
+
+Consider the following LaTeX (_and_ SLaTeX) file
+\verb{quick.tex}:
+
+\wideline
+\begin{verbatim}
+% quick.tex
+\documentstyle[slatex]{article}
+%or:
+% \documentstyle{article}
+% \input slatex.sty
+
+In Scheme, the expression \scheme|(set! x 42)| returns
+an unspecified value, rather than \scheme'42'.
+However, one could get a \scheme{set!} of the latter
+style by:
+
+\begin{schemedisplay}
+(define-syntax setq
+ (syntax-rules ()
+ [(setq x a)
+ (begin (set! x a)
+ x)]))
+\end{schemedisplay}
+
+\end{document}
+\end{verbatim}
+\wideline
+
+First, the SLaTeX definitions in the style file
+\verb{slatex.sty} are loaded into your LaTeX file ---
+this may be done either as a \verb{\documentstyle}
+option, or through an \verb{\input} command.
+
+\index{scheme@\verb{\scheme}!using grouped argument}
+
+In-text code is introduced by the SLaTeX control
+sequence \verb{\scheme} and is flanked by a pair of
+identical characters that are not alphabets or
+"\verb|{|". As a special convenient case, SLaTeX also
+allows the form \verb|\scheme{...}|.
+
+The SLaTeX control sequences for displayed code are the
+opening \verb|\begin{schemedisplay}| and the closing
+\verb|\end{schemedisplay}|.
+
+The file is now SLaTeX'd by running the command
+\verb{slatex} on it from the Unix or DOS command line:
+
+\begin{verbatim}
+slatex quick
+\end{verbatim}
+or
+\begin{verbatim}
+slatex quick.tex
+\end{verbatim}
+This calls a Scheme program \verb{slatex.scm} that
+typesets the Scheme code fragments in \verb{quick.tex}
+into temporary files. Thereafter, \verb{quick.tex} along with
+the temporary files are then passed to LaTeX. (For
+information on judiciously reusing temporary files, see
+\verb{\slatexseparateincludes}.)
+The resulting
+\verb{quick.dvi} file, when viewed or printed looks like:
+
+\enableslatex
+\wideline
+In Scheme, the expression \scheme|(set! x 42)| returns
+an unspecified value, rather than
+\scheme'42'. However, one could get a \scheme{set!} of
+the latter style by:
+
+\begin{schemedisplay}
+(define-syntax setq
+ (syntax-rules ()
+ [(setq x a)
+ (begin (set! x a)
+ x)]))
+\end{schemedisplay}
+\wideline
+
+\index{recognizing new syntactic keywords automatically}
+
+Note that \scheme{setq}, although not normally a
+syntactic keyword in Scheme is nevertheless
+automatically recognized as such because of the context
+in which it occurs. No special treatment is needed to
+ensure that it will continue be treated as such in any
+subsequent Scheme code in the document.
+
+\slatexdisable{enableslatex}
+
+\subsection{For plain TeX users}
+\index{plain TeX}
+\index{scheme@\verb{\scheme}}
+\index{schemedisplay@\verb{schemedisplay}!in plain TeX}
+\index{in-text Scheme code}
+\index{displayed Scheme code}
+
+Plain TeX users invoke SLaTeX much the same way, but
+for only two exceptions. First, since TeX doesn't have
+\verb{\documentstyle}, the file \verb{slatex.sty} is
+introduced via an \verb{\input} statement before its
+commands can be used in the plain TeX source.
+
+\index{environments}
+
+Second, since plain TeX does not have LaTeX's
+\verb|\begin{|_env_\verb|}...\end{|_env_\verb|}|
+style of environments, any
+environment commands in SLaTeX are invoked with the
+opening \verb{\}_env_ and the closing \verb{\end}_env_.
+
+The plain TeX version of \verb{quick.tex} looks like:
+
+\wideline
+\begin{verbatim}
+% quick.tex
+\input slatex.sty
+
+In Scheme, the expression \scheme|(set! x 42)| returns
+an unspecified value, rather than \scheme'42'.
+However, one could get a \scheme{set!} of the latter
+style by:
+
+\schemedisplay
+(define-syntax setq
+ (syntax-rules ()
+ [(setq x a)
+ (begin (set! x a)
+ x)]))
+\endschemedisplay
+
+\bye
+\end{verbatim}
+\wideline
+
+The file is now SLaTeX'd by invoking \verb{slatex} as
+before --- SLaTeX is clever enough to figure out
+whether the file it operates on should later be send to
+LaTeX or plain Tex.
+
+\section{The style files}
+\label{slatex.sty}
+\index{slatex.sty@\verb{slatex.sty}}
+
+In short, the LaTeX (or TeX) file that is given to
+SLaTeX undergoes some code-setting preprocessing and is
+then handed over to LaTeX (or TeX). The style file
+\verb{slatex.sty} defines the appropriate commands so
+that LaTeX (or TeX) can recognize the SLaTeX-specific
+directives and either process or ignore them. You may
+either \verb|\input| the file \verb{slatex.sty} as
+usual, or use it as the \verb|\documentstyle| option
+\verb{slatex}.
+
+\index{cltl.sty@\verb{cltl.sty}}
+\index{SLaTeX database!for Scheme}
+\index{SLaTeX database!for Common Lisp}
+\index{SLaTeX database!modifying}
+
+The default database of SLaTeX recognizes the keywords
+and constants of Scheme. The database can be modified
+with the commands \verb{\setkeyword},
+\verb{\setconstant}, \verb{\setvariable},
+\verb{\setspecialsymbol} and \verb{\unsetspecialsymbol}
+(q.v.). If you're using Common Lisp rather than
+Scheme, use \verb{cltl.sty} instead of
+\verb{slatex.sty}.
+\verb{cltl.sty} loads \verb{slatex.sty} and modifies
+the database to reflect Common Lisp. You may fashion
+your own \verb{.sty} files on the model of
+\verb{cltl.sty}.
+
+\section{SLaTeX's control sequences}
+\label{glossary}
+\index{SLaTeX control sequences}
+
+You've already seen the SLaTeX control sequence
+\verb|\scheme| and the environment
+\verb{schemedisplay}. These suffice for quite a few
+instances of handling code. However, you will
+occasionally require more control on the typesetting
+process, and the rest of this section describes the
+complete
+\footnote{At least that's what you're supposed
+to think...} list of SLaTeX control sequences shows you
+the ropes.
+
+{\re
+\verb{schemedisplay}}
+\index{schemedisplay@\verb{schemedisplay}}
+\index{displayed Scheme code}
+
+[In plain TeX: \verb{\schemedisplay} ...
+\verb{\endschemedisplay}; in LaTeX:
+\verb|\begin{schemedisplay}| ...
+\verb|\end{schemedisplay}|; but see \verb{\defslatexenvstyle}.]
+
+Typesets the enclosed code, which is typically several
+lines of code indented as you normally do in your
+Scheme files. E.g.,
+
+\begin{verbatim}
+\begin{schemedisplay}
+(define compose ;this is also known as $B$
+ (lambda (f g)
+ (lambda (x)
+ (apply f (g x)))))
+\end{schemedisplay}
+is the "compose" function.
+\end{verbatim}
+produces
+
+\enableslatex
+\begin{schemedisplay}
+(define compose ;this is also known as $B$
+ (lambda (f g)
+ (lambda (x)
+ (apply f (g x)))))
+\end{schemedisplay}
+\slatexdisable{enableslatex}
+is the "compose" function.
+
+As with all LaTeX environment enders, if the line after
+\verb|\end{schemedisplay}| contains
+non-whitespace text, the paragraph continues.
+Otherwise --- i.e., when \verb|\end{schemedisplay}| is
+followed by at least one blank line --- a fresh
+paragraph is started. Similarly, in plain TeX, a fresh
+paragraph is started after a \verb{schemedisplay} only
+if
+\verb|\endschemedisplay| is followed by at least one
+blank line.
+
+\index{Scheme comments}
+
+Comments in Scheme are usually introduced by "\verb{;}"
+(semicolon). The rest of the line after a "\verb{;}"
+is set as a line in LaTeX LR mode.
+
+\index{TeX paragraphs amidst Scheme code}
+
+Separate _blocks_ of code can either be introduced in
+different \verb{schemedisplay} environments or put in a
+single \verb{schemedisplay} and separated by a line with
+a "\verb{;}" in the first column. This "\verb{;}" is
+not typeset and anything following it on the line is
+set in (La)TeX LR paragraph mode. Consecutive lines
+with "\verb{;}" in the first column are treated
+as input for a TeX paragraph, with words possibly
+moved around from line to line to ensure justification.
+When in paragraph mode, the first line that has _no_
+leading "\verb{;}" signals a fresh block
+of Scheme code within the
+\verb{schemedisplay}. (The \verb{schemedisplay} may
+end, or commence, on either a paragraph or a Scheme
+code block.)
+
+E.g.,
+
+\begin{verbatim}
+\begin{schemedisplay}
+(define even? ; testing evenness
+ (lambda (n)
+ (if (= n 0) #t (not (odd? (- n 1))))))
+; The procedures {\it even?} above
+; and {\it odd?} below are mutually
+; recursive.
+(define odd? ; testing oddness
+ (lambda (n)
+ (if (= n 0) #f (not (even? (- n 1))))))
+\end{schemedisplay}
+\end{verbatim}
+produces
+
+\enableslatex
+\begin{schemedisplay}
+(define even? ; testing evenness
+ (lambda (n)
+ (if (= n 0) #t (not (odd? (- n 1))))))
+; The procedures {\it even?} above
+; and {\it odd?} below are mutually
+; recursive.
+(define odd? ; testing oddness
+ (lambda (n)
+ (if (= n 0) #f (not (even? (- n 1))))))
+\end{schemedisplay}
+\slatexdisable{enableslatex}
+
+SLaTeX can recognize that blocks of code are separate
+if you have at least one empty line separating them.
+I.e., there is no need for empty "\verb{;}" lines. This
+convenience is to accommodate Scheme files where
+definitions are usually separated by one or more blank
+lines.
+
+\index{schemedisplay@\verb{schemedisplay}!allowing page
+breaks in}
+
+Intervening paragraphs, either with lines with a
+leading "\verb{;}", or with blank lines, are ideal
+spots for \verb{schemedisplay} to allow pagebreaks. In
+fact, the default setting for \verb{schemedisplay} also
+allows pagebreaks _within_ a Scheme block, but it is
+easy to disable this (see entry for
+\verb{\rightcodeskip}).
+
+The space surrounding displayed Scheme code can be
+modified by setting the _skip_s \verb{\abovecodeskip},
+\verb{\belowcodeskip}, \verb{\leftcodeskip}, and
+\verb{\rightcodeskip} (q.v.).
+
+Note: see \verb{schemeregion}.
+
+{\re
+\verb{\scheme}}
+\index{scheme@\verb{\scheme}}
+\index{in-text Scheme code}
+
+Typesets its argument, which is enclosed in arbitrary
+but identical non-alphabetic and non-\verb|{|
+characters, as in-text code. Special case:
+\verb|\scheme{...}| is a convenience (provided the
+\verb|...| doesn't contain a
+\verb|}|). E.g., \verb+\scheme|(call/cc (lambda (x) x))|+
+and \verb+\scheme{(call/cc (lambda (x) x))}+ both
+produce
+\enableslatex
+\scheme{(call/cc (lambda (x) x))}.
+\slatexdisable{enableslatex}
+\index{scheme@\verb{\scheme}!using grouped argument}
+
+\index{nesting SLaTeX control sequences}
+It _is_ permitted to intermix calls to
+\verb{schemedisplay} and
+\verb|\scheme|. Thus,
+
+\begin{verbatim}
+\begin{schemedisplay}
+(define factorial
+ (lambda (n)
+ (if (= n 0) ; \scheme{(zero? n)} also possible
+ 1 (* n (factorial (- n 1)))))) ; or \scheme{... (sub1 1)}
+\end{schemedisplay}
+\end{verbatim}
+produces
+
+\enableslatex
+\begin{schemedisplay}
+(define factorial
+ (lambda (n)
+ (if (= n 0) ; \scheme{(zero? n)} also possible
+ 1
+ (* n (factorial (- n 1)))))) ; or \scheme{... (sub1 1)}
+\end{schemedisplay}
+\slatexdisable{enableslatex}
+
+Note: see \verb{schemeregion}.
+
+{\re
+\verb{\schemeresult}}
+\index{schemeresult@\verb{\schemeresult}}
+
+Typesets its argument, which is enclosed in arbitrary
+but identical non-alphabetic and non-\verb|{|
+characters, as in-text Scheme "result" or data: i.e.,
+keyword and variable fonts are disabled. Special
+convenient case (as for \verb|\scheme|):
+\verb|\schemeresult{...}|. E.g.,
+\index{schemeresult@\verb{\schemeresult}!using grouped argument}
+
+\begin{verbatim}
+\scheme|((lambda () (cons 'lambda 'cons)))| yields
+\schemeresult|(lambda . cons)|.
+\end{verbatim}
+produces
+
+\enableslatex
+\scheme|((lambda () (cons 'lambda 'cons)))| yields
+\schemeresult|(lambda . cons)|.
+\slatexdisable{enableslatex}
+
+{\re
+\verb{schemebox}}
+\index{schemebox@\verb{schemebox}}
+\index{boxed Scheme code}
+
+[In plain TeX: \verb{\schemebox} ...
+\verb{\endschemebox}; in LaTeX:
+\verb|\begin{schemebox}| ...
+\verb|\end{schemebox}|; but see \verb{defslatexenvstyle}.]
+
+The \verb{schemebox} environment is similar to
+\verb{schemedisplay} except that the code is provided
+as a "box" (i.e., it is not "displayed" in the standard
+way). Indeed, when the appropriate skip parameters are
+set, \verb{schemedisplay} itself _may_
+\footnote{Yes, _may_: Not all \verb{schemedisplay}s invoke
+\verb{schemebox}, and if you're curious why,
+see entry for \verb{\rightcodeskip}. It is a matter of
+whether pagebreaks within Scheme code are allowed or
+not.} use a
+\verb{schemebox} to create a box of code that is
+set off with all-round space as a display.
+
+Saving a \verb{schemebox} in an explicit box allows you
+to move your typeset code arbitrarily.
+
+Note: see \verb{schemeregion}.
+
+{\re
+\verb{\schemeinput}}
+\index{schemeinput@\verb{schemeinput}}
+\index{inputting Scheme files as is}
+
+This can be used to input Scheme files as typeset code.
+(Unlike LaTeX's \verb|\input|, \verb|\schemeinput|'s
+argument must always be grouped.) The Scheme file can
+be specified either by its full name, or without its
+extension, if the latter is \verb{.scm}, \verb{.ss} or
+\verb{.s}. E.g.,
+
+\begin{verbatim}
+\schemeinput{evenodd.scm} % the .scm is optional!
+\end{verbatim}
+(where \verb{evenodd.scm} is the name of a Scheme file
+containing the code for
+\enableslatex
+\scheme{even?} and \scheme{odd?} above) produces the same
+effect as the
+\verb{schemedisplay} version.
+\slatexdisable{enableslatex}
+
+Note: see \verb{schemeregion}.
+
+{\re
+\verb{schemeregion}}
+\index{schemeregion@\verb{schemeregion}}
+\index{nesting SLaTeX control sequences}
+
+[In plain TeX: \verb{\schemeregion} ...
+\verb{\endschemeregion}; in LaTeX:
+\verb|\begin{schemeregion}| ...
+\verb|\end{schemeregion}|; but see \verb{defslatexenvstyle}.]
+
+Calls to \verb|\scheme|, \verb|\schemeresult|,
+\verb{schemedisplay}, \verb{schemebox} or
+\verb|schemeinput| can be nested in (a Scheme comment)
+of other calls. In LaTeX text, they can occur in
+bodies of environments or otherwise grouped. However,
+they cannot normally be passed as arguments to macros
+or included in bodies of macro definitions, even though
+these are complete calls and not parameterized with
+respect to macro arguments. To be able to do this, you
+should cordon off such a text with the
+\verb{schemeregion} environment. SLaTeX is fairly
+generous about where exactly you throw the cordon.
+
+E.g., you cannot have
+
+\begin{verbatim}
+...
+The code fragment
+$\underline{\hbox{\scheme{(call/cc I)}}}$ is ...
+...
+\end{verbatim}
+but you _can_ have
+
+\begin{verbatim}
+\begin{schemeregion}
+...
+The code fragment
+$\underline{\hbox{\scheme{(call/cc I)}}}$ is ...
+...
+\end{schemeregion}
+\end{verbatim}
+and this will produce
+
+\enableslatex
+\begin{schemeregion}
+...
+
+The code fragment
+$\underline{\hbox{\scheme{(call/cc I)}}}$ is ...
+
+...
+\end{schemeregion}
+\slatexdisable{enableslatex}
+
+Thus, the \verb{schemeregion} environment makes it
+possible to put SLaTeX-specific commands inside macro
+arguments or macro definitions without causing rupture.
+Normally, this can't be done since SLaTeX-specific
+commands correspond to \verb{comment}-like regions of
+LaTeX code once SLaTeX is done preprocessing your text.
+These \verb{comment} regions share the characteristic of
+LaTeX's \verb{verbatim} regions, which also can't appear
+in macro arguments or definitions.
+
+To solve this, you enclose the offending text in a
+\verb{schemeregion} environment. This "inlines" all
+the calls to SLaTeX in its body instead of commenting
+them and then invoking \verb|\input|, thus escaping
+the fate described above. They are no-ops as far as
+non-SLaTeX commands are concerned. However, while a
+\verb{schemeregion} allows its constituent SLaTeX
+commands to be included in macro arguments and bodies,
+it itself cannot be so included. Thus, your
+\verb{schemeregion} should be in a position that
+satisfies the property A: either directly at the
+"top-level" or in a LaTeX environment that satisfies A.
+Since this recursive rule might look weird, you may
+just stick to calling \verb{schemeregion} at the
+"top-level". Or, you may even wrap each of your LaTeX
+files in one huge \verb{schemeregion} if you so wish.
+This will cover any obscure "non-robust" use of the
+SLaTeX primitives --- however, SLaTeX will run slower.
+(The term "robust" is not necessarily used in the same
+sense as in LaTeX.)
+
+Note that SLaTeX commands are made robust only if they
+are surrounded textually (lexically) by a
+\verb{schemeregion}. A region marker doesn't have
+dynamic scope in the sense that LaTeX files loaded
+using \verb|\input| from within a
+\verb{schemeregion} will not inherit it. In summary, a
+\verb{schemeregion} makes "robust" all calls to
+\verb|\scheme|, \verb{schemedisplay}, \verb{schemebox}
+and
+\verb|\schemeinput| within it.
+
+{\re
+\verb{\setkeyword}
+\verb{\setconstant}
+\verb{\setvariable}}
+\index{setkeyword@\verb{\setkeyword}}
+\index{setconstant@\verb{\setconstant}}
+\index{setvariable@\verb{\setvariable}}
+\index{SLaTeX database!modifying}
+
+SLaTeX has a database containing information about
+which code tokens are to be treated as {\bf keywords},
+which as {\sf constants}, and which as _variables_.
+However, there will always be instances where the user
+wants to add their own tokens to these categories, or
+perhaps even modify the categories as prescribed by
+SLaTeX. The control sequences that enable the user to
+do these are
+\verb|\setkeyword|, \verb|\setconstant|, and
+\verb|\setvariable|. Their arguments are entered as
+a (space-separated) list enclosed in braces
+(\verb|{}|): SLaTeX learns that these are henceforth
+to be typeset in the appropriate font. E.g.,
+
+\enableslatex
+\begin{verbatim}
+\setconstant{infinity -infinity}
+\end{verbatim}
+tells SLaTeX that \scheme{infinity} and
+\scheme{-infinity} are to be typeset as constants.
+\slatexdisable{enableslatex}
+
+\index{recognizing new syntactic keywords automatically}
+
+The user need not use \verb|\setkeyword| specify such
+new keywords as are introduced by Scheme's and Common
+Lisp's syntactic definition facilities, viz.,
+\enableslatex
+\scheme{define-syntax}/\scheme{syntax-rules},
+\scheme{defmacro}, \scheme{extend-syntax},
+\scheme{define-macro!}: SLaTeX automatically recognizes
+new macros defined using these facilities.
+\slatexdisable{enableslatex}
+
+{\re
+\verb{\setspecialsymbol}
+\verb{\unsetspecialsymbol}}
+\index{setspecialsymbol@\verb{\setspecialsymbol}}
+\index{unsetspecialsymbol@\verb{\unsetspecialsymbol}}
+\index{SLaTeX database!modifying}
+\index{recognizing special symbols}
+
+These commands are useful to generate
+"mathematical"-looking typeset versions of your code,
+over and beyond the fonting capabilities provided by
+default. For instance, although your code is
+restricted to using ascii identifiers that follow some
+convention, the corresponding typeset code could be
+more mnemonic and utilize the full suite of
+mathematical and other symbols provided by TeX. This
+of course should not require you to interfere with your
+code itself, which should run in its ascii
+representation. It is only the typeset version that
+has the new look. For instance, you might want all
+occurrences of \verb|lambda|, \verb|and|,
+\verb|equiv?|,
+\verb|below?|, \verb|above?|, \verb|a1| and \verb|a2| in
+your code to be typeset as $\lambda$, $\land$, $\equiv$,
+$\sqsubseteq$, $\sqsupseteq$, $a_1$ and $a_2$ respectively.
+To do this, you should \verb|\setspecialsymbol| the
+concerned identifier to the desired TeX expansion, viz.,
+
+\enableslatex
+\begin{verbatim}
+\setspecialsymbol{lambda}{$\lambda$}
+\setspecialsymbol{and}{$\land$}
+\setspecialsymbol{equiv?}{$\equiv$}
+\setspecialsymbol{below?}{$\sqsubseteq$}
+\setspecialsymbol{above?}{$\sqsupseteq$}
+\setspecialsymbol{a1}{$a_1$}
+\setspecialsymbol{a2}{$a_2$}
+\end{verbatim}
+\slatexdisable{enableslatex}
+Now, typing
+
+\begin{verbatim}
+\begin{schemedisplay}
+(define equiv?
+ (lambda (a1 a2)
+ (and (below? a1 a2) (above? a1 a2))))
+\end{schemedisplay}
+\end{verbatim}
+produces
+
+\enableslatex
+\begin{schemedisplay}
+(define equiv?
+ (lambda (a1 a2)
+ (and (below? a1 a2) (above? a1 a2))))
+\end{schemedisplay}
+\slatexdisable{enableslatex}
+Note that with the above settings, \verb|lambda| and
+\verb|and| have lost their default keyword status, i.e.,
+they will not be typed {\bf boldface}. To retrieve the
+original status of special symbols, you should use
+\verb|\unsetspecialsymbol|, e.g.
+
+\enableslatex
+\begin{verbatim}
+\unsetspecialsymbol{lambda and}
+\end{verbatim}
+Typing the same program after unsetting the special symbols
+as above produces, as expected:
+
+\begin{schemedisplay}
+(define equiv?
+ (lambda (a1 a2)
+ (and (below? a1 a2) (above? a1 a2))))
+\end{schemedisplay}
+\slatexdisable{enableslatex}
+
+In effect, \verb|\setspecialsymbol| extends the
+basic "fonting" capability to arbitrary special
+typeset versions.
+
+{\re
+\verb{\schemecasesensitive}}
+\index{schemecasesensitive@\verb{\schemecasesensitive}}
+\index{case sensitivity}
+
+SLaTeX always typesets output that is of the same case
+as your input, regardless of the setting of the
+\verb|\schemecasesensitive| command. However, this command
+can be used to signal to SLaTeX that all case variations of
+an identifier are to be treated identically. E.g. typing
+\verb|\schemecasesensitive{false}| implies that while
+\verb|lambda| continues to be a keyword, so also are
+\verb|Lambda|, \verb|LAMBDA| and \verb|LaMbDa|.
+\verb|\schemecasesensitive{true}| reverts it back to
+the default mode where case is significant in
+determining the class of a token.
+
+Note that the status \verb|\schemecasesensitive| also
+affects the "special symbols" of the previous item.
+Thus, in the default case-_sensitive_ setting, only the
+case-significant symbol as mentioned in the call to
+\verb|\setspecialsymbol| will be replaced by the
+corresponding LaTeX expansion. In a case-_in_sensitive
+setting, all case variations of the special symbol will
+be replaced.
+
+{\re
+\verb{\abovecodeskip}
+\verb{\belowcodeskip}
+\verb{\leftcodeskip}
+\verb{\rightcodeskip}}
+\index{abovecodeskip@\verb{\abovecodeskip}}
+\index{belowcodeskip@\verb{\belowcodeskip}}
+\index{leftcodeskip@\verb{\leftcodeskip}}
+\index{rightcodeskip@\verb{\rightcodeskip}}
+\index{schemedisplay@\verb{schemedisplay}!adjusting display parameters}
+
+These are the parameters used by \verb{schemedisplay} for
+positioning the displayed code. The default values are
+
+\begin{verbatim}
+\abovecodeskip \medskipamount
+\belowcodeskip \medskipamount
+\leftcodeskip 0pt
+\rightcodeskip 0pt
+\end{verbatim}
+This produces a flushleft display. The defaults can be
+changed to get new display styles. E.g., the
+assignment
+
+\begin{verbatim}
+\leftcodeskip5em
+\end{verbatim}
+shifts the display from the left by a constant 5 ems.
+
+\index{schemedisplay@\verb{schemedisplay}!allowing page
+breaks in}
+\index{schemedisplay@\verb{schemedisplay}!disallowing
+page breaks in}
+
+In both the above cases, the \verb{schemedisplay}
+environment will be broken naturally across page
+boundaries at the right spot if the code is too long to
+fit a single page. In fact, automatic pagebreaks
+within the Scheme code are allowed if and only if
+\verb{\rightcodeskip} is 0pt (its default value). For
+all other values of \verb{\rightcodeskip}, each Scheme
+code block in a \verb{schemedisplay} is guaranteed to
+be on the same page. If you like your current left
+indentation, and you're not sure of what value to give
+\verb{\rightcodeskip}, but nevertheless don't want
+Scheme code broken across pages, you could set
+
+\begin{verbatim}
+\rightcodeskip=0.01pt %or
+\rightcodeskip=0pt plus 1fil
+\end{verbatim}
+
+The following explains why the above disable page
+breaks within the Scheme block. For example, suppose
+you'd set
+
+\begin{verbatim}
+\leftcodeskip=0pt plus 1fil
+\rightcodeskip=0pt plus 1fil
+\end{verbatim}
+This will get you a _centered_ display style. This is
+of course because the skip on each side of the code
+produces a spring~\cite{tex} that pushes the code to
+the center. But for this spring action to work nicely,
+the code must have been collected into an unbreakable
+box --- which is precisely what
+\verb{schemedisplay} does for each of its code blocks
+whenever it notices that the prevailing value of
+\verb{\rightcodeskip} is not the default zero.
+\footnote{0pt plus 1fil $\ne$ 0pt}
+
+It is this behind-the-scenes selective boxing that
+dictates whether a \verb{schemedisplay} block can or
+cannot be broken across a page boundary. And the
+value of \verb{\rightcodeskip} is used to govern this
+selection in a "reasonable" manner.
+
+{\re
+\verb{\keywordfont}
+\verb{\constantfont}
+\verb{\variablefont}}
+\index{keywordfont@\verb{\keywordfont}}
+\index{constantfont@\verb{\constantfont}}
+\index{variablefont@\verb{\variablefont}}
+\index{specifying SLaTeX's fonts}
+
+These decide the typefaces used for keywords, constants,
+and variables. The default definitions are:
+
+\begin{verbatim}
+\def\keywordfont#1{{\bf#1}}
+\def\constantfont#1{{\sf#1}}
+\def\variablefont#1{{\it#1\/}}
+\end{verbatim}
+
+This is close to the Little Lisper~\cite{ll} style.
+Redefine these control sequences for font changes. As
+an extreme case, defining all of them to
+\verb|{{\tt#1}}| typesets everything in monospace
+typewriter font, as, for instance, in SICP~\cite{sicp}.
+
+{\re
+\verb{\defschemedisplaytoken}
+\verb{\defschemetoken}
+\verb{\defschemeresulttoken}
+\verb{\defschemeinputtoken}
+\verb{\defschemeregiontoken}}
+\index{defschemedisplaytoken@\verb{\defschemedisplaytoken}}
+\index{defschemetoken@\verb{\defschemetoken}}
+\index{defschemeresulttoken@\verb{\defschemeresulttoken}}
+\index{defschemeboxtoken@\verb{\defschemeboxtoken}}
+\index{defschemeinputtoken@\verb{\defschemeinputtoken}}
+\index{defining SLaTeX control sequences}
+
+These define the tokens used by SLaTeX to trigger
+typesetting of in-text code, display code, box code,
+and Scheme files. The default tokens are, as already
+described, \verb{schemedisplay}, \verb|\scheme|,
+\verb|\schemeresult|, \verb{schemebox},
+\verb|\schemeinput| and \verb{schemeregion}
+respectively. If you want shorter or more mnemonic
+tokens, the \verb|\defscheme*token| control sequences
+prove useful. E.g., if you want \verb|\code| to be
+your new control sequence for in-text code, use
+\verb|\defschemetoken{code}|. All instances of
+\verb|\code+...+| after this definition produce
+in-text code, unless overridden by an
+\verb|\undefschemetoken| command.
+
+One can have at any time any number of tokens for the
+same activity. One consequence of this is that one can
+have nested \verb{schemeregion}s, provided one has
+different names for the nested call. Otherwise, the
+\verb|\end| of an inner region will prematurely
+terminate an outer region.
+
+{\re
+\verb{\undefschemedisplaytoken}
+\verb{\undefschemetoken}
+\verb{\undefschemeresulttoken}
+\verb{\undefschemeinputtoken}
+\verb{\undefschemeregiontoken}}
+\index{undefschemedisplaytoken@\verb{\undefschemedisplaytoken}}
+\index{undefschemetoken@\verb{\undefschemetoken}}
+\index{undefschemeresulttoken@\verb{\undefschemeresulttoken}}
+\index{undefschemeboxtoken@\verb{\undefschemeboxtoken}}
+\index{undefschemeinputtoken@\verb{\undefschemeinputtoken}}
+\index{undefschemeregiontoken@\verb{\undefschemeregiontoken}}
+\index{undefining SLaTeX control sequences}
+
+These _un_define the tokens used for triggering
+typesetting in-text code, display code, box code,
+Scheme files, and robust Scheme regions. Use these if
+you want to use these tokens for other purposes and do
+not want to unwittingly trip up the SLaTeX system.
+
+{\re
+\verb{\defschememathescape}
+\verb{\undefschememathescape}}
+\index{defschememathescape@\verb{\defschememathescape}}
+\index{undefschememathescape@\verb{\undefschememathescape}}
+\index{TeX mathmode in SLaTeX}
+\index{escape character for mathmode within Scheme}
+
+\verb|\defschememathescape{$}| defines the character
+\verb|$| as a mathematical escape character to be used
+within scheme code. (Any character other than
+\verb|}| and whitespace may be chosen instead of
+\verb|$|.) This allows one to use LaTeX-like
+mathematical subformulas within Scheme code, e.g.,
+
+\begin{verbatim}
+\defschememathescape{$}
+
+\begin{schemedisplay}
+(define $\equiv$
+ (lambda (a$_1$ a$_2$)
+ ($\land$ ($\sqsubseteq$ a$_1$ a$_2$)
+ ($\sqsupseteq$ a$_1$ a$_2$))))
+\end{schemedisplay}
+\end{verbatim}
+produces
+
+\enableslatex
+\defschememathescape{$}
+
+\begin{schemedisplay}
+(define $\equiv$
+ (lambda (a$_1$ a$_2$)
+ ($\land$ ($\sqsubseteq$ a$_1$ a$_2$)
+ ($\sqsupseteq$ a$_1$ a$_2$))))
+\end{schemedisplay}
+\undefschememathescape{$}
+\slatexdisable{enableslatex}
+\verb|\undefschememathescape{$}| disables the
+math-escape nature, if any, of \verb|$|.
+
+{\re
+\verb{\slatexdisable}}
+\index{slatexdisable@\verb{\slatexdisable}}
+\index{disabling SLaTeX}
+
+The tokens for typesetting code, as also the token
+\verb|\input| (which is sensitive to SLaTeX, since
+the latter uses it to recursively process files within
+files), can only be used as calls. If they occur in
+the bodies of macro definitions, or their names are
+used for defining other control sequences, SLaTeX will
+not be able to process them. Sometimes, one wants to
+use these tokens, say \verb|\input|, without having
+SLaTeX try to process the inputted file. Or the name
+\verb|\scheme| may be used in a verbatim environment,
+and we don't want such an occurrence to trigger the
+codesetting half of SLaTeX to look for code.
+
+Avoiding such uses altogether can be unduly
+restrictive.
+\footnote{Especially when one is writing a "How to ..."
+manual like this where one both uses _and_ mentions the
+control sequences!} One way out is to judiciously use
+the \verb|\undefscheme*token| commands to temporarily
+remove the SLaTeX-specificity of these names. Even
+this can be painful. SLaTeX therefore provides the
+commands \verb|\slatexdisable|. This takes one
+argument word and makes the corresponding control
+sequence out of it. Further, from this point in the
+text, SLaTeX is disabled _until_ the manufactured
+control sequence shows up. This mechanism makes it
+possible to restrict SLaTeX to only appropriate
+portions of the text. Note that the token
+\verb|\slatexdisable| itself can appear in the text
+succeeding its call. The only token that can restore
+SLaTeX-sensitivity is the one created during the call
+to \verb|\slatexdisable|.
+
+A typical example of the use of \verb|\slatexdisable|
+is when you use the names \verb|\scheme| and
+\verb|\begin{schemedisplay}| in a \verb{verbatim}
+environment. E.g.,
+
+{\medskip
+\obeylines\parindent0pt
+\verb|\slatexdisable{slatexenable}|
+\verb|\begin{verbatim}|
+\verb|slatex provides the command \scheme and the pair|
+\verb|\begin{schemedisplay} and \end{schemedisplay} to typeset|
+\verb|in-text and displayed Scheme code respectively.|
+\verb|\end{verbatim}|
+\verb|\slatexenable|
+\medskip}
+
+produces the required
+
+\begin{verbatim}
+slatex provides the command \scheme and the pair
+\begin{schemedisplay} and \end{schemedisplay} to typeset
+in-text and display Scheme code respectively.
+\end{verbatim}
+
+{\re
+\verb{\slatexignorecurrentfile}}
+\index{slatexignorecurrentfile@\verb{\slatexignorecurrentfile}}
+\index{disabling SLaTeX}
+
+This is a SLaTeX pragma included to improve efficiency.
+If you're sure that the remaining portion of a certain
+LaTeX (or TeX) file (including the files that would be
+\verb|\input|ed by it) don't contain any SLaTeX
+commands, then you may place this control sequence in
+it at this point to signal SLaTeX that no preprocessing
+is necessary for the rest of the file.
+
+{\re
+\verb{\defslatexenvstyle}}
+\index{defslatexenvstyle@\verb{\defslatexenvstyle}}
+\index{plain TeX}
+\index{LaTeX}
+\index{environments}
+
+As section~\ref{quick} showed, the differences in SLaTeX
+usage between plain TeX and LaTeX is simply a matter of
+the difference in the "environment" styles of the two
+formats. It is easy get the behavior of the one
+format with the other.
+
+\begin{enumerate}
+\o If you wish to use the plain-TeX style in LaTeX,
+type
+\begin{verbatim}
+\defslatexenvstyle{tex}
+\end{verbatim}
+before first such use.
+
+\o Similarly, if you wish to use the LaTeX
+\verb{\begin}/\verb{\end} style in plain TeX, use
+\begin{verbatim}
+\defslatexenvstyle{latex}
+\end{verbatim}
+_provided you have already defined \verb{\begin} and
+\verb{\end} appropriately!_
+
+Before doing this, you should keep in mind that
+TeX already has an
+\verb{\end} command --- which is used by TeX's
+\verb{\bye} --- that ends the document. This function
+should be saved under a different name, before
+\verb{\end} can be redefined as an environment closer.
+The following is one way to accomplish this:
+\begin{verbatim}
+\let\plaintexend\end
+\outer\def\bye{\par\vfill\supereject\plaintexend}
+\def\begin#1{\csname#1\endcsname}
+\def\end#1{\csname end#1\endcsname}
+\end{verbatim}
+\end{enumerate}
+
+In either case, you can revert to the default style with
+\verb|\defslatexenvstyle{latex}| and
+\verb|\defslatexenvstyle{tex}| respectively.
+
+{\re
+\verb{\slatexseparateincludes}}
+\index{slatexseparateincludes@\verb{slatexseparateincludes}}
+\index{reusing SLaTeX's temporary files}
+
+By default, the temporary files of SLaTeX use the name
+of the topmost TeX file, i.e., the name stored under
+\verb{\jobname}. In large LaTeX documents using
+\verb{\include}, this may be unduly restrictive.
+
+To recapitulate, the \verb{slatex} command creates
+temporary files to store typeset code and then passes
+the baton on to TeX or LaTeX. If no significant change
+has been made to the Scheme code (either in content or
+in relative positioning) in the document, then
+successive calls to (La)TeX could be made directly
+using the old temporary files. This could be a time-saver,
+since it avoids calling up the Scheme typesetter.
+
+However, in a large LaTeX document with
+\verb{\include}s, these successive calls to LaTeX often
+entail juggling the \verb{\include}s that are chosen.
+In this case, even though the relative position of the
+Scheme code is preserved within each \verb{include}d
+file, the sequence perceived by the main file changes.
+This spoils the invariance we needed if we'd wanted to
+avoid calling SLaTeX unnecessarily.
+
+\index{reusing SLaTeX's temporary files!exploiting
+LaTeX's \verb{\include}}
+
+To solve this, the SLaTeX command sequence
+\verb{\slatexseparateincludes} --- which must be called
+before the first occurrence of Scheme code in your
+document ---
+guarantees that each
+\verb{\include}d file will generate its own pool of
+temp files. Thus, if the SLaTeX
+files are created once for each \verb{\include}, they
+will be correctly loaded no matter what sequence of
+\verb{\include}s is taken.
+
+{\re
+\verb{\schemecodehook}}
+\index{schemecodehook@\verb{\schemecodehook}}
+\index{hook for \verb{schemedisplay} and
+\verb{schemebox}}
+
+The user can define \verb{\schemecodehook} to be
+anything. The hook will be evaluated inside each
+subsequent call to \verb{schemedisplay} and
+\verb{schemebox}. E.g.,
+
+\begin{verbatim}
+\let\schemecodehook\tiny
+\end{verbatim}
+converts your Scheme displays and boxes into {\tiny
+small print}.
+
+The default value of the hook is \verb{\relax}, a
+no-op.
+
+\section{Setting up a file that resets SLaTeX's
+defaults}
+\label{preamble}
+\index{writing personal preamble}
+\index{SLaTeX database!modifying}
+
+A sample style modification file for SLaTeX would
+include redefinition of the names of the codesetting
+control sequences, adjustment of the display
+parameters, modification of the font assignments for
+keywords/constants/variables/special symbols, and
+addition of new keywords/constants/variables/special
+symbols to SLaTeX's database.
+
+Let's assume you want
+
+\begin{itemize}
+\o a centered display style with no vertical skips;
+
+\o the names \verb|\code|, \verb{schemefrag}, \verb{scmbox},
+\verb|\sinput| instead of \verb|\scheme|,
+\verb{schemefrag}, \verb{schemebox} and
+\verb|\schemeinput|;
+
+\o tokens to disregard case;
+
+\o the keywords to come out it \verb{typewriter}, the
+constants in roman, and the variables in {\sl slant};
+
+\o "\verb{und}" and "\verb{oder}" as keywords,
+"\verb{true}" and "\verb{false}" as constants,
+"\verb{define}" as a variable (overriding default as
+keyword!), "\verb{F}" as a constant (\verb{f} will also
+be a constant, due to case-insensitivity!);
+
+\o "\verb{top}" and "\verb{bottom}" to print as
+$\top$ and $\bot$ respectively.
+\end{itemize}
+
+This could be set up as
+
+\begin{verbatim}
+\abovecodeskip 0pt
+\belowcodeskip 0pt
+\leftcodeskip 0pt plus 1fil
+\rightcodeskip 0pt plus 1fil
+
+\undefschemetoken{scheme}
+\undefschemeboxtoken{schemebox}
+\undefschemedisplaytoken{schemedisplay}
+\undefschemeinputtoken{schemeinput}
+
+\defschemetoken{code}
+\defschemeboxtoken{scmbox}
+\defschemedisplaytoken{schemegrag}
+\defschemeinputtoken{sinput}
+
+\schemecasesensitive{false}
+
+\def\keywordfont#1{{\tt#1}}
+\def\constantfont#1{{\rm#1}}
+\def\variablefont#1{{\sl#1\/}}
+
+\setkeyword{und oder}
+\setconstant{true false}
+\setvariable{define}
+\setconstant{F}
+
+\setspecialsymbol{top}{$\top$}
+\setspecialsymbol{bottom}{$\bottom$}
+\end{verbatim}
+
+This file can then be \verb|\input| in the preamble of
+your LaTeX document.
+
+\section{How to obtain and install SLaTeX}
+\label{ftp}
+\index{obtaining and installing SLaTeX}
+
+\enableslatex
+\leftcodeskip=0pt plus 1fil
+\rightcodeskip=0pt plus 1fil
+\slatexdisable{enableslatex}
+
+SLaTeX is available via anonymous ftp from
+\verb{cs.rice.edu} (or \verb{titan.cs.rice.edu}).
+Login as
+\verb{anonymous}, give your userid as password, change
+to the directory \verb{public/dorai}, convert to
+\verb{bin} mode, and get the file
+\verb{slatex}_NN_\verb{.tar.gz}, where _NN_ is some
+number. Un\verb{gzip}ping and un\verb{tar}ring
+produces a directory \verb{slatex}, containing the
+SLaTeX files. (The file \verb{manifest} lists the
+files in the distribution --- make sure that nothing is
+missing.)
+
+To install SLaTeX on your system:
+
+\begin{enumerate}
+\o First change directory (\verb{cd}) to \verb{slatex}, the
+directory housing the SLaTeX files.
+\footnote{Some of the SLaTeX files use DOS-style CR-LF
+newlines. You may want to use an appropriate newline
+modifier to the SLaTeX files to make the files comply
+with your operating system's newline format.}
+
+\o Edit the file \verb{config.dat} as suggested by the
+comments in the file itself.
+
+\o Invoke your Scheme or Common Lisp interpreter.
+Load the file \verb{config.scm}, i.e., type
+
+\enableslatex
+\begin{schemedisplay}
+(load "config.scm")
+\end{schemedisplay}
+\slatexdisable{enableslatex}
+at the Scheme (or Common Lisp) prompt. This will
+configure SLaTeX for your Scheme dialect and operating
+system, creating a Scheme file called
+\verb{slatex.scm}. (If you informed \verb{config.dat}
+that your Scheme dialect is Chez, the file
+\verb{slatex.scm} is a compiled version rather than
+Scheme source.) The configuration process also creates
+a batch file \verb{slatex.bat} (on DOS) or a shell
+script \verb{slatex} (on Unix), for convenient
+invocation of SLaTeX from your operating system command
+line. A Scheme/Common Lisp file \verb{callsla.scm} is
+also created --- this lets you call SLaTeX from the
+Scheme/Common Lisp prompt.
+
+\o Exit Scheme/Common Lisp.
+\end{enumerate}
+
+To set up paths and modify shell script/batch file:
+
+\begin{enumerate}
+\o Copy (or move, or link) \verb{slatex.scm} into a
+suitable place, e.g., your \verb{bin} or \verb{lib}
+directory, or the system \verb{bin} or \verb{lib}.
+
+\o Copy (or move, or link) \verb{slatex.sty} into a
+suitable place, i.e., somewhere in your \verb{TEXINPUTS}
+path. For installing on a multiuser system, place in
+the directory containing the LaTeX files (on mine this
+is \verb{/usr/local/lib/tex/macros}).
+
+
+\o \enableslatex
+Copy (or move, or link) the shell script
+\verb{slatex} or the batch file \verb{slatex.bat} to a
+suitable place in your \verb{PATH}, e.g., your {bin} or
+the system {bin} directory. Note that
+\verb{slatex}(\verb{.bat}) sets
+\scheme{SLaTeX.*texinputs*}. If you're making the same
+shell script (or batch file) available to multiple
+users, you should change the line
+\begin{schemedisplay}
+(set! SLaTeX.*texinputs* "...")
+\end{schemedisplay}
+to
+\begin{schemedisplay}
+(set! SLaTeX.*texinputs* (getenv "TEXINPUTS"))
+\end{schemedisplay}
+or some other dialect-dependent way of obtaining the
+\verb{TEXINPUTS} environment variable.
+\slatexdisable{enableslatex}
+
+\o Run \verb{slatex} on \verb{slatex-d.tex} (this
+file!) for documentation. (This also serves as a check
+that SLaTeX does indeed work on your machine.) Refer
+to \verb{slatex-d.dvi} when befuddled.
+\end{enumerate}
+
+If your dialect did not allow a nice enough shell
+script or batch file, the following provides an
+alternate route to unlocking SLaTeX.
+
+\subsection{Other ways of invoking SLaTeX}
+
+The configuration process creates shell script/batch
+file \verb{slatex}(\verb{.bat}) for a standard invoking
+mechanism for SLaTeX. The shell script/batch file is
+created to exploit the way your Scheme is called, e.g.,
+matters like whether it accepts \verb{echo}'d
+s-expressions (e.g., Chez) , whether it loads command
+line files (e.g., SCM) , and whether it always checks
+for an "init" file (e.g., MIT C Scheme).
+
+\begin{enumerate}
+\o If your Scheme doesn't fall into either of these
+categories, you may have to write your own
+shell script/batch file or devise some other mechanism.
+
+\o The shell script/batch file invokes
+Scheme/Common Lisp. If,
+however, you are already in Scheme/Common Lisp and
+spend most of the time continuously at the
+Scheme/Common Lisp prompt rather than the operating
+system prompt, you may avoid some of the delays
+inherent in the shell script/batch file.
+\end{enumerate}
+
+\enableslatex
+The file \verb{callsla.scm}, which contains just one
+small procedure named \scheme{call-slatex}, and which
+is created by the configuration process, provides a
+simple calling mechanism from Scheme/Common Lisp, as
+opposed to the operating system command line. You may
+use it as an alternative to the
+\verb{slatex}(\verb{.bat}) shell script/batch file.
+The usage is as follows: load
+\verb{callsla.scm} into Scheme/Common Lisp
+
+\begin{schemedisplay}
+(load "callsla.scm")
+\end{schemedisplay}
+and type
+
+\setspecialsymbol{<tex-file>}{\va{$\langle$tex-file$\rangle$}}
+\begin{schemedisplay}
+(call-slatex <tex-file>)
+\end{schemedisplay}
+when you need to call SLaTeX on the (La)TeX file
+\scheme{<tex-file>}. This invokes the SLaTeX preprocessor on
+\scheme{<tex-file>}. If your Scheme has a
+\scheme{system} procedure
+that can call the operating system command line,
+\scheme{call-slatex} will also send your file to TeX or
+LaTeX. If your Scheme does not have such a procedure,
+\scheme{call-slatex} will simply prod you to call TeX
+or LaTeX
+yourself.
+\slatexdisable{enableslatex}
+
+The outline of the shell script/batch file or
+\verb{callsla.scm} or of any strategy you devise for
+using SLaTeX should include the following actions:
+
+\begin{enumerate}
+\o Load the file \verb{slatex.scm} (created by the
+configuration process) into Scheme/Common Lisp.
+
+\o \enableslatex
+Set the variable \scheme{SLaTeX.*texinputs*} to the
+path \verb{TEXINPUTS} or \verb{TEXINPUT} used by
+TeX
+\footnote{There is some variation on the name of
+this environment variable. Unix TeX's prefer
+\verb{TEXINPUTS} with an \verb{S}, while DOS (e.g.,
+Eberhard Mattes's emTeX) favors \verb{TEXINPUT} without
+the \verb{S}.}
+to look for
+\slatexdisable{enableslatex}
+\verb|\input|
+files.
+
+
+\o \enableslatex
+Call the procedure
+\scheme{SLaTeX.process-main-tex-file} on the \verb{.tex}
+file to be processed.
+\slatexdisable{enableslatex}
+
+\o Call either \verb{latex} or \verb{tex} on the \verb{.tex} file.
+\end{enumerate}
+
+
+\enableslatex
+You may devise your own way of calling
+\scheme{SLaTeX.process-main-tex-file}, provided your
+method makes sure that \verb{slatex.scm} has been
+loaded, \scheme{SLaTeX.*texinputs*} set appropriately
+_before_ the call and \verb{latex}/\verb{tex} is called
+_after_ the call.
+
+Note that if you prefer to stay in Scheme/Common Lisp
+most of the time, it is a good idea to pre-load the
+procedure \scheme{call-slatex}, perhaps through an
+"init" file. \scheme{call-slatex} is just a
+"one-liner" "call-by-need" hook to SLaTeX and does not
+take up much resources. (Global name clashes between
+your own code and SLaTeX code won't occur unless you
+use variable names starting with "\scheme{SLaTeX.}") If
+you made no calls to \scheme{call-slatex}, the bigger
+file \verb{slatex.scm} is not loaded at all. If you
+make several calls to \scheme{call-slatex},
+\verb{slatex.scm} is loaded only once, at the time of
+the first call.
+\slatexdisable{enableslatex}
+
+\subsection{Dialects SLaTeX runs on}
+\index{dialects SLaTeX runs on}
+
+\enableslatex
+SLaTeX is implemented in R4RS-compliant Scheme (macros
+are not needed). The code uses the non-standard
+procedures \scheme{delete-file},
+\scheme{file-exists?} and \scheme{force-output}, but
+a Scheme without these procedures can also run SLaTeX
+(the configuration defines the corresponding variables
+to be dummy procedures, since they are not crucial).
+The distribution comes with code to allow SLaTeX to run
+also on Common Lisp. The files \verb{readme} and
+\verb{install} contain all the information necessary to
+configure SLaTeX for your system.
+\slatexdisable{enableslatex}
+
+SLaTeX has been tested successfully in the following
+dialects:
+
+\begin{itemize}
+\o _On Unix:_
+Chez Scheme (R. Kent Dybvig), Ibuki Common
+Lisp (1987), MIT C Scheme, Elk (Oliver Laumann),
+Scheme-to-C (Joel Bartlett), Scm (Aubrey Jaffer) and
+UMB Scheme (William Campbell);
+
+\o _On MS-DOS:_
+MIT C Scheme, Scm (Aubrey Jaffer), Austin Kyoto Common
+Lisp (William Schelter's enhanced version of Taiichi
+Yuasa and Masami Hagiya's KCL) and CLisp (Bruno Haible
+and Michael Stoll).
+\iffalse PCScheme/Geneva (Larry Bartholdi and
+Marc Vuilleumier) \fi
+\end{itemize}
+
+If your Scheme is not mentioned here but _is_
+R4RS-compliant, please send a note to the author at
+\verb{dorai@cs.rice.edu} describing your Scheme's
+procedures for deleting files, testing file existence,
+and forcing output, if any, and the configuration file
+will be enhanced to accommodate the new dialect.
+
+Bug reports are most welcome --- send to
+\verb{dorai@cs.rice.edu}.
+\index{bug reports}
+
+\begin{thebibliography}{9}
+\bibitem{sicp} H. Abelson and G.J. Sussman with J.
+Sussman. Structure and Interpretation of Computer
+Programs. MIT Press, 1985.
+
+\bibitem{r4rs} W. Clinger and J. Rees, eds.
+Revised$^4$ Report on the Algorithmic Language Scheme.
+1991.
+
+\bibitem{ll} D.P. Friedman and M. Felleisen. The
+Little Lisper. Science Research Associates, 1989.
+
+\bibitem{tex} D.E. Knuth. The TeXbook.
+Addison-Wesley, 1984.
+
+\bibitem{latex} L. Lamport. LaTeX User's Guide and
+Reference Manual. Addison-Wesley, 1986.
+
+\bibitem{schemeweb} J. Ramsdell. SchemeWeb. Scheme
+Repository, nexus.yorku.ca, maintained by O. Yigit.
+
+\bibitem{lisp2tex} C. Queinnec. LiSP2TeX. Scheme
+Repository.
+
+\bibitem{cltl2} G.L. Steele Jr. Common Lisp: The
+Language, 2nd ed. Digital Press, 1990.
+\end{thebibliography}
+
+%input slatex-d.ind, the index, if available.
+%slatex-d.ind is generated by running
+% makeind(e)x slatex-d
+%after running latex on slatex-d. The next call
+% latex slatex-d
+%will include slatex-d.ind
+
+\inputifpossible{slatex-d.ind}
+
+\end{document}
+
+\index{schemedisplay@\verb{schemedisplay}!with plain TeX}
+\index{schemebox@\verb{schemebox}!with plain TeX}
+\index{schemeregion@\verb{schemeregion}!with plain TeX}
Trap