~ 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