pax_global_header00006660000000000000000000000064132113054430014506gustar00rootroot0000000000000052 comment=5e4f0ca67bac448e19a24c09f12fc16d24cd6b6d stex-1.2.1+git20171204.g5e4f0ca/000077500000000000000000000000001321130544300153675ustar00rootroot00000000000000stex-1.2.1+git20171204.g5e4f0ca/.gitignore000066400000000000000000000000171321130544300173550ustar00rootroot00000000000000*~ .*.sw? .sw? stex-1.2.1+git20171204.g5e4f0ca/Makefile000066400000000000000000000046461321130544300170410ustar00rootroot00000000000000VERSION=1.2 # override PREFIX, Scheme, and LIB as necessary PREFIX=/usr # scheme executable Scheme=$(PREFIX)/bin/scheme # target location for stex LIB=$(PREFIX)/lib/stex$(VERSION) m := $(shell echo '(machine-type)' | $(Scheme) -q) Install=./sbin/install exec = $m/scheme-prep $m/html-prep $m/fixbibtex all: $(exec) $m/scheme-prep: src/dsm.ss src/preplib.ss src/script.ss src/scheme-prep.ss if [ ! -d $m ] ; then mkdir $m ; fi sed -e 's;^#! /usr/bin/scheme --program;#! $(Scheme) --program;' src/scheme-prep.ss > $m/scheme-prep.ss echo '(reset-handler abort) (library-directories (quote "src::$m")) (compile-imported-libraries #t) (generate-wpo-files #t) (compile-program "$m/scheme-prep.ss") (compile-whole-program "$m/scheme-prep.wpo" "$m/scheme-prep")' | $(Scheme) -q chmod 755 $m/scheme-prep $m/html-prep: src/dsm.ss src/preplib.ss src/script.ss src/html-prep.ss if [ ! -d $m ] ; then mkdir $m ; fi sed -e 's;^#! /usr/bin/scheme --program;#! $(Scheme) --program;' src/html-prep.ss > $m/html-prep.ss echo '(reset-handler abort) (library-directories (quote "src::$m")) (compile-imported-libraries #t) (generate-wpo-files #t) (compile-program "$m/html-prep.ss") (compile-whole-program "$m/html-prep.wpo" "$m/html-prep")' | $(Scheme) -q chmod 755 $m/html-prep $m/fixbibtex: src/fixbibtex.ss -if [ ! -d $m ] ; then mkdir $m ; fi sed -e 's;^#! /usr/bin/scheme --program;#! $(Scheme) --program;' src/fixbibtex.ss > $m/fixbibtex.ss echo '(reset-handler abort) (library-directories (quote "src::$m")) (compile-imported-libraries #t) (generate-wpo-files #t) (compile-program "$m/fixbibtex.ss") (compile-whole-program "$m/fixbibtex.wpo" "$m/fixbibtex")' | $(Scheme) -q chmod 755 $m/fixbibtex install: $(exec) $(Install) -o root -g root -m 755 -d $(LIB) $(Install) -o root -g root -m 755 -d $(LIB)/inputs $(Install) -o root -g root -m 644 inputs/* $(LIB)/inputs $(Install) -o root -g root -m 755 -d $(LIB)/gifs $(Install) -o root -g root -m 644 gifs/* $(LIB)/gifs $(Install) -o root -g root -m 755 -d $(LIB)/math $(Install) -o root -g root -m 644 math/* $(LIB)/math $(Install) -o root -g root -m 755 -d $(LIB)/$m $(Install) -o root -g root -m 644 $(exec) $(LIB)/$m (umask 022; sed -e 's;^LIB=.*;LIB=$(LIB);' Mf-stex > $(LIB)/Mf-stex) (umask 022; sed -e 's;include ~/stex/Mf-stex;include $(LIB)/Mf-stex;' Makefile.template > $(LIB)/Makefile.template) uninstall: /bin/rm -rf $(LIB) clean: /bin/rm -f Make.out distclean: clean /bin/rm -rf $m stex-1.2.1+git20171204.g5e4f0ca/Makefile.template000066400000000000000000000011131321130544300206350ustar00rootroot00000000000000VERSION=1.2 Scheme=scheme STEXLIB=/usr/lib/stex$(VERSION) # define default document pathname here # override on command line with 'make x=newdoc' x = ??? # define latex processor: latex or pdflatex latex = pdflatex # define stex macro files here stexmacrofiles = # list bibliography files here bib = # define index if an index is to be generated # index=yes include $(STEXLIB)/Mf-stex # define or override suffixes here # define any additional targets here # define any dependencies here # define cleanup targets here: $(x).clean: $(x).reallyclean: $(x).reallyreallyclean: stex-1.2.1+git20171204.g5e4f0ca/Mf-stex000066400000000000000000000070221321130544300166360ustar00rootroot00000000000000# Mf-stex expects to be included in a make file that defines: # Scheme the path of the Chez Scheme executable # STEXLIB the path to the stex library (the library containing this file) m := $(shell echo '(machine-type)' | $(Scheme) -q) TEXINPUTS:=.:$(STEXLIB)/inputs: export TEXINPUTS ifeq ($(wildcard $(STEXLIB)/$m/scheme-prep),) Sprep = $(Scheme) --libdirs "$(STEXLIB)/src" --program $(STEXLIB)/src/scheme-prep.ss else Sprep = $(STEXLIB)/$m/scheme-prep endif ifeq ($(wildcard $(STEXLIB)/$m/html-prep),) Hprep = $(Scheme) --libdirs "$(STEXLIB)/src" --program $(STEXLIB)/src/html-prep.ss else Hprep = $(STEXLIB)/$m/html-prep endif ifeq ($(wildcard $(STEXLIB)/$m/fixbibtex),) fixbibtex = $(Scheme) --libdirs "$(STEXLIB)/src" --program $(STEXLIB)/src/fixbibtex.ss else fixbibtex = $(STEXLIB)/$m/fixbibtex endif mathdir=math/$(x) mathfiles=$(mathdir)/mathfiles # solaris /bin/sh doesn't support '!' in test SHELL=bash stexsrc = $(x).stex texsrc = $(x).tex spellobj = $(x).spell .SUFFIXES: .SUFFIXES: .stex .tex .spell .fig .ps .png .pdf .eps .stex.tex: $(Sprep) $(stexmacrofiles) $* chmod -w $*.tex .tex.spell: latexspell $*.tex .fig.ps: fig2dev -Leps $*.fig $*.ps .fig.png: fig2dev -Lppm $*.fig | pnmcrop | pnmtopng -transparent white > $*.png chmod go=r $*.png .ps.png: echo | gs -q -dNOPAUSE -dSAFER -sDEVICE=ppmraw -sOutputFile=- -r90x90 $*.ps | pnmcrop | pnmtopng -transparent white > $*.png # need to generate eps first to compute bounding box # need --gs on my machine at home or it fails to find bounding box .ps.eps: ps2epsi $*.ps $*.eps .eps.pdf: epstopdf --gs $*.eps .fig.pdf: fig2dev -Leps $*.fig | epstopdf --filter > $*.pdf ifeq "$(latex)" "latex" doitformebaby: $(x).ps $(x).html $(x).ps: $(x).thirdrun dvips -o $(x).ps $(x).dvi $(x).pdf: $(x).ps ps2pdf $*.ps $*.pdf chmod 644 $*.pdf else doitformebaby: $(x).pdf $(x).html $(x).pdf: $(x).thirdrun chmod 644 $(x).pdf endif $(x).dvi: $(x).thirdrun $(x).thirdrun: $(x).secondrun ifdef index makeindex $(x) endif $(latex) $(x) touch $(x).thirdrun $(x).secondrun: $(x).firstrun $(bib) ifneq ($(strip $(bib)),) bibtex $(x) $(fixbibtex) $(x).bbl endif ifdef index makeindex $(x) endif $(latex) $(x) touch $(x).secondrun $(x).firstrun: $(texsrc) touch $(x).htoc $(latex) $(x) touch $(x).firstrun all.tex: $(texsrc) $(x).html: $(x).mathrun $(x).mathrun: gifs $(mathfiles) @(cd $(mathdir); make) touch $(x).mathrun gifs: (cd $(STEXLIB); tar -cf - gifs) | tar -xpf - math: (cd $(STEXLIB); tar -cf - math) | tar -xpf - $(mathfiles): $(x).hthirdrun $(figps) echo -n gifs= > $(mathfiles) (cd $(mathdir); echo *.tex | sed -e "s/\.tex/.gif/g") >> $(mathfiles) $(x).hthirdrun: $(x).hsecondrun $(Hprep) --mathdir $(mathdir) $(x) chmod 444 *.html touch $(x).hthirdrun $(x).hsecondrun: $(x).hfirstrun $(Hprep) --mathdir $(mathdir) $(x) chmod 444 *.html touch $(x).hsecondrun $(x).hfirstrun: math $(x).thirdrun (if [ ! -e $(mathdir) ] ; then mkdir -p -m u=rwx,g=srx,o=rx $(mathdir); ln -s ../Makefile ../mathmacros $(mathdir); fi) $(Hprep) --mathdir $(mathdir) $(x) touch $(x).hfirstrun spell: $(spellobj) $(x).spell: $(x).bbl $(x).tex latexspell $(x).bbl latexspell $(x).tex clean: $(x).clean -/bin/rm -f *.log *.dvi *.aux *.out *.toc *.tmp *.idx *.ilg *.ind *.blg *.bbl *.rfm *.sfm *.firstrun *.secondrun *.thirdrun -/bin/rm -f *.haux *.htoc *.hidx *.hfirstrun *.hsecondrun *.hthirdrun *.mathrun -/bin/rm -f *.tex reallyclean: clean $(x).reallyclean -/bin/rm -f *.html *.ps *.pdf *.png reallyreallyclean: reallyclean $(x).reallyreallyclean -/bin/rm -rf $(mathdir) stex-1.2.1+git20171204.g5e4f0ca/ReadMe000066400000000000000000000035421321130544300164530ustar00rootroot00000000000000stex: stex => latex and latex => html converters and associated tools Copyright (c) 1998-2016 R. Kent Dybvig and Oscar Waddell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- This directory contains the following files and subdirectories as of April 2016: doc a short stex overview gifs/ support for building 'ghost' right arrows inputs/ sample class files, style files, etc. Makefile for compiling stex itself Makefile.template template make file for stex-based docs Mf-stex common (included) makefile for stex-based docs math/ base math subdirectory for stex-based docs ReadMe this file sbin/ helper scripts src/ stex sources See doc/stex.html for a brief overview of stex and how to use it. stex-1.2.1+git20171204.g5e4f0ca/doc/000077500000000000000000000000001321130544300161345ustar00rootroot00000000000000stex-1.2.1+git20171204.g5e4f0ca/doc/Makefile000066400000000000000000000010371321130544300175750ustar00rootroot00000000000000# define default document pathname here # override on command line with 'make x=newdoc' x = stex # define latex processor: latex or pdflatex latex = pdflatex # define stex macro files here stexmacrofiles = # list bibliography files here bib = # define index if an index is to be generated # index=yes include ~/stex/Mf-stex # define or override suffixes here # define any additional targets here # define any dependencies here # define cleanup targets here: $(x).clean: -rm -f $x.rawsst $(x).reallyclean: $(x).reallyreallyclean: stex-1.2.1+git20171204.g5e4f0ca/doc/stex.css000066400000000000000000000022651321130544300176360ustar00rootroot00000000000000BODY {background-color: #FFFFFF} a:link, a:active, a:visited { color:#6d380b; text-decoration:underline } a:hover { color:white; text-decoration:underline; background:#6d380b } a.plain:link, a.plain:active, a.plain:visited { color:#6d380b; text-decoration:none } a.plain:hover { color:white; text-decoration:none; background:#6d380b } a.toc:link, a.toc:active, a.toc:visited {font-family: sans-serif; color:#6d380b; text-decoration:none} a.toc:hover {font-family: sans-serif; color:white; text-decoration:none; background:#6d380b} a.image:link, a.image:active, a.image:visited, a.image:hover { color: #6d380b; background: #FFFFFF; } ul.tocchapter { list-style: none; } ul.tocsection { list-style: circle; color: #923a3a } hr.copyright { width: 50% } input.default { background: #ffffff; color: #000000; vertical-align: middle} h1, h2, h3, h4 {font-family: sans-serif; color: #6d380b} h1 {font-size: 2em} h2 {margin-top: 30px; font-size: 1.5em} h3 {margin-top: 30px; font-size: 1.17em} h1, h2, h3, h4 {font-weight: bold} .title { font-family: sans-serif; font-weight: bold; font-size: 2.5em; color: #6d380b; white-space: nowrap} .formdef { color: #6d380b } table.indent {margin-left: 20px} stex-1.2.1+git20171204.g5e4f0ca/doc/stex.html000066400000000000000000000576771321130544300200330ustar00rootroot00000000000000 Introduction to stex

Introduction to stex

R. Kent Dybvig and Oscar Waddell

April 2016

1. Overview
2. Installation
3. Usage notes
4. Basic stex commands
4.1. Inline code
4.2. Code displays
4.3. Variables
4.4. Raw text in code
4.5. Generated output
4.6. Verbatim Scheme displays
5. Scheme transcripts
5.1. Automatic transcript generation
5.2. Loading initialization code
6. html-prep support for the tabular environment

1. Overview

The stex package consists of two main programs and some supporting items, such as make files, make-file templates, class files, and style files. The two main programs are scheme-prep and html-prep. scheme-prep performs a conversion from "stex"-formatted files into latex-formatted files, while html-prep converts (some) latex-formatted files into html-formatted files.

An stex file is really just a latex file extended with a handful of commands for including Scheme code (or pretty much any other kind of code, as long as you don't plan to use the Scheme-specific transcript support) in a document, plus a couple of additional features rather arbitrarily thrown in.

The subset of latex-formatted files html-prep is capable of handling is rather small but has nevertheless been useful for our purposes, which include producing html versions of a couple of books (The Scheme Programming Language, Editions 2-4 and the Chez Scheme User's Guides for Versions 6-9), the scheme.com web site, class websites, class assignments, and various other documents.

2. Installation

A prerequisite to building and using stex is to have Chez Scheme or Petite Chez Scheme installed on your system. You'll also need pdflatex, dvips, ghostscript, and netbpm. We've run stex under Linux and OS X but have not tried to run it under Windows.

The simplest way to install stex for your personal use is to clone the stex directory into your home directory, cd into the stex directory, and run make:

make BIN=bindir

where bindir is the directory where make will find the scheme or petite executables.

This will create a subdirectory, named for the installed Chez Scheme machine type, containing binary versions of the programs.

You can also use "make install" to make stex available for other users.

sudo make install BIN=bindir LIB=libdir

where bindir is as described above, and libdir is the directory where the stex library directory should be installed.

3. Usage notes

The simplest way to get started with stex is to get this document to build (in the doc directory) and create your own document by cloning this document's source file (stex.stex) and make file (Makefile). If you've installed stex in your home directory, you should be able to build this document by running "make" without arguments in the doc directory. If you've installed stex elsewhere, you'll first have to modify the include for Mf-stex to reflect its installed location.

Makefile is where you declare your stex sources and various other things, like bibtex and graphics files. If you don't have anything much more complicated than this document, you might just need to change the line that declares the main stex entry point, i.e., the line that reads x = stex, to reflect the name of your document.

The make is orchestrated by Mf-stex, which knows how to run scheme-prep, html-prep, pdflatex (multiple times), and various other commands to produce both pdf and html versions of the stex document.

You can also consult the more elaborate stex source and make files for the Chez Scheme User's Guide in the csug directory of a Chez Scheme release.

4. Basic stex commands

4.1. Inline code

An stex document includes inline Scheme (or other) code via the \scheme command, e.g.:

When called with two arguments, \scheme{cons} creates a pair of the two
arguments, e.g., \scheme{(cons 3 4)} produces \scheme{(3 . 4)}.

produces:

When called with two arguments, cons creates a pair of the two arguments, e.g., (cons 3 4) produces (3 . 4).

4.2. Code displays

An stex document includes out-of-line Scheme (or other) code via \schemedisplay and \endschemedisplay, e.g.:

\schemedisplay
(define fact
  (lambda (x)
    "a light year is a measure of distance"))

(define fib
  (lambda (x)
    "a light year is a measure of time"))
\endschemedisplay

produces:

(define fact
  (lambda (x)
    "a light year is a measure of distance"))

(define fib
  (lambda (x)
    "a light year is a measure of time"))

Within a Scheme display, ;=> is converted into a double right arrow (<graphic>), ;-> into a single right arrow (<graphic>), and ;== into a phantom of the same size. This is useful for showing what a piece of code translates or evaluates to, e.g.:

A \scheme{let} expression expands into a call to a \scheme{lambda}
expression, e.g.:
\schemedisplay
(let ([a 17]) ;-> ((lambda (a) (+ a a))
  (+ a a))    ;==  17)
\endschemedisplay

A \scheme{let} expression first evaluates the right-hand-side
expression, then evaluates the body in an environment that binds
the left-hand-side variable to the resulting value, e.g.:
\schemedisplay
(let ([a 17]) ;=> 17
  (+ a a))
\endschemedisplay

produces

A let expression expands into a call to a lambda expression, e.g.:

(let ([a 17]) <graphic> ((lambda (a) (+ a a))
  (+ a a))      17)

A let expression first evaluates the right-hand-side expression, then evaluates the body in an environment that binds the left-hand-side variable to the resulting value, e.g.:

(let ([a 17]) <graphic> 17
  (+ a a))

4.3. Variables

Code can include emphasized variables via the \var command, e.g.:

\scheme{(let ([\var{x} \var{e}]) \var{body})} binds the variable \var{x} to
the value of \var{e} in \var{body}.

produces:

(let ([x e]) body) binds the variable x to the value of e in body.

If the text within a \var form contains an underscore, the following character or bracketed subform is converted into a subscript, e.g., \var{abc_3} produces abc3, and \var{7e5_16} produces 7e516.

\var forms may appear within a \scheme form, within a Scheme display formed by \schemedisplay and \endschemedisplay commands, or by itself outside of either.

4.4. Raw text in code

Raw text can be included in code via the \raw command. For example:

\schemedisplay
(sqrt \raw{$x$}) \is \raw{$\sqrt{x}$}.
\endschemedisplay

produces:

(sqrt x<graphic> <graphic>.

4.5. Generated output

Output generated by a Scheme program can be inserted into the output via \generated and \endgenerated commands, e.g.:

\generated
(let ()
  (define fibs
    (lambda (x y n)
      (if (= n 0)
          '()
          (cons x (fibs y (+ x y) (- n 1))))))
  (let ([n 5])
    (printf "first ~r primes: ~{~s~^, ~}\n" n (fibs 0 1 n))))
\endgenerated

produces:

first five primes: 0, 1, 1, 2, 3

4.6. Verbatim Scheme displays

When special features, like \var forms, need to be suppressed within a Scheme display, a document can use \schemeverbatim and \endschemeverbatim instead of \schemedisplay and \endschemedisplay. This document makes extensive use of this feature.

5. Scheme transcripts

5.1. Automatic transcript generation

The scheme-prep package supports a \transcript command for automatically generating Scheme transcripts from input supplied in the document source. All text from the \transcript marker up to and including the \endtranscript marker is replaced with a transcript generated by supplying the intervening text as the input to a Scheme café (REPL). If the Scheme transcript needs to contain the sequence \endtranscript, a different terminator may be specified as an optional argument to \transcript. The terminator must be a backslash followed by one or more alphabetic characters, and is specified without the backslash in the optional argument.

Three pairs of commands may be redefined to customize the typesetting of different elements within generated transcripts. To modify the typesetting of error messages, redefine \transerr and \endtranserr. To modify the typesetting of user input read from the current input port of the café, redefine \transin and \endtransin. To modify the typesetting of program output written to the current output port of new café, redefine \transout and \endtransout.

For example, the following:

\transcript
(define f
  (lambda (x)       ; indentation and comments are
    (if (zero? x)   ; preserved in the transcript
        1
        (* x (f (- x 1))))))
(values f (f 0) (f 5) (f 20))
(trace f)
(f 4)
\endtranscript

produces:

> (define f
    (lambda (x)       ; indentation and comments are
      (if (zero? x)   ; preserved in the transcript
          1
          (* x (f (- x 1))))))
> (values f (f 0) (f 5) (f 20))
#<procedure f>
1
120
2432902008176640000
> (trace f)
(f)
> (f 4)
|(f 4)
| (f 3)
| |(f 2)
| | (f 1)
| | |(f 0)
| | |1
| | 1
| |2
| 6
|24
24

The following example shows how to specify a different transcript terminator and shows the default formatting imposed by \transerr, \transin, and \transout.

\transcript[\stopthistranscript]
#e4.5
(begin (display "Enter a character: ") (read-char))
(begin (display "Enter a character: ") (read-char))Z
(begin (clear-input-port) (display "Enter a character: ") (read-char))
Z
(list (read-char) (read-char) (read-char))abc def
(define silly-repl
  (lambda (prompt)
    (display prompt)
    (let ([x (read)])
      (unless (eof-object? x)
        (let ([result (eval x)])
          (unless (eq? result (void))
            (pretty-print result))
          (silly-repl prompt))))))
(silly-repl "Enter a Scheme expression: ")
(list 1
      2
      3)
(silly-repl "Now what? ")
(define interview
  (lambda ()
    (let* ([fname (begin (display "First name: ") (read))]
           [lname (begin (display "Last name: ") (read))])
      (printf "Hello ~a ~a!~%" fname lname))))
(interview)
john
  doe
#!eof
(printf "good to be back~%")
#!eof
\stopthistranscript

produces:

> #e4.5
9/2
> (begin (display "Enter a character: ") (read-char))
Enter a character: #\newline
> (begin (display "Enter a character: ") (read-char))Z
Enter a character: #\Z
> (begin (clear-input-port) (display "Enter a character: ") (read-char))
Enter a character: Z
#\Z
> (list (read-char) (read-char) (read-char))abc def
(#\b #\c #\a)

Exception: variable def is not bound
Type (debug) to enter the debugger.
> (define silly-repl
    (lambda (prompt)
      (display prompt)
      (let ([x (read)])
        (unless (eof-object? x)
          (let ([result (eval x)])
            (unless (eq? result (void))
              (pretty-print result))
            (silly-repl prompt))))))
> (silly-repl "Enter a Scheme expression: ")
Enter a Scheme expression: (list 1
                                 2
                                 3)
(1 2 3)
Enter a Scheme expression: 
(silly-repl "Now what? ")
Now what? (define interview
            (lambda ()
              (let* ([fname (begin (display "First name: ") (read))]
                     [lname (begin (display "Last name: ") (read))])
                (printf "Hello ~a ~a!~%" fname lname))))
Now what? (interview)
First name: john
Last name:   doe
Hello john doe!
Now what? 
#!eof
Enter a Scheme expression: (printf "good to be back~%")
good to be back
Enter a Scheme expression: 
#!eof

Transcripts do not include a trailing prompt by design. This is done in such a way that an explicitly displayed string that happens to look like the prompt is not suppressed. For example:

\transcript
(begin (display "> \n") (exit))
\endtranscript

should leave the apparent prompt alone since it is generated as program output.

> (begin (display "> \n") (exit))

Prompt suppression works even with changes to waiter-prompt-string. For example:

\transcript
(waiter-prompt-string "antelope? ")
"no thanks"
\endtranscript

produces no trailing "antelope? " prompt:

> (waiter-prompt-string "antelope? ")
antelope?  "no thanks"
"no thanks"

5.2. Loading initialization code

The stex commands \schemeinit and \endschemeinit are used to bracket Scheme expressions that should be evaluated without generating a transcript of the results. This is useful, for example, when writing the description of a programming assignment. The solutions can be loaded via \schemeinit and a transcript showing how the solutions behave can be generated using the \transcript command.

For example, the following text:

\schemeinit
(waiter-prompt-string ">")    ; restore the original prompt setting so we
                              ; don't get "antelope?" as the prompt
(define compute-length
  (lambda (x)
    (cond
      [(list? x) (length x)]
      [(vector? x) (vector-length x)]
      [(string? x) (string-length x)]
      [else (errorf 'compute-length "cannot handle ~s" ls)])))
\endschemeinit
\emph{The \scheme{compute-length} procedure behaves as follows:}
\transcript
(compute-length '())
(compute-length '(a b c))
(compute-length "abcd")
(compute-length (vector 1 2 3 4 5 6))
(compute-length compute-length)
\endtranscript

produces the output shown below.

The compute-length procedure behaves as follows:

> (compute-length '())
0
> (compute-length '(a b c))
3
> (compute-length "abcd")
4
> (compute-length (vector 1 2 3 4 5 6))
6
> (compute-length compute-length)

Exception in compute-length: cannot handle #<procedure compute-length>
Type (debug) to enter the debugger.

the last line of input intentionally causes an error, which is displayed just as it would be displayed in a café.

6. html-prep support for the tabular environment

Support for tables comes with a few caveats:

  1. @{} directives within tabular column specifiers are flat-out ignored for the time being.
  2. | directives within tabular column specifiers are essentially ignored. Their only effect is to globally enable borders for the entire HTML table.
  3. \hrule and \cline are not yet implemented.
  4. no warranty is expressed or implied.

The following code:

\begin{tabular}{rcl|r}
y &=& f(x) & without loss of generality \\
z & \multicolumn{2}{r}{whee} & this is fun? \\
\multicolumn{4}{c}{
 \begin{tabular}{cc}
   1 & 2 \\
   3 & 4
 \end{tabular}
} \\
a & b & c & d \\
12345 & z & \multicolumn{2}{l}{\scheme{(define~x~"foo")}}
\end{tabular}

generates this table:

y = f(x) without loss of generality
z whee this is fun?
1 2
3 4
a b c d
12345 z (define x "foo")

© 1998-2016 R. Kent Dybvig and Oscar Waddell stex-1.2.1+git20171204.g5e4f0ca/doc/stex.pdf000066400000000000000000004347731321130544300176340ustar00rootroot00000000000000%PDF-1.5 % 3 0 obj << /Length 2717 /Filter /FlateDecode >> stream xڍYK۸W|1Ue1$gN6[VHpv|FhlN`KlWamnTm (66[zCnw=P Z_yQp`SC^>sdxE~9pC_6^q8v (5#+Oc,Vיzc9#0ݱPE*OhWt%v==­O_pbAP!oC!` }rJ4ݹloUl NӖ: Bu`` 0?ǢkME6!l3u@=y2njz5~ʄDxg !\e0́D]5Gfc4+CE < ]#&㢒9>HWƙE3hB ⑿nkĒ &CzݢPqvΡm^ jE ߱7B8Kc:(*+u)]eW]e97!Ƙ:#k'=t 5Sf" )K#KP(gL}\D1\KBTYn@sfqq{G4b!aI2/ fÂykpOg?& {3׏cu0ؑqfz+r&_sfm %^X/ Pbp=TeHȒ G#:5pb Z6@ f/o~*v\=ЙwkY 嬤lEIv+ sQdRxuna{Lnx2-BglHM1{΢ ;ݴHlPnCՙrh;g*gu g-^<՝Y.za#D#o d {@~pɅM+,{o߭R`Ъ{;a^V/Iܒ ٢DX}8VUu=N2sK0U|G)]i?g+˶ bZAj$(txPS75Ge^ؕ||#aj%JmecYE[:eZgr^aeFOKIf[͂W:K٭]3 ͸2񊪖rV 'Wy܎FfKT_Z_zy813O;iSp6@l'# \w9 rZLI)#2" *w(Vd;]ʖ7e+ \IXotΊtHދV_A&B>ꙥJmy 4ˏ,$?6&Zh{e:NoH{{d&)+lѷ0e A Hd?ի,'i1\iksl>iǖ ^WQ('ܟGd2zi 4򢢴3Ƨ($l9Tg+/(5 S`o'SAF]/N͋< Joq;ݔl١_pP[4V;ՀYK&sd&Ol ny$y!&Oŗ& e7uφ'kNtE]Cj/%sU7U"iHqK;"E6I$\v]UY W,)eK.N#2Jk)R4'cw"8q#B|EID2X4)BzB+o=WYdsW/KiJ @Q_/Q*5O$p endstream endobj 14 0 obj << /Length 1625 /Filter /FlateDecode >> stream xXK6 WLsX+ï)M=ehzښ#~ ,{7({cOIE"l7g_>{6٤,Dmbyonͯ^U6zHx>q&BUi3C 1^$n"H/b-z8J-4.5 Ya⭐g`5T>PyPوH1n=)haF^֕`htu Ɖhе6!DHxbGIޢ̃Kgʶq[w` ,.$,M@'˳&YeZGMCbJY[`ֹ;w,MpI;*YNQUbvBf?]`FH'/ݹp9I Gdvn{祲om@配w.)kNW:3\AɈ2Ũ8 d*p &Lr,G9"f1;';I7bZ0r(KydbMCW!"`BLeWC͸r WG+ U4W'j;P"&e*ᕩ"~!eK 硘X+yo2g^QCmr4O*|"P,{#12C;*nW>d+;UC`[t|YҶ8dAat.SC$a)Lȋ7?kijeC?zghk,y+\E#gҟ;Ϊ4=̕r^kC%ngMI/ %$x!Ž_WlyIx7fp32`Iwg0)V!KDrѶA۷7{֮tC> stream xڵXK6Pl4fħ Mޚ,zIsmzWl>ĵIz%)r8GMG^;Bzq%8F1Muq| )Wj>9AT]gum;)m+VYQv]crn7{vC7:ENA~YbDz~~|4U&N^f̔J:$7m#:H'#@" EdM̅QE1",2D,˹_b=6>UMr3vWOK*c8t eEV"*|!H< )89s ֏!)ȉdzw!i ٟoApZ&z=Bp An| FЧ&\Fq_F6YӘzhl>on5Du;cR(*!p}3 !L4 F+\PR!{0WZv/W\8~fGD֮W?>yѽ(^"pGNx7MS8рn܄N?=H&3j̯$a: !rϵ$i4R+T~\&rqŧi< o&~^^8njS)GI7^Zm,CA%)nϋCEB67Qw=Ĺm&fq)k.gSx4no4}&'eXB\щ:2:Q:KDTȿPX ʂm@p}l endstream endobj 22 0 obj << /Length 2014 /Filter /FlateDecode >> stream xڭَ}ᗨiZA8p A2HQgѡԳ;ߞ*VjiyHɺ/1Bx2I)8v]RP@Xq?:8h/7].$JA;DPc( .Q<ay/;SӺ0pҢl:FeU#!#5\E" Tzx%gEie&R΃Aa;E^5n@JV܋oh+n"8L<~FHߜ0+ z/ xNևT6Οʻn:+70h&iDCqAKib\ϯ*ʦg}u*]h8aݷ ϗ˿nx+EՂBifD[Cl9a@gR [tp5(Bj/9.1X\IZ !8ƈ8]ˑW%!!g&3u`ݝ˚&d8%9Xv {>`JAwڰEi*dɚQTGt#+\$GAN 뫀4|r>'pS? =Y d*`! o\Rn'myZ 6Y_W .+R{rj׎N<I lրti[x9)i?ME?7D>1(}(;N\ JT╍&ϽmrhM*c"Q CE%" oxi•ۊg 8&,|wZ\5m^nofɧޣ#"ƙ$ТqǁGIG7AzVדg&ۚƝ !A͠*SUO7"a$\3-iA'aprmAC(mUAP!` ໪[tI11IY{r8юH\Ds*9~3tɫ:Z6Eu9zjLě< 8 &oXpD0qL ifYzrqMQ RAʖ-]V`:cG&gAXgh9F愀a:Kǰ37NxZ!T*[.`L@=xs_lSl6l^Q4 HY7W-5j`Ko yXq1$gc $v-! PFagq*bg*!BF;žmAp3T* jdB#*] ŒǮ2NmUxq2:mKNB<8SraBu4:Ix㲽#玫(JPGj8Q"K,'`O lзYQQ3…GR5$6 P[p삤cg{tJL')1`.vwP[LKh]F"U+O9|VeD /~9&g A ]tbykRU`Nьs?NoUsq'G,/%hDUs/E jerԱHe@̳y/N++CAj<iyx@~'W=&#O _c0/wI*X䅚^zu[o@*ׯJDhf"j\$Z.r{Tn27lgu }K\VKAzZ\#pmoʈ,0ŏU7?#b]~#2(480@׬,z{K緿$Fk9Muݠk2풡&4 g^x@䖄G,qlqw=Lb endstream endobj 25 0 obj << /Length 902 /Filter /FlateDecode >> stream xڽWKo0 W%fW?vrZc+&+]2Oز$=lE#%R ,`}jG؊GX[D kZGFmy5rC:uzkN@2peЬfB>QrhGOqi5Q8K inĦqp(Qn%;A4%IEf#W9U39aҩHR!ĄRbjWW5"+cVQ1GLe^Umi3&++궢W(bJ@eRH18>!-QB8nހ; G`=y@-;1eg6Fqj9mOALVl5xi,u"O}8+Qz61t\zTMIBTf\h7IL̮+t (Ls~XoJ*O)|oSR]Gc8;\TuҋNRl\-mvjmW$aZvUo:xNhy6#B!sB-#c{YPz6wރSy]g2$dC uNt o,2RChkEW/0 a7x/hP endstream endobj 28 0 obj << /Length 974 /Filter /FlateDecode >> stream xKo0_ᶚNµ#C'Mj;M[Nr0$t6`a{ \j8=8":pc L '`2lh:M1tLS\[a, O5'G_G{\Cu|6"&(gCK`.aBzT %<@`v{lDͯdIH*4ž:٠IJIt Z%$ ɶ 6ܺ'?z=|~w$Jk67/~/# wLJ,Z qm^VTgQ+u#$_Y( ȳ+[zH1&|5 $R_y,;/6O^;ﱦ#hۆr!48f`- $$%mJX(@Z4 hz `}蜑! \ž -oISSu k^G ]v- tĆtaTVn"sn:a짽2jAr-Ӽܛ2s 6u/E e u全xPP%r[J6.=Uŋ˵ǒ<4 VAdqe7^ES"HEc:ƽrË.@^{,1j5*Ex rRx OJtp`k#u6~s0ksSXE!˲?-vW7o]+IeP:`4(ͶIK!VG" X?ie Sjw3 t'C e8 e4z~-Y݁5W ˚wvL*;vې@ uOau.U B*wojé:; Ї|l@ŬG1˩NSݘTb#; |<:ry܉\JiB @Cĸפ;9NLuXo*Yby'-͘JgD9(+Ӄߕw endstream endobj 32 0 obj << /Length 1488 /Filter /FlateDecode >> stream xڵXK6p(""RO'@Ȧ(h|@[\]Dj!%[JSp83%͌_..Ƚ'fK .ū+"ly3["f 0fbv}dJ&d[zef>I+j><>!"IPojTw]J\S?2J=na'^<ӨR51.+%ji&|i7(rS.{^,fh5!iQ:i@bg7d2 L\v},q3KǝU>xOc>M(hrG^ˤZj!d%5\W]qPLTBnشxDq%621ɼe)&E"EuksD*Cΐ؜fX ) ZW,TS1bDn (r"(J̉׀R!հz}HaI v*T¸&+|϶MuG=Q#|g)G[p-lс_]u Ib^hCK4.OHMU]U87s;>^n\#}}V3Ki%NbᒷLsM˶Sw@t:=q "1i?e4s>Q l) ]" ?yYaV >wy,$lv~ttA|ƔAꆿsRHުIUYQ`m^E.~ҵc77kMߡ/u6# IQı6HebPH$ 5+aZJ4V Ƶ&ytJ,DqX Qh a]oLjBT ѤHØ}.45=72.@LJdfi Я!)rWj8V5?a;Hۈ`妆90 $~ }%~ Vw7n.`pL>TI uon}U/Ȼm N]r]i۪1 2ka%s4oY0 sL#h9'2m< iOU]ulkcs#qæj@RNv&!5+N:18$ RcpW&kvVf;AW{XiPcr1:5SumHP'j̓GhNS1d8^P93[{(NPSny߷ݢn )VG~fV I+MzNN†YtԉNHxz|ootG@ܯf6A{bUs9eO2\[Bi7Vc|9}ri1x?CZ=&yWs֭W‹cl퇮(*wrU 0502mF1 endstream endobj 36 0 obj << /Length 1358 /Filter /FlateDecode >> stream xڭWK60R EEE{odYȒz7{g8-fуM{!f~G_ll-BY=hf;.*&ݪ҅n,.l]=,j~`V!-wU*7WŦiTe]mWjܫ>;XiH'_&Yٛo*m˚9 > IC@C+kOGxM/M:~sN֥n!bZs4rdViS#$3i!DCs"2BŋwJKO_͹Sӧ+ǹq\H9nIt+lX"b<38ԦJpo*[_%oegd|0+8oEcB Ϸ!UU˂b]LliM,(ݏ:>~ʢcgjmf-iTE MpF.1ky :O0>}"$(ɓ3]صrM.%U4<4Sl0O U]8Om-'Kx? Ռ[uJ,z}"XE3,9]狹|G[%24n nA$<Liw[ժ~Q4]35Nx^̼C&.O)-y=|bu];O0`\.LcϦFI0'%'$$[^cQ,wjbv~VIKPz 33]>"xEq>Fb 6!S7FsXIkSL< Pޕw;2Jǥ̤Vu^o6y<7VԨb3 Yڸ-:W~ ~N/<($N/d|!>?, @쫦qǢZ'baF^7I`k7y2] @[XXuf;^K t~_ʮh"2 xy^\Mdw"55*">d>M[D# lUBtth1:{xU,/>-J D>kxR YCw@@ Sl]iq<-WJCsgӃ"]]xn,Wj-N/ozkjxyx8_2V>찓Q\G#$~1F]*~qD`e+~~^%y<ǃ /.yמKSreǼ.WFH3QtkLGOp;sM{G<:ay^a2@ endstream endobj 42 0 obj << /Length 471 /Filter /FlateDecode >> stream xڥSMk0W}"i$Y*B V[Ɩnk6#Ye{> stream xڍP. [qPݵ8 X^\(N)[w-.#{LkoPiHX@@( + @JERΉBCځ耜]YH9g4lq(8|Nvv !΂i P8\Ph `+kszs {3PBÁvM9P ;+ޅl% pC e*Wk(4-k˟ M% < gW 39;@SÀ`O; 47;<VKFVe,~\ @7 hlG@:_;..`=i3yl]od v݆# ͳ agg sk <A(9~{v8,-A?(.@7  l(D, ?ӏ3, vqlzjL$ `apprG *8XBXBQ~ߨ ['_r,Yr<#OG ~ۿ98l ؠ@B=5sWg'>Oo{yQ!B65-U$,[#"4[ ,sέ V/%7d/)kÚ՛|M5ƷQf^K|!C&eyp }ۮHʏ{-da(tzK}W d%F;0MY! $Nb<A goU؛)2-NDd/.pi%w>(xDdENR!S#t.fIPn}ݑnlc> BS$gXA=PdI y&LЃ`j$88ngIxO(sĞRw-ӏ8. l L=İfƀKLmAS.k 0`7?ȝZN8* 1,61(#Wb=i0'$ai&b  6%xCfa؂!H#J>h25dlT,#p(K+U5_:Q>͘X7?͝Tgwݟ0j ,GK1](`dq$U[8CȱKXe_}訃kIlb^G!qVU*'$eE&q$u[7Z*}\^Bhx&~EWX@;[|™ND|6Pz呭.ٖg !m*c%xWmT|[\ Hw4~x(n3.}Nc98#.#*i״,LSn_{iLÓRCc[%f;pUHtlf3KﰗT]W/JW\ }v樦P,e6F=nPF$b[ηvya, Eԟ_. D(6^I8T*Py酑-J\Ӷgt`zTE5vW'ӎu]2:$'z{Gɽ4ZV)}aAah4og`m[stM+|9ͦݱ-t (M_+>K]&Jy+wCw n|MԽаGCu|;v b S2ƚ{ yݵi,Ko (ܿ9.^wHe ʹ/6J-;AjÇգUͼ&U|VOM,z9`-\GvPڶZ_.1#B{/Y[7WS̕} &L:sǫo. IxXjbf> gJTC>႗< B-*Jk(06d:zJ,=wi`6Uh(K=q#a1av,".ie).zSH$Bmh%Af״ǵjQ@LhX֞:5+PZxKX 4] mkc4,I׆oK40J<0r[c mzewc 0AI=>8vl_2n{\ЃHVQ<|2kCNS)j.Ǚ-\8ƮF19m.q}DyQX߂xe&ZHIm_9(5!0n:G*\eiZi )ֶ̬L^4eVƥ:yfgj-DSE`xp%>9*eNICMbyG&bq&K{uP^!3`v5 XxˆX.pPc ZնiRWEv:Ce1^Ls.Zx$.tPaUn=@i.)xz|p}\:x/1]>PSOYkb6</JT5t(b,s9X}ۛ@2!jC؉J*i(+Qt otMy >8Ԕo_&"s].`*ݽZ8椺 ?d ~ -$6TALseJ1< A%6eBOʹ0+1sbBֹ.}YyMʽ(>"u5Y7tF(/|T2P,ٜ/:^Y[4l4bwad|w?3?kZ)Fu1@ze&|C§"r1G20PGn ~ĝ{k&ÂHπъ0kaIQ53lN"M踳w hY'vV JXqmw^v?j 'JAK#9|s_̍^DW 79 9eLAy_2 N~Ry7oD~6X-hnѶE Vpzx.Gm+bR>l$oMx6m̴0GiG4J1HKS5ˇ 7"_2YQ֊?q3 [H M ]uU} ѧM -r<rińkP.A~4+gNZ<-jMM X2#fnbW*VTynOMڬJ\821ĐFGFrùn19a M+Pg]E||Ezil2M< D7x>N தD\ +kv_/Kyh#^Cj{ʟA/÷Y´3sG#4~TO6[ahaTGN^{wuF‰+SVIz0 Rh3H OL dVZrk\rǎ56#Schx 28znq/1.74VbK$x 0#Mt#%Ltmũ tYEM[8e~S.-_hR&0ڣ##dܡmDRuB2wL kdZZkY 2J 4T5XzJi}ܧfo^D>O:q*D7- SQrPaUvPW5T(#Dr38Lm q!yEI^3W+U<|C1=Ӫ}ؒpvlUؐ `V/\72zmMq9 ~$첺@Վ~r.ñ驖,#0ثM3K{NEvBpqp1Z㉣Eՠԡݲx>݂=/ I3_$uW  ;"UbV0ѯѵqrU]y.`Fv)\#YbayLnP!e*zj(NG[qPaկp:S#$VK^CBlN:.\%P~y >1G'[qw<_ٞ&Mg`ӟdCONq=Zh.8IԌ@Hq:w1M\X7ʰ=;ҬU>gXOyu>2BgگaSE/ü4}dj5ff"=z3ěUG ǰ=3k^[<$CکJ0ͦOV7N}*bIX7;UJcT} UnêT4CiQ8RU p*a3H%x%#e[&B9z֊C![d5K 48q!>}5\XQˈM$Ӓs{;e5FHN5ř>@*撎d`;a2"zC 6}E9u=qftk}=.:&ת{~li'6%L.5n4hIgϣzL)!$#ijW%8OhS"^rls`6G~6V3 ɑjW*SPi;)}l^ܛڏ8N`g2'vNplV,k'wuAo9"zzmj!I[9] dKXFd5ټ~"v̌7UQ̦d LM=.!w^գ40.!9eX8ݚct:.H*Be,_=DDF Y_k\ZFG|mr񹫑K>:|N:`E@T ZA^.~ |QLƽ9 zwUt6j{2)Wd(Dl[vvvS-s{Q|H*2J_wa}GEHE3jP&8sGդD Q[]Ls Qʹ3^C =UHrLٗe:֟9ʙ;5zbPI<Բ(1EZ1yZaJct8ok;ړu{]4JxIч.5#;Q5T{8< x93ILBԏ vT1\0$?'3=E+jY-&׼3N~mG׋ NuӐ> طvCwC5ˁB5]n_1}0ߪ6" Ơ5k ~I$YciaBR=aDk-a` edY8O!.tCuGww<Obr V+pDz7A'|eϓ{MLZGFwt169q6?tx/.7lTӡ쓊K6LJи+A)j n_*;5=f+?@teeFǐ޵M}2vNҪ/D4"7Z㵥^'#FPT('~x}CsVVR lW 1co _RNL|1X :j86m-@k\i]ɂp%,IرXz,փ iHpGpTZ} s gG7`@zMEѾ>*s#,xk/ Ȝ_d;.$\(ٖ Ą0ݷƫحadHAxA}EFgiIƯ,4 V{Td^N/W·0ر.啧Z7#^{m-VtSǖ:N|bXG j x-XG`;mWƳŐ#؊#Ba&5/ߟ<(?9=8eS.HV]@K;BܥiSZQrCr+9D=p+<EBi"wJ?,O[L`(K>sjq^z@O!_Əͅ[WQ$ź˦N~cw: ]$wuxNpq mx^Rd%0w<G%~YCl**Hܓ$yiTWsGQ%,+$U`"boHvGcTYԤ5QuD" /sca)C VSq>Џ*hƄ"F/v 8@cwV>  i-bAj;|i^^!# ~#;9!dT7 &Ԭn yzNJf5!|$?":i8IpڌںQ*Pot˔CucdC>WdqZ LL@.zWR1ڰuUHCzdX۝!ߑ3*:WEznO, F2ۋ̗3۴\1 !~1; u8(}X=Fl_tcCSCb5|; ^9A 5;OTKRQ~ܡ0.hB"bGwWy`W|=+e4VpǶt$ːVib}MR~k)B]#J8Yb` gĭ_uJF*|`CfPzBq,T!y{3Hvu©J>^,JDehd?mv5%tM~Z }km u fV)."܍׽S+FvsSeҔ$S5ǀVvcye=u!]4Sv@{&Eˀc$LEFvkEp6wl yd>\&_C1[/|U='奓۫cMN./#M?kK4 OoKzWLd5v)6mD3k~ٚ'ˏVҪBx]koV_h=G$+Pjy̮|9kna"d[3Ʃ\ٖOLeiclI0e8Ye;;Җm9uwa+ӗ*&J!x[nl+ɔY~(V!oJ2Ϝv ßj7Fr,_L+X+!SiANӯ 7.YzI5Y[lĚ;jÎɥBn?Bg6=)leKf%7QWEbi_M dFz])4_Ə簁\Ip6/%< zX^Ȣ_҆$q+mT&;nd\%@,3HlmemzO> stream xڍP\k Cp'-Cpw`Cpww %ACp v9畜{kfj]OTIA$ig ba03123"RRY:Y#G-lya!d@7Cy;[5 `ef t43dlAbv`Ks -My- jgb rr4NNLL@GF; G@L Pڀ]#"%@_ U;3'W xX[l\mMA`[v@d/c|9F_,mvm-mf G/Cݛ?hi 4~3: ) UMNW6Kؚ؀l'n ݝ߇kekjdfikjWL궖 iۼANfff.Nr3`+=o%_=foe-@o?@ " ` 2EM 2~;@mX}6av>b&IYeyUq_ `aapq07fomy7_[ @wDQbx))019ފف:QN_!N`LE\,&? $ŔbA<&"nVEzEޘi!zg_WLߪ1/|&3K?zv8, pxBX,߸ZY`;?~ٿ?ey,o\t|s"8Q%wэ7vNvpx;\oH?E ~{}?/ dhg.FЕǤTZpoT$̀-HH͍*ɳIk\h[rדȁviAb"5}g/ +Vn\gnT|{)՜HO Qz%yY xdN tnh7s9S$2q?؊ qˬyN@7Ӯw\SSRٺjڧjD#Q >Xl*W+AH²wkd=P_OLV m/9pZ6-D鵅} 'gUͯM<5 . ZBͯKy'ff V{HO dE\\%+fBAOU #R<1OF 0 ~B7d@ fϽ#/կ{O wv4Ŋh4fr;Zޣ̋]Z;ɇ(5ߕ#uE,vo7q&UQp/ 8[E/O*Gx5#~g(PXVqs72ﻅvŝ lrr ~ptٵz9zRy̐=`튄pޥj|HQ<.ig*(<0::6^&vA#z6! !>i?Nos3ˋI>=hP|A4ԫ$)f(OLE&)ߞK!G 衕MbCv?Q؟c&N_Gt.2cO<@xpi6 ]t[{=X+: ɽUi󚫲ȿ[|ԜOY*H|T\셁0G݃p5$qMjq[ "Y49n>h hU2{WF1c;miYQ8J.抷{}ʮ \%y#0LR3CAjox²JAT̤T w2x0V?~2: .XcӇ7Y*0~j>6#&ra2\TzPPM ]%HXXrLz6¸b C-!T8\SEM-rvLҘsd- 2_ڒ?4Te2  al,Af-~%YbDw?;}Ape g,m-L  iv6aLdLeMUΣZNOpQ4˘4aQވݹcU<"I9TW1HUߦ|\L\cv *~۶D2MD¶"G}=X*<59jȞ4T[cw71{Js RJz]";+dʻ}+WoA ;}k;Tym] UBX5̺?; AtЃ=D" `{ؓY̆ʳ=>\j7kyߑuR4. o+A׍> *ݎR3ksu?qjЦ}քoi\Q)AwtEH'ݤZc\ Y㏁dv̦Ʊ@9fRV4i/ ec1!ڜq;Gz|CCuYN3VʆKI6's|yaqa (ߝeaׯ0lD;IÙ4{[.K Iki)OQ8f<_V5Iܨ$FHk0~ӧC i{,>Zm腄vҶIsA2S K=ͽwkJǡlR:?؟8GlL--|P 2҉]'#Yb^GDܪc_M9K+%%;\]5-y&F`Pxu/,θ٧<yxw>؀]n2Qs. ڋ[rܿ'\Oqͨ3y(]x5^YVC?޴G)5uPLEiȴi<1r66~<^{T&i1$|{g\z 9O=Y ^U w!c>ΪML@`Vb Q٥/t5x% 8 R */וQF.ss9!}jT~N\ډe5 )Orՙ畫.NL|C "}0ٞǭf6H*RЕ ڨ} Yἄ僸 B~2gK"V=J})B?((MTCvl;H.xIМ ղYI~  Jn_ɐx cMqU+qV(I,=O_H1cA{FJ $a C>Fݤ;a47Ei5;՜zr y1Q0 epZrd Z4w #a?K&SSӤ3y)ۧR‰HMKWo˴\gx9;}'L3_3mhĄr2}d܇uC,OO@ uvb~ o.?.嶴?+&V&0W(cq$[o|ڻqHU=o3x1? Z88aEʉuXeǾa=Qp[guܤKTfR5Ȓ22;VŢ,_q%F[ئ˻DAk9tc%o[bPS4o.Hw 6اV3,ܜ &mM6kT$%EoڥB.]DcI?\|aoy f;nM@j WiqBxMN 9<0eŮ󚓬xRէOKɯfd+FR'IM~6bDjIxCf41 s09a-J%c Ӟt^6v(q6a \'6#=3$*#yhaGD^EI9> feVnE_6-9+>6V* E{O'ɫaO:%?*_zqI-h^f˭CGuB=P%g%MgB9RO{[ $!tg1QJ܅ts# L149eDJndΐ(|ĈIvsQeDuxoszQ켱ƫ$6y#T#q,Tp&W]Z ,!⭞5p%KwT$:ӥn]62BLSU>4!$B*K';yLBi_F^<-SĻH>cn@ e\id]‾ʶא0u^yӃ宴M0FWލ 1T*C6 fθ]YG)9N:ql{q>h{9jJqVչłb*#5sAGc'EIZ M!c][ )+p5v8 $} dI"L`q:uGd_87["mPޖSk) ` W>_XE߸׹v]Kv=c-ǁ^:2(m$C1%9#V?]@o"> `iM nzL4&Ii?r@CĦLA_!xk)E޼_F.깢hب K:K,>T—xlgJ ukęd+NBDd,{ByN=( B+2Y>,D)/^%7٬G"7H,[-VvIeDPd&݁w[{Iy?ݾnZLjE~xRNmqղv7K͆n*rIn=&H 8}Cushif w2XVd8WxCթuS GvfXJJ%89PX$`7w2{pWҎ7_ܥxlƵ '>:~q!z ?0ɡx?P;hi*P)lEGR D垠LP5;pj[x+sH`"שPަN|fTgKX>Kn4ԃ tf~Ek-TI}\!`iw9a@Looi(yVaJ?>~K l\}KMpdT{V$?̀*d}L #؁%-D/qֵbJ3XʼbM 8WbOL}ƿo:5=Wd\>sx1Ą;"P'8bik>dOxMxQרSnnִ^L.F㌬JItK_=CAILݰYD421dCf0WSoHز8`Y7!A7pIdHj:2nLTA]uv\>6C t~_?HJxc8ncu8IAXS)dz%(AXVPSZ٪^*_(Me$DO \z߶8/Y7W"z(šdb;&4>7r%N Uae|3`8!W'hdLxA+K$:-ҳicY2F\Z6ӆzޖfrd֟+YLg !E|ʸbqd'׻?޳kmE,J>KF19d&&mXQ %Z&WA"~`)PΉvdRoUI`fr@msEA ϝaEo%fI5e{H˖3\k:c6]K8lU<S[r 9UUAK̛Rbynrn`:tW0{Oͳci%6bm #a{GYLeihMMgM%3Ʉ|+iY>lۦo-}YM8Rahq;BnÏ0E7wFA5rZ(oVNX|Z6k;VQ=ɃuM[rʟA=̦11i0B5 $#٬$;"1K49 mT">H[xc4% 6|&شTN%[%)?xz0V?;B]9Y)t$J:ؾS_X^v@:Ƞ5W%jݝ*_Nf}rpRձ`) FBǛRC劊~+2,^5~hO?ճ(Ʀts ̼ )ˠ yYt<._;ޣgˆL ϒ태wƣP  ; )Pmm4Kfcjq zZ`%*"Bk9.GNTU`b5vM)vӺ j].e&qQjl†U_RE$h7GnpeK.Vp 莉'OE 2OSL湐h,PiA4l~hvV'=E2-cx%A]x,{}6Q/8 _Acc }G>5b F`URGs|q`Nldd%ѢH1q)^C rq]RJB@ST Qi ii%@.4/"zUrQiO Es#USAq[5zfYr,-/e 6Z6k*Kbou (Ӵ_xN)j[?gr Pq++>>w,HS0ReNgt Ϙsym4d/o!kl _(*305Fp_Y$U/D|0k-?m͔a3OaER^~&=_:-w~'>͖0 Fee{R)mU>M} v,yh]den_8P,3PmFK=i-nu]9.9Hl1t0S0M*S!E)X‰Rj')%DVj~>%%Va'PXsrYiVCݜ1KˇigTEՓ"i֏غ}+" Z:h[my)7-EJsubqѲc~Z%624Wlkm}L&>Bt]zQ#mjGO#e{z7h5U|Oh>t49L1 ؙ8wm pUf03-xM_,%22pq]PSIdbIw]\/A8ls 䯔ꝸl:7=\. ' ar 5fvqDOFqT(1XZ Ir{Nٔüb}2w}_ecz^1-o\nH W9{Kik,'+bӳ|ab| XygZtW_h1+N[z9ii7h D#W^:"A|X;x(1וRUqa8yRB*ĢSyh9T~CFWoNjaos%QBc1 Zk^3:)'ϭcfsՠZkBbxKF-&K$sՊD2JD<6ḬYԙd ǣeqNAA-4 8CCP=O ΖcM$==OĨIU⿚ e3M\A⸕[ a4(lPmS>p`d eWJ67ƹG5XyͿoZ7\XTGWz]D8u˔+M'<S-fħdsl:5SeB^u3+eU,^۷4K;r;^,3kծoΦ 5BKϚPm*}bpqMmG>e0{֊r` UKpnJՖ'Ōl(H"thzbo|:. LMS1YB9 =~gilhJx:.uQ& }SYu.=/7/@]@on1Ț۪kMN~pWNUa^*d4B# ɩ/i_:7b`3*L6z(C8n _iAЯFkҔ]Esʶckxd 7g0q6Ź_zmu1+`Q?A~8fTPFd5?n!'t18inAr&&A$4 GU}3 /6UZNbućsUʪnbp_sR0ktRƾUNᬛ!E̼l W8jJ@| [WSs1Q x\XG줗kGXyִy҅{:L8%l$wLCjMRװhJrC-aI3a'X2 X-M~A 5ErĂ \WCDCJ!3=.i=i/uiɅv& kyXwS$PSy6SV=QGj(aLߑN2AG8$]蠰6(!bE+.[HTȕ>}^a:ڡ1r毎J@}F u"XtwЃ,g۴EK3$! T$wgۅ|I0c)`ٞY0X*r]8C d$bNcI*ZLj GO%WYIB2T<1dPoQSm9-FLB!Ux7r-gs[xE'aK ^M 'BQ2Wc}pnWg&-{G%c)+yDBs΄i .;*+bQBǑ ;!-dL-ӈja'"/nZgOX?'c;)#+g)ɓ-B ؼ& .;aA}o7JHj`u k+]GlȄ0'ԭKc|Ɏ뉕$x];SW*>gTs= "571! \ rC*f<!skxFOa+*mS4N=b3 Zj% {kQaQVX+Pë!ZcM4)#6„N;akOh㾀a3**W8^EUx뎤4ZF@<@=r9U#ߊLYѯ_cqC8 SjӼB(bNڟeY+WSì%lRR_bRո(v)sQSR0BIiHJCWLz̃'./ZKTZ,2Mwܤ~Ƭ &X%H@ ,h'GME>]8.IUo8|ꮺ>نO7$DE7JOBdlX[rF, BPW@8iGBJ)\G{O8θe\uT{6<I]Bw%Dly2 0vCQwXN %i(e'M NK,ල8(ø#e ]Ǫh#iܡɨlMv l_w_$7\Ee^B],64[>>:iϹ{ J'=}nIP.б+0ˮ舦ekkNh9Ɇ*xwp.~5NdQx=7>w`:1'D)ˠs0 f3O9B,#7^޵\:³"F*h=SaQۓSi؃m®2ڿ=MiI< ICJs{ }$'NfУD8y7 ro1΀ W([VH]6 /hJG"p[Ox uK{ VP!Ea_6&$ y,P$A~{9.RgįѰ̌׍ҥКp88Y?c#d58e< kYPD۽6ed pg8b!f2naz1#z5tߖIBᢸT]ߊE*"ىfT3E ))5 >{)aԋ2^P"g. ornY *~`UU@U[yy*8d[ݶ*#N"aŕZD´>E"GBtt-aIDsb/sf o@Z1s{^&OGH1tpl5.eg(O4¯B LYu}Xo>;F1.62KJH3GtCe-lP[/KQw]e((JcM+舰]s`r9htNeXQh{P SobG7.Lz:c+NϋlܵW0Ŕ֒"&F~oTI)lG?'g-? at/y!F~流 ? 1ɾ 0][:јP& endstream endobj 59 0 obj << /Length1 1550 /Length2 3169 /Length3 0 /Length 4151 /Filter /FlateDecode >> stream xڍt 8mv"4B QoXFC) ![H4bZR(%$ "{$,[D |s3s^ym}^V{G-cќNckH H8 SRr/LədtS&džlXbitoDH$'48?+:Ȃ)Lņ SL68 U(#Pf3 . QYp:l pA@d~D44`)N^ ǑNbsqL"( HcA1򀣥5` Ҿ4_~D/%i8h>C‚"B[wY3NXZ7m=4c2q0$(m==꡽$ybp Ј΄-, Ke u ~A]=37c;'2L @4`g5?dBR"GzxE'>r;tg93>ٲ3/`ۼn<'kvF1 IJK8i^@tJX{dæh鋩c[sg]L%O܌vj av}5Xwة"V>XIUKn4;yr]4uD5[ߠV{ޫz:453[zBV$GxykHLj>VujAaW\Hۚ:٣64鰺/;;=y;3{|6tSQBC*8: ا w nf9=JSF_.6uߡO'V7ـL5d qnУk B3Y }|26C/tӌX@~^a;oAޱ+=x3EBއ_u"`}> 7kfבfRU]+=^{Y"iq]n=Hk݉j6 R:֑%VlIzC5Ua.Ҷ-b+{h׉L?IoUAb7 v5QBel %r>̟^qPvJܞZgUㅻEޭMO3~˭9;w;!.{:,:`*\m#y[ݽ9zmCO}s-]YL.zXd^6c#QheєHg4n&3),eƎ+c Iń=:]ydERojW[Z㳍! =MIH#!dZʲNGt4>?%~Ͷ7C[{KcHT/rO<)9ͥlǹHjl7GUc#踈bU Խma舅2ឯ5'gOq8Zݧ'UTnbjXxTh a.1` q9Pѵxyk*$Eiz[{o|"HbD@8JiUK/pn̹\y݁NȱBi{*6;󂓭 =[SU08o倩mK֯q-?Q\zԧy;ΖkLQ5Yg&mJ`y*{u׾lqY}=iܸɳ]bO[Qk_sbflImìx@SaڶK &ԝ}Q<^iCay21/!F9e23uW7 _m1F]͡ʅ5LWj^TAٽܬc&ٽ̫Ow91"B,!.|-3jRr9.~h^ѲN<^[3¤^YȈ0 8Zz_y?Kr+2Ng^CeJ򊎷ۦg T/50l2_VfBê_ tVu Ʊ=wAC47K֭7uˌw~Moɒb!¤g oMz|`ɤLzDHŁCz֖zVO.iU 50Z5e(sd zo|4I* |ْ;D'ӫ(İ=4mh %QG抔[n!VO2a`6 XCZH'tWݓo1Lu/6y#!ǒmB˞Ulr;ԻrjxuDt0\Y]M"ʤ}ޅXXd= =hsnJ8=mCfwKԕ`}#l9TVFřyy,/weBA@q绾M HK߱ծv'ʨh##q3T[ꕦ ,HR {5U➧2 `98{WluLN媤NtJ_.jI2UsOɌ֗k?ʊd +OW[Q͢%aϗ5N jrltȆp7NJA_<}[eX\rKxJj !1[ҽǻj K*qW49 's%:I29CU+]?v45mW,^amhQt1zvyLJEMR8[uS-Ur_748j$*|uw'Ιxރ6Uo_9^@k>Æ#~FW;̎ܽS:ZƉt+0׃Rp9ׇgkωb{Lب+kuj %o;VhjWnмnVܗ=)vY,DȤT)gxk+si\CW;1 dߠ%&hQ:9ěUm>hQ$~j=߭m C'$¶f5B/_s^Www٫k@"lp[4yO,컂{q9`_:`}y|JQ]*[b]/Ԛ>awY97 _9=Q!~Je\x oGR-er&m~IiVΓktJnC䋶 $Rh6nϴpzcJ:86 hؑwI0rkZ;\@ FAR9wO>znDDD- endstream endobj 61 0 obj << /Length1 1394 /Length2 6056 /Length3 0 /Length 7008 /Filter /FlateDecode >> stream xڍwT6҄REФ;"5$!PMID@Q:H >kݻV3g㖾=D` I@ !1 [01p$B?Jh)Cx|  b໒ PDK!p{PaJH7rw~`h8@N07|F(haXvbQ7(c0 ^ ԅ&;1 FH' p( <@@|v6PCk\,W?_(醂 GSzaA!+U:`; G0kVA+!`,pQ2 [p]HOߒapц Wsa @;uH`썂2/|PH|0~O?% C@;#wt[ ZA G"\ 5bAu=m]}?-˨ DA@0HDxg}O᫁p@/]ԋkC? g0]$0 ׿n A_3h~eW7Cx>@_C`wWfV , G<" z8FׇcNi[orppL_rZڰŕq6!wJWLEDOe5&cL;g?hhyOuϟ? dxۃl%xFmN7ӁTTHXo^7OٖM7੡px3}OoCB;%=y*'?~)W?nUiΉfFZ"H& KƎ#Llm6lvHk?YL z \n2p!+n B1"bHNGB;}3tDլFT>|A%QȂXesa_ 1:0=zU| wo:U~t:оVCH^q!Մ$q)^ܻkEW⮸yvB{Ė1GCZԜ!rd8k<ewirݛqcNX ]xxc0>} zDn٪>v/[HC?- ˒X/?^?'+H7Tg3}tAv3ּ "hYeey}_pnve^^P[y#ڕDPqb#{Ii31uBIz֭ A-OLZB}dbs*)!ACe~OQS81FF^T.!3رEۛ[˷ˑ(R,5 㛽;D÷˵k+6ɛcL ]ӛ#;(:R4!HQ@M@}aIƬF>isa9THs b4S*dCDe6Yߢ^xxOU:YRךdIWCg#_+COPzUm1HkUZ_,3!? w*ї:"@[.=ge=gKV7!}IϞq;ÎW=E+U{u͹+˅bIiO|T0mgvY'q$̠@``%[yN% W $0Hn1M-f"2͈{Œ J]7#%>Vi/*r/b`ЙAVe̥&ֽضq&)U{@0#cu>șwF̤@< fbVZ-0gt+8n$}0ׇ JJk\ZKd/j 0$EHA}>PWH]]h.%ļ{W~T"KznulG L7Iy] ! Aڔ<3L2: £?UP'V4q[߿t3{C͂6؋g5hh'(;$Bq_3O.Ifɤ|y&6 rqu*Vt>7?\MJn?|r0G;fYQ[[ٷU##nMj'H<$kj7$wq}bdp3t_״`w&K~.V (Hb\X+ףEK/rو6Mbi]%`z&?pkL/;LXh?<*J} xNz6%5`gS,p6x0ȸ:TtDL0w{Y~-T7! .$Ha]3/W" rZ46YmmUa@EUZzV~ۮ[!P;[C׊2WADnx|:h̕Ή֘GY**N^] * ĽL^~ Za/T,&"٤Ȱ Ɯ=2~ w|[Dr抹~(֜ӸhIv)\9~u-jF~֦@ᯕ[F;h ancD11(?"(HM'()&vd۷J^Jg$/iC͵\kbRR+>qלPw1^[ۥ6gIA kq1[~nP\YH__֏fG9tyvbCx%ұƓ1KU,)Ъ0pbɇJd߲4Lo:C9RCUJUca  /[Jik_l_kVʀLsO.prqѸy/sP2 FQߝ+U鍧[_cl0:8$|t ռ+W^mF)UowrޣK%FjxcC#~m%XEekƛHPc.yAC} l\V:KLiȩcˇ?%Uμ{-òSbUd±=~ ETATP %|p<4ƹ*w-(O7_l(/u+i)1N2R|µWuվT( c3K'/dr,c-f-X};l#?('_ْ()d=-bU-NԎIU4,sg΂c͎84$`Z SUۃU^?Oq5dfkwirS kvD=nlwsq[s]3ԜQdU/PE9(=~-Y:? 8;ФSce9ҵDdP.]=D_ 8h"PCo6zu~J&!N_C6Eog"?OʇJn_R&#.EV65zJQG^\]GeV?zBe s{UL]5ͩo%e$w/`di=sBS "gI\ 1(W;. ʃ cUqM˩Q_ t/yz[͍[fNcݾe |*j8ړ5nyDڑIn8n61 t'ſG0?zO,e7nvxN],Ot(5rZx ),Fֺ+Gqqjf̷r*B1o9QCS귅8IRQZUv;·dl%qm(KK:Wu7Mh, aYCFB{NZ>iBg~PzlZE/3Mޢtu/iOӅ1gi&jY?)cR_7:gњ9S9\bݎG[ [|G l|67yZDRCh>W(O0F0,WT \]ۃRqш!w  ~7_j}25\BtvJEͳ?+{AJKY)QkM=nCX./raI;d-L9>BhfBЦBIwb>'o3U)i!'[hvEl ]v뭽uKeP:%AY_IWD˲afkENOC~;39;FG;̤~|#&rɛVߓ^/_kEsd&rKcvǓƀUH+]ܩzzy=Vcbd|ަF4pwU6 Hgy 5lѵ|0Kg|khSfW㏸m>K10mX:/ ʘTk]4^gJ&c+PU|gهA9BAhʾ9V6ɝNS/~[f#k =͛b|ƯbΆ3&¾'\ROFWMNVSsOU;g$_S$,YBECMx¸p{F;H=-ϑd8hSEx+(k6fNzqA(hA[GFyY$tSqӞ~͞aK&Ckd´I93U[8e]zgsp[t4q`Yq2v.P>0zPFkqV)nN)%?:W_@q5 η#5au}|68&-Sysi,ڏ+YFQ߰ 9[4d"w˺J(Ȁs v3cN>pcFyLp㧍~nE.9;%KwU'{?)XIWvMW!R۝[ہ(%:ʟ>{yb,V;N+c"+JkzRmt٦z'J4ka-m(t2] +J d棓)l#klmES#o^Tlp߮1Wd& LZ.7E~2 弪f5t'ghuvI2 w&wċHȎB1g_ s endstream endobj 63 0 obj << /Length1 2515 /Length2 21810 /Length3 0 /Length 23252 /Filter /FlateDecode >> stream xڌP\k. ] ]@p ,w NW[SŬ5P*1ۛ%A. ,̼1Uf33#33+<%-1<&/1' X&nSd]m,lN^.^ff+33;Mܬ Y{Rf4."v@'k3@ hhfb P7xWj~+^&&wwwF;gF{'KAz@ tr~ P4]#<%@oZA`W9 NP(9Am@ #;5/g33{;5`am (I3xL@ Ml&n&ֶ&`NnQ  L'ߝwy,A0wu`Y;e1,.fff.60b^\\v6q\\V7ga[L ?b|'k3xX̿?y2=_eRTDE= Vf!?we/_=ӂi3, c)ڃ3f?,ϣ߄} IW[ۿ?j;k[ C^{U[o xD@Yhlbf-e knҁWp_* xs;rpLL?OW-MX:3у}M ?37$%vv< ?e{c .< &VA€in _̻/ _\Ϳ `] SOd+.҃ks8Q9߂ [Y:S;-7UZo ҰQw&64-fa{ ,`VPE;.O8b׸pq^ApgtT_L.Nk ̼_/g4_7 i!pgʠa^tjw}@~JSt#:ԍ%A}-D}]xKJϓQN+vx>"8Bu]gGoA~ʍ\q+ly$lnGeSl!V#F?x2,. ,-4z+l"Q,[:k uVN< <]\#EdqKV<!ѧ02fW[FzjF;X?B1kK0Ȕ[1\j>;,DhvYؤ.L}} X4wy?;g Koj*"tgҋZY&J.s}өD_rK~6 :}g,df!6on̩j=ϊM8':?[+25J0\t^(^I"ɱp>@Q.#ճ3_5isDR5 Q4~Chph/ύMy!ցY{P܆:WH~dj@^RH/[=pnvM(Z[_d)} ċzj#Xڕ!sPQ.%7jj<%PS+ Z號"1Em[_ |kt~+ rM:&"yU]~6{v48%JSpHPXJ*_D:kQ$YYn?\@SbM\(BgjޔT h + oۺr.%t~^V/7 jȟ4"T;l-b s.>\CM"4 meBYzNLv B֥ }7Lg-UE`͢3(* \{pLʜԥouOq|?q;@[}r}cug Pe,$cu?_Dv!tГ6si@$T+Pp_p8]S+uW W`*izMJ~{[ Vl ںKA2_vMZav+̋дYzג,{>ڶS*KkШ3ap`|^hWeA$ D `իCmuT_^cn:] m0s[a3SaK. a>GsF6Ob-3 >zo*^[c$amɺeP Z{4 P+jxŧEoڕ?2CMxA}5֌@RTz8LoМ}cLg{ TK0d×^S6q2-g!-EW0uY6X†ɷ61^ĨnM]>G|j'/.L& 'yoءgKmkYqt2'i~l{v?@9ϦfQsH qy\6+ ]B9B\/<82'`7Eh). y"  [NOpYxI ~9CB8ad)ۂ{ w:;TcZK;; /xXYLp֋Spb^"EylzY>"P,t7Si;Ϭe2@oe`ӄ>ȂlP$lX[>3m }l,_v٤P#[SJn{K?s*fwHw-mf@}6w,I7,n).3a!Y9ÜaRzl&i=-Ka`^q,^>mHMܱeq(9rɶ>_683=j*RGvԫMrk%Q1|`YEc݀6t`}U-߫*jH*jbѧyu Pk'˘Q0Z+QKl CI}WSNk mϩh^+Cq)le\!<^a;]Va:\D@iBF؆F˖I ~|5%rgƮfx}*a4a.bީQ!~vQ5XYjokYM\@uog| m@[y1d^(~:c|TQv]'ge?b5Qr4T[ X"30ʇgya$J:r]t5k޽L $4ԣ_323:;%yxrfEGď#2j0,4+=0y2 ?5OT1T,T$vt0G@ϵIj|DA=MC6[XNXA+i݂Ksҫl{ާU-e\h,&% d դߧB%@@%4k.M*EH==۶xϧ0sH?{A+En0Ye2E&UVGe5tpXBt2̱ӏ#d JO4ּ:B{JD/0؂ R^Һn H^[?Dc=)7pׅ0eBn楅W-ƃ?42f_?Q 1Smu,z>r%c \ω};h0lr0~wװŅ)fe=vd ~=a(.CkQfcEAPi |po`8MJ}j[TB$hMڵ"vE o|9;բ?".h e 4-&eC-V{] RaD[ zVv޾‚ B[|ЫpXS\v'EwX)j_}PdpMe_>(6iDOMȒ{Ϸ3o"euR!Ip=OdP}Ta4 o#a$Q-1E;^lvM|$8zC䤹؍aP Mf4 [T I>Tz%T֥Q*]23W$B 8{Դ~2WдZk[|o_f\P z8L,5!yU} lꞹ9ck҇o\p9~y0Ǒ3 ~M0"%1)Or#;ifHp  /t>)ƒWdۑk嵒an'w3KX36EߪW"9 9#1|N{+EV2fa{W~^ #7l֮[4~L W/qNyBlWlJ l%܀{.6,"{N/QXUU/x#nr$>p㩚 9O*!z+]ڼPAKBft7pNJ+jv/~}+j{CkW ޭh輯'#61BV笠{~uIH=mϊƮLLr 'nJ~uFWI*ѥr,"סPa%job}ӎgfl#:1'f#U"]MEuR5dj/\RéHqITj)i Q^_ QEn̥ = t5 0>GXmGQXp~ݦ9%0^J.A,y5l-fQ$Xɽ% 6 nqRcL d(\ 1 x/IMz^TmkB~"TTQ\S@ Op#$w҇$ћ}VCeRvJ|#ߘ2ŋRſaʢMc)rD5\zF >ޒur>WǭxaßƔ1L-z bŒE=n~֠/Z٨Q¥arbnG Ӊ0=c'lasYJ a$G}xl@MhAVoB.;r̄`fTksWqs~?"ٵ[zOtѬi1b;g-  obGANq&X!u1dwu -\~ (cY^4HL˞Spj}k/y!:`c3ތ, tBL ^m-6첹%0K0=<c,z&Cy{)G;g΍72İr쿊,o;>B[}!c'C Z&1 :/t*[ \c(V5}?OWlݯLSR>.I"r}sKm4 /&1Jg`Xfr;>-<4V޺!e>,~ՏSq_XqIʘ\uVꞻDُUv-nKSy9Ndc!N7 48>}g)IVEg39rJ0 .SңQ/#>5#wqQ j4],1e)){˃DEH{MMAV`KzsHO{yYDk丠m 9 #+4.i^WIY=xX*.Tژnh"n31$AB!W {^Z ꊕjvW9MEϟs<}bĩaȓO~kVrKO g)%gs"zF4e뤺Gɼ%i2[X{AEQEa3(qѽ7. ^;/,&&x3D>Kl,}X[·,?VHN lOz؁"XOʀ$!,1h]TŒǜ9564̊&CYaB^qx?ڙw6w1XYpm\qR?3Zqey&T>h0z0x>&5dt'cV|Ͼ'ͩؗF8#sG7Cl:O8.WE`z}h^ZQ88GVB'೴Ru+7*sgf 7b܈baщCœHe en,Ey'7 s}^ٝ51n3* O)H <i(Hjz>Ο:E $n@bqMxoC:m:AX+cF=0=m ػ EoʌY~mN .{ޒU},/pUY=wQa=Q@钦:g·j7EkMBIsGfBf(?,]=n &׊K*Uڍ~͢bΔ[΄6t6rVczeAdɊ7 :? $ũ !{P6Va1/^$-'3Z2b4 |;Ϻ'pDkw?AfjJ*+GCnpkP¢>)Ṵ̈́%XtLVf 1`th ̑ $\ ۡZ%fSuّ6a^;hl >Ot5S )Tx@>ԟ]тCӳ5pjh qwv@ߒ7^*a02y9#1"z53Ȟ2;I*?J-L֜. D k8g07̓pSNMo.ĦOU lfmFXF?;&*P_@ {I@$D2Kc))`6o,LbB)𼻅d%mk .uךAoW` eJt)硢d,ʤdv)!}2!8s{g7VMd2l -#yǙX V 9fnwlyg V_܉ѧDty*X'؄J?  x~[j)NJ̷l;.QtZ 2m|w7r9zYBcjf ڹ5Xyk7ċc[Tћ[@OU |W_Xm/w悇i*Wuc$5\C %dqrL@ M ,fN/켆O!2|իr̼P ^,*"YB߯C {j2誧G!A-+N?c%4UD,,¾¬㵶H"^\G# NLfn-D/ *i:G/Ǐ3ňCrDQW A?Xs&mh 3@\~׏W 1U,bE1Y=82vrJ8rnuou[WݕN􂆠~g)WQQ0/z\6J%Ey3F^H=z붭"ț-HGS]Vǟ@1jWxN x9 )J.f}a6J?DSxeTLa;754_orKGK#w7# v`DR@8" aDnN'/qM)+IԬ넁(.JkvBoɗZz}pb:.3 BIOyiپ~ȯTO3!:A)HrBТ4(X:Y}}*;$eznjq؋~lj (E} FKݗsմ uf>D% sE/-2T][Zr' xtF2#ޙs~\;IЗ1A d%}H6?;1heӚsk@#7csu";wZٖ1P6s p\jegzLsPwxX+._j$$ )0 ~~yǂ]ʡQԫ9S [ n9PqnZ*͖p{pVxg9[|ǯ@%lMZ]xg ߭ο ֖%50xZ.v\c WEmLv_̒o'hy|IuP.9q5X(%uR_UHy:=ht?E#M^.~@{ڡS\{Y*}V,\}^e$8Dk°ԼuT]K6 dL,"Vzg|C.hksՔtnkjY/zbQ8;Ƨd]8Y4*B A. v M$ 仯Z{rm!@GѼsD~!m;K{ z[/id/fÇ9 Ml 6lN|W<8s*V(Bses,Dtn$X4n E0Bt_fce[Ꜻ8j+XO>Q^`O?+ppۘ7͟7qNi:q~y1Bqh1K2ږl>jؚLow wȶpZ5< 'gN"a? d0]r&h)%L)<ݛ*m^r/J$,LXBJ1',0\a(2RYGSƐKgp5b y\5J]owt]p9&Y:_b^X_)/Vsz_C)UD!L7EY]%Cj4yj 9oO{RvQIDǗNn#~rB?2bE;V3GғʰR=[CGPWH#Y8D>Q33w4jVhw\yVZְ{q (U(8H4 T܍ztf_DPQo%_m앷Z@[lnapC:}LXq{Up_V@~`/)b7:6,?smlH{.dS J;A5ЛBo^[N6SXGG@^8h(@H t?2ԲP({D}qNv 6'@`/9E!.lZ>B]ƵgL.TgC(7"#.0wmȥnlk] =aЃ*2F5h^| {L{vnUpNWYӅd ٩V/֢7vyB>:Fe)dQ/YWHR(á A(%/~`˿ud:Y~W MFꄄvUK+k&J 6oJGô|k=LEOිѧ9mj 0 Ks}dӬGMml98wR.lWW@/{Зoj+ҌpܵL@Rpn)UNZ~Lg"*;Ѓ+ ۴A9MױB6|FLy\ZlڈJǮf~ڊF8Z!{E͏ (ͯKi pbi9xT\fxb( I.Oa9W 0$,֓8Ce$z> D7sfe֦#פ}A myS< " o2jm5oeD-i>qō ~WP"hͩ@-2"2uɖymRh,1nJ3+%ZnI&f>ퟍ5Dx.`"ls4%K͐<]߻/vۜWR3":n,0lw)ں!%[IKE2qK|o95uyVJCZmݴ}|owID ϽsBk,\}[d~<\?6 *Aa=6ɤHdʨ$PL%i(<F3|)wDSgGp#)U Ȧu3"jɛ2yzKDe֐ZVž8/!*]98/k yr,{O yTm82&F: }G}d& e=yJjPsEPݕk@~:.Y0\X K5glWG};5H'AqgptY#ào;Dj 6_V3(mWgxO,?=ett?D{Mq߭+A%uR}hU%fɃ1 v+Ur;\֕HXb^k" Co}<}6墬гyM!b-T0 y[ڸQ{96ĦÏE+o٪uŵzw$1'׌zݞ_zsmCN}.]Ly-vaQB\7C7͐a ҠbX֠)pQYX[Q/ 5&# xQ/t].k Z$+I'R ][L 5㧢eF6,GAzJ7'OwoQD #Kc* Ǥ2Es{@U~vp$:c-# r.(,jG}?fSq2@`t}^]FCǗ8XnW _˸b7W/|5cTt::[b'Op@S rm('B_]SD%EzUӚX9WIh9m P6C+^K4;C8;2xzr̷&OVm!.w:'ɂ.~h(>/^a٥Mp1뀖w Ą0HDR?0{,ˮ: ),Db4v"`d+JT=Es| RsYE6:H0R"q?8Z =ztUpvVݻ(<0`!KyPxlB0NVx], JGQ.!i sΘMD9Aփ'}oGo; 9``8atQ%_ramޚ}[tN齹Up % $T֭j} 8c20N0FCRz^əa"pnISUi\m|Q !|KJ0̫VWUC%“(ˣ 7TNe"ʴiH 1r]Y`wL'i_ _x~Ij5U7I@U3b<.k0nE ע/RuԖ ZjH'CۆfAG03٪ ~!F7%DQ;ǞL0rۥZ1F٨Xu}B[DL :6s3gY5^W<1 x0EcZ2ɅJ]9LUY;u$I#xY| RGmf׉Ԛ(Y3 c:G)LɁf cʱ)D+>eb{4c1'^E]g/wkS|+LMpy<+ɀ+-HO)̗D>{m]G!Qb/'v">[%HA.}uH[uBJDNJ3eFRiorrBnPOڈ+(.WttIT۸ l=,_cMzPcP\PSWr ī:ˊWE*Eʂv@|“8G;L'T)M][Sw@ W8@ʝF B@uJpɃOo:.NF13Z1h>}+'YmK҂Qð%UgymlG]CiDA0^ڃ fi\i+J~@ͤ!SЁ0p"ہ M%bGIrO'5K4L;/RpӣE @{2b-WVG9\DgyٽjD\, A;p{`壢!jJXzZXL": SeOSQ4lcFRn-^LIɽb %S\SG(n-3/P{L >\kсGϭ!ӆF[TtGzc Ba'@&N}Re[~dJ>0yjNtFZ‘㯍? @oݥ=鏓DH6Z͔XQv[4˿WJ";\/y 9THj#S]=.Qu˔_FB3Cɤ}WY>6p݈+6LeK?qlxdCUJX~N`!C Mݸ0INJ_{M؟?Po&fujN[(ww^:Fbw<}av"`r)ę4oc8JPn1>JaI؊UC僜+Pr7(TXDs#&Ys_*)1]尋|AʤhYuSyef}{NMUD$' E/QA?d98aF!`jp w;65!C2&}07p? `hsвG,X'gK47Yԅ[喺3o kvdiCL=%0E6:hx!Uzx@shDsFqLOĖ{t(QWC݄3ϐ}ӂC^oQC &BacW~01Рuѿ 5nsb,R2 pbVиpLb^"vn :pa6a\.-Zoc 3}}y)QܝGk6,T m6vЉyma&5d=?/.KI"$:;Mr4sli6)+"eІp_uKyĥɮN@IM00a+hEngrA݀NK H(T*NZyxLME5M\5/ں򈆉4`LlENg{h[?>BN=I ,,``sNѴ1\Lsc}:_UÏ4iæDcJj{pP| Ad( ͧN9{Nc%<$s|1˸PyjwLS RE%N>QƜG`>h}įͺJeMVT4sՆ &5%Pz`nw$RdE#uktK,m/5zQIf&Z6/8>߲%`YȾI%yGTp-;*knVrՕplQ@?fYqK&$\Į*oacj=՞06??Wj^^,2PRLq7#H`BX2JJ~ŚN98saLys|*7paďCfڻ9}!7S#?BјFX{wcP BJ{zZ5~B[? S3Ҙ1=7M*ۤ=oz0AwtAK,QiD OA'vKˎ'yJwN|X"GcmFi4h2o d%0kQ\a0վ8v[2{PЫdR?~͔"?wGān (T%+]]?kOUu;||9QM&zxmy E!Ix^/KaOt cޗ̅sFdG\\P.V%ogs{ת?q$UÅ}JM҉{3$+"%.A`źy0V2 } !V&Hbiq:t [QEHaKop{ D{h8R7FA{^=b. Y 05,F6? %2A1Rl_ }$o-V:>r_ÈD YIV @^H?WDhLz\̤VR]b=\o_cjRLVr&V,zU٤?G#+Z,m}Ϻnfl;%ZDO+vܭ%0T.eF?kc4 ئ!/=uGu/3˔`HpI.@ @-bBs.Z=E1OdЭPV#ltAHK vhBs c}&]f6e-ݏ 6>67qC枱 M-ڧLaBKel1Qg\kQdc0+Z ہ,+4Wܛ:Pv2ي)MwQlz6i䇖gMGJ?٠f0>E|`D.|Dfw)b ̫+6,Ы0Ҭpwkc)'пn cCaԝJLJ("\<{1i,a~&vG|BFHDd̞>PA,XSd Q>k6B˚WdN՟午%QjTfwmqc)Q@{}q9gTrX'a2õǞe]5(] _9w*6Lώ;_/NcSy]|{<y ο*Ć@}QA.Sera[ T2xe3.x0BMqcM4GczĢ[}K& [L96HYt]prԗc+Omn}=EE0˚9t@dޯTڛyP-bGU{.Td(=J1`3*ijen40-ߝ˞>SX י\ gUL iAO1 H&Ƀ|}"3bӆXlD50ÊpqFr ͑X5J_7 KifqeO1ZVR<~^rz+GC7}ߒ!"6B d00Z>C[}qwy;0!:-@^|IvgsD_kȬJB]*-U\NW?<ެNFMn3S{/ZVP[`邺c>] dX5ׄe7/-uX!W¤ўWAZNdCk.:]2QZizVnqHT endstream endobj 65 0 obj << /Length1 1367 /Length2 5909 /Length3 0 /Length 6848 /Filter /FlateDecode >> stream xڍTT떥H] (&޻PD$&!!@hҫtH/"AT RW){wYkfe?w>;{0]I&`(8$@QJ Cp6gF<4$WR@⿀h@⅀L$Fh܃_"]pe  @bp, AL 8EE( DCp?Rp%IIooo &,F\`~ 0O&ArAx[p,pa@"pE' ., f877@ n п Br8!p@P@} _CzŀbsDɟi.nYFQ8 pŵHެ spB`N?yb$Q{pC? 6g8 e{8"3 i . ~/8w?O w/pcx-@߿/C>WB~2q)Y@QA / 39 ߡ('4@w_6e - 7oeЋ_!f8 y"B qG }.8뉻 Bހ֬ tO!rM3׈C0s,?EDhϯ @BYP/#gI] 0)Y9P/$%+ ]H0@R]. 8?7 HHX셺~mο P 4T9̵6Z[|ڍ aqil YpUv"P3K]~"[R,ZIRLe~Iƺ{6n̈́F<h {uekUr)OFcoyv'uY vp!o(I"`+NnI*3+)Nv>v;6.?4#IE`;e 䆐)AXIMAbA{ o2LΗ9EWbfɈs3|,Rq$wLV$œZǃꖍ"̫*Zs?c]=ФH9;xsފ~p|w4ksEeX򀹳;74nTPr>`d5K4+tPf:S*"BY"$ܯ;0T6+Ȟ^Z+!)֢Lж{s;p3< NJJ!y7(Ҧ0 _IBdt Tq'}'=v,w8$m`8 ~KPqai6pXG9Q71=+*ނ|=S籹t=6,cY%r,G̪j|% ٝ5ǭ=zߜ=WY.ΊH#S |s7/ $H9b&\hY ґ!.p2)jJlfF&t?e Nv3]~EK Q]ϸpcQhwAFE)CyBšN6U[`cяðy{4Qjd'#e ,TF$**᝛kn6'̾eX"Nc䲎VA&{y g+@?11D0M|)ic\/2Xķ;&f3$R !ض^ RE>3~6"h1+n#v{8%PXXb~]&ynYOA)L;QO_|xi?+y;9trpU)rk6 V 4Rz󄆂Df]=>tYN̝B妱kyg0~G@:0\F"|\ Y~I 6ʤh,JVZ&o R(1`k}Q1D:f<)wHd.46Y g MjjI@ c╵^@wԬڇݪ/ob=ëojb=pW砵P֗v :Sn6!_ɇ8~PX/xvʽОx{@:JqD (5H:~07LJ)܈&L_MȻjfrͤ@g C=e^*rdӫ{j˯0Bܶ^@rͪ3AVN<%~KHbKӈWC.Yqhl@ףt$ֽlWBbX*el5Hfδ~|ڧf_TMGTviӽө?BED20ήH|, 3፺T1nzwGS=V= 1?ʙ@JuƛoDV{'P0|6\MwZM$8d(TXGG)v_u`8=fG:ҾօL:Ռ~~Ոp?ώᔼ[iz%Kvݯ5f.F2J}D8 qMcJ0k;!E8!`|~7o)LI0+0*Ad74cUq=ղW6͑|f?&" OZ00T5 ./# x"(#L>\C_Y^Yoj5jh{cH^k_;91)<13v4xBqf=琒*In쇒 *sx3ǎN|ތ-7aBa"JG8cTaɉݰq*ܥdk }HgWc ڍ03]rDk+yWb+aqA>vVf'.:A&xwm3m$a ^ڎ-{j*dLeR SqT1>S}R/Cܮ:((ioT6& 6v}8L@O]X, 'BAKLd/,jNc~֒c2Ucͷ'}ϱp}[Sft ]e$B8qc$Tb!SiiVނ:&t ?ұL1QiϦ?wTUaH#]GOJ9[k(poհ`Pl:>=Vr'|!ZfEe(J?u-w$$ѰÁ}L1hkORH L⃮]K^-2́zކL)/D'NJfA<_gnph5.l wA 2ᨤ\]f,OUYeUo8H=3]38VӼ xa3;3y:x^-] |ۙ4k(5F?y?r;O ig9API:{眺fA2 (E0(eJ6'ISeԦedkpH^5u*s qӝi]ǡAٚ꺇`<-Et谵Rfk.ztdtb%'*GY"e/XeYuS_h,M'de'9G`T"< Uy}?j~dId(L%3 C匃Jz6XvKܻRd̈́v*!x/ bS ZbϞ jp^ƅR(0ӹ~ ɏCLGB[Yl,V٤V&a5!;GX3(t$,!i,zba\^'_I :wQQ/J]^WG}jlTˀVpKOǬ_;M9/ve޾vn\36E|+=4pF݋sox*Vlumhz#؋y1FU4_bwaTL0Ksᙽ%X1eI|+~\KGB9yfR@D2H Horu-54;r.UQ=U[79v5Mg٭W!t9x3#.wJcSDhPl f6SgdJбa*էl+eB^ON-"xf͍t]%Cm0siO2mpKG/C9]OAl;)%تV=#GK7Lb,?V'8 9BGݲz.6zhMLK޽}Qe8mQ#%q^NǽnGi.j3Ó qOͫWF4 RhпL5Q'z]1.ܚ|t!q'TW.P/;qE򪳋)u7ҕؼtѫ)AML3Me6 b%̰7āgcߤm۴-E(ލ%-ҮͿDBCIc~5đ->f-KVONܒݤ4:o}GT7ӄ]5Swa*U+bc^ܧ(xjDT*k$-k^ *rݚK/hJ>]}E'G{|kG͘i'<.ḻE< _P} !+t}yLM,"TTF)IN[woij{x@K>65aPoq VGܻΑR-/(qיBȶ;qXhQ#ppR5Ա*ӂY5tKo3O#7<4&ѹMx3^=-|d໬P`LRV =#9wo,.c!ݟN mȄyTNU=lC6eAwIh i`΍Nb?$wmFF Jέ2z׾z2<*vϬյ n>ѬL&Mz ҃5BKT[VzĊUZoɵrE%hrgi ,j,Vyt[FG@#6?p=r**d|i|.XNY,FA<&q'+ANXj5M> stream xڍvTl7%1:I(cm H*H) )H(ҍHIH()%;~L𲉹+F!` %7 h`hcPA (7"*@`$,G4FG %zh TGa8BB0a D^^Nw8P `P# aPo9BH@X 4]IX yX8 5.L @`n($(08 KC1@BmlA !+; >PTtCxÁZ@rƢ P(Bp8j k:, a%_~!\&UDQ8,W F z(kW?% ˃s2`0XN 0ЯA>F/5PFp~x,am@wGd'nd1@M0x [hw? 2W74=&55t /.)!II,&P_]E%kBC\Fhb@n_oW-?oV_ E"#`M`]jwE!۪8rX-D y/y#Pp4ACX"<X& v.IY +&H2@<@CWxoA(4$ tCc)-_߲4%o<0?* ` B_Sh۞/o7Vr/* .[?Oa(҄_dGaT:>.i L7_QmH1m< 9uJ6YnLzZC-nrbEZOܪ'wΤ0K;l]IJ Y}Ӳ≖ O]y(EvFryERExy{GYHb88yHލ\}J}l#rXHVKzy}f+u]?JL;b:ʙX S~n-mOSK'rꇯ]\ ̩5w?ϫ4ͫǑ^q9DkJEg* %Ọ(m0+tR9 rt,qV#Q:JiwjXʊrw?b`RPŃ1)9)mig^wB>j`Z4*J4$>*n :4$؄Z8yYhnw Aq$y6rD|ܑٔ<*ށI*Q &Zv o?k@U֯rP+NwnȌE\u\O9b*O"/w|mm,T.mf(Өw0>N,禬+  |ȚT "nZxi;& ƋIՄw+ \Űxݣw psxwW냊̓P᥎5O=+6HJ^뇉D4($c}͟*/LL :jЏ5H?.gaHVޤV~T<,FpuWZg3jS\C${Gz"hUuim U(@V夬p::+N;Ev#pRR? F$P}I!WFefm()t$0m+pٵ!g/HsqtM.f#ιYL;T\N+}R[Sd"UB@Q̞(fL- :'u130ޏp`XŌg(WQOBgED(u}e"?#.3 nڴdԫSuy=7R5kHȈȴV?FoGm^Iry!$,m YŔ)*2cûWDP^%-+]VjUͫgT>k|gilJL"9VX꽥G e3+ Dqɫ9G>g[OTs-z#1OSƋme%ҷq#5Gc"ݺWTzYA}m[[l+O#/V]3fn~fyD1jC2јu{ ߧDj+oE<60zM&\Т2fxA\n~zKt˻HTU>aքvd¶o*j+3b rڸkɑS1 <EΈ*VYu1[ K} 9!A>5Xʭ~hie&Qk~%3^ToWmyx\boa0myӰ1{&;CD -|zl-p8fM+ly/)sbem,Gq$fYs;$־5;vu%Kr͋G+?NIGsM3tA|FE];:m붚% )7㳰 =?O]Q|6XM,K~ER|(Z+9т'լ7 yqcɸ#IӨm(~2K̻sIu?k#k"9ܶDRG|DaRj.d|^k\MxX7!WǪqxTLZ< )E״蚪8KDh28ʬ+vV{ thՙbͻSb뷛YJN?yg@9暬2i9;o}iu77d-E⥚31r.D+ v2,JYGv'Y /6z3Vo*Iv͒GQ+{ яh|1O*;ӓ_JCTls 6*dhtR_~6vcQ}Cߘ:6_޺|w,EYy=f%A Oި nGCe'<4!rB5[t֮aomX{ȝ(,]fi qtw~B_:Uɢ+ڢީ\S i4pN}# <$v~?k)Dn0 ɻC/߸e5a\mjYJ+"l,s2sqyD!7FW4zŴu%Q [} .u;;eXaC?fwu4>x68!M;øXZ r2:)[|Q0zoIEF^z4o@<3Eq}8r X־ap㺘;)e /1|@ǰ{6wk@_Ok*7ϑʥ;3;F[m3-w{:LوMI3hfK~~}^߰t%hmU_HlvE.ַW5=bӞ"U)ǮN؁(ƢxuCg#) “}Xjx=Z21,.if [_:YDYŭJk'$f <1AOn7&Ͷk'LelmqK&\§or=@n x/<:_РE`EU=f?!yEP\-\b:;^fRLz'T9A7LܮSܾmqK[dCZpڇRk64bAiπ%% Ɠwwe )WRsKVi&WƸM8V3"좕 P͋4)^eu]T6W!wE&Zb(Bs..H~)5wDo^)+P!}S|XRÇQWCaǹnf^iOpy9X(5.djTrM ƈ!gW>u)A^K few'PbU۵`.>SUo4Ս f'TϲFWCVDq3Hx)W_gbL>%ݭ%]9Z-)J[C+I"Ha3)SoSm)Qsu ", p*oY;ft}'~3MM/͛cseC7=7%:@l{RYZ(_!w?҂km.Ǩgh-DžY E4\iSYfL[U7Ȥ#!ofmlE)-EjDug4"[~"p|ώx؏)e)w=qOuFӆ*^p7~^0F5;AQo1M&sG{ w1Th|64%Nm_՝yATy͟\|jpDp:8bTN-h^9`%ҧEC*K)F֠Af5S y;w3Ad$A>Kd<uRV0G[ɞe~ǮG~7\. EB|w1J7iǨͻK8uD1

mo\: 2#I_DZd,zuxI Ijk$:oF E&QK_cyj/+;lvU}o,Tuˤ=G3M2y`[1Sf0YO >);^<&aAAr{YL1+3ljHc~sY۩L@(ec(KM.dCw³2/ u@1mbAd*1WC-~|[} D2n?(WoݥɎk?׎1 endstream endobj 69 0 obj << /Length1 1356 /Length2 6064 /Length3 0 /Length 6998 /Filter /FlateDecode >> stream xڍtT6]J H ! ) 303 ]҈ Jt H(Q{߷Y7g}>y; "B-G!BBD`$Jn #0 k$ڦhDiuwK $K=v-: B+\`G$-\8p   Bz#cG$URPS!;<x}~ жvnL`F1쑞pmmAP:jg 4: g?|;ѿmma.P/0`:ʚH` h A` we9=5CH ա4KV)\\@P$W}`8}^ yB}P;_-ع An 5ſ=&@HrPz~|\a{t ?=G䃰pw#v`[$'; GOF̄~@sxput Tnߐ< (ą?ZB?jP{@O[WOoapKf, ٢?oWew7 ?Pk0oWw$Z0GZ ;jHk_" FtH[?Tc7%0 ҅!?PH0lя-R"B2~3 (!!t{~{c`x3 oq Oz?KHeMXv[C-~Xc^ӥUFQor5LnA mnHt(ܓD55l];I eigJ{M2%x(LoM:IFu-+sC$V>\7!J%f8.aW>h7^"|45s[,^G᣹x0 BMzd`O!|?Cⷝ(j*&GD/g}kE4{<9qu4imtWx$HWf'{QzF{*8a\Irgǘ,Hx5Ѳ+dXcnеX.K81%R__%0&V-L w lfJӊ-rbW3H/cP،QД(6I$i+c "P48-i۹"~Ŏ1õo_rӅ7P2\x)cT@Rj=>.SwQG+oki;p`Fd&qvee(䵗UZM;0bl]bw Lq͜D9#::)Y$|!~z grܩж߹]Oj6$ըi0ǻͫ,qOe-2H t6&4nU>rjSVHe5M\f@1wxJJC(p:oXJVR^7eg`CW=u`/CgX~3;oS+ 7Co鍼 ]/ڑ3?REJZ#JþҰMd gk̗]l%gP{Ĺ30J$ BѼeu%^uΩF%Msb;Uu2Flu-PP4v'ͫzXäH٣ޮ a +}$ű4._$-R`H]iÎ-&!֐*7CL M2EmYs$ ِ*l,b@o|Oe ٯJj|es]˶qsc:i1i2.ő"2Z{ڭRwq; 2kx8)LohuQH:utv|o~M+%_w_doG b\&,1bnq/H9)t-{{ Sq2(oY-7f)}0KO38s=c"Q`E·{jŕ@HV- BLY Wdr8S}8ѱl/4tQ LgΘ'>Bk9ZG%&н﨔^=a8S_h1yD,nSLC0St 4Z!nE-/8e֖@n4g[Ÿw(O$)۳>nq`bᲁ=ssǴ.Ser -pMʫ|='Gmټ:5,Gw=g._яV}9asF±,Lz2qoJ7#S8߰3SN-;XPs|*dƁK!a? 쵓)S}L +9e{pΠzkV.ţ< i8{&~" +qdrSFr<o:E'|jEn\kVvJ icj\2X7HԿ! lG*cZΒ]g('HXe1}r#7L :%RQcM쑢GMJ3$@-P$snHD s>p.٦*r8a:o ]F֛ށ~&ٽOޫoi[ꮦ7O䍈=w0WYpŐ8C\6R_OIWWK_c* =}-I㄁S=p1tth*9=UKޠ n6/PV5T]Se yq՚4Fh\D9˃U7tNӥaz%}u9&gss }n7Ks`ʢ]_$PpxjzHdju+"FOJv\.mCh |%*X@qmF`$Wa3f|㶚W 2DZosV}aȁ`tV*2jNV]N{8wcH٫Bϖ&i>ݮBVީ ~/+wZS*ީx2qU"J/:E;Y}#c<1{b~}!GJe#E&5}^~bzBk"nۢm"zp 鋯UTP6WX͑OOqߡAE1:e.NBeI'38|Sxehv W`Ι8c3ȗ偍r1A\:Ň23q=mӔ 8?,qK Ga +_`k}i7LћUca˴iIAZ X)=lJTpTґx^FNDe;mR p& v"LPI_#@՚{xeTA- ܽ9n@=\ rwSTyُ͙_6?XFg0*1\׿k1fyNf-gJM5A>Vx(.e3Mop3 P7Gצc!vFko&GZ (h8٬2iBޔ*3*+ޭX*Oa%5xb*}>!}0lFrɚ#Ia6}XyiՀXܹ1I2&0uNfUЬpbN?i}GG75 1fm`ㆫ_i&pA[=(}"XNV-*b+l7r`gSpQ9/yi!{Y-EBۈޙc~Cb`@O ;pa}I6n-q 8}*ol$&CmVf%N/Q$f+fk>+M 76Wpe)v .rqWO"S< %KjT6KxmSSdD3/`^~EP^ LQ+D#S"_ž +O$gWi5Yc(rKVY!4s3(.R%Xpn͗xe2[.rs7a&;/>wNODHrn5oQE|_f*/Z-PC)ίEJ8^y*^[TD|q1y 2LH_Iq푅i/y4.S$FwС{?wlkjBy͑lFd,AfQX aޅ5Ϭ AB^PavC5g}Ytb=eF0B9W- "N*o=1_ OW]<+cEBх)/a=gX6pb%UH}H.szPOȃ&w7Ck&*tn *%pfp(G?80Y5>j㜃LJɎr0|lVb75L=Ƀu̾t+ :6ז#ꇔlu׫Q~0M>5|;t}gNPxc6tݚ.p`ёʆG%|mʅ4}lO[ReXIAhL2-X,jrwgrrkЀ ~= o *"Ϫ~u{7Y~A&VjxTS]#{TGǚilyF5ޜIMIugIxi{:#U/ Q*V|>ޱ#%d"&\ u8z KjLbԻs?K^.Y,hMW- ~ t )(n*!dPæ@Nzmhܽlgط:Uij"ODS5LDJb,Ziуn! ZӘ4*MGހT_C .҉wŻKWOF}@ ;au ^e_ʽbͪG>BFU{^N_p o,`}& endstream endobj 71 0 obj << /Length1 1504 /Length2 6819 /Length3 0 /Length 7825 /Filter /FlateDecode >> stream xڍxT>"RHwHwJw#1 00 )ҝt#JJ 򍾾k}ߚf~ygﳟ}fְ0ȃ#/P20 ⲰB08.1 K+DaJ@$P B Q ~~ ?߆W  hp."jD#wBA@8@ t8va Az#" tvEpp ~ :CƋ0tE 쐞@W  C\j/cͿ  +p;A  0@GE_@Ba@[ԁy=U@PF_aPǬ +"!pܽ4 vO!jJlP1{ /."",<@@|60v&è}].;T$ $b;: FGO'K8[̧gm //8G\ 3.'U!:S?g,mJ_z?O忢BTa<_t¼XDM5 655Z0Y5$5 p{y? @ `](j~ "ܠn?q!9n74S s_e85l"+kJ+J0뷘|p@Cj# 1ٺA?a?`~i?TW w( ꊚCxA@sdЎZyZO1յxHa$K_MOlUT#i eSs~_ƽZIUC)o(};{ka#h'DӢ6 m,0,ؒLD{?tmD]אfObI\- Ռ&nПCc/:byoXf .{?M@F*G1w$qHﴼ8F0'7KhVxOl̩,ӘGt[sbw=4_d3"7$7FK1!" uRF_T)2R:E:E,%8z=Yۺ b[iu;ؔh#Cw̦EV~X>{gGƣ ri>rQTA @Bȶ&.Q*iU8,8Esk݄j,Q[0?o&#i[nQ]LuDy#<߶4yJՊih,,nvTWXFpZ~UkB5WklhÝگuD~riaFk t[' *'U\0|+K@qr;v(,"n*[kA%LĹ*@es&{hIFt,3lS}'i1=ItcX-!o2oW=ЖJ)nJיF%-V42QDj]qxe'b0Y1>m٣- Q>drvЁ'LߚR2)y+,ad)9RYsRdv:Pm˫]Zgx.fՆT}AB!^? t|5h𾌙txoТɢ/D"jd9#a{DK~_v-Ʌs.Tԃ`RzYW1a\vձPJV][8[8"U#_t4 ANc>Hv}#&>Kmfd+3&hǦx潲^k=X=S-g bKӈ>e |G#4 9#@bG]N38 D޵Xb<<3l5uvjI,Klvke }nőh?C_8YFi/rnf+/|! M\_0ʈ` ,# ˛IzN %sS7f>k9}+=ίiRonU/mt2-wdgOmt"[HLzx]CF=K񴗭"o%Sw6=ĝc)U]$i7Iԇٓl}+2A>y2ԥ)a*qc3VNw m?$?b6f%HX5M_&ě "zetj6gM_r/̼SڋZkccвgOM^! J L1HCB.M,H(ק:/b/NX ._8ŌC3QmW{%-y< 9z_З}zn<_=>r!*$3|QWaC6c/Xyobk7[gOVVD5hM|V\叫DDΊүu+G:3q(~!];S]2c+vc/{Y\8K{A=Ml>gK8/g ;{35W Nw7nR9Z{OV"e>&lo7eT7zO6&{GXOs-S!s+E>c0PhYģԚƴ:]>RZڡT~Z[4:/'ρ@7%dszAn=5xO~:@d]|[rAE4sKY@NkBa"/3r2v6K+H:8!|feQ#V4CDaj];8gsy"^X$||a ̷yE{GK)?Lte$j21Ry9Y΋ɷ/.<)׫ͪ朖);ɰ8iXQu*Gl=)lmw|`2^Qig?o:R/&I^2R0ɠY"&&fF,k)U,`5HpꚵyOju0a氖vo+DP$̛M*h7H܅Ѻ Dc&[vㆣ{2co-HgB2>JWaw:m/|Rښ0-q<s*BG_}En)y^YuƓ_*'> Z^ e&7^vAf_81;91[>گ!8ٵ!jW0I;9!sW2IsFZ)9ٝƳtIOT0'vIc8kHJvb9nX@EG'(_qR<5 4?EJ8a˖ :SsL؝\y?dߨaY-%*acgu[j=Vજu}~zdZѠ{;ki2Oٲ{`9!P9M*,, *]/MnQ"Z!WNZ2Ǜ<bHP=216* ̟2 8f[g5jm:T3|%֤iVi@6Q{',yZW+]vpi.(,{6LK i%L'>fS,gIlUkfI-!VfSܸ/UJߧ*-ȺbyO鮰H (D`^,^?Xu`т6l}lH2m#5st[YY`Nf#>&a0R@umA']]T('hcm<@c7[kfEHv>E֩7 jI2baDL%*>.\MϯZewDlO& 'Yz&Ta: 41bq-('R?cd "] x#8V@h]bW'{AjA#>lT.&۰20`bTn])<;)5OLf}ۖC%7$\ ?7mՕ۟㨩lK 1 tAE*tDeL;uְB_LMH#eTz^{YLv\v'"xHKs:d3Ms)kobbgc|-Oc[s"ǒiiݘ=2V!rR4K/kM^5 !#*nË{J> ьvC5#!X@:LzkܭH5WJExc3bءCVsI04g)s8Tl͵ҥ¿E,Yf @ӬpX_?L7^LqmoFk߱Ы*9M=V-1zŵߓ+xXt{3)=˰9̲f8f3x|uZku 4z~׏}`?qcpӞ4_˲=lKW}<^k^\KtXps }!r&*FwteHWb[) 6Y]kO۶ziΏk `$yxj,j4g,>OC7.)7 ƂZR2 uРBiE!wILz&m/CtnN%< j9s%W^~XX ;ؓ%I6hzw-/ V[UN˖X÷6hsn6lLߎ5J2L|bq^0TyZ~dwVZ".>#]K]4E`%+XsU8]ý=ww(y?#[3;ޕ=joSeY2(J_In@N0nXUy*F g1 pm(oOTN}k5#sSi :Χ7ւ4ԡܞTfR.)OKh.zkZE,:EA,ulk\6{zG}7ܐu?kM2֡8%s먢7u^U:+C.o}m ZZq$N:anaܾ+]z4iCw}ڹ4XYm˳l30N -@Zjv9^1'3ﺴiE/[n3xbrǢ@dΆ|sTgOS{8qWeVtsh{ݙM)p4_qud*jǾH]SOQš0=P X+(MS&opdת73gg$q?ly~V%(wض:/|xzxDgм:L:$0K`q!g0+ r.cjwp@biNQMiz:YI}ڶt[[NWR>WSWw*"H#T'\FS ?e҂YKun%tSJlL׸r oƽ9تw!G^Yhr3~h/c=ø8کeW c;h8\}]y!tŕ,14OWצ]7d,≩pt}YIN*B'=,SJx^k88*ƺ2;:0փM*qF_cbI|w#i2#C9 ` P'[TtOy1anKv~q3 h8*(eӓTi]> Ȁ&J,ً Бbx&\']An>#l=98 ]0m(z ցӫUNb,[hܪsUAt[]*bJWQM(ˋaݨ'qv's*}:U endstream endobj 73 0 obj << /Length1 1798 /Length2 12718 /Length3 0 /Length 13851 /Filter /FlateDecode >> stream xڍP۶-w ]݂C4x݃?_^Q|ck)TԙEMR`3; @\QC ƁLMcG:9|w@^m&@E{0@ ` @{'>+<@V>Йyy?0:LE-@ xW :+ā͍ΙR XԀ@'W9J&vGcAhXr[@LW- v~Mq e `G!d33{;l R ,wlGk 5O&)QUlr88l2, 6!9^݃˵ۻ,@`s?0wq`]ǼY!n666t7bO'cA^&@o#dvv9 0ZT5-¯r|d{;폿2xU=?U\]FVQ)&fb0sp9^? oʕ[xzN^zRU.@ٸ^gf$bkdwīr] [h  ku 핅n(U\,l\AR w bfjko 0P |Kff8JOu$e~0qr2@~W bJsb!)N\V?L"6?j`5XMAVAܯ>3{ccNVAv+_jO+ W^VVпkwWjvuae|%/_?4@@W࿫-_\_ srs|%'7sqrz} We@3{3@rѷnۣ\ha[DwsS;wk؇/u6:l6竛,L7>c :+pȷs-O.E& ϶ShKo~Z fA G D lMm)jr>=#ڿK](b'=8@sL=J|O,o<$|JGg<.?Mvk\|+RVͲ^o 'V|+h)!?CDAc|F''7mQgq4JJt,O iILC)8*^fHCNQ &M_ֳFc ͜. j wZ9$ޏK2XiYcY*3g/zt w0AuUt0U\Oe[ 9oZ"/םJ3E5|j$ 1x BX6T;%Tb"& {,1Ќ)H$KNU09ʢ*+oU*JJdtyC=DE.9Cؕ.>ٕPd?7^mwUQ,@`1>/$mB&D;,9E)O{>( `"Tкwx-E MĦGG5?J̠yy\dOcBA7bL/J:Fu^gdxCiy|oLR&.M.J-o%g^=q 0UwJ3U%al' !?C1g:5PPnz ΓNJF*:iO,n?㹏͑(:} tFd{J@͖>j|9gb~C}yԫq1m\nYU_+ٲH9͐b;N+pZ05> Kkh?[8KRVmRb$PNX7 Di}]j.#$Lqh2˴F5'άEoE3o19O~I҅eV`'*wi knkqulSX!+c>˷9& r%ΨS7<<3P9^_TE.Y&@L3 PsE tzQwxap3_\z8%hN3< X< ̽Ozo=)x;`F[Ob(8q2ehdwv(tO{O>aM.G|`@׭Vng' bCJr"Bᢲ{b`g@BH)7 <ԣYnVVnbݡJ_,RcIgh0q7-Q6'V( {b储m\ G1,]=<ǦCYHP}-yϣ |-GM:R]Qs`xrVg:~vSa¤*G9Ϫzol.i[x+#Xuh-q0u9IP7xx+Mj,=JWDdJ^\Vi[UwC͍xHaey.V(~,wIi/e+qp RsOtkdO]@~T%T1y#(+;N}̇qc:tg1[Bv=3 a砢``~`^8̧Qeؚ2!hbZgG݀,ps ?Zh! HaE3aWxRV; 2 ZYNUwQ{*$EK*G׾jQiFhe3.CMRKxǢ6_I_=->a1 %d]c8l%\ܔ)|W\{ر'$ u`y]\Ԉbw+Fy)"J?./o_;N .Ě z^lOS|ƺ@ _Ö6Le jh?M >p3">*m FVLy/ԽKc@\Bp,FE  V/"k+fr{BaN׀z[U:3&2lbed`I*tOXspdNe-B |Q)֡g2JF>Rn\5S:yv N0DTdCװ u: cɳ~Zq'Q~hQIP7_]62c9i1UPXjs"es.3qPUU |ӹa*`<#&vV(z.HVz.[ɌC5P2ȲGYLGujed{)X],xG7e [LQٙGDEvz7𮴻du0'?i2S;7>Y,q͒9Q3[hϝ.|; ᡤ9=b+%5W<_ GtXR -9!`ފyA<43`'J_vgmUjODL$\3#Ѓ|=J)5i:&`] nts!=8՛ù{BM 8LR+  'C~%tX8wd/z¡υc) P߈H|P=/QM?DkJ،c-g+EP%qK΄sY9{ۘD9=vbZu/=5Պ+_f,S]ފg$}ڨczc#Z6t]΄]t3n F0aKI}1iPП27;ppDGe]\bP5hm71؛A/,+Re &e_"eZav)yJ22|^o #˂O巀4MUX.ŎLRejv&pmK5 _TorD05ߗez!DnuvJ͟/7`u'rn eO Q6 E*OFd|?sN~] )ϫR"ȿNBZb19N'N1 -aqH2/YNKfY{7hXA,^پc, w,\u'K 3Ѧ;\Ť|Egs#ߠ>^`¨g#tDX+v&Wd_}ۘ_4(C~:Y z kZ"q<+7G׎srfAv2{+m{8Sj=[Cb4reĸ] ] >gDhE'#5n0:﹆p)!,?t%6bl2;4DPZ3JCytʲA6r¥E\L2hדH\uŔF;I0 8;A*n3Qf ┖u\dOF`23Sr*\q%#3p N]5KvT Ⱦy;(#Ow<#r>bf#\[X.p8'œǮmiN] ,TT}>E%?W `%?8!#Bcrǯ#ԶӀH mnضϕL}+HÏˈdtlP`_ֿL1H7v+ t5H;ϷuJܗӵyBM :gqcMR($r v',wZĵ1y@) >|NGdFmRKN6_,x^;ѳMt&Y)1c>5b&d sMwU^oYDa`6ٲ^Q(>ꡢ';K *oETDW2c};Lqd4&t v3ZyED Ƣq RPXpIU[ 7 Â/AzSCݣ~˲|K[ av&k內 &%-_uۍ>AËTmLMZ,i?PK:9h^dD_oEPf3{ʲB[y m]Ѓ{Xf>e.G6f!w4;6 u̍/駖&+߁ sJEO8%{4*aX2ȋ)d{J+ﴼziI"l/NڐQe`xc?iq%%*֬]xm,o:Q-4{!$!j/t5θIPåBQ1Zc|a:\$ C-FcbK{<%xB=JZⴈoaj:(*Ca}Gy EFWBh M5~v0ƫEPgA[dA}^ow1}\GʠKΏQyC.UIC17:C&=;fC]:B_$l~_wvip "_->t[=2/!H5Eе|9@99mU5A#fBsR44tRVɚ% 4i<^ꜭAĬdU3CKf`=>y{|)D.d EػkJfzI[A!pE\kv^1۬QPfp:8r ¥ӉV2, w&"1VpXT/+K:f<qBG~sd8X}Tx3QDkf'bM*ٻBbl:$I:4Db5 a1lƏcЗZ-ZՏ4}Iko6+>Zlδn! kKZ,/K8I}tzn2>ւ #dn@y[^$e1IdA8l2d!ۻ-0PU?\4a :4>|{T`Opi۔v1<-l;$ٽTntfO:'RciaYt?pOჄ/2(.V#3Ĝ|&[h<3SoJW36oUǽ9gs~zAO`.NkYyNפ6{%7D9B(V67=OMJةCV2Ο8V2;jhaǨ*F6-i`Bu# pm%J5=6&VQh|b=3^m&PN9y8y*a !c|᫉-]֝A9cꆈ>\U;T]_EHSH hw!L ~XHSlT6ļšHn3o`+B%M5u_`IJ!<5D.%NBm\lw VGѪ2!ʈ#El#}47#Bs2RhE3> =&z6 XD;%'GMKdoM@!x~r#-?YOĕ^rp6ɘ iJZ`C ACnnWrGWQ[EM ?җ}u! x7*LKVu yTP3TK3rT+9 z RK6]%'h1~g?CXFDt_~V d8'F;L;O=l@5HpwvxNt GVzG;j:hv%ՓAO^@Frl0J-EgmWvN-;/~JBy0%*t5~FnƩ"՛BseCzo}ZHҢyr Kz[`pT3l9s>8V F&*`UD~hwOє\`ۣVFU9\ɖneFiU*}ia8 1G&F`ЈA@Bdd _4%!'IñyirDuz+gߍƉJXJ|! u26xMJ10~Tr`CcRM3#Fӏ&Ӓ(BF7H@ x&+N`bpQ+Q|D>YRW6y)GKYO3i %^*6a }WˇABDnUL~LNVdcRqL[onZjG HlVڼz˾_*=c&~#efdԋs$`DQjbx_, |4}F"{H6#zBV)\[vר9uS>6c4e%Z cJ_稒ihapLOp-Eno<}&Q3Q6ɷqW<ae=l7isOF,SEbЩ^U%w]I W7 heN7sѢlŞ!j,.iez`e ~ѨiiՏ&.hY1{5p%%-ڡ+1}}s]_?ۗR&x[vG~\Ī͓Eםh)܍W_ >L-ecوP/{ϠZG+2kQ_DܻT3~ڸu0|p‚Nw5x\eW_`!q[r pU6bIr)"JWlɗ1оa nݝj47zBSo w 2/yc:^czRϑpD诅Q_ 2N2_>8/h8 خ:A8\wk?T^R(T&N ^JGP%e߳qjɹj,Yt_9ϧM֛ٖM[? i[ jr'(r&SM$?HWo#..a>f̎tEv'5+a,7[s3t*'+B퉢.ߡ,aSK0sR  +>{.[6h;B<, t3:q¥v+ҖvO~P1ScB(*Z+Z;޿vh_:It;߇!@_Ga`VDdj!$ԐCצa?& ۪&9c'a-z0E_/~MvVx)@@VF*w̪`65G(wu?2^4QpXy Q"uUx4sB, /k+鉇3N@N>\?GN<6~mܤ5KF8GDr7jס"\cmvZq@}CǸ>UV:g~؆ޓ"WF>C[RrH<{C_}V`&^v//@uA<Ėy{sZ5ѡY4q>F#Nf7D 4ʻ$z8a' t( 0{с6P40rC/J5?>=`tQma~]NaA { Jxw^B`=ZCi_2//)8x)$wLt"YO?>gV вq5tѴT0h2QV9Py1~3=W{qF 6p%P$yeoOj"Bz]ȨW<@Qt0PNCv5uQYx [!R]ݷ"͒8M40PUc OpQﮂ: `-(SHM>Knq푼rݪVIBWB8O6Ne.<~fvz;xetz9Y.LN|5QiȝMhB߲G ;_r큃)KhJsqbXJӅN f-ʹަ֯DQUyyK7Ȩy[ϲz\⭟ D(6iVw@}[|JR7^Z#rxX٭Gg;)kbQ-vs0-w NjPd0Y|O}F #7c)`?nm?&MM~z qk;*wrp,p3ClQV7+ض 26Tsy#Ude8co}7Wf%m"y)/6v/{֎Ț]';[]7tNUo4(T㦥εui,f NRF߀4b* @<c|݅hhP˕ms=+Iߑ"K D񆓯Zd%өģ1ߙDijC)"S6zyi섶Fb,bG^5T/ Ti"{S&sO43:NaoD哙ʺs"{MLHZjXĢU6r|Y~١y uLeP1Ej 0+o} X1ѺFysc(6ƀ[KiƘWMc**׋{(DvtLT%ZCQc̱ X~O9hMhe}8!L Ǔi ^FB_[IS rLJ͋EK^0&fNitG{ǗϡEu&4F`$<~02)ꔳ5qSV-މH~Ji"}%P!F7.I$߅X` <]QC!\uko! ߾q PT'6X&+Fa\%Oʡ*qkN% KPzU9®c|72^3 3xԤݥ#|]\\k|ON|:ad) vB @W"`.dw * V3}ƂNo疋> stream xڌPXw']{pI` <{p v;3M2{UUk}sJ2e5FQ3{ #+ @\A]†HIrOH B hI 6Vv++7 N| c7@ kotFwtYX#Ɣq- djlP0vڂ=MA@PX8133:3;Y2A.U3 h2@OjLuK 5{swc' ,G\̀Nw<@h `ebӿ@v665u0YA6@< 엡=1lW)Q18s6u9839l~\fI;3q{[[3$@N@Sp=i9Wfv GW?6`o:̿{:Rsvẃ?n@+O"++ d0Z@1N . xX,~03{;YA\UTRU{9lNvn/,Ơ㤌=`U_nL?A /=xncb y:oH/=?zc[?uu=x&U\mV v6,)\L-dTwY,,G^.Sk ɿT@ףٯ%c;9{"' F3_C `fw;!j)'Yo`x̒"no`~e~#0o`V-~#o `F`il_ɿ6`6cgSdj jo0o6116v1v8-'cS 1?_Vֿ@+?0qC4̿pЯYb]vpml|0.xzqK Ygڲ+dlarO`Nz_O&Op:.% o\Ip ck~##'vmjk#$l;h0XY:V}8^~b0Kcpal\H w⿐+_n_B{}G8XY\8N&/8߶g֋oW Pn0p? 82?|;80oWxM]rm}=KV5_Dwg(w5i\Qh6EWw$iDICTZ| cUv['q'Ek^#3<9n쐥vtAUźu+] U٫Cz,fԈ/1ɘ'sa|mz3kT6$[g-nk\͹@5A,ނwqaĆB& -hH) &(oK-V2B]1>t^P'z3hxEOュ%++Ӛ ]a]mmF5G_l8{<>Vi%=V'3{jmeg )hX ܔCWXzU-&z]CR+L{9:fbYik]I.q8Ĉɴn儩pKT"9XL!ߦqꞠk$ffLN '.Eԥ [L jLѬ(< 6Gc{q9]D}-YRwQ`yZ:؏D gV] $mA ZȩufIPBIꛘ&xɉƵ\\?)zE/< vL:@{$򹆯Fz:YOzNp6-P:x x$yE˒}w!)#:j8۔Hrhr3(BY钛ʊ | ajl"\zYŒsZ~+Wp-{`o.lKG+5Ɗ**~n*V}3Ė6q'NBmuV6 t$qo3z9/6ڴ4FVW){ h!meMO!tFLiSFTy1=:" w \ hL7m#۶,!'IntRcXj/"mNj5GķL/<}[v7:җc$ P?,g͘O%bn5 wnGYj| Nh{N:+6` g֏`^cB`L/<,ve)@j=.ZŐњS*M;D#x?#M*\#Syh$q[^٫?g'O'O4ň>ih(UeG/l=2tcfH10L.2Ė ϡ$t,َg~~UB8}ћh~J. >N,?y74%ZWOj|Qe_RP~ZHYTߌA %]%ﰎs szxcI}/P΋'. ^ҬY-XeM#{1ۉjA>漤 ZLb&LA) xbr,, m}ʨZQf)?p{ t­qbza  ;"d8kD~z3|˻UdEW8zޗe4npOi4 b0 mT{nxrSgb/":~kw"y@]"}!qȗ!xΠgx -l`"y5d1ua-#;?_k@My쯷 C=ȅW^hPj^P, :I˪@r2ӝrGNyjCQ+?@#U:V*S}oNnNA# Iz*+9p_&w |!lIC5,fn:1 %QA/Zҫu_S`j͵DQ RW /epQwU9o[}]/Y7RL6<2QźNd͏a1?e}<̶&\UȎǃfhxAᴌ8zoLB7:4wGoDBƹ͔z5Ãc/ V+2(HFH=xe`9#-ɓt1TY(Q =VTJS~b&a'.)#7SI$W!wwJÉb姾*3(tD}t'R 0x,ަLܛ nn+sRˏ)-9_Ng4؄/-ϰU˰8 j2܈&WU%W hCǠl+~VOVcQG#[VFeOr x9}?תFY^7V2tjX!3k/MwĮ:jNJ7 *^Vby^?NچKVT꧿PRxs5Qt~;hwKgK?Z>U ]`2P .lAJL[=nW=G8y<4 4l'm"e\А%5Vt{Dž/ٱe^t*#%Ij ft6x&XVC!%Pm}E,=T.~ֺEAPmr*HE:Nlz=锻REv2^w ֧۩%_ȥs:MAwo]*C8?YM{ 8ۯ$I˩MF?Soӫ}gyJ$`"~O@Ut x97dS1 H U)M;` Umeƀ }SaC kN^5oYͳmJw >.2dg'XXCI`5 C'g-*29o]Fhu{Ev| 7 􍝸v洮P52@A@(^R9mTo$k(VIbY4xqŃL?t91@A!pS>}?ͤ#PA ^.MfnJ#+K]s>펯1˨K e¯-#u 7t O+9󫊩yB)%"ÆΔ~/g\?eTk|S=y(Kc78};89JSPmѿhP 8Qk|ɪ^-ʢޖ3*e/ 0gCT\..ï>F.wVTWc6 7HKX5kFwLA&G.e1GL C3]SUNnVnz GH[u[ǯ'O7 piHN<,ywL[aĸ@/QPZR摚1Kߜq4^s|g3ܮZ`5x /WK]itx_e+YEÒ7tjW8)HB"K!npn`H<)ԐPw@2`X'Bhz*5S1 >*`tڋCWJ?58?$H6} H8үٗqTh1K5´7P Y;#u.C\ǹ霚‰>%)d6vÖ*\^sTeeG;گ?xGXl9Shg9 ]2n u7qՕmZ24r)Y=u!L6{v/[٧lc5!,$^ɸF)bQ5e7ǵ+}O(>M5 i255J9 \wĨ}/"EИݔi%aۏ tvO Z%-XpUtȋPJ" Mvk5-QK&Hhvʡݤ̧AT7B9uXNg;OW)S;+;t2zt ;gQytE[5 8Q~n2bl үjI`_:]CG۹g2O ASU!/o!RzW|*BWa3?fH-1Dݱ;/Th`@aB~[ryJ^B: 3PAm&1;ʏO΃ޞ5Dlet"bX%^Nwgg_ SAFB.~pF}<=ypAB|5xn~'e}I{b%A+||Zե""7f '-D}Nr( J;cq"H{ؾr{? ^} Ff.n{av%2>Ϙ1$QƭU .?b{$pt|G[vQݯtPDa[Lx99bS 0;\nQ ȼUv3$o7Wz:&4ë' ᬯ>v7q$VzT duznVW56թNlfz7}C*a:sQ;\׶)LƬ Sy8D G) eD`\izn9ؑ*ySlIQ*vCͼE$>Y= fjufj2;ҔlecNyTvgMj&'#C̆tܖ$)n,σI̓[}n(r(l(Vn[Q l]ih˃Y%BSm—fq );(nN`=mUFb!дi̗̚\B}MsImx~*=j~xt >@0NfuvqW=5-f#=X[ՍFP#g%;DŽjeTBu@Ye.w-SLx̞[k|jg (ޕ4[/5A@;bHIv k!ze$ifDD|tqj柝bN2-sQ>?b6*= afŢb E݌HI㣷jK 2 LzaIOmDHyl/VLx<̱ŇSE}C)싽+^N Z'>iD\ZK'!ذ 8 3V(3*/R_(ߛ3N]l13ɼ[-|5~e=gݴ($A_g`:X %p)bx̆4RC͵^/|W~jaQ|55d2\/["HoˆMcB2Jyq~0 uI±= r@L2'5H2ih~3- +IZG{.5 SwfVg*\.)\V =G>RlԻ/KvQoAX3>i S 5* pϺ" ϪiB=>LRf'A]#IrQNw@v]Ctҿ%x5} HqtII eߣd\ؓԥ- /b{ݵW-Mڠ}(6?>)UEH.37( "/oL{ }ٞDtcOŌ&*_ǒ~! ߸9g{ٌZ\*;Vgxl;Cґ3s.;vRa m1eȈ[a4fF~ڭ&z? ?]=$|.>2@&N 10u,D,7 ԿGW3]rU;g޷mn\@{B!%E}eKiLAI= gܱǒd3igZ7Fϐ0v'L?봀IJ+/ OH#0 sR%J2 {o' Ff8dFHs9<VRvq$|oLjEDURbl2؛±RXc& ϣsTDaXsJ2.)| iaPJ K4fcPugX-F{&bҀ9(釱7~Ea!^^-af.Wq4Y5*oV1i ҦKPӗsW~3@v$h|îG1̮ T߉5"ϣUlYIb kc ߙw%Iu[fD"$@N% rHĊaԲI2s|@1 Jo}l@d@Hj_Fl5f9D{DSamd;!d Id;t1ls}9^f:cU؍sy~O2Yfq>/JNF@>(UZdr~d͟Գ?;S5  $,=MuʥVU^}R$Xӣ+UWuj)yAW4\QLUz MSfɛ{`E4uJGb{׆C-XȔ薑\Ӡ)/YB!i5N2^m;E|~ x)uh[|1.؆Иy[&xyٽs~>%*{o;:lԱwEFf҈** ʱFe\7erEJDEڜWC~]@WEƋ"(rT5M*湄P1`jD랝4u+P">2:ǤN*/.gUY>NH =;6QgFNAf7 ƭwa}^J Lhe5>8FqOc7r UkqmBͩ0ѷE$ӈ*deۙ-#"xRl>bϹ{4K.:i!=m8Mz~:F9}EW/:b:ͻOܧmZL5ѴG 8~huű ~Gl}~Z)X!ո,V=jƁv؉3h?Ӑ\`65^~`%Dw%Vb)GBc'3OR̯vF=kBJ,bxZH7娏nrMgkɮ.sKJZ@<@if )d^; G֨{"VfPr\-Jz7Y -|iꢉG”Ԭ &iKIt+&?<U7, x{VryƗutQ/S:D?Fb<#Wd-yNv8|ǯOp)X]:ü9?|vpfvZW ޺j*eP{%q22G ))\!!8n-yB- -9{FtDYܸtKV/j._䐷 $Ϊԇ'm -D*v̤%.>МH(p~AߍA!2Xgǭg:O ʙhCn$-×ժKAc,PK| a2h#SWxSRC53{|ڰs%U> I7rY.lTp+nfq7d 0dNJ)th=uy> 斝91q2c7 L=Bkj/|FesZdV2z)%|}U=<"dE|l\Ѣ. dS~|i!}AEKdtUEJ67R{|=T5YaOz[bCفqб7ͧ˚ckPE:݁U5g&<}%j]GbKنcG|X.No9nj=)zxRæK5_c*Z8('*8\UE֕6\s:*wiLD\I D̈́[4ƒzNc1}cI[!giO1 y_x[U]vpNc!-o)2FlkKzf EΑHiGTLsRObsd2oE? tG/`Y @M^9*VyX{^z}yk ,- Ʊ-wQLqnc$TtNdXH%DJmg,#Hht~)sieb4>6!fo-^ <-DΫN y 9̴+ sIv7*oC0$: ƔŰb[VN,eHSF>V6{df~2|uoo+=QNO1Z@Zk'>Ui .]q\%]qrav5qb=y5YMFi*y1 3(Ѱ ӮV_ /y͚1ԶAX׽X+c,{y@ǺP? G~u ꢲ \lMϭ ꩍӵjK7{=%2liTc4ma j nOxC.Sr/ $*a2ʄ2-<㩗 Hm 0YM@nf%tOqN]nVׯW#0V^#֭T)bzݬb7&M(|' `*gM !TorF;zc:dEҫAcIJN9-o룡H] =Rge{/q4(&63үRp_ݕb+\XfEvz$Ri:O=! ksvc3*G[.,蔃  "kz* Em75xOJO.xEk~&JxZ_Ni AV=z{P?fpEAb-Io(KDZd7/I@+VЇo< (r6 :Q=sRBEo/ d"lBnniILrO܅psɔֺVl:8Aj+DK N7DZU!@g.^)Iu>Wb-6_3\3K/w[.;)Gf,fMp$3qsP?O?CDwO33 LDFog(<:a0?< u\Hp".~Iz99S]DAMP3ުq1zpK5=u -Z\B%u c?0DJ*!!0@Zg!M-RW=5vCcnoo 2L9!@[z/ q]rۼ _y"@=6)??rUՇ,?1/N .Odix^Vb .Mz2A&Iŵ9K }8[~5O0w- ILѕ ~SI;7 Ijs_7X ޗiK.m!p;"@RcҷjJDIHLfc6THSk^[@e&G@yN&Npv 0iXianNUByD~S&W!m H\h.dp-{t=!^="+C:m@Vog?J{|nyۅ?>D<>yR#ajAm-JT,Mq>2"H) ncZ؎Uiz DJd$rZMrEtS# 'm !6Zn7МL&f$`BJItOi M1Ѹk(YgژӤE>E "d!-lT.2PlgN%qFp>ĵf7m0jGsnG9ʣT0J,䛈pPJUܵ˟xP 5HV.BhV&_NmaJ֬Ȏ$wQ{Α_j_+!Pm|gf-|!4!epԲ|dRgغWA 2kпi^Fanyz)9l̿-2 |77(Ӝnmy"h:jie<70Dgm"Eױ,VfbOulN` rVWK'T{@Dޜ9Z>֬U6Bs?Z@!tB3̬R%<.+ f?lc*\\W<[vƒ;+" a8(.Rޏψ>^_gk_5tCܔWM߰]ml*P-o9YS'dʼnLUQ:79 (t1ZH~ϼWhCsfuIɿUm ɸ^BT[A3Júj{{OJٝB>Gx%N01~u G(SɈ]Bz `KUݻS5*HNnLA/X_''U#~a rJCK/F{IO*m}P6~qLyyl[1%Yѭ!侥8V_|{;x>TEMW$pyV'yCQ0>~h@hai c++I??ylE]~e nEÍ*Hwژ ވ4Ry#Sr]P\bHdlc>rV OxzBGX~C]̜WȴЀ1w$Z'_#me>|ę&ML׾t<)7tysEPl& O`m\xvy3ӿ/t!_"2ۮ/yɋE-@eg$oupq (0;ƓjMUo ;)-0VQtJ&:Jxa[\f1.xzcHNɅXpi篍A.A]>X endstream endobj 77 0 obj << /Length1 1442 /Length2 2035 /Length3 0 /Length 2961 /Filter /FlateDecode >> stream xڍT 8UkNroNS8G"CƤ}c Q\Jcp3**c"yϳ^kk}k}~;5LLoȒp5X0sq!EEˀ1n3flE}d. c"M@#ld99;,a"hda:]/Pt`a vd.CWI!n%T \.KXd>̥' * ~hX"pÜ3@ !4P!6@Wֶ!`y:X@[d2c 4K[,7U$38L4@do0:X82:| fq9ẌA1 3 "L>Ţ&c\؟Y/`P?)t` 4$ ,& 1PL0. S̷@ҏ^aT&;b # 2Ah5uI *;Bo tEwK PY*=-T|/MqAI;1sqy~0#hE5`D <\2ću#a%Qw\ }nW0`r`4xO1T\_ࠔ Av~\0Iڀf0xID P5R9arN hL6Fp[,p[:"Q$h;Sߙh%ޜCtCh_+! Iя_U1DHZ^7vtb ~3q͋qm&U^|MOjSqzoмC4~ͱWVzxi"Tգ%N f5z2P*p>r0VlqqJh-*79ScoZ3f8rpT="U]Uu!)gje{=͊=53I*eQ*ޜ;.i\Ɗ__9l glkv -Qj>b;lMM,ZC`EÃ>9&/mݴc|:ؽƖVׇ*pIʆXwo.ƿn d*,nGU2~lSU3T|%+ Oݐ…874OEH l\;DM=oި7gp4Ipgٶi %]j3VW%T>:I }]%=7+X^zip!!n@Itqbku6pһ]Tp>$I-y$=߫VXr.SAbE3nݡ-3dù)7 &ghugV\ cj95wҨJ+?OfsqrM:a_E58$biLoZkFRo~uۦw>)t,<`$ȒI͘Mt$Qd%Kksv$c㶦K\Z>߀uD~^\H+FH/{4+x>v{-Y)[Fprri> TK7X%GFV}\ןgX}ԤPM*)U$ZF2L<>ᵱ9o^\KX&+ybѲH\r0R3e2.Pfee+`}>vT!qϒ,j2C^S;kZ /{ hYJ^Tv_+|/7?_T>m֎U}ꊓ\2a=V>q?~nzwӑgT=. D^GΞtlk*nvP+8\$ֹ63A%:Jt:}d%_\i:)묝fi)!vU"/rdq7欰.HVy]{M:23p|CDFXC+ӵndeZ.`qꌄT!NѺоt5WO"ύcR4xWiKuZإD /y;³m'5ΝHwo9=uL!Qigһ٢mm|n\v=1W2E?><ڷ费\gIaa$& K|z ̚zFӑJҕVMNc*SogѰ[,OnxyK L ӅvoIψ8Pםe:!]NZmmG7kSpvY;Fg$fџMiq>2H{3bj[u w3>JVbTG s]_ endstream endobj 81 0 obj << /Producer (pdfTeX-1.40.15) /Creator (TeX) /CreationDate (D:20160411095711-04'00') /ModDate (D:20160411095711-04'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014) kpathsea version 6.2.0) >> endobj 10 0 obj << /Type /ObjStm /N 58 /First 446 /Length 2654 /Filter /FlateDecode >> stream xZYo9~ׯ.  IlON-wlmdё8뷪RS-MXERL0"4TLȤc:X&-33%)\LfJlGy :&hɤ8&* H"0Nf@sw^v AqQ|x' ZY bV1`5"u@Y ,`3́9,s@?{0x#@DЀgU 0 Q@ d)&`xjx1va[Ǣ{a{hK@Jʃ;mpZ~ZNFqi฼ۣ;Qo>u`֡L$wIf 8V=Ҽy¢J"u5)1~^M٧FHbzݯn{qmB%3x@bX>$&)7DnxR~t.Ɉw8ueծ%UVu}ՆjqXk1MdR]5o3%4`䬃8Bn]8*DrA4u>OB  :4&A"A x,xJLt.@Yfiִs5AZEgzA7?F/EqZ-#R[ KOp8o'0Z`ESHRIi|b@P,NZsz:>FԦd](v y^ih0Yk#pedqy@N$R~I)$-WeUƊiMՇ"3oNHErA(Gۍ|&O3J>34 z P,C*JOӁ2Ķwh}%Avu(#ffoZFl=QeS&Iz?eyRv1A<grEyjS&֩Zd5tQa=/l)"䢪x-$1u/K/eSVH\GS[Uf_פH )ho"v PTYK|P%oRx;^13OUͣr]NRN69$M~j1)):=M|(VZ{0>"ZLHI3i:"NpYR08]VarLxފ8l:btcCt(ju/F99E8L62 d_~>D+6zCB_roqݝ70doo;豈Aq7DMgֱg Z: WƭI.Nq_5G18L{[ëAɀٴy`] x\cL/y?5q{][>>wMg>>MS5_V4j;|!?/)?7-p1\UIP K@GҤ@MeɧG|ƿh A /-"%  @)Jea$]9=j9N[0deG'%ڶVՖ&$N}qUK1&9[NL1bn1E(_=*!_QW/ziI7#5/䚗_g7 j /U| a7&^ʿɴ¿Fb@DLoK6قNo?>C[r6)Ɵ՟\e|s{ů7EyQIl@nC-ٴYzum -WSZm*Klv_;oK*gѡ{_֦]˂F3/Ÿ蕴3{qoPF?ư1~`q^"VZ82dvZau.Zc$tsqZV1jcm*)XP r|R /y1ԧ]Lݓ/E2`E(C _bU5Jh0&JE% qj\jI] 5iB v0b5릟,WWk,i)bt+7iaC[>p]Lv1)e+w%B O(IHGE!<4$\W.ҝ_ n.y`oW+#k7znV%ٺ]o.ql^ 8善p[CjL5p[:d-K+L&exTԐe&n.y i_ 5_djQWbMP֨ +}[zY >y/'#!?Gm~ҡ(w|n~\aBY-kVPGWt.HMn endstream endobj 82 0 obj << /Type /XRef /Index [0 83] /Size 83 /W [1 3 1] /Root 80 0 R /Info 81 0 R /ID [ ] /Length 235 /Filter /FlateDecode >> stream x;NBQᵎxAE*/ ҄a8cbc%p &`j{D Ptř8=qй񓾘Ky"XtĢX >,$zL}x<"M~Bt޵Ź8YJ|͉X.6DQl(-Q!`O+&ނk|vfݵG\5r|媓)W|̻׫_@ `yK endstream endobj startxref 145429 %%EOF stex-1.2.1+git20171204.g5e4f0ca/doc/stex.stex000066400000000000000000000414621321130544300200330ustar00rootroot00000000000000\documentclass{monograph} \usepackage{scheme} \iflatex \usepackage{fullpage} \pagestyle{plain} \fi \ifhtml \documenttitle[stex.css]{Introduction to stex} \fi \begin{document} \title{Introduction to stex} \author{R. Kent Dybvig and Oscar Waddell} \date{April 2016} \maketitle \def\copyrightnotice{\copyright~1998--2016 R. Kent Dybvig and Oscar Waddell} \ifhtml \tableofcontents \fi \iflatex % block paragraphs \setlength\parskip{4pt plus 1pt} \setlength\parindent{0pt} \renewenvironment{quotation} {\list{}{\listparindent 1.5em% \itemindent 0pt% \rightmargin \leftmargin \parsep 0pt plus 1pt}% \item\relax} {\endlist} \fi \section{Overview} The \emph{stex} package consists of two main programs and some supporting items, such as make files, make-file templates, class files, and style files. The two main programs are \textbf{scheme-prep} and \textbf{html-prep}. \textbf{scheme-prep} performs a conversion from ``stex''-formatted files into latex-formatted files, while \textbf{html-prep} converts (some) latex-formatted files into html-formatted files. An stex file is really just a latex file extended with a handful of commands for including Scheme code (or pretty much any other kind of code, as long as you don't plan to use the Scheme-specific transcript support) in a document, plus a couple of additional features rather arbitrarily thrown in. The subset of latex-formatted files \textbf{html-prep} is capable of handling is rather small but has nevertheless been useful for our purposes, which include producing html versions of a couple of books (\emph{The Scheme Programming Language}, Editions 2--4 and the Chez Scheme User's Guides for Versions 6--9), the scheme.com web site, class websites, class assignments, and various other documents. \section{Installation} A prerequisite to building and using stex is to have Chez Scheme or Petite Chez Scheme installed on your system. You'll also need pdflatex, dvips, ghostscript, and netbpm. We've run stex under Linux and OS X but have not tried to run it under Windows. The simplest way to install stex for your personal use is to clone the stex directory into your home directory, cd into the stex directory, and run make: \schemedisplay make BIN=\var{bindir} \endschemedisplay where \var{bindir} is the directory where make will find the scheme or petite executables. This will create a subdirectory, named for the installed Chez Scheme machine type, containing binary versions of the programs. You can also use ``make install'' to make stex available for other users. \schemedisplay sudo make install BIN=\var{bindir} LIB=\var{libdir} \endschemedisplay where \var{bindir} is as described above, and \var{libdir} is the directory where the stex library directory should be installed. \section{Usage notes} The simplest way to get started with stex is to get this document to build (in the doc directory) and create your own document by cloning this document's source file (stex.stex) and make file (Makefile). If you've installed stex in your home directory, you should be able to build this document by running ``make'' without arguments in the doc directory. If you've installed stex elsewhere, you'll first have to modify the include for Mf-stex to reflect its installed location. Makefile is where you declare your stex sources and various other things, like bibtex and graphics files. If you don't have anything much more complicated than this document, you might just need to change the line that declares the main stex entry point, i.e., the line that reads \scheme{x = stex}, to reflect the name of your document. The make is orchestrated by Mf-stex, which knows how to run \textbf{scheme-prep}, \textbf{html-prep}, \textbf{pdflatex} (multiple times), and various other commands to produce both pdf and html versions of the stex document. You can also consult the more elaborate stex source and make files for the Chez Scheme User's Guide in the csug directory of a Chez Scheme release. \section{Basic stex commands} \subsection{Inline code} An stex document includes inline Scheme (or other) code via the \scheme{\scheme} command, e.g.: \begin{quotation} \schemeverbatim When called with two arguments, \scheme{cons} creates a pair of the two arguments, e.g., \scheme{(cons 3 4)} produces \scheme{(3 . 4)}. \endschemeverbatim \end{quotation} produces: \begin{quotation} When called with two arguments, \scheme{cons} creates a pair of the two arguments, e.g., \scheme{(cons 3 4)} produces \scheme{(3 . 4)}. \end{quotation} \subsection{Code displays} An stex document includes out-of-line Scheme (or other) code via \scheme{\schemedisplay} and \scheme{\endschemedisplay}, e.g.: \begin{quotation} \schemeverbatim \schemedisplay (define fact (lambda (x) "a light year is a measure of distance")) (define fib (lambda (x) "a light year is a measure of time")) \endschemedisplay \endschemeverbatim \end{quotation} produces: \begin{quotation} \schemedisplay (define fact (lambda (x) "a light year is a measure of distance")) (define fib (lambda (x) "a light year is a measure of time")) \endschemedisplay \end{quotation} Within a Scheme display, \scheme{;=>} is converted into a double right arrow ($\Rightarrow$), \scheme{;->} into a single right arrow ($\rightarrow$), and \scheme{;==} into a phantom of the same size. This is useful for showing what a piece of code translates or evaluates to, e.g.: \begin{quotation} \schemeverbatim A \scheme{let} expression expands into a call to a \scheme{lambda} expression, e.g.: \schemedisplay (let ([a 17]) ;-> ((lambda (a) (+ a a)) (+ a a)) ;== 17) \endschemedisplay A \scheme{let} expression first evaluates the right-hand-side expression, then evaluates the body in an environment that binds the left-hand-side variable to the resulting value, e.g.: \schemedisplay (let ([a 17]) ;=> 17 (+ a a)) \endschemedisplay \endschemeverbatim \end{quotation} produces \begin{quotation} A \scheme{let} expression expands into a call to a \scheme{lambda} expression, e.g.: \schemedisplay (let ([a 17]) ;-> ((lambda (a) (+ a a)) (+ a a)) ;== 17) \endschemedisplay A \scheme{let} expression first evaluates the right-hand-side expression, then evaluates the body in an environment that binds the left-hand-side variable to the resulting value, e.g.: \schemedisplay (let ([a 17]) ;=> 17 (+ a a)) \endschemedisplay \end{quotation} \subsection{Variables} Code can include emphasized variables via the \scheme{\raw{{\schbackslash}var}} command, e.g.: \begin{quotation} \schemeverbatim \scheme{(let ([\var{x} \var{e}]) \var{body})} binds the variable \var{x} to the value of \var{e} in \var{body}. \endschemeverbatim \end{quotation} produces: \begin{quotation} \scheme{(let ([\var{x} \var{e}]) \var{body})} binds the variable \var{x} to the value of \var{e} in \var{body}. \end{quotation} If the text within a \scheme{\raw{{\schbackslash}var}} form contains an underscore, the following character or bracketed subform is converted into a subscript, e.g., \scheme{\raw{{\schbackslash}var{\schlbrace}abc\_3{\schrbrace}}} produces \var{abc_3}, and \scheme{\raw{{\schbackslash}var{\schlbrace}7e5\_{16}{\schrbrace}}} produces \var{7e5_{16}}. \scheme{\raw{{\schbackslash}var}} forms may appear within a \scheme{\scheme} form, within a Scheme display formed by \scheme{\schemedisplay} and \scheme{\endschemedisplay} commands, or by itself outside of either. \subsection{Raw text in code} Raw text can be included in code via the \scheme{\raw{{\schbackslash}raw}} command. For example: \begin{quotation} \schemeverbatim \schemedisplay (sqrt \raw{$x$}) \is \raw{$\sqrt{x}$}. \endschemedisplay \endschemeverbatim \end{quotation} produces: \begin{quotation} \schemedisplay (sqrt \raw{$x$}) ;=> \raw{$\sqrt{x}$}. \endschemedisplay \end{quotation} \subsection{Generated output} Output generated by a Scheme program can be inserted into the output via \scheme{\generated} and \scheme{\endgenerated} commands, e.g.: \begin{quotation} \schemeverbatim \generated (let () (define fibs (lambda (x y n) (if (= n 0) '() (cons x (fibs y (+ x y) (- n 1)))))) (let ([n 5]) (printf "first ~r primes: ~{~s~^, ~}\n" n (fibs 0 1 n)))) \endgenerated \endschemeverbatim \end{quotation} produces: \begin{quotation} \generated (let () (define fibs (lambda (x y n) (if (= n 0) '() (cons x (fibs y (+ x y) (- n 1)))))) (let ([n 5]) (printf "first ~r primes: ~{~s~^, ~}\n" n (fibs 0 1 n)))) \endgenerated \end{quotation} \subsection{Verbatim Scheme displays} When special features, like \scheme{\raw{{\schbackslash}var}} forms, need to be suppressed within a Scheme display, a document can use \scheme{\schemeverbatim} and \scheme{\endschemeverbatim} instead of \scheme{\schemedisplay} and \scheme{\endschemedisplay}. This document makes extensive use of this feature. \section{Scheme transcripts} \subsection{Automatic transcript generation} The \textbf{scheme-prep} package supports a \scheme{\transcript} command for automatically generating Scheme transcripts from input supplied in the document source. All text from the \scheme{\transcript} marker up to and including the \scheme{\endtranscript} marker is replaced with a transcript generated by supplying the intervening text as the input to a Scheme caf\'e (REPL). If the Scheme transcript needs to contain the sequence \scheme{\endtranscript}, a different terminator may be specified as an optional argument to \scheme{\transcript}. The terminator must be a backslash followed by one or more alphabetic characters, and is specified without the backslash in the optional argument. Three pairs of commands may be redefined to customize the typesetting of different elements within generated transcripts. To modify the typesetting of error messages, redefine \scheme{\transerr} and \scheme{\endtranserr}. To modify the typesetting of user input read from the current input port of the caf\'e, redefine \scheme{\transin} and \scheme{\endtransin}. To modify the typesetting of program output written to the current output port of new caf\'e, redefine \scheme{\transout} and \scheme{\endtransout}. For example, the following: \begin{quotation} \schemeverbatim \transcript (define f (lambda (x) ; indentation and comments are (if (zero? x) ; preserved in the transcript 1 (* x (f (- x 1)))))) (values f (f 0) (f 5) (f 20)) (trace f) (f 4) \endtranscript \endschemeverbatim \end{quotation} produces: \begin{quotation} \transcript (define f (lambda (x) ; indentation and comments are (if (zero? x) ; preserved in the transcript 1 (* x (f (- x 1)))))) (values f (f 0) (f 5) (f 20)) (trace f) (f 4) \endtranscript \end{quotation} The following example shows how to specify a different transcript terminator and shows the default formatting imposed by \scheme{\transerr}, \scheme{\transin}, and \scheme{\transout}. \begin{quotation} \schemeverbatim \transcript[\stopthistranscript] #e4.5 (begin (display "Enter a character: ") (read-char)) (begin (display "Enter a character: ") (read-char))Z (begin (clear-input-port) (display "Enter a character: ") (read-char)) Z (list (read-char) (read-char) (read-char))abc def (define silly-repl (lambda (prompt) (display prompt) (let ([x (read)]) (unless (eof-object? x) (let ([result (eval x)]) (unless (eq? result (void)) (pretty-print result)) (silly-repl prompt)))))) (silly-repl "Enter a Scheme expression: ") (list 1 2 3) (silly-repl "Now what? ") (define interview (lambda () (let* ([fname (begin (display "First name: ") (read))] [lname (begin (display "Last name: ") (read))]) (printf "Hello ~a ~a!~%" fname lname)))) (interview) john doe #!eof (printf "good to be back~%") #!eof \stopthistranscript \endschemeverbatim \end{quotation} produces: \begin{quotation} \transcript[\stopthistranscript] #e4.5 (begin (display "Enter a character: ") (read-char)) (begin (display "Enter a character: ") (read-char))Z (begin (clear-input-port) (display "Enter a character: ") (read-char)) Z (list (read-char) (read-char) (read-char))abc def (define silly-repl (lambda (prompt) (display prompt) (let ([x (read)]) (unless (eof-object? x) (let ([result (eval x)]) (unless (eq? result (void)) (pretty-print result)) (silly-repl prompt)))))) (silly-repl "Enter a Scheme expression: ") (list 1 2 3) (silly-repl "Now what? ") (define interview (lambda () (let* ([fname (begin (display "First name: ") (read))] [lname (begin (display "Last name: ") (read))]) (printf "Hello ~a ~a!~%" fname lname)))) (interview) john doe #!eof (printf "good to be back~%") #!eof \stopthistranscript \end{quotation} Transcripts do not include a trailing prompt by design. This is done in such a way that an explicitly displayed string that happens to look like the prompt is not suppressed. For example: \begin{quotation} \schemeverbatim \transcript (begin (display "> \n") (exit)) \endtranscript \endschemeverbatim \end{quotation} should leave the apparent prompt alone since it is generated as program output. \begin{quotation} \transcript (begin (display "> \n") (exit)) \endtranscript \end{quotation} Prompt suppression works even with changes to \scheme{waiter-prompt-string}. For example: \begin{quotation} \schemeverbatim \transcript (waiter-prompt-string "antelope? ") "no thanks" \endtranscript \endschemeverbatim \end{quotation} produces no trailing "antelope? " prompt: \begin{quotation} \transcript (waiter-prompt-string "antelope? ") "no thanks" \endtranscript \end{quotation} \subsection{Loading initialization code} The \scheme{stex} commands \scheme{\schemeinit} and \scheme{\endschemeinit} are used to bracket Scheme expressions that should be evaluated without generating a transcript of the results. This is useful, for example, when writing the description of a programming assignment. The solutions can be loaded via \scheme{\schemeinit} and a transcript showing how the solutions behave can be generated using the \scheme{\transcript} command. For example, the following text: \begin{quotation} \schemeverbatim \schemeinit (waiter-prompt-string ">") ; restore the original prompt setting so we ; don't get "antelope?" as the prompt (define compute-length (lambda (x) (cond [(list? x) (length x)] [(vector? x) (vector-length x)] [(string? x) (string-length x)] [else (errorf 'compute-length "cannot handle ~s" ls)]))) \endschemeinit \emph{The \scheme{compute-length} procedure behaves as follows:} \transcript (compute-length '()) (compute-length '(a b c)) (compute-length "abcd") (compute-length (vector 1 2 3 4 5 6)) (compute-length compute-length) \endtranscript \endschemeverbatim \end{quotation} produces the output shown below. \begin{quotation} \schemeinit (waiter-prompt-string ">") ; restore the original prompt setting so we ; don't get "antelope?" as the prompt (define compute-length (lambda (x) (cond [(list? x) (length x)] [(vector? x) (vector-length x)] [(string? x) (string-length x)] [else (errorf 'compute-length "cannot handle ~s" x)]))) \endschemeinit \emph{The \scheme{compute-length} procedure behaves as follows:} \transcript (compute-length '()) (compute-length '(a b c)) (compute-length "abcd") (compute-length (vector 1 2 3 4 5 6)) (compute-length compute-length) \endtranscript \end{quotation} the last line of input intentionally causes an error, which is displayed just as it would be displayed in a caf\'e. \section{html-prep support for the \texttt{tabular} environment} Support for tables comes with a few caveats: \begin{enumerate} \item \scheme{@\schlbrace\schrbrace} directives within \scheme{tabular} column specifiers are flat-out ignored for the time being. \item \scheme{|} directives within \scheme{tabular} column specifiers are essentially ignored. Their only effect is to globally enable borders for the entire HTML table. \item \scheme{\hrule} and \scheme{\cline} are not yet implemented. \item no warranty is expressed or implied. \end{enumerate} The following code: \begin{quotation} \begin{verbatim} \begin{tabular}{rcl|r} y &=& f(x) & without loss of generality \\ z & \multicolumn{2}{r}{whee} & this is fun? \\ \multicolumn{4}{c}{ \begin{tabular}{cc} 1 & 2 \\ 3 & 4 \end{tabular} } \\ a & b & c & d \\ 12345 & z & \multicolumn{2}{l}{\scheme{(define x "foo")}} \end{tabular} \end{verbatim} \end{quotation} generates this table: \begin{quotation} \begin{tabular}{rcl|r} y &=& f(x) & without loss of generality \\ z & \multicolumn{2}{r}{whee} & this is fun? \\ \multicolumn{4}{c}{ \begin{tabular}{cc} 1 & 2 \\ 3 & 4 \end{tabular} } \\ a & b & c & d \\ 12345 & z & \multicolumn{2}{l}{\scheme{(define x "foo")}} \end{tabular} \end{quotation} \end{document} stex-1.2.1+git20171204.g5e4f0ca/gifs/000077500000000000000000000000001321130544300163175ustar00rootroot00000000000000stex-1.2.1+git20171204.g5e4f0ca/gifs/Makefile000066400000000000000000000031041321130544300177550ustar00rootroot00000000000000gifs = ghostRightarrow.gif density=-r90x90 .SUFFIXES: .SUFFIXES: .tex .gif # translate ps file to ppm, crop to minimum background, and translate ppm # to gif with white (background) transparent # .tex.gif: echo | latex $* &&\ dvips -f < $*.dvi |\ gs -q -dNOPAUSE -dSAFER -sDEVICE=ppmraw -sOutputFile=-\ ${density} - |\ pnmcrop |\ ppmtogif -transparent white > $*.gif /bin/rm -f $*.dvi $*.log *.aux test -f $*.gif && chmod 644 $*.gif all: ${gifs} # make ghostRightarrow.gif a completely transparent version of Rightarrow.ps # # translate ps to gif as above but w/o making white transparent, map black # to white, convert to ppm, and convert back to gif with white transparent # # could skip intermediate conversion to gif if we could map black to white # with some ppm tool # # it seems like should be able to replace last three steps with # giftrans -g '#000000=#ffffff' -t '#ffffff' # or at least # giftrans -g '#000000=#ffffff' | giftrans -t '#ffffff' # but giftrans changes only the first white color it sees, not all # ghostRightarrow.gif: Rightarrow.tex echo | latex Rightarrow &&\ dvips -f < Rightarrow.dvi |\ gs -q -dNOPAUSE -dSAFER -sDEVICE=ppmraw -sOutputFile=-\ ${density} - |\ pnmcrop |\ ppmtogif |\ giftrans -g '#000000=#ffffff' |\ giftopnm |\ ppmtogif -transparent white > $*.gif /bin/rm -f Rightarrow.dvi Rightarrow.log Rightarrow.aux test -f $*.gif && chmod 644 $*.gif clean: rm -f *.log *.aux *.dvi Make.out distclean: clean rm -f *.gif stex-1.2.1+git20171204.g5e4f0ca/gifs/Rightarrow.tex000066400000000000000000000001361321130544300211710ustar00rootroot00000000000000\documentclass[12pt]{article} \begin{document} \pagestyle{empty} $\Rightarrow$ \end{document} stex-1.2.1+git20171204.g5e4f0ca/gifs/ghostRightarrow.gif000066400000000000000000000000621321130544300222010ustar00rootroot00000000000000GIF89a !,  ;stex-1.2.1+git20171204.g5e4f0ca/inputs/000077500000000000000000000000001321130544300167115ustar00rootroot00000000000000stex-1.2.1+git20171204.g5e4f0ca/inputs/assign-prep.stex000066400000000000000000000001371321130544300220470ustar00rootroot00000000000000\xdef\selfstudy#1{% \xedef\studylab{\genlab}\raw{\selfstudy}{#1}{\studylab}\label{\studylab}} stex-1.2.1+git20171204.g5e4f0ca/inputs/assignment.bst000066400000000000000000000511001321130544300215700ustar00rootroot00000000000000% adapted from BibTeX standard bibliography style `plain' % support for annotations (annote) and urls (documentURL) % Version 0.99b (8-Dec-10 release) for BibTeX versions 0.99a or later. % Copyright (C) 1984, 1985, 1988, 2010 Howard Trickey and Oren Patashnik. % Unlimited copying and redistribution of this file are permitted as long as % it is unmodified. Modifications (and redistribution of modified versions) % are also permitted, but only if the resulting file is renamed to something % besides btxbst.doc, plain.bst, unsrt.bst, alpha.bst, and abbrv.bst. % This restriction helps ensure that all standard styles are identical. % The file btxbst.doc has the documentation for this style. ENTRY { address annote author booktitle chapter documenturl edition editor howpublished institution journal key month note number organization pages publisher school series title type volume year } {} { label } INTEGERS { output.state before.all mid.sentence after.sentence after.block } FUNCTION {init.state.consts} { #0 'before.all := #1 'mid.sentence := #2 'after.sentence := #3 'after.block := } STRINGS { s t } FUNCTION {output.nonnull} { 's := output.state mid.sentence = { ", " * write$ } { output.state after.block = { add.period$ write$ newline$ "\newblock " write$ } { output.state before.all = 'write$ { add.period$ " " * write$ } if$ } if$ mid.sentence 'output.state := } if$ s } FUNCTION {output} { duplicate$ empty$ 'pop$ 'output.nonnull if$ } FUNCTION {output.check} { 't := duplicate$ empty$ { pop$ "empty " t * " in " * cite$ * warning$ } 'output.nonnull if$ } FUNCTION {output.bibitem} { newline$ "\bibitem{" write$ cite$ write$ "}" write$ newline$ "" before.all 'output.state := } FUNCTION {fin.entry} { add.period$ write$ % newline$ documenturl missing$ 'skip$ { " " write$ "\verb'" write$ documenturl write$ "'." write$ } if$ annote missing$ 'skip$ { " " write$ "{\it " write$ annote write$ "}" write$ } if$ % "\end{quotation}" newline$ } FUNCTION {new.block} { output.state before.all = 'skip$ { after.block 'output.state := } if$ } FUNCTION {new.sentence} { output.state after.block = 'skip$ { output.state before.all = 'skip$ { after.sentence 'output.state := } if$ } if$ } FUNCTION {not} { { #0 } { #1 } if$ } FUNCTION {and} { 'skip$ { pop$ #0 } if$ } FUNCTION {or} { { pop$ #1 } 'skip$ if$ } FUNCTION {new.block.checka} { empty$ 'skip$ 'new.block if$ } FUNCTION {new.block.checkb} { empty$ swap$ empty$ and 'skip$ 'new.block if$ } FUNCTION {new.sentence.checka} { empty$ 'skip$ 'new.sentence if$ } FUNCTION {new.sentence.checkb} { empty$ swap$ empty$ and 'skip$ 'new.sentence if$ } FUNCTION {field.or.null} { duplicate$ empty$ { pop$ "" } 'skip$ if$ } FUNCTION {emphasize} { duplicate$ empty$ { pop$ "" } { "{\em " swap$ * "}" * } if$ } INTEGERS { nameptr namesleft numnames } FUNCTION {format.names} { 's := #1 'nameptr := s num.names$ 'numnames := numnames 'namesleft := { namesleft #0 > } { s nameptr "{ff~}{vv~}{ll}{, jj}" format.name$ 't := nameptr #1 > { namesleft #1 > { ", " * t * } { numnames #2 > { "," * } 'skip$ if$ t "others" = { " et~al." * } { " and " * t * } if$ } if$ } 't if$ nameptr #1 + 'nameptr := namesleft #1 - 'namesleft := } while$ } FUNCTION {format.authors} { author empty$ { "" } { author format.names } if$ } FUNCTION {format.editors} { editor empty$ { "" } { editor format.names editor num.names$ #1 > { ", editors" * } { ", editor" * } if$ } if$ } FUNCTION {format.title} { title empty$ { "" } { title "t" change.case$ } if$ } FUNCTION {n.dashify} { 't := "" { t empty$ not } { t #1 #1 substring$ "-" = { t #1 #2 substring$ "--" = not { "--" * t #2 global.max$ substring$ 't := } { { t #1 #1 substring$ "-" = } { "-" * t #2 global.max$ substring$ 't := } while$ } if$ } { t #1 #1 substring$ * t #2 global.max$ substring$ 't := } if$ } while$ } FUNCTION {format.date} { year empty$ { month empty$ { "" } { "there's a month but no year in " cite$ * warning$ month } if$ } { month empty$ 'year { month " " * year * } if$ } if$ } FUNCTION {format.btitle} { title emphasize } FUNCTION {tie.or.space.connect} { duplicate$ text.length$ #3 < { "~" } { " " } if$ swap$ * * } FUNCTION {either.or.check} { empty$ 'pop$ { "can't use both " swap$ * " fields in " * cite$ * warning$ } if$ } FUNCTION {format.bvolume} { volume empty$ { "" } { "volume" volume tie.or.space.connect series empty$ 'skip$ { " of " * series emphasize * } if$ "volume and number" number either.or.check } if$ } FUNCTION {format.number.series} { volume empty$ { number empty$ { series field.or.null } { output.state mid.sentence = { "number" } { "Number" } if$ number tie.or.space.connect series empty$ { "there's a number but no series in " cite$ * warning$ } { " in " * series * } if$ } if$ } { "" } if$ } FUNCTION {format.edition} { edition empty$ { "" } { output.state mid.sentence = { edition "l" change.case$ " edition" * } { edition "t" change.case$ " edition" * } if$ } if$ } INTEGERS { multiresult } FUNCTION {multi.page.check} { 't := #0 'multiresult := { multiresult not t empty$ not and } { t #1 #1 substring$ duplicate$ "-" = swap$ duplicate$ "," = swap$ "+" = or or { #1 'multiresult := } { t #2 global.max$ substring$ 't := } if$ } while$ multiresult } FUNCTION {format.pages} { pages empty$ { "" } { pages multi.page.check { "pages" pages n.dashify tie.or.space.connect } { "page" pages tie.or.space.connect } if$ } if$ } FUNCTION {format.vol.num.pages} { volume field.or.null number empty$ 'skip$ { "(" number * ")" * * volume empty$ { "there's a number but no volume in " cite$ * warning$ } 'skip$ if$ } if$ pages empty$ 'skip$ { duplicate$ empty$ { pop$ format.pages } { ":" * pages n.dashify * } if$ } if$ } FUNCTION {format.chapter.pages} { chapter empty$ 'format.pages { type empty$ { "chapter" } { type "l" change.case$ } if$ chapter tie.or.space.connect pages empty$ 'skip$ { ", " * format.pages * } if$ } if$ } FUNCTION {format.in.ed.booktitle} { booktitle empty$ { "" } { editor empty$ { "In " booktitle emphasize * } { "In " format.editors * ", " * booktitle emphasize * } if$ } if$ } FUNCTION {empty.misc.check} { author empty$ title empty$ howpublished empty$ month empty$ year empty$ note empty$ and and and and and key empty$ not and { "all relevant fields are empty in " cite$ * warning$ } 'skip$ if$ } FUNCTION {format.thesis.type} { type empty$ 'skip$ { pop$ type "t" change.case$ } if$ } FUNCTION {format.tr.number} { type empty$ { "Technical Report" } 'type if$ number empty$ { "t" change.case$ } { number tie.or.space.connect } if$ } FUNCTION {format.article.crossref} { key empty$ { journal empty$ { "need key or journal for " cite$ * " to crossref " * crossref * warning$ "" } { "In {\em " journal * "\/}" * } if$ } { "In " key * } if$ " \cite{" * crossref * "}" * } FUNCTION {format.crossref.editor} { editor #1 "{vv~}{ll}" format.name$ editor num.names$ duplicate$ #2 > { pop$ " et~al." * } { #2 < 'skip$ { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" = { " et~al." * } { " and " * editor #2 "{vv~}{ll}" format.name$ * } if$ } if$ } if$ } FUNCTION {format.book.crossref} { volume empty$ { "empty volume in " cite$ * "'s crossref of " * crossref * warning$ "In " } { "Volume" volume tie.or.space.connect " of " * } if$ editor empty$ editor field.or.null author field.or.null = or { key empty$ { series empty$ { "need editor, key, or series for " cite$ * " to crossref " * crossref * warning$ "" * } { "{\em " * series * "\/}" * } if$ } { key * } if$ } { format.crossref.editor * } if$ " \cite{" * crossref * "}" * } FUNCTION {format.incoll.inproc.crossref} { editor empty$ editor field.or.null author field.or.null = or { key empty$ { booktitle empty$ { "need editor, key, or booktitle for " cite$ * " to crossref " * crossref * warning$ "" } { "In {\em " booktitle * "\/}" * } if$ } { "In " key * } if$ } { "In " format.crossref.editor * } if$ " \cite{" * crossref * "}" * } FUNCTION {article} { output.bibitem format.authors "author" output.check new.block format.title "title" output.check new.block crossref missing$ { journal volume empty$ 'skip$ { " " * volume * } if$ emphasize output number empty$ 'skip$ { number output } if$ format.pages output format.date output } { format.article.crossref output.nonnull format.pages output } if$ new.block note output fin.entry } FUNCTION {book} { output.bibitem author empty$ { format.editors "author and editor" output.check } { format.authors output.nonnull crossref missing$ { "author and editor" editor either.or.check } 'skip$ if$ } if$ new.block format.btitle "title" output.check crossref missing$ { format.bvolume output new.block format.number.series output new.sentence publisher "publisher" output.check address output } { new.block format.book.crossref output.nonnull } if$ format.edition output format.date "year" output.check new.block note output fin.entry } FUNCTION {booklet} { output.bibitem format.authors output new.block format.title "title" output.check howpublished address new.block.checkb howpublished output address output format.date output new.block note output fin.entry } FUNCTION {inbook} { output.bibitem author empty$ { format.editors "author and editor" output.check } { format.authors output.nonnull crossref missing$ { "author and editor" editor either.or.check } 'skip$ if$ } if$ new.block format.btitle "title" output.check crossref missing$ { format.bvolume output format.chapter.pages "chapter and pages" output.check new.block format.number.series output new.sentence publisher "publisher" output.check address output } { format.chapter.pages "chapter and pages" output.check new.block format.book.crossref output.nonnull } if$ format.edition output format.date "year" output.check new.block note output fin.entry } FUNCTION {incollection} { output.bibitem format.authors "author" output.check new.block format.title "title" output.check new.block crossref missing$ { format.in.ed.booktitle "booktitle" output.check format.bvolume output format.number.series output format.chapter.pages output new.sentence publisher "publisher" output.check address output format.edition output format.date "year" output.check } { format.incoll.inproc.crossref output.nonnull format.chapter.pages output } if$ new.block note output fin.entry } FUNCTION {inproceedings} { output.bibitem format.authors "author" output.check new.block format.title "title" output.check new.block crossref missing$ { format.in.ed.booktitle "booktitle" output.check format.bvolume output format.number.series output format.pages output address empty$ { organization publisher new.sentence.checkb organization output publisher output format.date "year" output.check } { address output.nonnull format.date "year" output.check new.sentence organization output publisher output } if$ } { format.incoll.inproc.crossref output.nonnull format.pages output } if$ new.block note output fin.entry } FUNCTION {conference} { inproceedings } FUNCTION {manual} { output.bibitem author empty$ { organization empty$ 'skip$ { organization output.nonnull address output } if$ } { format.authors output.nonnull } if$ new.block format.btitle "title" output.check author empty$ { organization empty$ { address new.block.checka address output } 'skip$ if$ } { organization address new.block.checkb organization output address output } if$ format.edition output format.date output new.block note output fin.entry } FUNCTION {mastersthesis} { output.bibitem format.authors "author" output.check new.block format.title "title" output.check new.block "Master's thesis" format.thesis.type output.nonnull school "school" output.check address output format.date "year" output.check new.block note output fin.entry } FUNCTION {misc} { output.bibitem format.authors output title howpublished new.block.checkb format.title output howpublished new.block.checka howpublished output format.date output new.block note output fin.entry empty.misc.check } FUNCTION {phdthesis} { output.bibitem format.authors "author" output.check new.block format.btitle "title" output.check new.block "PhD thesis" format.thesis.type output.nonnull school "school" output.check address output format.date "year" output.check new.block note output fin.entry } FUNCTION {proceedings} { output.bibitem editor empty$ { organization output } { format.editors output.nonnull } if$ new.block format.btitle "title" output.check format.bvolume output format.number.series output address empty$ { editor empty$ { publisher new.sentence.checka } { organization publisher new.sentence.checkb organization output } if$ publisher output format.date "year" output.check } { address output.nonnull format.date "year" output.check new.sentence editor empty$ 'skip$ { organization output } if$ publisher output } if$ new.block note output fin.entry } FUNCTION {techreport} { output.bibitem format.authors "author" output.check new.block format.title "title" output.check new.block format.tr.number output.nonnull institution "institution" output.check address output format.date "year" output.check new.block note output fin.entry } FUNCTION {unpublished} { output.bibitem format.authors "author" output.check new.block format.title "title" output.check new.block note "note" output.check format.date output fin.entry } FUNCTION {default.type} { misc } MACRO {jan} {"January"} MACRO {feb} {"February"} MACRO {mar} {"March"} MACRO {apr} {"April"} MACRO {may} {"May"} MACRO {jun} {"June"} MACRO {jul} {"July"} MACRO {aug} {"August"} MACRO {sep} {"September"} MACRO {oct} {"October"} MACRO {nov} {"November"} MACRO {dec} {"December"} MACRO {acmcs} {"ACM Computing Surveys"} MACRO {acta} {"Acta Informatica"} MACRO {cacm} {"Communications of the ACM"} MACRO {ibmjrd} {"IBM Journal of Research and Development"} MACRO {ibmsj} {"IBM Systems Journal"} MACRO {ieeese} {"IEEE Transactions on Software Engineering"} MACRO {ieeetc} {"IEEE Transactions on Computers"} MACRO {ieeetcad} {"IEEE Transactions on Computer-Aided Design of Integrated Circuits"} MACRO {ipl} {"Information Processing Letters"} MACRO {jacm} {"Journal of the ACM"} MACRO {jcss} {"Journal of Computer and System Sciences"} MACRO {scp} {"Science of Computer Programming"} MACRO {sicomp} {"SIAM Journal on Computing"} MACRO {tocs} {"ACM Transactions on Computer Systems"} MACRO {tods} {"ACM Transactions on Database Systems"} MACRO {tog} {"ACM Transactions on Graphics"} MACRO {toms} {"ACM Transactions on Mathematical Software"} MACRO {toois} {"ACM Transactions on Office Information Systems"} MACRO {toplas} {"ACM Transactions on Programming Languages and Systems"} MACRO {tcs} {"Theoretical Computer Science"} READ FUNCTION {sortify} { purify$ "l" change.case$ } INTEGERS { len } FUNCTION {chop.word} { 's := 'len := s #1 len substring$ = { s len #1 + global.max$ substring$ } 's if$ } FUNCTION {sort.format.names} { 's := #1 'nameptr := "" s num.names$ 'numnames := numnames 'namesleft := { namesleft #0 > } { nameptr #1 > { " " * } 'skip$ if$ s nameptr "{vv{ } }{ll{ }}{ ff{ }}{ jj{ }}" format.name$ 't := nameptr numnames = t "others" = and { "et al" * } { t sortify * } if$ nameptr #1 + 'nameptr := namesleft #1 - 'namesleft := } while$ } FUNCTION {sort.format.title} { 't := "A " #2 "An " #3 "The " #4 t chop.word chop.word chop.word sortify #1 global.max$ substring$ } FUNCTION {author.sort} { author empty$ { key empty$ { "to sort, need author or key in " cite$ * warning$ "" } { key sortify } if$ } { author sort.format.names } if$ } FUNCTION {author.editor.sort} { author empty$ { editor empty$ { key empty$ { "to sort, need author, editor, or key in " cite$ * warning$ "" } { key sortify } if$ } { editor sort.format.names } if$ } { author sort.format.names } if$ } FUNCTION {author.organization.sort} { author empty$ { organization empty$ { key empty$ { "to sort, need author, organization, or key in " cite$ * warning$ "" } { key sortify } if$ } { "The " #4 organization chop.word sortify } if$ } { author sort.format.names } if$ } FUNCTION {editor.organization.sort} { editor empty$ { organization empty$ { key empty$ { "to sort, need editor, organization, or key in " cite$ * warning$ "" } { key sortify } if$ } { "The " #4 organization chop.word sortify } if$ } { editor sort.format.names } if$ } FUNCTION {presort} { type$ "book" = type$ "inbook" = or 'author.editor.sort { type$ "proceedings" = 'editor.organization.sort { type$ "manual" = 'author.organization.sort 'author.sort if$ } if$ } if$ " " * year field.or.null sortify * " " * title field.or.null sort.format.title * #1 entry.max$ substring$ 'sort.key$ := } ITERATE {presort} SORT STRINGS { longest.label } INTEGERS { number.label longest.label.width } FUNCTION {initialize.longest.label} { "" 'longest.label := #1 'number.label := #0 'longest.label.width := } FUNCTION {longest.label.pass} { number.label int.to.str$ 'label := number.label #1 + 'number.label := label width$ longest.label.width > { label 'longest.label := label width$ 'longest.label.width := } 'skip$ if$ } EXECUTE {initialize.longest.label} ITERATE {longest.label.pass} FUNCTION {begin.bib} { preamble$ empty$ 'skip$ { preamble$ write$ newline$ } if$ "\begin{thebibliography}{" longest.label * "}" * write$ newline$ } EXECUTE {begin.bib} EXECUTE {init.state.consts} ITERATE {call.type$} FUNCTION {end.bib} { newline$ "\end{thebibliography}" write$ newline$ } EXECUTE {end.bib} stex-1.2.1+git20171204.g5e4f0ca/inputs/assignment.cls000066400000000000000000000205421321130544300215670ustar00rootroot00000000000000%%% assignment.cls \ProvidesClass{assignment} \def\ProvidesClass#1[#2]{\relax} % \input article.cls \LoadClass{article} \def\copyrightnotice{\ifauthor\copyright~\number\year~\theauthor\fi} \def\ps@plain{\let\@mkboth\@gobbletwo \let\@oddhead\@empty\def\@oddfoot{\reset@font \footer}\let\@evenhead\@empty\let\@evenfoot\@oddfoot} \def\footer{\hfil\ifnum\c@page =1 \copyrightnotice\else\thepage\fi\hfil} \let\trueenddocument=\enddocument \def\enddocument{ \theselfstudy \trueenddocument} \newif\iftitle\titlefalse \newif\ifauthor\authorfalse \newif\ifdate\datefalse \def\title#1{\def\thetitle{#1}\titletrue} \def\author#1{\def\theauthor{#1}\authortrue} \def\date#1{\def\thedate{#1}\datetrue} \def\maketitle{ \begin{flushleft} \iftitle{\LARGE\textbf{\thetitle}} \\[6pt]\fi \ifauthor{\Large\textbf{\theauthor}} \\\fi \ifdate{\vskip 3pt\Large\textbf{\thedate}} \\\fi \end{flushleft}} %%% to support hypertext index entries \def\hindex#1{\index} % ignore the label here---no links in printed version \newcommand{\hyperlink}[3][]{#3} \newcommand{\href}[3][]{#3} \newcommand{\hpageref}[3][]{#3} \let\true@ref=\ref\renewcommand{\ref}[2][]{\true@ref{#2}} \let\true@pageref=\pageref\renewcommand{\pageref}[2][]{\true@pageref{#2}} \newif\iflatex\latextrue \newif\ifhtml\htmlfalse %%% table of contents \renewcommand{\@pnumwidth}{1.55em} \renewcommand{\@tocrmarg} {2.55em} \renewcommand{\@dotsep}{4.5} \setcounter{tocdepth}{2} \newcommand*{\l@chapter}[2]{% \ifnum \c@tocdepth >\m@ne \addpenalty{-\@highpenalty}% \vskip 1.0em \@plus\p@ \setlength\@tempdima{1.5em}% \begingroup \parindent \z@ \rightskip \@pnumwidth \parfillskip -\@pnumwidth \leavevmode \bfseries \advance\leftskip\@tempdima \hskip -\leftskip #1\nobreak\hfil \nobreak\hbox to\@pnumwidth{\hss #2}\par \penalty\@highpenalty \endgroup \fi} \renewcommand*{\l@section}[2]{\expandafter\l@xection#1\hobbes{#2}} \renewcommand*{\l@subsection}[2]{\expandafter\l@subxection#1\hobbes{#2}} \renewcommand*{\l@subsubsection}[2]{\expandafter\l@subsubxection#1\hobbes{#2}} \def\lead{\leaders\hbox to .3em{{\footnotesize \hss.\hss}}\hfil} \def\l@xection#1\calvin#2\hobbes#3{% \strut#1.&\multispan{3}{#2~}\lead&~#3\cr &\multispan{3}{\hphantom{#2~\hspace{2em}}}\hfil&\cr } \def\l@subxection#1\calvin#2\hobbes#3{% \strut.&\multispan{2}{#2~}\lead&~#3\cr &&\multispan{2}{\hphantom{#2~\hspace{2em}}}\hfil&\cr } \def\l@subsubxection#1\calvin#2\hobbes#3{% \strut&.&\multispan{1}{#2~}\lead&~#3\cr &&&\multispan{1}{\hphantom{#2~\hspace{2em}}}\hfil&\cr } \def\inserttoc{ \bigskip{\bfseries Contents}\medskip \begingroup\offinterlineskip \halign{\hfil##\hspace{.5em}&##\hfil\hspace{.5em}&##\hfil\hspace{.5em}&##\hfil\hspace{.5em}&\hfil##\cr \input{\jobname.toc} }\endgroup} \renewcommand{\tableofcontents}{% \def\numberline ##1{##1\calvin} \IfFileExists{\jobname.toc}{\inserttoc}{\typeout{No file \jobname.toc}} \begingroup \def\contentsline##1##2##3{\relax} \@starttoc{toc} \endgroup } \newcounter{exercise} \renewcommand{\theexercise}{\arabic{exercise}} \def\@startexercise{\par\bigskip \refstepcounter{exercise}\goodbreak \par\hrule width \hsize{\hfil}\\\nobreak \textbf{Exercise \theexercise. }\ignorespaces} \newenvironment{exercise} {\begingroup \def\afterschemedisplay{\removelastskip\penalty10000\vskip5pt} \let\newexercise=\@startexercise\newexercise} {\par\removelastskip\penalty10000\kern6pt\hrule width \hsize{\hfil}\endgroup} \newcounter{subexercise}[exercise] \renewcommand{\thesubexercise}{\theexercise\alph{subexercise}} \newcommand{\subexercise}{\par\refstepcounter{subexercise}\medskip\textbf{\thesubexercise. }} %%% self study questions %%% we'd like to create the self study file and load it all on the same %%% pass, but this is not TeXnically feasible if we want to include page %%% numbers. TeX delays file writing and closing until its output %%% routines run so that it can get the page numbers correct, so the file %%% may not be complete by the time we input it. If we use \immediate %%% to get the writing and closing done earlier, the page numbers won't %%% be correct. so we create \jobname.rawsst and count on the make file to %%% copy it to \jobname.sst before the next run. We will need to do something %%% even more elaborate once we start generating a book with self-study %%% questions in each chapter. \newwrite\sstudy \newcounter{selfstudycounter} \renewcommand{\theselfstudycounter}{\arabic{selfstudycounter}} \openout\sstudy=\jobname.rawsst \newif\ifselfstudy\selfstudyfalse \def\selfstudy{\stepcounter{selfstudycounter}\selfstudytrue \begingroup\@sanitize\addselfstudy} \def\addselfstudy#1#2{\endgroup \edef\sstudyhead{\write\sstudy}% \edef\sstudyentry{{\string\sstudyentry{#1}{#2}{\theselfstudycounter}}}% \expandafter\sstudyhead\sstudyentry} \def\theselfstudy{\ifselfstudy\realselfstudy\fi} \def\realselfstudy{\begingroup \def\sstudyentry##1##2##3{\par\bigskip\textbf{##3. } ##1 [Page \pageref{##2}]} \section{Questions for self study}\label{section:selfstudy} \input \jobname.sst \endgroup} %%% bibliography \newdimen\bibindent \bibindent=1.5em \renewcommand{\newblock}{} \renewenvironment{thebibliography}[1] {\chapter{Bibliography} \list{\@biblabel{\arabic{enumiv}}}% {\settowidth\labelwidth{\@biblabel{#1}}% \leftmargin\labelwidth \advance\leftmargin\labelsep \usecounter{enumiv}% \let\p@enumiv\@empty \renewcommand{\theenumiv}{\arabic{enumiv}}}% \renewcommand{\newblock}{\hskip .11em \@plus.33em \@minus.07em}% \sloppy\clubpenalty4000\widowpenalty4000% \sfcode`\.=\@m} {\def\@noitemerr {\@latex@warning{Empty `thebibliography' environment}}% \endlist} %%% index \def\notsupposedtobehereindexname{\indexname} \renewenvironment{theindex} {\if@openright\cleardoublepage\else\clearpage\fi \raggedright \columnseprule \z@ \columnsep 35\p@ \twocolumn[\plainchapterhead{\indexname}]% \addcontentsline{toc}{chapter}{\indexname}% \chaptermark{\indexname}{\notsupposedtobehereindexname}% \thispagestyle{plain}\parindent\z@ \parskip\z@ \@plus .3\p@\relax \let\item\@idxitem} {\clearpage} \renewcommand{\@idxitem} {\par\hangindent 40\p@} \renewcommand{\subitem} {\par\hangindent 40\p@ \hspace*{20\p@}} \renewcommand{\subsubitem}{\par\hangindent 40\p@ \hspace*{30\p@}} \renewcommand{\indexspace}{\par \vskip 10\p@ \@plus5\p@ \@minus3\p@\relax} %%% latex.ltx redefinitions %% leave padding page blank (no header) \def\cleardoublepage{\clearpage\if@twoside \ifodd\c@page\else {\pagestyle{empty}\hbox{}\newpage\if@twocolumn\hbox{}\newpage\fi}\fi\fi} %% change section headers to "1.1. foo" instead of "1.1 foo" \def\@seccntformat#1{\csname the#1\endcsname. } %% change numbered table of contents lines to "1.1. foo" instead of "1.1 foo" \def\numberline#1{#1. } \renewenvironment{description} {\list{}{\labelwidth\z@ \itemindent-\leftmargin \let\makelabel\descriptionlabel}} {\endlist} \renewcommand*\descriptionlabel[1]{\hspace\labelsep #1} \def\itemvdots{\item[] \mbox{\vdots}} \def\parheader#1 {\medskip\noindent{\bf #1.}~~} %%% grammar support \newenvironment{grammar} {\begingroup \def\orbar{&\bar&} \def\nobar{&&} \def\longis{&$\longrightarrow$&} \penalty-100\vskip 4pt\begin{tabular}{lcl}} {\end{tabular}\penalty-200\vskip 4pt\endgroup} \def\bar{$\vert$} \def\ang#1{$\langle${\small\rm{}#1}$\rangle$} \def\kstar{\raise.5ex\hbox{\scheme{*}}} \def\kplus{\raise.5ex\hbox{\scheme{+}}} \newcounter{alphacount} \def\alphalabel{\textit{\alph{alphacount}}.} \newenvironment{alphalist} {\begingroup\let\beforeschemedisplay=\relax\let\afterschemedisplay=\relax \begin{list}{\alphalabel}{\usecounter{alphacount}\itemsep=0pt\parsep=0pt% \topsep=0pt}} {\end{list}\endgroup} %%% final set up \renewcommand{\contentsname}{Contents} \newcommand{\bibname}{Bibliography} \renewcommand{\indexname}{Index} \renewcommand{\today}{\ifcase\month\or January\or February\or March\or April\or May\or June\or July\or August\or September\or October\or November\or December\fi \space\number\day, \number\year} \setlength\columnsep{10\p@} \setlength\columnseprule{0\p@} \pagestyle{headings} \pagenumbering{arabic} \if@twoside\else\raggedbottom\fi \endinput %%% end of assignment.cls stex-1.2.1+git20171204.g5e4f0ca/inputs/assignment.hcls000066400000000000000000000122211321130544300217320ustar00rootroot00000000000000%%% assignment.hcls \newif\iflatex\latexfalse \newif\ifhtml\htmltrue % should be built in \newenvironment{center} {\raw{

}} {\raw{
}} \def\copyrightnotice{\ifauthor\par\raw{
}\copyright~\year~\theauthor\par\fi} \let\trueenddocument=\enddocument \def\enddocument{ \theselfstudy \begin{divertoutput}[toc] \ifsubsubsec\raw{}\fi \ifsubsec\raw{}\fi \end{divertoutput} \copyrightnotice\trueenddocument} \newif\iftitle\titlefalse \newif\ifdate\datefalse \newif\ifauthor\authorfalse \def\title#1{\def\thetitle{#1}\titletrue} \def\date#1{\def\thedate{#1}\datetrue} \def\author#1{\def\theauthor{#1}\authortrue} \def\maketitle{% \iftitle\raw{

}\thetitle\raw{

}\fi \ifauthor \ifdate \raw{

}\theauthor\\\thedate\raw{

}% \else \raw{

}\theauthor\raw{

}% \fi \else \ifdate\raw{

}\thedate\raw{

}\fi \fi} %%% table of contents \newif\ifsubsec\subsecfalse \newif\ifsubsubsec\subsubsecfalse \newcommand{\tableofcontents}{ \raw{} \rawinput{\jobname.htoc} \raw{
} \openrawfile{toc}{\jobname.htoc}} % we \let\label=\nolabel within toc entries to avoid inserting % labels that belong with the labeled entity, not the toc \def\nolabel#1{} %%% \section \newcounter{section} \renewcommand{\thesection}{\arabic{section}} \newcommand{\section}[1]{ \refstepcounter{section} \edef\templabel{\genlab} \raw{


}\label{\templabel}\thesection. #1\raw{

} \begin{divertoutput}[toc] \ifsubsubsec\raw{}\fi \subsubsecfalse \ifsubsec\raw{}\fi \subsecfalse \raw{}\textbf{\thesection.~}\raw{}\textbf{\href[plain]{\templabel}{{\let\label=\nolabel #1}}}\raw{} \end{divertoutput} } %%% \subsection \newcounter{subsection}[section] \renewcommand{\thesubsection}{\thesection.\arabic{subsection}} \newcommand{\subsection}[1]{ \refstepcounter{subsection} \edef\templabel{\genlab} \raw{


}\label{\templabel}\thesubsection. #1\raw{

} \begin{divertoutput}[toc] \ifsubsubsec\raw{}\fi \subsubsecfalse \ifsubsec\else\raw{}\fi \subsectrue \raw{} \end{divertoutput} } %%% \subsubsection \newcounter{subsubsection}[subsection] \renewcommand{\thesubsubsection}{\thesubsection.\arabic{subsubsection}} \newcommand{\subsubsection}[1]{ \refstepcounter{subsubsection} \edef\templabel{\genlab} \raw{


}\label{\templabel}\thesubsubsection. #1\raw{

} \begin{divertoutput}[toc] \ifsubsubsec\else\raw{}\fi \ifsubsec\raw{
}\textbf{\thesubsection.~}\raw{}\textbf{\href[plain]{\templabel}{{\let\label=\nolabel #1}}}\raw{
}\fi \subsubsectrue \raw{} \end{divertoutput} } %%% figure \newcounter{figure} \renewcommand{\thefigure}{\arabic{figure}} \newcommand{\caption}[1]{\\ Figure \thefigure.~#1} \newenvironment{figure} {\begingroup\refstepcounter{figure}} {\endgroup} %%% exercise \newcounter{exercise} \renewcommand{\theexercise}{\arabic{exercise}} \def\@startexercise{\refstepcounter{exercise} \raw{
} \textbf{Exercise \theexercise. }} \newenvironment{exercise} {\begingroup\def\newexercise{\@startexercise}\newexercise} {\raw{
}} \newcounter{subexercise}[exercise] \renewcommand{\thesubexercise}{\theexercise\alph{subexercise}} \newcommand{\subexercise}{\par\refstepcounter{subexercise}\textbf{\thesubexercise. }} %%% self-study \newif\ifselfstudy\selfstudyfalse \def\selfstudy#1#2{\selfstudytrue} \def\theselfstudy{\ifselfstudy\realselfstudy\fi} \def\realselfstudy{\begingroup \def\sstudyentry##1##2##3{\raw{

}\textbf{##3.} ##1 [see \hyperlink{######2}{here}]\raw{

}} \section{Questions for self study}\label{section:selfstudy} \input{\jobname.sst} \endgroup} %%% alphalist \newcounter{alphalist} \def\alphalist{\begingroup\setcounter{alphalist}{0} \def\endalphalistitem{}% \renewcommand{\item}{\endalphalistitem \def\endalphalistiem{\raw{}}% \stepcounter{alphalist}% \raw{
}\textbf{\thesubsubsection.~}\raw{}\textbf{\href[plain]{\templabel}{{\let\label=\nolabel #1}}}\raw{
}\alph{alphalist}.\raw{}} \raw{}} \def\endalphalist{\endalphalistitem\raw{
}\endgroup} %%% define our own (compact) description environment \def\description{\begingroup \renewcommand{\item}[1][]{\raw{
}##1\raw{
}}\raw{
}} \def\enddescription{\raw{
}\endgroup} %%% index \newcommand{\see}[2]{\emph{see} #1} \newenvironment{theindex} {\begingroup\newcommand{\itemindent}{\raw{   }} \renewcommand{\item}{\raw{
}} \newcommand{\subitem}{\raw{
}\itemindent} \newcommand{\subsubitem}{\raw{
}\itemindent\itemindent}} {\par\endgroup} \def\parheader#1 {\medskip\noindent{\bf #1.}~~} %%% grammar support \newenvironment{grammar} {\begingroup \def\orbar{&\bar&} \def\nobar{&&} \def\longis{&$\longrightarrow$&} \begin{tabular}{lcl}} {\end{tabular}\endgroup} \def\bar{\raw{|}} \def\kplus{\raw{+}} \def\kstar{\raw{*}} \def\ang#1{\raw{<}#1\raw{>}} \def\mbox#1{#1} %%% hyperlink support \newcommand{\hyperlink}[3][]{\raw{}#3\raw{}} stex-1.2.1+git20171204.g5e4f0ca/inputs/exam.cls000066400000000000000000000054051321130544300203520ustar00rootroot00000000000000%%% exam.cls \ProvidesClass{exam} \def\ProvidesClass#1[#2]{\relax} \input article.cls \newif\iftitle\titlefalse \newif\ifauthor\authorfalse \def\title#1{\def\thetitle{#1}\titletrue} \def\author#1{\def\theauthor{#1}\authortrue} \def\maketitle{ \begin{flushleft} \iftitle{\LARGE\textbf{\thetitle}} \\[6pt]\fi \ifauthor{\Large\textbf{\theauthor}} \\\fi \end{flushleft}} \newcounter{quiz} \renewcommand{\thequiz}{\arabic{quiz}} \newenvironment{quiz} {\refstepcounter{quiz} \ifnum\thequiz>1\pagebreak\fi \centerline{\baselineskip=18pt \hbox to 3in{\vtop{\noindent \quizname\\\quizdate}} \hfill \hbox to 3in{\vtop{\noindent Name:\\Network ID:\\Lab section:\\Lecture section:}}} \bigskip} {} \newcounter{problem}[quiz] \renewcommand{\theproblem}{\arabic{problem}} \newenvironment{problem} {\par\bigskip\refstepcounter{problem} \goodbreak \par\nobreak \textbf{Problem \theproblem. }} {\removelastskip\bigskip\vfill} \newcounter{subproblem}[problem] \renewcommand{\thesubproblem}{\alph{subproblem}} \newcommand{\subproblem}{\par\refstepcounter{subproblem}\medskip\textbf{\theproblem\thesubproblem. }} %%% latex.ltx redefinitions %% change section headers to "1.1. foo" instead of "1.1 foo" \def\@seccntformat#1{\csname the#1\endcsname. } \renewenvironment{description} {\list{}{\labelwidth\z@ \itemindent-\leftmargin \let\makelabel\descriptionlabel}} {\endlist} \renewcommand*\descriptionlabel[1]{\hspace\labelsep #1} \def\itemvdots{\item[] \mbox{\vdots}} \def\parheader#1 {\medskip\noindent{\bf #1.}~~} \newenvironment{grammar} {\begingroup \def\orbar{\hbox to 2em{\hfil}$\vert$\hbox to .75em{\hfil}} \def\longis{ $\longrightarrow$\hbox to .75em{\hfil}} \penalty-100\vskip 6pt plus 1pt\parindent=0pt\interlinepenalty=5000} {\penalty-200\vskip6pt plus 1pt\endgroup} \def\bar{$\vert$} \def\ang#1{$\langle${\small\rm{}#1}$\rangle$} \def\kstar{\raise.5ex\hbox{\scheme{*}}} \def\kplus{\raise.5ex\hbox{\scheme{+}}} \newcounter{alphacount} \def\alphalabel{\textit{\alph{alphacount}}.} \newenvironment{alphalist} {\begingroup\let\beforeschemedisplay=\relax\let\afterschemedisplay=\relax \begin{list}{\alphalabel}{\usecounter{alphacount}\itemsep=0pt\parsep=0pt% \topsep=0pt}} {\end{list}\endgroup} %%% final set up \renewcommand{\contentsname}{Contents} \newcommand{\bibname}{Bibliography} \renewcommand{\indexname}{Index} \renewcommand{\today}{\ifcase\month\or January\or February\or March\or April\or May\or June\or July\or August\or September\or October\or November\or December\fi \space\number\day, \number\year} \setlength\columnsep{10\p@} \setlength\columnseprule{0\p@} \pagestyle{headings} \pagenumbering{arabic} \if@twoside\else\raggedbottom\fi \endinput %%% end of assignment.cls stex-1.2.1+git20171204.g5e4f0ca/inputs/fullpage.sty000066400000000000000000000015161321130544300212540ustar00rootroot00000000000000% This is FULLPAGE.STY by H.Partl, Version 2 as of 15 Dec 1988. % Document Style Option to fill the paper just like Plain TeX. \typeout{Style Option FULLPAGE Version 2 as of 15 Dec 1988} \topmargin 0pt \advance \topmargin by -\headheight \advance \topmargin by -\headsep \textheight 8.9in \oddsidemargin 0pt \evensidemargin \oddsidemargin \marginparwidth 0.5in \textwidth 6.5in % For users of A4 paper: The above values are suited for american 8.5x11in % paper. If your output driver performs a conversion for A4 paper, keep % those values. If your output driver conforms to the TeX standard (1in/1in), % then you should add the following commands to center the text on A4 paper: % \advance\hoffset by -3mm % A4 is narrower. % \advance\voffset by 8mm % A4 is taller. \endinput stex-1.2.1+git20171204.g5e4f0ca/inputs/grammar.hsty000066400000000000000000000007361321130544300212560ustar00rootroot00000000000000%%% grammar support \newenvironment{grammar} {\begingroup \def\orbar{\raw{
|}} \def\nobar{\raw{}} \def\longis{\raw{}$\longrightarrow$\raw{}} \def\\{\raw{
}} \raw{
}} {\raw{
}\endgroup} \def\bar{\raw{|}} \def\kplus{\raw{+}} \def\kstar{\raw{*}} \def\ang#1{\raw{<}#1\raw{>}} stex-1.2.1+git20171204.g5e4f0ca/inputs/grammar.sty000066400000000000000000000007601321130544300211030ustar00rootroot00000000000000\newenvironment{grammar} {\begingroup \def\orbar{\hbox to 2em{\hfil}$\vert$\hbox to .75em{\hfil}} \def\nobar{\hbox to 2em{\hfil}\phantom{$\vert$}\hbox to .75em{\hfil}} \def\longis{ $\longrightarrow$\hbox to .75em{\hfil}} \penalty-100\vskip 6pt plus 1pt\parindent=0pt\interlinepenalty=5000} {\penalty-200\vskip6pt plus 1pt\endgroup} \def\bar{$\vert$} \def\ang#1{$\langle${\small\rm{}#1}$\rangle$} \def\kstar{\raise.5ex\hbox{\scheme{*}}} \def\kplus{\raise.5ex\hbox{\scheme{+}}} stex-1.2.1+git20171204.g5e4f0ca/inputs/html-prep.tex000066400000000000000000000024461321130544300213510ustar00rootroot00000000000000%%% html-prep.tex %%% /* these don't handle nesting properly, i.e., nested \emph */ \def\emph#1{\raw{}#1\raw{}} \def\textit#1{\raw{}#1\raw{}} \def\textsl#1{\raw{}#1\raw{}} % really want slant font \def\textbf#1{\raw{}#1\raw{}} \def\texttt#1{\raw{}#1\raw{}} \def\copyright{\raw{©}} \def\protect{} \def\bigskip{\raw{

}} \def\medskip{\raw{

}} \def\smallskip{\raw{

}} \def\nobreak{} \def\noindent{} \def\_{\raw{_}} \def\par{\raw{

}} \def\dots{\raw{...}} \def\vdots{$\vdots$} \def\null{} \def\${\raw{$}} \def\&{\raw{&}} \def\%{\raw{%}} \def\#{\raw{##}} \newcommand{\item}[1][]{\itemoutsideoflist} \def\itemize{\begingroup \renewcommand{\item}[1][]{\raw{

  • }##1}\raw{
      }} \def\enditemize{\raw{
    }\endgroup\par} \newcounter{enumeratecounter} \def\enumerate{\begingroup\setcounter{enumeratecounter}{0}% \renewcommand{\item}[1][]{\refstepcounter{enumeratecounter}\raw{
  • }##1}\raw{
      }} \def\endenumerate{\raw{
    }\endgroup\par} \def\description{\begingroup \renewcommand{\item}[1][]{\raw{
    }##1\raw{
    }}\raw{
    }} \def\enddescription{\raw{
    }\endgroup\par} \newenvironment{flushleft}{}{} \newenvironment{thebibliography}[1] {\begingroup\def\newblock{}} {\endgroup} \newenvironment{quotation} {\raw{
    }} {\raw{
    }} stex-1.2.1+git20171204.g5e4f0ca/inputs/monograph.cls000066400000000000000000000126521321130544300214140ustar00rootroot00000000000000%%% monograph.cls \ProvidesClass{monograph} \def\ProvidesClass#1[#2]{\relax} \input article.cls \def\copyrightnotice{\ifauthor\copyright~\number\year~\theauthor\fi} \def\ps@plain{\let\@mkboth\@gobbletwo \let\@oddhead\@empty\def\@oddfoot{\reset@font \footer}\let\@evenhead\@empty\let\@evenfoot\@oddfoot} \def\footer{\hfil\ifnum\c@page =1 \copyrightnotice\else\thepage\fi\hfil} \newif\iftitle\titlefalse \newif\ifauthor\authorfalse \newif\ifdate\datefalse \def\title#1{\def\thetitle{#1}\titletrue} \def\author#1{\def\theauthor{#1}\authortrue} \def\date#1{\def\thedate{#1}\datetrue} \def\maketitle{ \begin{flushleft} \iftitle{\LARGE\textbf{\thetitle} \\[6pt]}\fi \ifauthor{\Large\textbf{\theauthor} \\[6pt]}\fi \ifdate{\large\textbf{\thedate} \\}\fi \end{flushleft}} %%% to support hypertext index entries \def\hindex#1{\index} % ignore the label here---no links in printed version \newcommand{\hyperlink}[3][]{#3} \newcommand{\href}[3][]{#3} \newcommand{\hpageref}[3][]{#3} \newif\iflatex\latextrue \newif\ifhtml\htmlfalse %%% table of contents \renewcommand{\@pnumwidth}{1.55em} \renewcommand{\@tocrmarg} {2.55em} \renewcommand{\@dotsep}{4.5} \setcounter{tocdepth}{2} \newcommand*{\l@chapter}[2]{% \ifnum \c@tocdepth >\m@ne \addpenalty{-\@highpenalty}% \vskip 1.0em \@plus\p@ \setlength\@tempdima{1.5em}% \begingroup \parindent \z@ \rightskip \@pnumwidth \parfillskip -\@pnumwidth \leavevmode \bfseries \advance\leftskip\@tempdima \hskip -\leftskip #1\nobreak\hfil \nobreak\hbox to\@pnumwidth{\hss #2}\par \penalty\@highpenalty \endgroup \fi} \renewcommand*{\l@section}[2] {\vspace{4pt}\hbox to \hsize{\bf #1\hfil#2}} \renewcommand*{\l@subsection}[2] {\vspace{2pt}\hbox to \hsize{\rm #1\hfill#2}} \def\numberline#1{#1} \renewcommand{\tableofcontents}{% \thispagestyle{plain}% \global\@topnum\z@ \section*{\contentsname}% \@starttoc{toc}} \newcounter{exercise} \renewcommand{\theexercise}{\arabic{exercise}} \def\@startexercise{\par\bigskip \refstepcounter{exercise}\goodbreak \par\hrule width \hsize{\hfil}\\\nobreak \textbf{Exercise \theexercise. }\ignorespaces} \newenvironment{exercise} {\begingroup \def\afterschemedisplay{\removelastskip\penalty10000\vskip5pt} \let\newexercise=\@startexercise\newexercise} {\par\removelastskip\penalty10000\kern6pt\hrule width \hsize{\hfil}\endgroup} \newcounter{subexercise}[exercise] \renewcommand{\thesubexercise}{\theexercise\alph{subexercise}} \newcommand{\subexercise}{\par\refstepcounter{subexercise}\medskip\textbf{\thesubexercise. }} %%% bibliography \newdimen\bibindent \bibindent=1.5em \renewcommand{\newblock}{} \renewenvironment{thebibliography}[1] {\section{\bibname} \list{\@biblabel{\arabic{enumiv}}}% {\settowidth\labelwidth{\@biblabel{#1}}% \leftmargin\labelwidth \advance\leftmargin\labelsep \usecounter{enumiv}% \let\p@enumiv\@empty \renewcommand{\theenumiv}{\arabic{enumiv}}}% \renewcommand{\newblock}{\hskip .11em \@plus.33em \@minus.07em}% \sloppy\clubpenalty4000\widowpenalty4000% \sfcode`\.=\@m} {\def\@noitemerr {\@latex@warning{Empty `thebibliography' environment}}% \endlist} %%% index \def\notsupposedtobehereindexname{\indexname} \renewenvironment{theindex} {\if@openright\cleardoublepage\else\clearpage\fi \raggedright \columnseprule \z@ \columnsep 35\p@ \twocolumn[\plainchapterhead{\indexname}]% \addcontentsline{toc}{chapter}{\indexname}% \chaptermark{\indexname}{\notsupposedtobehereindexname}% \thispagestyle{plain}\parindent\z@ \parskip\z@ \@plus .3\p@\relax \let\item\@idxitem} {\clearpage} \renewcommand{\@idxitem} {\par\hangindent 40\p@} \renewcommand{\subitem} {\par\hangindent 40\p@ \hspace*{20\p@}} \renewcommand{\subsubitem}{\par\hangindent 40\p@ \hspace*{30\p@}} \renewcommand{\indexspace}{\par \vskip 10\p@ \@plus5\p@ \@minus3\p@\relax} %%% latex.ltx redefinitions %% leave padding page blank (no header) \def\cleardoublepage{\clearpage\if@twoside \ifodd\c@page\else {\pagestyle{empty}\hbox{}\newpage\if@twocolumn\hbox{}\newpage\fi}\fi\fi} %% change section headers to "1.1. foo" instead of "1.1 foo" \def\@seccntformat#1{\csname the#1\endcsname. } %% change numbered table of contents lines to "1.1. foo" instead of "1.1 foo" \def\numberline#1{#1. } \renewenvironment{description} {\list{}{\labelwidth\z@ \itemindent-\leftmargin \let\makelabel\descriptionlabel}} {\endlist} \renewcommand*\descriptionlabel[1]{\hspace\labelsep #1} \def\itemvdots{\item[] \mbox{\vdots}} \newcommand{\parheader}[2][.~\ignorespaces]{\medskip\noindent{\bf #2#1}} \newcommand{\sectionstar}[1]{\section*{#1}} \newcommand{\subsectionstar}[1]{\subsection*{#1}} \newcommand{\subsubsectionstar}[1]{\subsubsection*{#1}} %%% final set up \renewcommand{\contentsname}{Contents} \newcommand{\bibname}{Bibliography} \renewcommand{\indexname}{Index} \renewcommand{\today}{\ifcase\month\or January\or February\or March\or April\or May\or June\or July\or August\or September\or October\or November\or December\fi \space\number\day, \number\year} \setlength\columnsep{10\p@} \setlength\columnseprule{0\p@} \pagestyle{headings} \pagenumbering{arabic} \if@twoside\else\raggedbottom\fi \endinput %%% end of monograph.cls stex-1.2.1+git20171204.g5e4f0ca/inputs/monograph.hcls000066400000000000000000000106771321130544300215710ustar00rootroot00000000000000%%% monograph.hcls \newif\iflatex\latexfalse \newif\ifhtml\htmltrue % should be built in \newenvironment{center} {\raw{
    }} {\raw{
    }} \def\copyrightnotice{\ifauthor\par\raw{
    }\copyright~\year~\theauthor\par\fi} \let\trueenddocument=\enddocument \def\enddocument{ \begin{divertoutput}[toc] \ifsubsubsec\raw{
  • }\fi \end{divertoutput} \copyrightnotice\trueenddocument} \newif\iftitle\titlefalse \newif\ifdate\datefalse \newif\ifauthor\authorfalse \def\title#1{\def\thetitle{#1}\titletrue} \def\date#1{\def\thedate{#1}\datetrue} \def\author#1{\def\theauthor{#1}\authortrue} \def\maketitle{% \iftitle\raw{

    }\thetitle\raw{

    }\fi \ifauthor\raw{

    }\theauthor\raw{

    }\fi \ifdate\raw{

    }\thedate\raw{

    }\fi } %%% table of contents \newif\ifsubsec\subsecfalse \newif\ifsubsubsec\subsubsecfalse \newcommand{\tableofcontents}{ \raw{} \rawinput{\jobname.htoc} \raw{
    } \openrawfile{toc}{\jobname.htoc}} \newcommand{\notableofcontents}{ \openrawfile{toc}{\jobname.htoc}} %%% \section \newcounter{section} \renewcommand{\thesection}{\arabic{section}} \newcommand{\section}[1]{ \refstepcounter{section} \edef\templabel{\genlab} \sectionstar{\label{\templabel}\thesection. #1} \begin{divertoutput}[toc] \ifsubsubsec\raw{}\fi \subsubsecfalse \ifsubsec\raw{}\fi \subsecfalse \raw{}\textbf{\thesection.~}\raw{}\textbf{\href[plain]{\templabel}{#1}}\raw{} \end{divertoutput} } \newcommand{\sectionstar}[1]{ \raw{

    }#1\raw{

    } } %%% \subsection \newcounter{subsection}[section] \renewcommand{\thesubsection}{\thesection.\arabic{subsection}} \newcommand{\subsection}[1]{ \refstepcounter{subsection} \edef\templabel{\genlab} \subsectionstar{\label{\templabel}\thesubsection. #1} \begin{divertoutput}[toc] \ifsubsubsec\raw{}\fi \subsubsecfalse \ifsubsec\else\raw{}\fi \subsectrue \raw{} \end{divertoutput} } \newcommand{\subsectionstar}[1]{ \raw{

    }#1\raw{

    } } %%% \subsubsection \newcounter{subsubsection}[subsection] \renewcommand{\thesubsubsection}{\thesubsection.\arabic{subsubsection}} \newcommand{\subsubsection}[1]{ \refstepcounter{subsubsection} \edef\templabel{\genlab} \subsubsectionstar{\label{\templabel}\thesubsubsection. #1} \begin{divertoutput}[toc] \ifsubsubsec\else\raw{
    }\textbf{\thesubsection.~}\raw{}\textbf{\href[plain]{\templabel}{#1}}\raw{
    }\fi \subsubsectrue \raw{} \end{divertoutput} } \newcommand{\subsubsectionstar}[1]{ \raw{

    }#1\raw{

    } } %%% figure \newcounter{figure} \renewcommand{\thefigure}{\arabic{figure}} \newcommand{\caption}[1]{\\ Figure \thefigure.~#1} \newenvironment{figure}[1][] {\begingroup\refstepcounter{figure}} {\endgroup} %%% exercise \newcounter{exercise} \renewcommand{\theexercise}{\arabic{exercise}} \def\@startexercise{\refstepcounter{exercise} \raw{
    } \textbf{Exercise \theexercise. }} \newenvironment{exercise} {\begingroup\def\newexercise{\@startexercise}\newexercise} {\raw{
    }} \newcounter{subexercise}[exercise] \renewcommand{\thesubexercise}{\theexercise\alph{subexercise}} \newcommand{\subexercise}{\par\refstepcounter{subexercise}\textbf{\thesubexercise. }} %%% alphalist \newcounter{alphalist} \def\alphalist{\begingroup\setcounter{alphalist}{0} \def\endalphalistitem{}% \renewcommand{\item}{\endalphalistitem \def\endalphalistiem{\raw{}}% \stepcounter{alphalist}% \raw{}}% \stepcounter{alphalist}% \raw{" (vector-ref (table-col-format colfmt) column) (get-output-string op)) (case (car pending) [(multicolumn) (P k ([pending (cdr pending)] [colfmt (car colfmts)] [colfmts (cdr colfmts)]))] [(tabular) (P k ())] [else (errorf 'html-prep.ss "emit-td somehow invoked with invalid pending ~s" (car pending))]))) (define sampersand (P lambda () (case (car pending) [(tabular multicolumn) (P emit-td () (P lambda () (let ([column (+ column 1)]) (when (>= column (vector-length (table-col-format colfmt))) (unread-char #\& ip) (input-error "Extra alignment character &")) (P s0 ([op (open-output-string)] [column column])))))] [else (input-error "Misplaced or extra alignment tab character &")]))) (define scr (P lambda () (read-optional-arg ip) ; waste bracketed skip amount, if any (case (car pending) [(tabular multicolumn) (P emit-td () (P lambda () (display "" (car ops)) (P s0 ([column 0]))))] [else (display "
    \n" op) (P s0)]))) ;----------------------------------------------------------------------- (define header-stuff (make-parameter #f)) (define style-sheet (make-parameter #f)) (define current-ofile (make-parameter #f)) ; for slabel (define current-ref-label (make-parameter #f)) (define document-title (make-parameter #f)) (define index-entries (make-parameter #f)) (define latex-cache (make-parameter #f)) (define output-file-counters (make-parameter #f)) (define haux-op (make-parameter #f)) (define jobname (make-parameter #f)) (define go (lambda (fn) (define bit-sink (let () (define make-bit-sink-port (lambda () (define handler (lambda (msg . args) (record-case (cons msg args) [block-write (p s n) (void)] [clear-output-port (p) (set-port-output-index! p 0)] [close-port (p) (set-port-output-size! p 0) (mark-port-closed! p)] [flush-output-port (p) (set-port-output-index! p 0)] [port-name (p) "bit-sink port"] [write-char (c p) (set-port-output-index! p 0)] [else (errorf 'bit-sink-port "operation ~s not handled" msg)]))) (let ([len 1024]) (let ([p (make-output-port handler (make-string len))]) p)))) (make-bit-sink-port))) (jobname fn) (let ([ip (open-input-file (tex-file-name fn))]) ; preplib parameters (parameterize ([current-ifile #f] [genlab-prefix "h"] [genlab-counters '()]) ; local parameters (parameterize ([header-stuff #f] [style-sheet #f] [current-ofile #f] [current-ref-label #f] [document-title "Untitled Document"] [index-entries '()] [latex-cache '()] [output-file-counters '()] [haux-op bit-sink]) (P s0 ([ip ip] [op bit-sink] [def-env '()] [pending '(top)] [groups '(top)] [ips '()] [ops '()] [ifiles (push-ifile ip '())] [ofiles '()] [rawfiles '()] [hard-spaces #f] [eofconts (list s0)] [undos (list '())] [column #f] ; need flow-sensitive static analysis [columns '()] [colfmt #f] ; need flow-sensitive static analysis [colfmts '()] [convert-quotes #t]))))))) (global-def def (P lambda () (let* ([cmd (state-case (c (read-char ip)) [(#\\) (read-command ip)] [else (input-error "invalid \\def syntax")])] [pattern (read-def-pattern ip)] [template (read-bracketed-text ip)]) (set-def! cmd def-env #f (P lambda () (P s0 ([ip (open-input-string (expand-template template (read-args ip pattern cmd) cmd))] [ips (cons ip ips)] [eofconts (cons s0 eofconts)])))) (P s0)))) ;\let\foo= (global-def let (P lambda () (let* ([cmd (state-case (c (read-char ip)) [(#\\) (read-command ip)] [else (input-error "invalid \\let syntax")])] [rhs (state-case (c (read-char ip)) [(#\=) (state-case (c (read-char ip)) [(#\\) (read-command ip)] [else (input-error "invalid \\let right-hand side")])] [else (input-error "expected = after \\let")])]) (set-def! cmd def-env #f (get-def rhs def-env)) (P s0)))) (global-def edef (P lambda () (let* ([cmd (state-case (c (read-char ip)) [(#\\) (read-command ip)] [else (input-error "invalid \\def syntax")])] [pattern (read-def-pattern ip)] [template (read-bracketed-text ip)]) (P process-string () template (P lambda (template) (set-def! cmd def-env #f (P lambda () (P s0 ([ip (open-input-string (expand-template template (read-args ip pattern cmd) cmd))] [ips (cons ip ips)] [eofconts (cons s0 eofconts)])))) (P s0)))))) (global-def newcommand (P lambda () (read-open-brace ip) (read-back-slash ip) (let ([cmd (read-command ip)]) (read-close-brace ip) (when (get-def cmd def-env) (input-error "\\newcommand: \\~a already defined" cmd)) (P snewcommand () cmd)))) (global-def renewcommand (P lambda () (read-open-brace ip) (read-back-slash ip) (let ([cmd (read-command ip)]) (read-close-brace ip) (unless (get-def cmd def-env) (input-error "\\renewcommand: \\~a undefined" cmd)) (P snewcommand () cmd)))) (global-def newenvironment (P lambda () (let ([cmd (string->symbol (read-bracketed-text ip))]) (when (get-def cmd def-env) (input-error "\\newenvironment: \\~a already defined" cmd)) (P snewenvironment () cmd)))) (global-def renewenvironment (P lambda () (let ([cmd (string->symbol (read-bracketed-text ip))]) (unless (get-def cmd def-env) (input-error "\\renewenvironment: \\~a undefined" cmd)) (P snewenvironment () cmd)))) (global-def begin (P lambda () (let ([cmd (string->symbol (read-bracketed-text ip))]) (cond [(get-def cmd def-env) => (lambda (proc) (P proc))] [else (input-error "undefined command \\begin{~a}" cmd)])))) (global-def end (P lambda () (let* ([cmd (string->symbol (read-bracketed-text ip))] [endcmd (string->symbol (format "end~a" cmd))]) (cond [(get-def endcmd def-env) => (lambda (proc) (P proc))] [else (input-error "undefined command \\end{~a}" cmd)])))) (global-def eqnarray* ; no endeqnarray*---we finish the job here (P lambda () (fprintf op "

    ~%") (seqnarray* ip op) (fprintf op "

    ~%") (P s0 ()))) (global-def divertoutput (P lambda () (let* ([level-str (or (read-optional-arg ip) "0")] [level (let ([i (string->number level-str)]) (and (fixnum? i) (let ([n (length ofiles)]) (and (fixnum? i) (if (fx< -1 i n) (fx- n i 1) (and (fx<= (- n) i -1) (fx- -1 i)))))))]) (cond [level (P s0 ([op (list-ref ofiles level)] [ops (cons op ops)]))] [(assoc level-str rawfiles) => (lambda (a) (P s0 ([op (cdr a)] [ops (cons op ops)])))] [else (input-error (format "invalid divertoutput file ~a" level-str))])))) (global-def enddivertoutput (P lambda () (P s0 ([op (car ops)] [ops (cdr ops)])))) (global-def begingroup (P lambda () (P sbegingroup () 'begingroup))) (global-def endgroup (P lambda () (P sendgroup () 'begingroup))) (global-def bgroup (P lambda () (P sbegingroup () 'bgroup))) (global-def egroup (P lambda () (P sendgroup () 'bgroup))) (global-def |[| ;] (P lambda () (fprintf op "

    ~%") (smathdisplay ip op) (fprintf op "

    ~%") (P s0))) (global-def raw (P lambda () (sraw (open-input-string (read-bracketed-text ip)) op) (P s0))) (global-def jobname (P lambda () (display (jobname) op) (P s0))) (global-def newif (P lambda () (snewif ip def-env) (P s0))) (numbering-command arabic (lambda (n) n)) (numbering-command alph (lambda (n) (when (> n 26) (input-error "counter value ~a too large for \\alph" n)) (string-ref "abcdefghijklmnopqrstuvwxyz" (- n 1)))) (numbering-command Alph (lambda (n) (when (> n 26) (input-error "counter value ~a too large for \\Alph" n)) (string-ref "ABCDEFGHIJKLMNOPQRSTUVWXYZ" (- n 1)))) (global-def newcounter (P lambda () (let* ([name-str (read-bracketed-text ip)] [counter (string->symbol name-str)] [within (read-optional-arg ip)]) (when (get-counter-value counter) (input-error "newcounter of existing counter ~a" counter)) (when within (let ([within (string->symbol within)]) (unless (get-counter-value within) (input-error "newcounter of ~a within unknown counter ~a" counter within)) (add-subcounter! within counter))) (set-counter-value! counter 0) (set-def! (string->symbol (string-append "the" name-str)) def-env #f (P lambda () (display (get-counter-value counter) op) (P s0)))) (P s0))) (global-def setcounter (P lambda () (let* ([counter (string->symbol (read-bracketed-text ip))] [num-str (read-bracketed-text ip)] [old-value (get-counter-value counter)] [new-value (string->number num-str)]) (unless old-value (input-error "setcounter of unknown counter ~a" counter)) (unless new-value (input-error "invalid setcounter value ~a" num-str)) (set-counter-value! counter new-value)) (P s0))) (global-def addtocounter (P lambda () (let* ([counter (string->symbol (read-bracketed-text ip))] [num-str (read-bracketed-text ip)] [old-value (get-counter-value counter)] [incr (string->number num-str)]) (unless old-value (input-error "addtocounter of unknown counter ~a" counter)) (unless incr (input-error "invalid addtocounter increment ~a" num-str)) (set-counter-value! counter (+ old-value incr))) (P s0))) (global-def stepcounter (P lambda () (let* ([counter (string->symbol (read-bracketed-text ip))] [old-value (get-counter-value counter)]) (unless old-value (input-error "\\stepcounter of unknown counter ~a" counter)) (set-counter-value! counter (+ old-value 1)) (for-each (lambda (x) (set-counter-value! x 0)) (subcounters counter))) (P s0))) (global-def refstepcounter (P lambda () (let* ([counter (string->symbol (read-bracketed-text ip))] [old-value (get-counter-value counter)]) (unless old-value (input-error "\\refstepcounter of unknown counter ~a" counter)) (set-counter-value! counter (+ old-value 1)) (for-each (lambda (x) (set-counter-value! x 0)) (subcounters counter)) (P process-string () (format "\\the~a" counter) (P lambda (s) (let ([tag (gensym)]) (current-ref-label (cons s (format "~a#~a" (current-ofile-name) tag))) (fprintf op "" tag)) (P s0)))))) (global-def pagebreak (P lambda () (read-optional-arg ip) ; ignore [...] (P s0))) (global-def verbatim ; no endverbatim---we finish the job here (P lambda () (define escape-char (lambda (c) (case c [(#\space #\tab #\newline #\return) (write-char c op)] [(#\<) (fprintf op "<")] [(#\>) (fprintf op ">")] [(#\&) (fprintf op "&")] [else (write-char c op)]))) (display "

    " op)
        (let loop ()
          (state-case (c (read-char ip))
            [(#\\)
             (let ([cmd (read-command ip)])
               (case cmd
                 [(end)
                  (state-case (c (read-char ip))
                    [(#\{)
                     (let ([what (read-alpha-command ip)])
                       (if (and (eq? what 'verbatim) (eqv? (peek-char ip) #\}))
                           (read-char ip)
                           (begin
                             (fprintf op "\\end{~a" what)
                             (loop))))]
                    [(eof) (unexpected-eof "within verbatim environment")]
                    [else (fprintf op "\\end") (escape-char c) (loop)])]
                 [else (fprintf op "\\~a" cmd) (loop)]))]
            [(eof) (unexpected-eof "within verbatim environment")]
            [else (escape-char c) (loop)]))
        (fprintf op "
    ~%") (P s0 ()))) (global-def |'| (P lambda () (state-case (c (read-char ip)) [(#\e) (fprintf op "é")] [(#\o) (fprintf op "ó")] [else (input-error "invalid \\' command \\'~a" c)]) (P s0))) (global-def |"| ; \"{} (P lambda () (let ([arg (read-bracketed-text ip)]) (unless (= (string-length arg) 1) (input-error "invalid \\\" argument ~s" arg)) (let ([c (string-ref arg 0)]) (case c [(#\a #\e #\i #\o #\u #\y #\A #\E #\I #\O #\U) (fprintf op "&~auml;" c)] [else (input-error "invalid \\\" command \\\"{~a}" c)]))) (P s0))) (global-def |c| ; \c{} (P lambda () (let ([arg (read-bracketed-text ip)]) (unless (= (string-length arg) 1) (input-error "invalid \\c argument ~s" arg)) (let ([c (string-ref arg 0)]) (case c [(#\c #\C) (fprintf op "&~acedil;" c)] [else (input-error "invalid \\c command \\c{~a}" c)]))) (P s0))) (global-def ss (P lambda () (fprintf op "ß") (P s0))) (global-def vskip (P lambda () ; it's a pain to parse tex amounts, so we choose to ignore ; everything up to the next line break instead...watch out! (let ([op (open-output-string)]) (let f () (state-case (c (read-char ip)) [(#\newline eof) (warningf 'vskip "discarded text: ~a" (get-output-string op)) (P s0)] [else (write-char c op) (f)]))))) (global-def large (P lambda () (fprintf op "") (P s0 ([undos (push-undo (P lambda (next) (fprintf op "") (P next)) undos)])))) (global-def Large (P lambda () (fprintf op "") (P s0 ([undos (push-undo (P lambda (next) (fprintf op "") (P next)) undos)])))) (global-def LARGE (P lambda () (fprintf op "") (P s0 ([undos (push-undo (P lambda (next) (fprintf op "") (P next)) undos)])))) (global-def small (P lambda () (fprintf op "") (P s0 ([undos (push-undo (P lambda (next) (fprintf op "") (P next)) undos)])))) (global-def footnotesize (P lambda () (fprintf op "") (P s0 ([undos (push-undo (P lambda (next) (fprintf op "") (P next)) undos)])))) (global-def tiny (P lambda () (fprintf op "") (P s0 ([undos (push-undo (P lambda (next) (fprintf op "") (P next)) undos)])))) (global-def normalsize (P lambda () (fprintf op "") (P s0 ([undos (push-undo (P lambda (next) (fprintf op "") (P next)) undos)])))) (global-def tt (P lambda () (fprintf op "") (P s0 ([convert-quotes #f] [undos (push-undo (P lambda (next) (fprintf op "") (P next ([convert-quotes #t]))) undos)])))) (global-def bf (P lambda () (fprintf op "") (P s0 ([undos (push-undo (P lambda (next) (fprintf op "") (P next)) undos)])))) (global-def it (P lambda () (fprintf op "") (P s0 ([undos (push-undo (P lambda (next) (fprintf op "") (P next)) undos)])))) (global-def hardspaces (P lambda () (let ([old-hs hard-spaces]) (P s0 ([hard-spaces #t] [undos (push-undo (P lambda (next) (P next ([hard-spaces old-hs]))) undos)]))))) (global-def include (P lambda () (P process-string () (read-bracketed-text ip) (P lambda (fn) (P sinclude () (format "~a.tex" fn)))))) (global-def input (P lambda () (P process-string () (read-bracketed-text ip) (P lambda (fn) (P sinclude () (tex-file-name fn)))))) (global-def rawinput (P lambda () (P process-string () (read-bracketed-text ip) (P lambda (fn) (call-with-port (guard (c [else (warningf #f "cannot open ~a" fn) #f]) (open-input-file fn)) (lambda (raw-ip) (let loop () (let ([c (read-char raw-ip)]) (unless (eof-object? c) (write-char c op) (loop)))))) (P s0))))) (global-def label (P lambda () (P process-string () (read-bracketed-text ip) (P lambda (s) (display (slabel (string->symbol s) "" s) op) (P s0))))) (global-def href (P lambda () (let ([class (read-optional-arg ip)]) (P process-string () (read-bracketed-text ip) (P lambda (lab) (P process-string () (read-bracketed-text ip) (P lambda (text) (let ([name (string->symbol lab)]) (fprintf op "~a" class (get-label name 'ref-url) text) (P s0))))))))) (global-def hpageref (P lambda () (let ([class (read-optional-arg ip)]) (P process-string () (read-bracketed-text ip) (P lambda (lab) (P process-string () (read-bracketed-text ip) (P lambda (text) (let ([name (string->symbol lab)]) (fprintf op "~a" class (get-label name 'pageref-url) text) (P s0))))))))) (global-def ref (P lambda () (let ([class (read-optional-arg ip)]) (P process-string () (read-bracketed-text ip) (P lambda (s) (let ([name (string->symbol s)]) (fprintf op "~a" class (get-label name 'ref-url) (get-label name 'ref))) (P s0)))))) (global-def pageref (P lambda () (let ([class (read-optional-arg ip)]) (P process-string () (read-bracketed-text ip) (P lambda (s) (let ([name (string->symbol s)]) (fprintf op "~a" class (get-label name 'pageref-url) (get-label name 'pageref))) (P s0)))))) (global-def cite (P lambda () (write-char #\[ op) (let ([keys (let ([sip (open-input-string (read-bracketed-text ip))] [buf (open-output-string)]) (let loop () (state-case (c (read-char sip)) [(#\,) (let ([key (get-output-string buf)]) (cons key (loop)))] [(eof) (list (get-output-string buf))] [else (write-char c buf) (loop)])))]) (do ([keys keys (cdr keys)] [sep "" ","]) ((null? keys) (write-char #\] op)) (let ([key (string->symbol (car keys))]) (fprintf op "~a~a" sep (get-label key 'pageref-url) (get-cite key))))) (P s0))) (global-def epsfbox (P lambda () (fprintf op "

    ~%") (punt-to-latex (format "\\input{epsf.sty}\\epsfbox{~a}" (read-bracketed-text ip)) op) (fprintf op "

    ~%") (P s0))) (global-def bibitem (P lambda () (let ([key (string->symbol (read-bracketed-text ip))]) (fprintf op "

    [~a] " (slabel key (get-cite key)))) (P s0))) (global-def openhtmlfile (P lambda () (P process-string () (read-bracketed-text ip) (P lambda (title) (let ([new-op (open-html-file (car ifiles) title)]) (P s0 ([op new-op] [ops (cons op ops)] [ofiles (push-ofile new-op ofiles)]))))))) (global-def closehtmlfile (P lambda () (unless (and (not (null? ofiles)) (eq? op (car ofiles))) (input-error "invalid context for \\closehtmlfile")) (close-html-port op) (P s0 ([op (car ops)] [ops (cdr ops)] [ofiles (pop-ofile ofiles)])))) (global-def openrawfile (P lambda () (let ([name (read-bracketed-text ip)]) (P process-string () (read-bracketed-text ip) (P lambda (path) (P s0 ([rawfiles (cons (cons name (open-output-file path 'replace)) rawfiles)]))))))) (global-def closerawfile (P lambda () (let ([name (read-bracketed-text ip)]) (cond [(assoc name rawfiles) => (lambda (a) (close-output-port (cdr a)) (P s0 ([rawfiles (remq a rawfiles)])))] [else (input-error "unrecognized raw file" name)])))) (global-def genlab (P lambda () (display (genlab) op) (P s0))) (global-def hindex (P lambda () (P process-string () (read-bracketed-text ip) (P lambda (s) (read-open-brace ip) (sindex ip op (string->symbol s)) (P s0))))) (global-def index (P lambda () (let ([lab (genlab)]) (display (slabel lab "") op) (read-open-brace ip) (sindex ip op lab) (P s0)))) (global-def makeindex (P lambda () (let ([buf (open-output-string)]) (smakeindex buf) (P s0 ([ip (open-input-string (get-output-string buf))] [ips (cons ip ips)] [eofconts (cons s0 eofconts)]))))) (global-def documentclass (P lambda () (read-optional-arg ip) (P sinclude () (with-source-path 'documentclass (format "~a.hcls" (read-bracketed-text ip)) (lambda (x) (printf "using ~a~%" x) x))))) (global-def document (P lambda () (let ([root (path-root (port-name (car ifiles)))]) (let ([auxfn (format "~a.aux" root)] [hauxfn (format "~a.haux" root)]) (guard (c [else (warningf #f "missing or incomplete aux file")]) (read-aux-file (format "~a.aux" root))) (guard (c [else (warningf #f "missing or incomplete haux file")]) (load hauxfn)) (haux-op (open-output-file hauxfn 'replace)))) (P s0 ([ip (open-input-string (format "\\openhtmlfile{\\raw{~a}}" (document-title)))] [ips (cons ip ips)] [eofconts (cons s0 eofconts)])))) (global-def enddocument (P lambda () (for-each close-output-port (map cdr rawfiles)) (P s0 ([ip (open-input-string "\\closehtmlfile")] [ips (cons ip ips)] [eofconts (cons s0 eofconts)])))) (global-def headerstuff (P lambda () (header-stuff (read-bracketed-text ip)) (P s0))) (global-def documenttitle (P lambda () (let ([fmt (read-optional-arg ip)]) (P process-string () (read-bracketed-text ip) (P lambda (title) (global-def thetitle (P lambda () (display title op) (P s0))) (style-sheet fmt) (document-title title) (P s0)))))) (global-def |{| (P lambda () (display "{" op) (P s0))) (global-def |}| (P lambda () (display "}" op) (P s0))) (global-def | | (P lambda () (display (if hard-spaces " " #\space) op) (P s0))) (global-def |\| scr) (global-def usepackage (P lambda () (let ([filename (string-append (read-bracketed-text ip) ".hsty")]) (P sinclude () (or (ormap (lambda (p) (let ([path (string-append p "/" filename)]) (and (file-exists? path) path))) (source-directories)) (input-error (format "hprep style file ~s not found in TEXINPUTS" filename))))))) (global-def year (P lambda () (let* ([s (date-and-time)] [len (string-length s)]) (display (substring s (- len 4) len) op)) (P s0))) (global-def url (P lambda () (define display-url (lambda (s op) (let ([n (string-length s)]) (let loop ([i 0] [escape? #f]) (unless (fx= i n) (loop (fx+ i 1) (let ([c (string-ref s i)]) (or (and (not escape?) (char=? c #\\)) (begin (write-char c op) #f))))))))) (display-url (read-bracketed-text ip) op) (P s0))) (let () (global-def tabular (P lambda () (let ([s (read-bracketed-text ip)]) (let ([col-format (parse-col-format s)]) (display (if (table-border? col-format) "

    }\textbf{\thesubsubsection.~}\raw{}\textbf{\href[plain]{\templabel}{#1}}\raw{
    }\alph{alphalist}.\raw{}} \raw{}} \def\endalphalist{\endalphalistitem\raw{
    }\endgroup} %%% define our own (compact) description environment \def\description{\begingroup \renewcommand{\item}[1][]{\raw{
    }##1\raw{
    }}\raw{
    }} \def\enddescription{\raw{
    }\endgroup} %%% index \newcommand{\see}[2]{\emph{see} #1} \newenvironment{theindex} {\begingroup\newcommand{\itemindent}{\raw{   }} \renewcommand{\item}{\raw{
    }} \newcommand{\subitem}{\raw{
    }\itemindent} \newcommand{\subsubitem}{\raw{
    }\itemindent\itemindent}} {\par\endgroup} \newcommand{\parheader}[2][. ]{\medskip\noindent{\bf #2#1}} \def\mbox#1{#1} %%% hyperlink support \newcommand{\hyperlink}[3][ref]{\raw{}#3\raw{}} stex-1.2.1+git20171204.g5e4f0ca/inputs/quiz.cls000066400000000000000000000053731321130544300204140ustar00rootroot00000000000000%%% quiz.cls \ProvidesClass{quiz} \def\ProvidesClass#1[#2]{\relax} \input article.cls \newif\iflatex\latextrue \newif\ifhtml\htmlfalse \newif\iftitle\titlefalse \newif\ifauthor\authorfalse \def\title#1{\def\thetitle{#1}\titletrue} \def\author#1{\def\theauthor{#1}\authortrue} \def\maketitle{ \begin{flushleft} \iftitle{\LARGE\textbf{\thetitle}} \\[6pt]\fi \ifauthor{\Large\textbf{\theauthor}} \\\fi \end{flushleft}} \newcounter{quiz} \renewcommand{\thequiz}{\arabic{quiz}} \newenvironment{quiz}[1] {\refstepcounter{quiz} \ifnum\thequiz>1\pagebreak\fi \hbox to \hsize{\quizname \hfill \hbox to 3in{\vtop{\noindent Name:\\Lab section: #1\\Lecture section:}}} \bigskip} {} \newcounter{problem}[quiz] \renewcommand{\theproblem}{\arabic{problem}} \newenvironment{problem}[1][\relax] {\par\bigskip\refstepcounter{problem} \goodbreak \par\nobreak \textbf{Problem \theproblem\ifx#1\relax\else~[#1 minutes].\fi~\ignorespaces}} {\removelastskip\bigskip\vfill} \newcounter{subproblem}[problem] \renewcommand{\thesubproblem}{\alph{subproblem}} \newcommand{\subproblem}{\par\refstepcounter{subproblem}\medskip\textbf{\theproblem\thesubproblem. }} %%% latex.ltx redefinitions %% change section headers to "1.1. foo" instead of "1.1 foo" \def\@seccntformat#1{\csname the#1\endcsname. } \renewenvironment{description} {\list{}{\labelwidth\z@ \itemindent-\leftmargin \let\makelabel\descriptionlabel}} {\endlist} \renewcommand*\descriptionlabel[1]{\hspace\labelsep #1} \def\itemvdots{\item[] \mbox{\vdots}} \def\parheader#1 {\medskip\noindent{\bf #1.}~~} %%% grammar support \newenvironment{grammar} {\begingroup \def\orbar{&\bar&} \def\nobar{&&} \def\longis{&$\longrightarrow$&} \penalty-100\vskip 4pt\begin{tabular}{lcl}} {\end{tabular}\penalty-200\vskip 4pt\endgroup} \def\bar{$\vert$} \def\ang#1{$\langle${\small\rm{}#1}$\rangle$} \def\kstar{\raise.5ex\hbox{\scheme{*}}} \def\kplus{\raise.5ex\hbox{\scheme{+}}} \newcounter{alphacount} \def\alphalabel{\textit{\alph{alphacount}}.} \newenvironment{alphalist} {\begingroup\let\beforeschemedisplay=\relax\let\afterschemedisplay=\relax \begin{list}{\alphalabel}{\usecounter{alphacount}\itemsep=0pt\parsep=0pt% \topsep=0pt}} {\end{list}\endgroup} %%% final set up \renewcommand{\contentsname}{Contents} \newcommand{\bibname}{Bibliography} \renewcommand{\indexname}{Index} \renewcommand{\today}{\ifcase\month\or January\or February\or March\or April\or May\or June\or July\or August\or September\or October\or November\or December\fi \space\number\day, \number\year} \setlength\columnsep{10\p@} \setlength\columnseprule{0\p@} \pagestyle{headings} \pagenumbering{arabic} \if@twoside\else\raggedbottom\fi \endinput %%% end of assignment.cls stex-1.2.1+git20171204.g5e4f0ca/inputs/scheme.hsty000066400000000000000000000030221321130544300210630ustar00rootroot00000000000000\def\transerr#1{\raw{}} \def\transin#1{\raw{}} \def\transout#1{\raw{}} \def\traceout#1{\raw{}} \def\endtranserr#1{\raw{}} \def\endtransin#1{\raw{}} \def\endtransout#1{\raw{}} \def\endtraceout#1{\raw{}} \def\schemeblankline{{\\\\}} \def\schemelinestart{} %%% handle numbered lines in scheme.sty and scheme.hsty %%% ---have scheme-prep produce only \schemelinestart % following is probably broken until we have tables, I suspect. % Actually, the right way to fix this may be to use CSS \def\schemelinestartnumbered#1{\raw{
    }#1\raw{
    }} \def\scheme#1{{\tt #1}} \def\longcode\schemedisplay{\schemedisplay} \def\noskip\schemedisplay{\schemedisplay} \def\schemedisplay{\par\begingroup\tt\hardspaces} \def\endschemedisplay{\endgroup\par} \def\schemeindent{} \def\schatsign{\raw{@}} \def\schbackslash{\raw{\}} \def\schcarat{\raw{^}} \def\schdot{\raw{.}} \def\schlbrace{\raw{&##123;}} \def\schrbrace{\raw{&##125;}} \def\schtilde{\raw{~}} \def\schunderscore{\raw{_}} \def\becomes{$\rightarrow$} \def\is{$\Rightarrow$} \def\si{\raw{}} \def\var#1{\emph{#1}} % frame="border" rules="all" makes mozilla do it right % border="1" makes konqueror do it right \def\startrepl{\raw{}} \def\startinteraction{\raw{
    }} \def\endrepl{\raw{
    }} \def\endinteraction{\raw{
    }} stex-1.2.1+git20171204.g5e4f0ca/inputs/scheme.sty000066400000000000000000000042501321130544300207170ustar00rootroot00000000000000\usepackage{color} \def\transerr#1{\begingroup\slshape} \def\transin#1{\begingroup\color{red}} \def\transout#1{\begingroup\color{blue}} \def\traceout#1{\begingroup\color{blue}} \def\endtranserr#1{\endgroup} \def\endtransin#1{\endgroup} \def\endtransout#1{\endgroup} \def\endtraceout#1{\endgroup} % this didn't work --- screwed up indentation: \long\def\showinteraction#1#2{\begin{minipage}[t]{4.375in}#1\end{minipage}\hfill\fbox{\begin{minipage}[t]{2in}#2\end{minipage}}} % so I resorted to this: \def\startrepl{\begin{minipage}[t]{4.3in}} % was 4.375 and 2 when interactionwindow = 28 \def\endrepl{\end{minipage}} \def\startinteraction{\begin{minipage}[t]{2.2in}\vrule\begin{minipage}[t]{2.2in}\hrule\schemeindent=2pt} \def\endinteraction{\hrule\end{minipage}\vrule\end{minipage}} \newskip\ttglue \ttglue=.5em plus .25em minus .15em \newskip\schemeindent \schemeindent=0pt {\obeyspaces\global\let =\ } \def\schtilde{\raisebox{-.5ex}{\hbox{\char`\~}}} \def\schdot{.} \def\schcarat{\char`\^} \def\schbackslash{\char`\\} \def\schatsign{\char`\@} \def\schunderscore{\char`\_} \def\schlbrace{\char`\{} \def\schrbrace{\char`\}} \def\scheme#1{\mbox{\ttfamily\frenchspacing\spaceskip=\ttglue#1}} \def\schemeblankline{\par\penalty-100\vskip .7\baselineskip} \def\schemelinestart{{\leavevmode\hbox{\hskip \schemeindent\relax}}} %%% handle numbered lines in scheme.sty and scheme.hsty %%% ---have scheme-prep produce only \schemelinestart \def\schemelinestartnumbered#1{{\leavevmode\hbox{\hbox to 1em {\hfil{\rm #1}} \hskip .5\schemeindent\relax}}} \def\noskip\schemedisplay{\begingroup% \parindent=0pt% \parskip=0pt% \def\becomes{\hbox to 2em{\hfil$\rightarrow$\hfil}}% \def\is{\hbox to 2em{\hfil$\Rightarrow$\hfil}}% \def\si{\hbox to 2em{\hfil}}% \interlinepenalty=2000% \tt\obeyspaces\frenchspacing} \def\schemedisplay{\beforeschemedisplay\noskip\schemedisplay} \def\longcode\schemedisplay{\penalty-200\vskip 8pt plus 4pt% \kern3pt\hrule\kern5pt\nobreak\noskip\schemedisplay} \def\endschemedisplay{\par\endgroup\afterschemedisplay} \def\var#1{{\normalsize\textrm{\textit{#1}}}} \def\raw#1{#1} \def\beforeschemedisplay{\penalty-100\vskip\parskip\vskip5pt} \def\afterschemedisplay{\penalty-200\vskip5pt} stex-1.2.1+git20171204.g5e4f0ca/inputs/website.cls000066400000000000000000000042731321130544300210640ustar00rootroot00000000000000%%% website.cls %%% Kent Dybvig and Oscar Waddell %%% August 2003 \ProvidesClass{website} \def\ProvidesClass#1[#2]{\relax} \LoadClass{article} \def\ps@plain{\let\@mkboth\@gobbletwo \let\@oddhead\@empty\def\@oddfoot{\reset@font \footer}\let\@evenhead\@empty\let\@evenfoot\@oddfoot} \def\footer{\hfil\ifnum\c@page =1 \copyrightnotice\else\thepage\fi\hfil} \newcommand{\webpage}[2][]{ \def\thetitle{#2} } \newcommand{\documenttitle}[2][]{ \def\thetitle{#2} } \def\maketitle{ \begin{flushleft} \LARGE\textbf{\thetitle} \end{flushleft}} \newcommand{\hr}[1][]{\bigskip\hrule} \newcommand{\copyrightnotice}{} %%% to support hypertext index entries \def\hindex#1{\index} % ignore the label here---no links in printed version \newcommand{\hyperlink}[3][]{#3} \newcommand{\href}[3][]{#3} \newcommand{\hpageref}[3][]{#3} \let\true@ref=\ref\renewcommand{\ref}[2][]{\true@ref{#2}} \let\true@pageref=\pageref\renewcommand{\pageref}[2][]{\true@pageref{#2}} %%% \mailto{id}{name} \newcommand{\mailto}[3][]{#3} %%% forms \newenvironment{form}[1]{}{} \newcommand{\formtextarea}[1]{\strut} \newcommand{\forminput}[1]{\strut} \newcommand{\formselect}[2]{\strut} \newcommand{\formoption}[2][]{\strut} \newif\iflatex\latextrue \newif\ifhtml\htmlfalse \newenvironment{DIV}[1] {\relax} {\relax} \def\span#1#2{#2} \newcommand{\img}[3][]{#2} %%% \parheader{title} \def\parheader#1 {\medskip\noindent{\bf #1.}~~} \newcounter{alphacount} \def\alphalabel{\textit{\alph{alphacount}}.} \newenvironment{alphalist} {\begingroup\let\beforeschemedisplay=\relax\let\afterschemedisplay=\relax \begin{list}{\alphalabel}{\usecounter{alphacount}\itemsep=0pt\parsep=0pt% \topsep=0pt}} {\end{list}\endgroup} %%% final set up \renewcommand{\contentsname}{Contents} \newcommand{\bibname}{Bibliography} \renewcommand{\indexname}{Index} \renewcommand{\today}{\ifcase\month\or January\or February\or March\or April\or May\or June\or July\or August\or September\or October\or November\or December\fi \space\number\day, \number\year} \setlength\columnsep{10\p@} \setlength\columnseprule{0\p@} \pagestyle{headings} \pagenumbering{arabic} \parindent=0pt \parskip=4pt \if@twoside\else\raggedbottom\fi \endinput %%% end of website.cls stex-1.2.1+git20171204.g5e4f0ca/inputs/website.hcls000066400000000000000000000046161321130544300212350ustar00rootroot00000000000000%%% website.hcls %%% Kent Dybvig and Oscar Waddell %%% August 2003 \newif\iflatex\latexfalse \newif\ifhtml\htmltrue \def\thetitleattributes{} %%% \webpage{title} \newcommand{\webpage}[2][]{ \endwebpage \def\thetitleattributes{#1} \def\thetitle{#2} \begingroup\renewcommand{\hyperlink}[3][]{##3}\openhtmlfile{#2}\endgroup \renewcommand{\endwebpage}{\copyrightnotice \closehtmlfile\renewcommand{\endwebpage}{}}} \newcommand{\endwebpage}{} \def\maketitle{\raw{}\thetitle\raw{}} \newcommand{\hr}[1][]{\raw{
    }} \def\copyright{\raw{©}} \newcommand{\copyrightnotice}{} \let\trueenddocument=\enddocument \def\enddocument{ \endwebpage \trueenddocument} %%% \section{title} \newcommand{\section}[1]{ \raw{

    }#1\raw{

    } } %%% \subsection{title} \newcommand{\subsection}[1]{ \raw{

    }#1\raw{

    } } %%% \subsection{title} \newcommand{\subsubsection}[1]{ \raw{

    }#1\raw{

    } } \newenvironment{DIV}[1] {\raw{
    }} {\raw{
    }} \def\span#1#2{\raw{}#2\raw{}} \newcommand{\img}[3][]{\raw{#2}} %%% \parheader{title} \def\parheader#1 {\medskip\noindent{\bf #1.}~~} %%% center: should be built in \newenvironment{center} {\raw{
    }} {\raw{
    }} %%% alphalist \newcounter{alphalist} \def\alphalist{\begingroup\setcounter{alphalist}{0} \def\endalphalistitem{}% \renewcommand{\item}{\endalphalistitem \def\endalphalistiem{\raw{
    }\textit{~~\alph{alphalist}}.\raw{}} \raw{}} \def\endalphalist{\endalphalistitem\raw{
    }\endgroup} %%% define our own (compact) description environment \def\description{\begingroup \renewcommand{\item}[1][]{\raw{
    }##1\raw{
    }}\raw{
    }} \def\enddescription{\raw{
    }\endgroup} %%% hyperlink support \newcommand{\hyperlink}[3][]{\raw{}#3\raw{}} %%% \mailto{id}{name} \newcommand{\mailto}[3][]{\raw{}{#3}\raw{}} %%% colors \def\textcolor#1#2{\raw{}#2\raw{}} %%% forms \newenvironment{form}[1]{\raw{
    }}{\raw{
    }} \newcommand{\formtextarea}[2]{\raw{}} \newcommand{\forminput}[1]{\raw{}} \newcommand{\formselect}[2]{\raw{}} \newcommand{\formoption}[2][]{\raw{}} stex-1.2.1+git20171204.g5e4f0ca/math/000077500000000000000000000000001321130544300163205ustar00rootroot00000000000000stex-1.2.1+git20171204.g5e4f0ca/math/Makefile000066400000000000000000000011121321130544300177530ustar00rootroot00000000000000include mathfiles density=-r90x90 .SUFFIXES: .SUFFIXES: .tex .gif # translate ps file to ppm, crop to minimum background, and translate ppm # to gif with white (background) transparent # .tex.gif: TEXINPUTS=.:../..:$(TEXINPUTS);\ echo | latex $* &&\ dvips -f < $*.dvi |\ gs -q -dNOPAUSE -dSAFER -sDEVICE=ppmraw -sOutputFile=-\ ${density} - |\ pnmcrop |\ ppmtogif -transparent white > $*.gif /bin/rm -f $*.dvi $*.log $*.aux test -f $*.gif && chmod 644 $*.gif all: ${gifs} ${gifs}: mathmacros clean: ; /bin/rm -f *.gif Make.out stex-1.2.1+git20171204.g5e4f0ca/math/mathmacros000066400000000000000000000011361321130544300204020ustar00rootroot00000000000000\usepackage{scheme} \catcode`@=11 % borrow the private macros of PLAIN (with care) \def\W#1{W_{\!\!#1}} \def\fftcases#1{\left\{\,\vcenter{\m@th\baselineskip=18pt \ialign{$##\hfil$&\quad##\hfil\crcr#1\crcr}}\right.} \input epsf \usepackage{graphicx} \setlength\fboxrule{.4\p@} \newlength{\chpicsize} \setlength{\chpicsize}{30pc} \addtolength{\chpicsize}{-\fboxrule} \addtolength{\chpicsize}{-\fboxrule} \def\chpic#1{\begingroup% \def\epsfsize##1##2{##1} \fboxsep=0pt \vbox{\noindent% \fbox{\vbox{\hbox to \chpicsize{\hfil\vbox to \chpicsize{\vfil% \epsfbox{#1}\vfil}\hfil}}}}\endgroup} stex-1.2.1+git20171204.g5e4f0ca/sbin/000077500000000000000000000000001321130544300163225ustar00rootroot00000000000000stex-1.2.1+git20171204.g5e4f0ca/sbin/install000077500000000000000000000030221321130544300177130ustar00rootroot00000000000000#! /bin/sh # follows symbolic links. to do otherwise is painful. usage() { echo "usage: $0 [ -o owner] [ -g group ] [ -m mode ] -d dir ..." echo " $0 [ -o owner] [ -g group ] [ -m mode ] file destfile" echo " $0 [ -o owner] [ -g group ] [ -m mode ] file file ... destdir" exit 1 } installone() { cp -f -p $1 $2 if [ "$owner" != "" ] ; then chown $owner $2; fi if [ "$group" != "" ] ; then chgrp $group $2; fi if [ "$mode" != "" ] ; then chmod $mode $2; fi } mkdir=0 while [ $# -ge 0 ] ; do case $1 in -d) mkdir=1 ;; -o) shift; owner=$1 ;; -g) shift; group=$1 ;; -m) shift; mode=$1 ;; -*) usage ;; *) break ;; esac shift done if [ $mkdir -eq 1 ] ; then dirs=$* for dir in $dirs ; do case $dir in /*) ;; *) echo "directory name must begin with /; $dir does not" ; exit 1 ;; esac stack="$dir" while [ "$dir" != "/" ] ; do stack="$dir $stack" dir=`dirname $dir` done for dir in $stack ; do if [ ! -e $dir ] ; then mkdir $dir if [ "$owner" != "" ] ; then chown $owner $dir ; fi if [ "$group" != "" ] ; then chgrp $group $dir ; fi if [ "$mode" != "" ] ; then chmod $mode $dir ; fi fi done done elif [ $# -eq 2 -a ! -d $2 ] ; then installone $1 $2 elif [ $# -ge 2 ] ; then files="" while [ $# -ne 1 ] ; do files="$files $1" shift done dest=$1 if [ ! -d $dest ]; then usage; fi for file in $files ; do installone $file $dest/`basename $file` done else usage fi stex-1.2.1+git20171204.g5e4f0ca/src/000077500000000000000000000000001321130544300161565ustar00rootroot00000000000000stex-1.2.1+git20171204.g5e4f0ca/src/dsm.ss000066400000000000000000000052351321130544300173150ustar00rootroot00000000000000;;; dsm.ss ;;; ;;; Copyright (c) 1998-2016 R. Kent Dybvig and Oscar Waddell ;;; ;;; Permission is hereby granted, free of charge, to any person obtaining a ;;; copy of this software and associated documentation files (the "Software"), ;;; to deal in the Software without restriction, including without limitation ;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, ;;; and/or sell copies of the Software, and to permit persons to whom the ;;; Software is furnished to do so, subject to the following conditions: ;;; ;;; The above copyright notice and this permission notice shall be included in ;;; all copies or substantial portions of the Software. ;;; ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ;;; DEALINGS IN THE SOFTWARE. ;;; authors: R. Kent Dybvig and Oscar Waddell (library (dsm) (export define-syntactic-monad) (import (chezscheme)) (define-syntax define-syntactic-monad (syntax-rules () [(_ name formal ...) (andmap identifier? #'(name formal ...)) (define-syntax name (lambda (x) (syntax-case x (lambda case-lambda) [(key lambda more-formals . body) (with-implicit (key formal ...) #'(lambda (formal ... . more-formals) . body))] [(key case-lambda (more-formals . body) (... ...)) (with-implicit (key formal ...) #'(case-lambda ((formal ... . more-formals) . body) (... ...)))] [(key proc ((x e) (... ...)) arg (... ...)) (andmap identifier? #'(x (... ...))) (with-implicit (key formal ...) (for-each (lambda (x) (unless (let mem ((ls #'(formal ...))) (and (not (null? ls)) (or (free-identifier=? x (car ls)) (mem (cdr ls))))) (syntax-error x (format "in syntactic monad ~s, unrecognized identifier" 'name)))) #'(x (... ...))) (with-syntax ([(t (... ...)) (generate-temporaries #'(arg (... ...)))]) #'(let ((p proc) (x e) (... ...) (t arg) (... ...)) (p formal ... t (... ...)))))] [(key proc) #'(key proc ())])))])) ) stex-1.2.1+git20171204.g5e4f0ca/src/fixbibtex.ss000077500000000000000000000020321321130544300205110ustar00rootroot00000000000000#! /usr/bin/scheme --program ;;; fixbibtex.ss ;;; fixbibtex removes the line breaks inserted by bibtex, sometimes ;;; in the middle of tex commands or urls. (import (chezscheme)) (unless (= (length (command-line-arguments)) 1) (printf "usage: fixbibtex \n") (exit 1)) (define fn (car (command-line-arguments))) (let ([s (call-with-port (open-input-file fn) get-string-all)]) (with-input-from-string s (lambda () (with-output-to-file fn (lambda () (define (s0 c) (unless (eof-object? c) (case c [(#\\) (write-char c) (s1 (read-char))] [(#\%) (s2 (read-char))] [else (write-char c) (s0 (read-char))]))) (define (s1 c) ; seen \ (unless (eof-object? c) (write-char c) (s0 (read-char)))) (define (s2 c) ; seen % (case c [(#\newline) (s0 (read-char))] [else (write-char #\%) (s0 c)])) (s0 (read-char))) 'replace)))) stex-1.2.1+git20171204.g5e4f0ca/src/html-prep.ss000077500000000000000000002055731321130544300204540ustar00rootroot00000000000000#! /usr/bin/scheme --program ;;; html-prep.ss ;;; ;;; Copyright (c) 1998-2016 R. Kent Dybvig and Oscar Waddell ;;; ;;; Permission is hereby granted, free of charge, to any person obtaining a ;;; copy of this software and associated documentation files (the "Software"), ;;; to deal in the Software without restriction, including without limitation ;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, ;;; and/or sell copies of the Software, and to permit persons to whom the ;;; Software is furnished to do so, subject to the following conditions: ;;; ;;; The above copyright notice and this permission notice shall be included in ;;; all copies or substantial portions of the Software. ;;; ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ;;; DEALINGS IN THE SOFTWARE. ;;; TODO ;;; * fix paragraph handling ;;; * verify compliance of generated documents ;;; * resolve multicolumn bug --- see ./multicolumn-bug.stex ;;; - I commented out lots of stuff that Kent added and it seems to ;;; work for the one example I care about at the moment (right now ;;; I'm just trying to get Assignment 14 out by hook or by crook) ;;; * move stuff now unique to html-prep.ss from preplib.ss ;;; * add ability to insert arbitrary content into header ;;; * update documentation ;;; html-prep now consults the TEXINPUTS environment variable to ;;; locate .hcls files. ;;; primitive commands (latex standard first, then extensions) ;;; & ;;; \& ;;; ~ ;;; -- (en-dash) ;;; --- (em-dash) ;;; \'e, \'o ;;; \"{} ;;; \c{} ;;; \\[ignored] ;;; \ ;;; $ ... $ (see below) ;;; { ... } (groups) ;;; \begingroup ... \endgroup ;;; \bgroup ... \egroup ;;; % ;;; \[ ... \] (see below) ;;; \begin{eqnarray*} ... \end{eqnarray*} (see below) ;;; \begin{divertoutput}[i] ... \end{divertoutput} ;;; i selects a currently opened file: ;;; 0 first file opened, 1 second file, ... ;;; or -1 most recent, -2 next most recent, ... ;;; \begin{verbatim} ... \end{verbatim} ;;; \bf ;;; \bibitem ;;; \cite{...} ;;; \emph{...} ;;; \epsfbox{...} ;;; \genlab ;;; \hindex{label}{stuff} (see below) ;;; \include{filename} ;;; \input{filename} ;;; \index{stuff} (see below) ;;; \it ;;; \label{...} ;;; \pagebreak[n] ;;; \pageref[class]{...} ;;; \ref[class]{...} ;;; \usepackage{...} ; implicit .hsty suffix ;;; \vskip (remainder of line ignored!) ;;; \def ;;; \newenvironment ;;; \renewenvironment ;;; \newif ;;; \newcounter ;;; \setcounter ;;; \addtocounter ;;; \stepcounter ;;; \tt ;;; \closehtmlfile ;;; \closerawfile ;;; \currentoutputfile ;;; \headerstuff{stuff} (raw stuff between ;;; \documenttitle[formats]{title} ;;; \hpageref[class]{label}{text} (pageref link around text) ;;; \href[class]{label}{text} (ref link around text) ;;; \hardspaces ;;; \rawinput{filename} (inserts raw html from filename) ;;; \makeindex ;;; \openhtmlfile ;;; \openrawfile ;;; \raw{...} ;;; \geq{...} ;;; \leq{...} ;;; \neq{...} ;;; \equiv{...} ;;; \LARGE ;;; \Large ;;; \large ;;; \small ;;; \footnotesize ;;; \tiny ;;; Within $ ... $, \[ ... \], \begin{eqnarray*} ... \end{eqnarray*} ;;; user-defined macros are not presently expanded ;;; \index and \hindex syntax ;;; \index{levels} or \index{levels|pageformat} ;;; \hindex{label}{levels} or \hindex{label}{levels|pageformat} ;;; levels --> level ;;; --> level!levels ;;; level --> keyentry (key and entry same) ;;; level --> key@entry (separate key and entry) ;;; index and hindex entries follow makeindex 2.13 syntax except that ;;; the special characters !, @, |, ", and \ are freely allowed within ;;; embeded {, } pairs in the "actual entry" portion of a level (the ;;; portion following @, if any). a modified version of makeindex 2.13 ;;; that supports this extension (with the -d [allow delimited special ;;; chars] flag) is available here as well. #!chezscheme (import (except (chezscheme) open-input-file) (dsm) (preplib) (script)) (define math-directory (make-parameter "math")) (define push-ofile (lambda (op ofiles) (current-ofile op) (cons op ofiles))) (define pop-ofile (lambda (ofiles) (let ([ofiles (cdr ofiles)]) (current-ofile (and (not (null? ofiles)) (car ofiles))) ofiles))) (define get-counter-value (lambda (count) (getprop count 'counter #f))) (define set-counter-value! (lambda (count value) (putprop count 'counter value))) (define add-subcounter! (lambda (counter subcounter) (putprop counter 'subcounters (cons subcounter (getprop counter 'subcounters '()))))) (define subcounters (lambda (counter) (getprop counter 'subcounters '()))) (define tex-file-name (lambda (fn) (if (or (string=? (format "~a.tex" (path-root fn)) fn) (file-exists? fn)) fn (format "~a.tex" fn)))) (define open-html-file (lambda (ip title) (define next-count (lambda (root) (cond [(assoc root (output-file-counters)) => (lambda (a) (let ([n (+ (cdr a) 1)]) (set-cdr! a n) n))] [else (output-file-counters (cons (cons root 0) (output-file-counters))) 0]))) ; generate sequence of names foo.html, foo_1.html, foo_2.html, ... (let ([op (let ([fn (let ([root (path-root (port-name (current-ifile)))]) (let ([n (next-count root)]) (if (= n 0) (format "~a.html" root) (format "~a_~d.html" root n))))]) (open-output-file fn 'replace))]) (fprintf op "") (fprintf op "~%") (fprintf op "~%~%") (fprintf op "~%") (fprintf op "~%~a~%" title) (when (header-stuff) (display (header-stuff) op)) (when (style-sheet) (fprintf op "\n" (style-sheet))) (fprintf op "~%~%") op))) (define close-html-port (lambda (p) (fprintf p "~%") (fprintf p "~%") (close-output-port p))) (define get-cite (lambda (key) (or (getprop key 'cite) (begin (warningf #f "bib entry ~a not found" key) "???")))) (define put-label! (lambda (name type value) (putprop name type value))) (define get-label (lambda (name type) (or (getprop name type) (begin (warningf #f "label (~a) ~a undefined" type name) "???")))) (define read-aux-file (lambda (fn) (let ([ip (open-input-file fn)]) (parameterize ([current-ifile ip]) (let loop ([newline? #f]) (state-case (c (read-char ip)) [(#\newline) (loop #t)] [(#\\) (when newline? (let ([cmd (read-command ip)]) (case cmd [(|@|) (let ([cmd (read-command ip)]) (case cmd [(input) (read-aux-file (read-bracketed-text ip))]))] [(bibcite) (let* ([key (read-bracketed-text ip)] [cite (read-bracketed-text ip)]) (putprop (string->symbol key) 'cite cite))] [(newlabel) (let* ([name (read-bracketed-text ip)] [ref (begin (read-open-brace ip) (read-bracketed-text ip))] [pageref (read-bracketed-text ip)]) (put-label! (string->symbol name) 'pageref pageref))]))) (loop #f)] [(eof) (close-port ip)] [else (loop #f)])))))) ;; structures (define-structure (index-entry url keys texts pageno pageformat prefix)) (define s$ (lambda (ip op) ; within $...$ (let ([s (let ([buf (open-output-string)]) (let loop () (state-case (c (read-char ip)) [(#\$) (get-output-string buf)] [(eof) (unexpected-eof "within $ ... $")] [(#\newline) (write-char #\space buf) (loop)] [else (write-char c buf) (loop)])))]) (emit-math s op)))) (define (scomment ip op hard-spaces) (state-case (c (read-char ip)) [(eof #\newline) (unless hard-spaces (let eat-spaces () (state-case (c (peek-char ip)) [(#\space #\tab) (read-char ip) (eat-spaces)] [else (void)])))] [else (scomment ip op hard-spaces)])) (define seqnarray* (lambda (ip op) ; within \begin{eqnarray*} ... \end{eqnarray*} (let ([s (let ([buf (open-output-string)]) (let loop () (state-case (c (read-char ip)) [(#\\) (let ([cmd (read-command ip)]) (case cmd [(end) (read-open-brace ip) (if (equal? (read-bracketed-text ip 1) "eqnarray*") (get-output-string buf) (input-error "expected \\end{eqnarray*}"))] [else (fprintf buf "\\~a" cmd) (loop)]))] [(eof) (unexpected-eof "within eqnarray*")] [else (write-char c buf) (loop)])))]) (punt-to-latex (format "\\begin{eqnarray*}~a\\end{eqnarray*}" s) op)))) (define smathdisplay (lambda (ip op) ; within \[ ... \] (let ([s (let ([buf (open-output-string)]) (let loop () (state-case (c (read-char ip)) [(#\\) (let ([cmd (read-command ip)]) (case cmd ;[ [(|]|) (get-output-string buf)] [else (fprintf buf "\\~a" cmd) (loop)]))] [(eof) (unexpected-eof "within \\[ ... \\]")] [else (write-char c buf) (loop)])))]) (emit-math s op)))) (define emit-math (lambda (s op) (cond [(htmlmath (open-input-string s) #f) => (lambda (html) (display html op))] [else (punt-to-latex (format "$~a$" s) op)]))) (define htmlmath (lambda (ip compact?) (let ([buf (open-output-string)]) (let loop ([unary? #t]) (state-case (c (read-char ip)) [(#\\) (let ([cmd (read-command ip)]) (case cmd [(|{|) (fprintf buf "~a" cmd) (loop #t)] [(|}|) (fprintf buf "~a" cmd) (loop #f)] [(|,| |;|) (loop unary?)] [(cdot) (fprintf buf (if (or compact? unary?) "·" " · ")) (loop #t)] [(dots) (fprintf buf "...") (loop #f)] [(gt) (fprintf buf (if (or compact? unary?) ">" " > ")) (loop #t)] [(lt) (fprintf buf (if (or compact? unary?) "<" " < ")) (loop #t)] [(ge geq) (fprintf buf (if (or compact? unary?) "≥" " ≥ ")) (loop #t)] [(le leq) (fprintf buf (if (or compact? unary?) "≤" " ≤ ")) (loop #t)] [(ne neq) (fprintf buf (if (or compact? unary?) "≠" " ≠ ")) (loop #t)] [(equiv) (fprintf buf (if (or compact? unary?) "≡" " ≡ ")) (loop #t)] [(log) (fprintf buf "log") (loop #t)] [(pm) (fprintf buf (if (or compact? unary?) "±" " ± ")) (loop #t)] [(div) (fprintf buf (if (or compact? unary?) "÷" " ÷ ")) (loop #t)] [(times) (fprintf buf (if (or compact? unary?) "×" " × ")) (loop #t)] [else #f]))] [(#\{) (loop unary?)] [(#\}) (loop unary?)] [(#\_) (state-case (c (read-char ip)) [(#\{) (cond [(htmlmath (open-input-string (read-bracketed-text ip 1)) #t) => (lambda (html) (fprintf buf "~a" html) (loop #f))] [else #f])] [(eof) #f] [else (fprintf buf "~a" c) (loop #f)])] [(#\^) (state-case (c (read-char ip)) [(#\{) (cond [(htmlmath (open-input-string (read-bracketed-text ip 1)) #t) => (lambda (html) (fprintf buf "~a" html) (loop #f))] [else #f])] [(eof) #f] [else (fprintf buf "~a" c) (loop #f)])] [((#\a - #\z) (#\A - #\Z)) (fprintf buf "") (let loop ([c c]) (write-char c buf) (state-case (c (peek-char ip)) [((#\a - #\z) (#\A - #\Z)) (read-char ip) (loop c)] [else (void)])) (fprintf buf "") (loop #f)] [(#\<) (fprintf buf (if (or compact? unary?) "<" " < ")) (loop #t)] [(#\>) (fprintf buf (if (or compact? unary?) ">" " > ")) (loop #t)] [(#\= #\+ #\-) (fprintf buf (if (or compact? unary?) "~c" " ~c ") c) (loop #t)] [(#\/ #\( #\[ #\,) (write-char c buf) (loop #t)] [((#\0 - #\9) #\. #\) #\] #\! #\| #\') (write-char c buf) (loop #f)] [(#\space) (loop unary?)] [(#\newline) (write-char c buf) (loop #t)] [(eof) (get-output-string buf)] [else (input-error "unexpected character ~s in math mode" c)]))))) (define punt-to-latex (lambda (s op) (define latex-header "\\documentclass[12pt]{article} \\input mathmacros % Kent wanted it moved back up here for some reason. \\begin{document} \\pagestyle{empty} %\\input mathmacros % I had moved it for a good reason that I don't recall. ") (define latex-trailer " \\end{document} ") (cond [(assoc s (latex-cache)) => (lambda (a) (fprintf op "\"<graphic\">" (cdr a)))] [else (let* ([fn (math-file-name)] [texfn (format "~a.tex" fn)] [giffn (format "~a.gif" fn)]) (fprintf op "\"<graphic\">" giffn) (latex-cache (cons (cons s (format "~a" giffn)) (latex-cache))) ; don't rewrite file unless different to avoid need to remake gif file (let ([s (format "~a~a~a" latex-header s latex-trailer)]) (unless (guard (c [else #f]) (equal? s (call-with-port (open-input-file texfn) get-string-all))) (call-with-port (open-output-file texfn 'replace) (lambda (texop) (display s texop))))))]))) (define math-file-name (let ([seq -1]) (lambda () (set! seq (+ seq 1)) (format "~a/~d" (math-directory) seq)))) (define haux-put-label (lambda (label type url) (write `(putprop ',label ',type ,url) (haux-op)) (newline (haux-op)))) (define current-ofile-name (lambda () (if (current-ofile) (port-name (current-ofile)) "nofile"))) (define slabel (case-lambda [(label text) (slabel label text (gensym))] [(label text tag) (let ([url (format "~a#~a" (current-ofile-name) tag)]) (haux-put-label label 'pageref-url url) (when (current-ref-label) (haux-put-label label 'ref (car (current-ref-label))) (haux-put-label label 'ref-url (cdr (current-ref-label))))) (format "~a" tag text)])) (define sindex ; 1. read contents of \index{} form ; separate at !s into 1 or more levels plus page format after |, if ; present; separate levels at @ into sort key and text, if present ; recognize quoted/escaped characters in the input ; 2. look up pageno & url corresponding ; 3. cons entry on to index-entries (lambda (ip op lab) (call-with-values (lambda () (parse-index ip #f)) (lambda (levels page-format) (let ([keys (map (lambda (level) (or (car level) (cdr level))) levels)] [texts (map cdr levels)] [pageno (get-label lab 'pageref)] [url (get-label lab 'pageref-url)]) (index-entries (cons (make-index-entry url keys texts pageno page-format "") (index-entries)))))))) (define smakeindex ; insert indexspace between letters? ; links per starting letter? (lambda (op) (define print-page (lambda (entry) (let ([pageno (format "\\raw{}~a~a\\raw{}" (index-entry-url entry) (index-entry-prefix entry) (index-entry-pageno entry))] [pageformat (index-entry-pageformat entry)]) (if (string=? pageformat "") (fprintf op ", ~a" pageno) (fprintf op ", \\~a{~a}" pageformat pageno))))) (define see? (lambda (pageformat) (and (fx> (string-length pageformat) 3) (string=? (substring pageformat 0 3) "see")))) (define remove-dups ; remove dup even if url is different, which it usually will be. ; to avoid entries like "begin, 51, 51". if they're on the same ; page in the printed version, they'll be close enough in the ; electronic version. remove duplicate "see" pageformat entries ; regardless of the page and url. (lambda (ls) (if (null? ls) ls (let f ([ls (cdr ls)] [prev (car ls)]) (if (null? ls) (list prev) (let ([x (car ls)]) (if (let ([xpageformat (index-entry-pageformat x)]) (and (see? xpageformat) (string=? (index-entry-pageformat prev) xpageformat))) (f (cdr ls) prev) (if (and (equal? (index-entry-texts x) (index-entry-texts prev)) (string=? (index-entry-prefix x) (index-entry-prefix prev)) (string=? (index-entry-pageno x) (index-entry-pageno prev))) (if (string=? (index-entry-pageformat x) (index-entry-pageformat prev)) (f (cdr ls) prev) (if (string=? (index-entry-pageformat prev) "") (f (cdr ls) x) (if (string=? (index-entry-pageformat x) "") (f (cdr ls) prev) (errorf #f "conflicting page formats for ~s and ~s" x prev)))) (cons prev (f (cdr ls) x)))))))))) (define print-item (lambda (entry texts level) (let f ([texts texts] [level level]) (if (null? texts) (print-page entry) (begin (fprintf op "~% \\") (do ([i level (- i 1)]) ((= i 0)) (display "sub" op)) (fprintf op "item ~a" (car texts)) (f (cdr texts) (+ level 1))))))) (define see-cmp (lambda (xpageformat ypageformat) (if (see? xpageformat) (if (see? ypageformat) (str-cmp xpageformat ypageformat) '>) (if (see? ypageformat) '< '=)))) (guard (c [else #f]) (let ([seed-entries (call-with-port (open-input-file "in.hidx") read)]) (index-entries (append seed-entries (index-entries))))) (parameterize ([print-vector-length #f]) (let ([out.hidx (open-output-file "out.hidx" 'replace)]) (fprintf out.hidx "(~%") ;) (for-each (lambda (x) (fprintf out.hidx "~s~%" x)) (index-entries)) ;( (fprintf out.hidx ")~%"))) (fprintf op "\\begin{theindex}~%") (let ([ls (sort (lambda (x y) ; sort based on each key. if the keys compare equal, ; sort based on text. if the text is equal, sort based ; on the remaining keys and texts. for matching ; keys and texts, push "see" formats to the back, then ; sort on prefix, pageno, and url (let f ([xkeys (index-entry-keys x)] [xtexts (index-entry-texts x)] [ykeys (index-entry-keys y)] [ytexts (index-entry-texts y)]) (cond [(null? xkeys) (or (not (null? ykeys)) (case (see-cmp (index-entry-pageformat x) (index-entry-pageformat y)) [(<) #t] [(>) #f] [else (case (str-cmp (index-entry-prefix x) (index-entry-prefix y)) [(<) #t] [(>) #f] [else (let ([nx (pageno->number (index-entry-pageno x))] [ny (pageno->number (index-entry-pageno y))]) (cond [(< nx ny) #t] [(> nx ny) #f] [else (str-cmp (index-entry-url x) (index-entry-url y))]))])]))] [(null? ykeys) #f] [else (case (str-cmp (car xkeys) (car ykeys)) [(<) #t] [(>) #f] [else ; separate different texts with same keys (case (str-cmp (car xtexts) (car ytexts)) [(<) #t] [(>) #f] [else (f (cdr xkeys) (cdr xtexts) (cdr ykeys) (cdr ytexts))])])]))) (index-entries))]) (let loop ([ls (remove-dups ls)] [last-texts '()]) (unless (null? ls) (let* ([entry (car ls)] [texts (index-entry-texts entry)]) (let f ([texts texts] [last-texts last-texts] [level 0]) (if (null? last-texts) (if (null? texts) (print-page entry) (print-item entry texts level)) (if (eq? (str-cmp (car texts) (car last-texts)) '=) (f (cdr texts) (cdr last-texts) (+ level 1)) (print-item entry texts level)))) (loop (cdr ls) texts))))) (fprintf op "\\end{theindex}~%"))) (define pageno->number (lambda (s) (let ([sip (open-input-string s)]) (let loop ([a -10000]) (state-case (c (read-char sip)) [(#\i) (state-case (c (peek-char sip)) [(#\v) (read-char sip) (loop (+ a 4))] [(#\x) (read-char sip) (loop (+ a 9))] [else (loop (+ a 1))])] [(#\v) (state-case (c (peek-char sip)) [(#\x) (read-char sip) (loop (+ a 5))] [else (loop (+ a 5))])] [(#\x) (loop (+ a 10))] [(eof) a] [else (or (string->number s) -1)]))))) (define char-table (let ([s (make-string 256 #\nul)]) (define fill! (lambda (i ls) (unless (null? ls) (for-each (lambda (c) (string-set! s (char->integer c) (integer->char i))) (if (char? (car ls)) (list (car ls)) (car ls))) (fill! (+ i 1) (cdr ls))))) (fill! 1 '( #\! #\" #\# #\$ #\% #\& #\' #\( #\) #\* #\+ #\, #\- #\. #\/ #\: #\; #\< #\= #\> #\? #\@ #\[ #\\ #\] #\^ #\_ #\` #\{ #\| #\} #\~ #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 (#\A #\a) (#\B #\b) (#\C #\c) (#\D #\d) (#\E #\e) (#\F #\f) (#\G #\g) (#\H #\h) (#\I #\i) (#\J #\j) (#\K #\k) (#\L #\l) (#\M #\m) (#\N #\n) (#\O #\o) (#\P #\p) (#\Q #\q) (#\R #\r) (#\S #\s) (#\T #\t) (#\U #\u) (#\V #\v) (#\W #\w) (#\X #\x) (#\Y #\y) (#\Z #\z))) s)) (define char-cvt ; place all non-alphabetic characters up front; commonize upper and ; lower case characters (lambda (c) (string-ref char-table (char->integer c)))) (define str-cmp ; returns <, =, > if xy (lambda (s1 s2) (let ([n1 (string-length s1)] [n2 (string-length s2)]) (let f ([i 0]) (if (fx= i n2) (if (fx= i n1) '= '>) (if (fx= i n1) '< (let ([c1 (char-cvt (string-ref s1 i))] [c2 (char-cvt (string-ref s2 i))]) (if (char))))))))) (define push-undo (lambda (p undos) (cons (cons p (car undos)) (cdr undos)))) (define-syntactic-monad P ip ; current input port op ; current output port def-env ; definition environment pending ; stack of pending latex "environments" groups ; stack of pending groups ips ; input port stack; does not include ip ops ; output port stack; does not include op ifiles ; stack of input files [(cons ip ips) w/o string ports] ofiles ; stack of output files [(cons op ops) w/o string ports] rawfiles ; assocation list of name, raw output-file pairs hard-spaces ; if #t, treat spaces as ~ eofconts ; stack of continuations to call on eof undos ; stack of lists of undo procs to call when group ends column ; current column in current table columns ; stack of current column in pending tables colfmt ; column format for current table colfmts ; stack of column formats for pending tables convert-quotes ; if #t, converts `` and '' to " and -- to - ) (define sinclude (P lambda (fn) (let ([new-ip (guard (c [else (warningf #f "cannot open ~a" fn) #f]) (open-input-file fn))]) (if new-ip (P s0 ([ip new-ip] [ips (cons ip ips)] [eofconts (cons s0 eofconts)] [ifiles (push-ifile new-ip ifiles)])) (P s0))))) (define sbegingroup (P lambda (g) (P s0 ([groups (cons g groups)] [def-env (cons '() def-env)] [undos (cons '() undos)])))) (define sundo (lambda (ls) (if (null? ls) s0 (P lambda () (P (car ls) () (sundo (cdr ls))))))) (define sendgroup (P lambda (g) (unless (eq? (car groups) g) (input-error "unmatched ~a" (if (eq? g 'bgroup) "close brace or egroup" "endgroup"))) (P (sundo (car undos)) ([groups (cdr groups)] [def-env (cdr def-env)] [undos (cdr undos)])))) (define snewcommand (P lambda (cmd) (define iota (lambda (i n) (if (> i n) '() (cons i (iota (+ i 1) n))))) (let* ([argcnt-str (read-optional-arg ip)] [argcnt (if argcnt-str (string->number argcnt-str) 0)] [opt (read-optional-arg ip)] [template (read-bracketed-text ip)]) (unless (and argcnt (<= (if opt 1 0) argcnt 9)) (input-error "invalid argument count ~a" argcnt-str)) (let ([pattern (if opt (cons opt (iota 2 argcnt)) (iota 1 argcnt))]) (set-def! cmd def-env #f (P lambda () (P s0 ([ip (open-input-string (expand-template template (read-args ip pattern cmd) cmd))] [ips (cons ip ips)] [eofconts (cons s0 eofconts)])))))) (P s0))) (define snewenvironment (P lambda (cmd) (define iota (lambda (i n) (if (> i n) '() (cons i (iota (+ i 1) n))))) (let* ([argcnt-str (read-optional-arg ip)] [argcnt (if argcnt-str (string->number argcnt-str) 0)] [opt (read-optional-arg ip)] [b (begin (suppress-white-space ip) (read-bracketed-text ip))] [e (begin (suppress-white-space ip) (read-bracketed-text ip))]) (unless (and argcnt (<= (if opt 1 0) argcnt 9)) (input-error "invalid argument count ~a" argcnt-str)) (let ([pattern (if opt (cons opt (iota 2 argcnt)) (iota 1 argcnt))]) (set-def! cmd def-env #f (P lambda () (P s0 ([ip (open-input-string (expand-template b (read-args ip pattern cmd) cmd))] [ips (cons ip ips)] [eofconts (cons s0 eofconts)] [pending (cons cmd pending)]))))) (let ([endcmd (string->symbol (format "end~a" cmd))]) (set-def! endcmd def-env #f (P lambda () (P s0 ([ip (open-input-string e)] [ips (cons ip ips)] [eofconts (cons (P lambda () (check-pending (car pending) cmd) (P s0 ([pending (cdr pending)]))) eofconts)])))))) (P s0))) (define check-pending (lambda (expected actual) (unless (eq? expected actual) (input-error "expected \\end{~a}, got \\end{~a} or \\end~a" expected actual actual)))) (define process-string (P lambda (s k) (P s0 ([ip (open-input-string s)] [ips (cons ip ips)] [eofconts (cons (P lambda () (P k ([op (car ops)] [ops (cdr ops)]) (get-output-string op))) eofconts)] [op (open-output-string)] [ops (cons op ops)])))) (define new-conditional (lambda (ifcmd def-env default cmdtrue cmdfalse) (define scan-if (let ([buf (open-output-string)]) (lambda (ip def-env hard-spaces) (let loop ([depth 0] [then-part #f]) (state-case (c (read-char ip)) [(#\\) (let ([cmd (read-command ip)]) (cond [(conditional? cmd def-env) (fprintf buf "\\~a" cmd) (loop (+ depth 1) then-part)] [(and (= depth 0) (eq? cmd 'else)) (if then-part (input-error "extra \\else found") (loop depth (get-output-string buf)))] [(eq? cmd 'fi) (if (= depth 0) (if then-part (values then-part (get-output-string buf)) (values (get-output-string buf) "")) (begin (fprintf buf "\\~a" cmd) (loop (- depth 1) then-part)))] [else (fprintf buf "\\~a" cmd) (loop depth then-part)]))] [(#\%) (scomment ip buf hard-spaces) (loop depth then-part)] [(#\{) (fprintf buf "{~a}" (read-bracketed-text ip 1)) (loop depth then-part)] [(#\}) (input-error "unmatched } within \\if ... \\fi")] [(eof) (input-error "unexpected end-of-file within \\if ... \\fi")] [else (write-char c buf) (loop depth then-part)]))))) (let ([cell (cons default (void))]) (set-def! ifcmd def-env #t (P lambda () (call-with-values (lambda () (scan-if ip def-env hard-spaces)) (lambda (then-part else-part) (let ([part (if (car cell) then-part else-part)]) (P s0 ([ip (open-input-string part)] [ips (cons ip ips)] [eofconts (cons s0 eofconts)]))))))) (when cmdtrue (set-def! cmdtrue def-env #f (P lambda () (set-car! cell #t) (P s0)))) (when cmdfalse (set-def! cmdfalse def-env #f (P lambda () (set-car! cell #f) (P s0))))))) (define (sraw ip op) (state-case (c (read-char ip)) [(#\\) (state-case (c2 (peek-char ip)) [(#\%) (write-char (read-char ip) op)] [else (write-char #\\ op)]) (sraw ip op)] [(eof) (void)] [else (write-char c op) (sraw ip op)])) (define snewif (lambda (ip def-env) (state-case (c (read-char ip)) [(#\\) (let ([ifcmd (read-command ip)]) (let ([ifcmd-str (symbol->string ifcmd)]) (unless (and (> (string-length ifcmd-str) 2) (string=? (substring ifcmd-str 0 2) "if")) (input-error "invalid conditional name ~a" ifcmd)) (let ([cmd (substring ifcmd-str 2 (string-length ifcmd-str))]) (new-conditional ifcmd def-env #f (string->symbol (string-append cmd "true")) (string->symbol (string-append cmd "false"))))))] [else (input-error "unexpected character following \\newif")]))) (define-syntax numbering-command (syntax-rules () [(_ who fmt) (global-def who (snumber 'who fmt))])) (define snumber (lambda (who fmt) (P lambda () (let* ([counter (string->symbol (read-bracketed-text ip))] [value (get-counter-value counter)]) (unless value (input-error "unknown counter in \\~a{~a}" who counter)) (display (fmt (get-counter-value counter)) op)) (P s0)))) (define s0 (P lambda () (state-case (c (read-char ip)) [(#\\) (let ([cmd (read-command ip)]) (cond [(get-def cmd def-env) => (lambda (proc) (unless (command-symbol? cmd) (if hard-spaces (let loop () ; squeeze out only empty lines (state-case (c (peek-char ip)) [(#\newline) (read-char ip) (loop)] [(#\%) (read-char ip) (scomment ip op hard-spaces) (loop)] [else (void)])) (suppress-white-space ip))) (P proc))] [else (unexpected-command cmd)]))] [(#\space #\tab) (if hard-spaces (display " " op) (write-char c op)) (P s0)] [(#\~) (display " " op) (P s0)] [(#\-) (if convert-quotes ; emit - for -- and --- for ---. IE4 and older versions of netscape ; can't handle the proper HTML en-dash and em-dash encodings. (if (eqv? (peek-char ip) #\-) (begin (read-char ip) (if (eqv? (peek-char ip) #\-) (begin (read-char ip) (display "---" op)) ; should be — (display "-" op))) ; should be – (write-char c op)) (write-char c op)) (P s0)] [(#\<) (fprintf op "<") (P s0)] [(#\>) (fprintf op ">") (P s0)] [(#\$) (s$ ip op) (P s0)] [(#\%) (scomment ip op hard-spaces) (P s0)] [(#\{) (P sbegingroup () 'group)] [(#\}) (P sendgroup () 'group)] [(#\` #\') (if (and convert-quotes (eqv? (peek-char ip) c)) (begin (read-char ip) (write-char #\" op)) (write-char c op)) (P s0)] [(#\newline) (write-char c op) (when (let loop ([par? #f]) ; insert par for multiple blank lines (state-case (c (peek-char ip)) [(#\newline) (read-char ip) (write-char c op) (loop #t)] [(#\space #\tab) (if hard-spaces par? (begin (read-char ip) (write-char c op) (loop par?)))] [(#\%) (read-char ip) (scomment ip op hard-spaces) (loop par?)] [else par?])) (fprintf op "

    ~%")) (P s0)] [(#\&) (P sampersand ())] [(eof) (close-input-port ip) (if (null? ips) (void) (P (car eofconts) ([ip (car ips)] [ips (cdr ips)] [ifiles (if (eq? ip (car ifiles)) (pop-ifile ifiles) ifiles)] [eofconts (cdr eofconts)])))] [else (write-char c op) (P s0)]))) ;----------------------------------------------------------------------- ; rudimentary table support (define-record table (col-format border?)) (define silenced? #f) (define parse-col-format (lambda (s) (let ([ip (open-input-string s)]) (let loop ([ls '()] [border? #f]) (state-case (c (read-char ip)) [(#\|) (unless silenced? (set! silenced? #t) (warningf 'tabular "support for rules in HTML tables is imprecise")) (loop ls #t)] [(#\c) (loop (cons " align=\"center\"" ls) border?)] [(#\l) (loop (cons " align=\"left\"" ls) border?)] [(#\r) (loop (cons " align=\"right\"" ls) border?)] [(#\@) (warningf 'tabular "ignoring @{~a} for now" (read-bracketed-text ip)) (loop ls border?)] [(eof) (make-table (list->vector (reverse ls)) border?)] [else (input-error (format "unexpected column format specifier ~a" c))]))))) (define emit-td (P lambda (k) (fprintf (car ops) "

    ~a
    " "
    ") op) (P s0 ([op (open-output-string)] [ops (cons op ops)] [column 0] ; could collapse these [columns (cons column columns)] [colfmt col-format] [colfmts (cons colfmt colfmts)] [pending (cons 'tabular pending)])))))) (global-def endtabular (P lambda () (P emit-td () (P lambda () (check-pending (car pending) 'tabular) (display "
    " (car ops)) (P s0 ([op (car ops)] [ops (cdr ops)] [column (car columns)] [columns (cdr columns)] [colfmt (car colfmts)] [colfmts (cdr colfmts)] [pending (cdr pending)])))))) (global-def multicolumn (P lambda () (let ([span (or (string->number (read-bracketed-text ip)) (input-error "number expected"))] [v (table-col-format colfmt)]) (unless (integer? span) (input-error "invalid \\multicolumn span")) (unless (<= 1 span (- (vector-length v) column)) (input-error (format "\\multicolumn span ~s out of range for ~s column table" span (vector-length v)))) (let* ([s (read-bracketed-text ip)] [fmt (parse-col-format s)]) (unless (= 1 (vector-length (table-col-format fmt))) (input-error (format "invalid \\multicolumn format ~a" s))) (P s0 ([ip (open-input-string (read-bracketed-text ip))] [ips (cons ip ips)] [colfmt (let ([newsize (- (vector-length v) span -1)]) (let ([new (make-vector newsize)]) (do ([i 0 (+ i 1)]) ((= i newsize) (make-table new (table-border? colfmt))) (vector-set! new i (cond [(< i column) (vector-ref v i)] [(= i column) (format " colspan=\"~a\"~a" span (vector-ref (table-col-format fmt) 0))] [else (vector-ref v (+ i span -1))])))))] [colfmts (cons colfmt colfmts)] [pending (cons 'multicolumn pending)] [eofconts (cons s0 eofconts)])))))) ) (populate-source-directories) (command-line-case (command-line) [((keyword --help)) (usage)] [((flags [--mathdir mathdir $ (math-directory mathdir)]) filename* ...) (for-each go (let ([found (find-filename "html-prep.tex")]) (if found (cons found filename*) filename*)))]) stex-1.2.1+git20171204.g5e4f0ca/src/preplib.ss000066400000000000000000000420711321130544300201660ustar00rootroot00000000000000;;; preplib.ss ;;; ;;; Copyright (c) 1998-2016 R. Kent Dybvig and Oscar Waddell ;;; ;;; Permission is hereby granted, free of charge, to any person obtaining a ;;; copy of this software and associated documentation files (the "Software"), ;;; to deal in the Software without restriction, including without limitation ;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, ;;; and/or sell copies of the Software, and to permit persons to whom the ;;; Software is furnished to do so, subject to the following conditions: ;;; ;;; The above copyright notice and this permission notice shall be included in ;;; all copies or substantial portions of the Software. ;;; ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ;;; DEALINGS IN THE SOFTWARE. #!chezscheme (library (preplib) (export current-ifile genlab-prefix genlab-counters state-case read-alpha-command read-command command-symbol? read-back-slash read-open-brace read-close-brace read-bracketed-text read-optional-arg push-ifile pop-ifile input-error unexpected-eof unexpected-command genlab read-integer read-def-pattern read-args expand-template suppress-white-space parse-index global-def set-def! get-def conditional? populate-source-directories anchored-filename? find-filename open-input-file) (import (except (chezscheme) open-input-file)) (define current-ifile (make-parameter #f)) (define genlab-prefix (make-parameter #f)) (define genlab-counters (make-parameter #f)) (define-syntax state-case (syntax-rules () [(_ (var exp) c1 c2 ...) (identifier? (syntax var)) (let ([var exp]) (state-case-help var c1 c2 ...))])) (define-syntax state-case-help (syntax-rules (else) [(_ var (else e1 e2 ...)) (begin e1 e2 ...)] [(_ var ((k ...) e1 e2 ...) c ...) (if (or (state-case-test var k) ...) (begin e1 e2 ...) (state-case-help var c ...))])) (define-syntax state-case-test (syntax-rules (eof -) [(_ var eof) (eof-object? var)] [(_ var (char1 - char2)) (and (char? var) (char<=? char1 var char2))] [(_ var char) (and (char? var) (char=? var char))])) ; doesn't allow @ even in document class or style files. this won't ; work for us anyway because we use character-based rather than ; token-based substitution, so macros that insert @ symbols into ; their output won't work outside of the original context (define read-alpha-command ; return symbol representing command; assume \ already seen and scan ; maximal string of alphabetic chars, e.g., \scheme => symbol scheme ; returns || when no command is recognized (let ([buf (open-output-string)]) (lambda (ip) (state-case (c (peek-char ip)) [((#\a - #\z) (#\A - #\Z)) (let loop () (write-char (read-char ip) buf) (state-case (c (peek-char ip)) [((#\a - #\z) (#\A - #\Z)) (loop)] [else (string->symbol (get-output-string buf))]))] [else '||])))) (define read-command ; like read-alpha-command, but allows single nonalphabetic char ; commands, e.g., \' => |'| (let ([buf (open-output-string)]) (lambda (ip) (state-case (c (peek-char ip)) [((#\a - #\z) (#\A - #\Z)) (let loop () (write-char (read-char ip) buf) (state-case (c (peek-char ip)) [((#\a - #\z) (#\A - #\Z)) (loop)] [else (string->symbol (get-output-string buf))]))] [(eof) '||] [else (read-char ip) (string->symbol (string c))])))) (define command-symbol? (lambda (cmd) ; true iff command is one character, nonalpabetic (let ([s (symbol->string cmd)]) (and (fx= (string-length s) 1) (state-case (c (string-ref s 0)) [((#\a - #\z) (#\A - #\Z)) #f] [else #t]))))) (define read-back-slash (lambda (ip) (if (eqv? (peek-char ip) #\\) (read-char ip) (input-error "back slash expected")))) (define read-open-brace (lambda (ip) (if (eqv? (peek-char ip) #\{) (read-char ip) (input-error "open brace expected")))) (define read-close-brace (lambda (ip) (if (eqv? (peek-char ip) #\}) (read-char ip) (input-error "close brace expected")))) (define read-bracketed-text (let ([buf (open-output-string)]) (case-lambda [(ip) (read-open-brace ip) (read-bracketed-text ip 1)] [(ip depth) (state-case (c (read-char ip)) [(#\}) (if (= depth 1) (get-output-string buf) (begin (write-char #\} buf) (read-bracketed-text ip (- depth 1))))] [(#\{) (write-char #\{ buf) (read-bracketed-text ip (+ depth 1))] [(eof) (input-error "file ended within bracketed text")] [else (write-char c buf) (read-bracketed-text ip depth)])]))) (define read-optional-arg (let ([buf (open-output-string)]) (lambda (ip) (state-case (c (peek-char ip)) [(#\[) (read-char ip) (let loop ([depth 0]) (state-case (c (read-char ip)) [(#\]) (if (= depth 0) (get-output-string buf) (begin (write-char c buf) (loop depth)))] [(#\{) (write-char c buf) (loop (+ depth 1))] [(#\}) (write-char c buf) (loop (- depth 1))] [(eof) (input-error "file ended within optional argument")] [else (write-char c buf) (loop depth)]))] [else #f])))) (define push-ifile (lambda (ip ifiles) (current-ifile ip) (cons ip ifiles))) (define pop-ifile (lambda (ifiles) (let ([ifiles (cdr ifiles)]) (current-ifile (and (not (null? ifiles)) (car ifiles))) ifiles))) (define input-error (lambda (msg . args) (define file-coordinates (lambda (ip) (let ([n (file-position ip)]) (file-position ip 0) (let f ([n n] [line 1] [char 1] [return? #f]) (if (= n 0) (values line char) (state-case (c (read-char ip)) [(#\newline) (f (- n 1) (if return? line (+ line 1)) 1 #f)] [(#\return) (f (- n 1) (+ line 1) 1 #t)] [(eof) (values line char)] [else (f (- n 1) line (+ char 1) #f)])))))) (let ([ip (current-ifile)]) (call-with-values (lambda () (file-coordinates ip)) (lambda (line char) (errorf #f "~a on line ~d, character ~d of ~s" (apply format msg args) line char (port-name ip))))))) (define unexpected-eof (lambda (where) (input-error "unexpected end-of-input ~a" where))) (define unexpected-command (lambda (cmd) (input-error "unexpected command '\\~a'" cmd))) (define genlab (lambda () (define next-count (lambda (fn) (cond [(assoc fn (genlab-counters)) => (lambda (a) (let ([n (+ (cdr a) 1)]) (set-cdr! a n) n))] [else (genlab-counters (cons (cons fn 0) (genlab-counters))) 0]))) (let ([name (path-root (port-name (current-ifile)))]) (string->symbol (format "~a:~a~d" name (genlab-prefix) (next-count name)))))) (define read-integer ; return integer or #f if none found (lambda (ip) (string->number (list->string (let loop () (state-case (c (peek-char ip)) [((#\0 - #\9)) (read-char ip) (cons c (loop))] [else '()])))))) (define read-def-pattern (lambda (ip) (let loop ([i 1]) (state-case (c (peek-char ip)) [(#\{) '()] [(#\#) (read-char ip) (state-case (c1 (peek-char ip)) [(#\#) (read-char ip) (list* c1 c (loop i))] [else (let ([n (read-integer ip)]) (if (eq? n i) (cons n (loop (+ i 1))) (input-error "invalid \\def argument specifier")))])] [(eof) (unexpected-eof "after \\def")] [else (read-char ip) (cons c (loop i))])))) (define read-args (lambda (ip pattern cmd) (define read-arg (lambda (ip cmd) (state-case (c (read-char ip)) [(#\\) (format "\\~a" (read-command ip))] [(#\{) (read-bracketed-text ip 1)] [(eof) (unexpected-eof (format "reading ~a arguments" cmd))] [else (string c)]))) (let loop ([pattern pattern]) (if (null? pattern) '() (let ([x (car pattern)]) (cond [(integer? x) (let ([arg (read-arg ip cmd)]) (cons arg (loop (cdr pattern))))] [(string? x) (let ([arg (read-optional-arg ip)]) (cons (or arg x) (loop (cdr pattern))))] [(eqv? x #\space) (suppress-white-space ip) (loop (cdr pattern))] [(eqv? (read-char ip) x) (loop (cdr pattern))] [else (input-error "~a use does not match pattern" cmd)])))))) (define expand-template (let ([buf (open-output-string)]) (lambda (template args cmd) (let ([sip (open-input-string template)]) (let loop () (state-case (c (read-char sip)) [(#\\) (write-char c buf) (state-case (c (peek-char sip)) [(#\#) (read-char sip) (write-char c buf)] [else (void)]) (loop)] [(#\#) (state-case (c (peek-char sip)) [(#\#) (read-char sip) (write-char #\# buf)] [else (let ([n (read-integer sip)]) (let ([n (and n (- n 1))]) (unless (and n (< -1 n (length args))) (input-error "invalid argument specifier in ~a template" cmd)) (display (list-ref args n) buf)))]) (loop)] [(eof) (get-output-string buf)] [else (write-char c buf) (loop)])))))) (define (suppress-white-space ip) (state-case (c (peek-char ip)) [(#\space #\tab #\newline) (read-char ip) (suppress-white-space ip)] [(#\%) (read-char ip) (let loop () (state-case (c (read-char ip)) [(eof #\newline) (void)] [else (loop)]))] [else (void)])) (define parse-index (let ([buf (open-output-string)]) ; if proper-nesting? is true, the characters ", @, !, and | lose their ; special meaning within nested groups. (lambda (ip proper-nesting?) (define nested-group (lambda (depth) (state-case (c (read-char ip)) [(#\{) (write-char c buf) (nested-group (+ depth 1))] [(#\}) (write-char c buf) (unless (= depth 0) (nested-group (- depth 1)))] [(#\@ #\! #\|) (if proper-nesting? (write-char c buf) (input-error "unquoted ~c within nested group in index entry" c)) (nested-group depth)] [(#\") (if proper-nesting? (write-char c buf) (state-case (c (read-char ip)) [(eof) (input-error "file ended within \\index{}")] [else (write-char c buf)])) (nested-group depth)] [(#\") (write-char c buf) (unless proper-nesting? (state-case (c (peek-char ip)) [(#\") (read-char ip) (write-char c buf)] [else (void)])) (nested-group depth)] [else (write-char c buf) (nested-group depth)]))) (define before@ (lambda (ls) ; ls is list of levels seen so far (state-case (c (read-char ip)) [(#\}) (let ([s (get-output-string buf)]) (values (reverse (cons (cons #f s) ls)) ""))] [(#\{) (write-char c buf) (nested-group 0) (before@ ls)] [(#\|) (let ([s (get-output-string buf)]) (values (reverse (cons (cons #f s) ls)) (read-bracketed-text ip 1)))] [(#\@) (after@ ls (get-output-string buf))] [(#\!) (let ([s (get-output-string buf)]) (before@ (cons (cons #f s) ls)))] [(#\") (state-case (c (read-char ip)) [(eof) (input-error "file ended within \\index{}")] [else (write-char c buf) (before@ ls)])] [(#\\) (write-char c buf) (state-case (c (peek-char ip)) [(#\") (read-char ip) (write-char c buf)] [else (void)]) (before@ ls)] [(eof) (input-error "file ended within \\index{}")] [else (write-char c buf) (before@ ls)]))) (define after@ (lambda (ls sort-key) ; ls is list of levels seen so far ; sort-key is sort key part of current level (state-case (c (read-char ip)) [(#\}) (let ([s (get-output-string buf)]) (values (reverse (cons (cons sort-key s) ls)) ""))] [(#\{) (write-char c buf) (nested-group 0) (after@ ls sort-key)] [(#\|) (let ([s (get-output-string buf)]) (values (reverse (cons (cons sort-key s) ls)) (read-bracketed-text ip 1)))] [(#\@) (input-error "at sign seen after at sign in \\index{}")] [(#\!) (let ([s (get-output-string buf)]) (before@ (cons (cons sort-key s) ls)))] [(#\") (state-case (c (read-char ip)) [(eof) (input-error "file ended within \\index{}")] [else ; leave out quote; reinsert later (write-char c buf) (after@ ls sort-key)])] [(#\\) (write-char c buf) (state-case (c (peek-char ip)) [(#\") (read-char ip) (write-char c buf)] [else (void)]) (after@ ls sort-key)] [(eof) (input-error "file ended within \\index{}")] [else (write-char c buf) (after@ ls sort-key)]))) (before@ '())))) ;; support for definitions (define-syntax global-def (syntax-rules () [(_ name expr) (set-def! 'name '() #f expr)])) (define set-def! (lambda (cmd env conditional? proc) (if (null? env) (putprop cmd 'def (cons conditional? proc)) (set-car! env (cons (list* cmd conditional? proc) (car env)))))) (module (get-def conditional?) (define lookup-env (lambda (cmd env) (cond [(null? env) (getprop cmd 'def '(#f . #f))] [(assq cmd (car env)) => cdr] [else (lookup-env cmd (cdr env))]))) (define get-def (lambda (cmd env) (cdr (lookup-env cmd env)))) (define conditional? (lambda (cmd env) (car (lookup-env cmd env))))) (define (populate-source-directories) (let ([inputs (or (getenv "TEXINPUTS") "")]) (unless (equal? inputs "") (let ([ip (open-input-string inputs)] [op (open-output-string)]) (source-directories (let loop ([ls '()]) (let ([c (read-char ip)]) (case c [(#\:) (loop (cons (get-output-string op) ls))] [(#!eof) (append (reverse ls) (source-directories))] [else (write-char c op) (loop ls)])))))))) (define anchored-filename? (lambda (s) (and (> (string-length s) 0) (memv (string-ref s 0) '(#\/ #\.))))) (define find-filename (lambda (fn) (if (anchored-filename? fn) fn (ormap (lambda (p) (let ([path (string-append p "/" fn)]) (and (file-exists? path) path))) (source-directories))))) (define open-input-file (lambda (fn . flags) (import scheme) (let ([path (find-filename fn)]) (unless path (errorf #f (if (anchored-filename? fn) "unable to find file ~a" "unable to find file ~a in search path") fn)) (apply open-input-file path flags)))) ) stex-1.2.1+git20171204.g5e4f0ca/src/scheme-prep.ss000077500000000000000000001324721321130544300207510ustar00rootroot00000000000000#! /usr/bin/scheme --program ;;; scheme-prep.ss ;;; ;;; Copyright (c) 1998-2016 R. Kent Dybvig and Oscar Waddell ;;; ;;; Permission is hereby granted, free of charge, to any person obtaining a ;;; copy of this software and associated documentation files (the "Software"), ;;; to deal in the Software without restriction, including without limitation ;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, ;;; and/or sell copies of the Software, and to permit persons to whom the ;;; Software is furnished to do so, subject to the following conditions: ;;; ;;; The above copyright notice and this permission notice shall be included in ;;; all copies or substantial portions of the Software. ;;; ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ;;; DEALINGS IN THE SOFTWARE. ;;; primitive commands ;;; \genlab ;;; \generated ... \endgenerated ; inject and process string returned by enclosed Scheme code ;;; \hindex ;;; \index ;;; \raw ;;; \scheme ;;; \schemeinit ... \endschemeinit ;;; \schemedisplay ... \endschemedisplay ;;; \schemedisplay[number-lines] ... \endschemedisplay ; insert line numbers ;;; \schemeverbatim ... \endschemeverbatim ;;; \schlbrace ;;; \schrbrace ;;; \transcript ... \endtranscript ;;; \transcript[endtranscript] ... \endtranscript ;;; \var ;;; \xdef ;;; \xedef ;;; \schemeoutput[mode]{filename} ; divert schemedisplay code to file ;;; \schemeoutput{} ; closes the open scheme output file ;;; commands inserted into the output ;;; \$, \&, \%, \#, \\ ;;; \dots ;;; \endschemedisplay ;;; \hindex ;;; \is ;;; \label ;;; \null ;;; \schemeindent ;;; \scheme ;;; \schemeblankline ;;; \schemedisplay ;;; \schemelinestart ; relies on defn of \schemeindent= ;;; \schatsign ;;; \schbackslash ;;; \schcarat ;;; \schdot ;;; \schlbrace ;;; \schrbrace ;;; \schtilde ;;; \schunderscore ;;; \si ;;; The transerr, etc. commands require an empty argument so that ;;; we can put them in a \raw{} in the schemedisplay we generate for ;;; the transcript and still keep both htmlprep and latex happy with ;;; the result. html-prep would also accept {\transin}, but latex ;;; was not happy with that. ;;; \transerr{} ... \endtranserr{} ; transcript error msg typesetting ;;; \transin{} ... \endtransin{} ; transcript user input typesetting ;;; \transout{} ... \endtransout{} ; transcript program output typesetting ;;; \var ;;; \vdots ;;; any undefined input command ;;; anything else inserted by \raw ;;; Valid within \scheme{...} ;;; \dots ;;; \raw{} ;;; \var{} ;;; \var{_} ;;; \ ;;; all other characters besides } and newline ;;; Valid within \schemedisplay ... \endschemedisplay ;;; \dots ;;; \raw{} ;;; \var{} ;;; \var{_} ;;; \vdots ;;; \ ;;; all other characters besides } ;;; \label{text} may appear immediately after \schemedisplay ;;; index and hindex entries follow makeindex 2.13 syntax except that ;;; the special characters !, @, |, ", and \ are freely allowed within ;;; embeded {, } pairs in the "actual entry" portion of a level (the ;;; portion following @, if any). a modified version of makeindex 2.13 ;;; that supports this extension (with the -d [allow delimited special ;;; chars] flag) is available here as well. ;;; ;;; in \index input, we also allow \scheme{...} to appear, with embedded ;;; special characters. ;;; \index syntax ;;; \index{levels} ;;; \index{levels|pageformat} ;;; levels --> level ;;; --> level!levels ;;; level --> keyentry (key and entry same) ;;; level --> key@entry (separate key and entry) ;;; ;;; Valid within keyentry ;;; \scheme{...} ;;; If multiple filenames are supplied on the command line, each file is ;;; processed in the same runtime image. Thus an \xdef in an earlier file ;;; persists through the processing of subsequent files. #!chezscheme (import (except (chezscheme) open-input-file) (dsm) (preplib) (script)) (define use-interaction-window (make-parameter #f)) (define interaction-window-width (make-parameter 28)) (define copy-through-newline (lambda (ip op) (state-case (c (read-char ip)) [(#\newline) (write-char c op)] [(eof) (void)] [else (write-char c op) (copy-through-newline ip op)]))) (define dovar (lambda (ip op) (read-open-brace ip) (display "\\var{" op) (let f () (state-case (c (read-char ip)) [(#\}) (write-char c op)] [(#\') (display "$'$" op) (f)] [(#\_) (display "$_" op) (state-case (c (read-char ip)) [(eof) (input-error "unexpected eof in \\var{}")] [(#\{) (fprintf op "{~a}" (read-bracketed-text ip 1))] [else (write-char c op)]) (write-char #\$ op) (f)] [(eof) (input-error "unexpected eof in \\var{}")] [else (write-char c op) (f)])))) (define (sscheme ip op) ; within \scheme ; unlike schemedisplay, does not allow { or }. { and } must be expressed ; as \schlbrace and \schrbrace (state-case (c (read-char ip)) [(#\{) (input-error "unexpected { within \\scheme{}")] [(#\}) (void)] [(#\\) ; use read-alpha-command instead of read-command to avoid ; improper handling of special characters that follow a slash, ; including } (let ([cmd (read-alpha-command ip)]) (case cmd [(dots) (display "{\\dots}" op) (sscheme ip op)] [(raw) (display (read-bracketed-text ip) op) (sscheme ip op)] [(var) (dovar ip op) (sscheme ip op)] [(schlbrace) (display "\\schlbrace" op) (sscheme ip op)] [(schrbrace) (display "\\schrbrace" op) (sscheme ip op)] [else ; assume random \ possibly followed by alphabetic chars (fprintf op "{\\schbackslash}~a" cmd) (sscheme ip op)]))] [(#\.) (display "{\\schdot}" op) (sscheme ip op)] [(#\~) (display "{\\schtilde}" op) (sscheme ip op)] [(#\^) (display "{\\schcarat}" op) (sscheme ip op)] [(#\@) (display "{\\schatsign}" op) (sscheme ip op)] [(#\_) (display "{\\schunderscore}" op) (sscheme ip op)] [(#\space) (display "~" op) (sscheme ip op)] [(#\$ #\& #\% #\#) (fprintf op "\\~c" c) (sscheme ip op)] [(#\newline) (input-error "line ended within \\scheme{}")] [(eof) (input-error "file ended within \\scheme{}")] [else (write-char c op) (sscheme ip op)])) (define sschemedisplay (P lambda (number-lines? labels) ; within a schemedisplay ; number-lines? ; Flag is true if we want the lines numbered. ; ; labels ; A list of labels to be attached to this schemedisplay. ; We insert them after the first newline in the schemedisplay ; (or before the \endschemedisplay if no newline) so that the ; label is attached to something other than whitespace (this ; prevents labels from referring to the preceeding page when the ; start of a schemedisplay falls right on a page break). (define print-line-start (lambda (line op) (if number-lines? (fprintf op "\\schemelinestartnumbered{~s}~%" line) (fprintf op "\\schemelinestart~%")))) (fprintf op "\\schemelinestart~%") (when sout (newline sout)) (let loop ([n? #f] [line 0] [labels labels]) ; n? is true if we've just passed a new line within the display; we use ; it to determine whether to insert \\\schemelinestart. (We insert ; \schemelinestart after \\ to prevent \\ from sucking up ensuing ; whitespace---including spaces used for indentation on the following ; line.) (state-case (c (read-char ip)) [(#\\) ; use read-alpha-command instead of read-alpha-command to avoid ; improper handling of special characters that follow a slash (let ([cmd (read-alpha-command ip)]) (case cmd [(endschemedisplay) (unless (null? labels) (for-each (lambda (l) (fprintf op "\\label{~a}" l)) labels)) (display "\\endschemedisplay" op)] [else (when n? (display "\\\\\n" op) (print-line-start line op)) (case cmd [(dots) (display "{\\dots}" op) (loop #f line labels)] [(var) (dovar ip op) (loop #f line labels)] [(raw) (fprintf op "~a" (read-bracketed-text ip)) (loop #f line labels)] [(vdots) (display "{\\vdots}" op) (loop #f line labels)] [else ; assume random \ possibly followed by alphabetic chars (fprintf op "{\\schbackslash}~a" cmd) (when sout (fprintf sout "\\~a" cmd)) (loop #f line labels)])]))] [else (when n? (display "\\\\\n" op) (print-line-start line op)) (when sout (write-char c sout)) (state-case (c c) [(#\;) ; convert ;=> into \is and ;== into \si (state-case (c (peek-char ip)) [(#\=) (read-char ip) (when sout (write-char c sout)) (state-case (c (peek-char ip)) [(#\>) (when sout (write-char c sout)) (read-char ip) (display "\\is" op) (loop #f line labels)] [(#\=) (when sout (write-char c sout)) (read-char ip) (display "\\si" op) (loop #f line labels)] [else (when sout (write-char c sout)) (display ";=" op) (loop #f line labels)])] [(#\-) ; should abstract this (read-char ip) (when sout (write-char c sout)) (state-case (c (peek-char ip)) [(#\>) (when sout (write-char c sout)) (read-char ip) (display "\\becomes" op) ; would prefer something else here (loop #f line labels)] [else (when sout (write-char c sout)) (display ";-" op) (loop #f line labels)])] [else (write-char #\; op) (loop #f line labels)])] ;; Convert space to ~ since \obeyspaces doesn't seem to work for us ;; when \schemedisplay appears within a macro (see f2002/quiz02.stex). [(#\space) (display "~" op) (loop #f line labels)] [(#\.) (display "{\\schdot}" op) (loop #f line labels)] [(#\~) (display "{\\schtilde}" op) (loop #f line labels)] [(#\^) (display "{\\schcarat}" op) (loop #f line labels)] [(#\@) (display "{\\schatsign}" op) (loop #f line labels)] [(#\_) (display "{\\schunderscore}" op) (loop #f line labels)] [(#\{) (display "{\\schlbrace}" op) (loop #f line labels)] [(#\}) (display "{\\schrbrace}" op) (loop #f line labels)] [(#\$ #\& #\% #\#) (fprintf op "\\~c" c) (loop #f line labels)] [(#\newline) (unless (null? labels) (for-each (lambda (l) (fprintf op "\\label{~a}" l)) labels)) (state-case (c (peek-char ip)) [(#\newline) (read-char ip) (fprintf op "~%\\schemeblankline") (print-line-start line op) (when sout (newline sout)) (loop #f (fx+ line 2) '())] [else (loop #t (fx+ line 1) '())])] [(eof) (errorf #f "file ended within schemedisplay")] [else (write-char c op) (loop #f line labels)])])))) (define (sindex ip op) ; 1. read entire contents of \index{} form, w/o intepreting \scheme{...} ; separate at !s into 1 or more levels plus page format ; after |, if present; separate levels at @ into sort key ; and text, if present ; 2. for each level, ; a. compute output sort key ; - if input sort key is given, use it ; - otherwise use stripped version of input text ; - insert quotes where needed ; b. preprocess input text to produce output text ; - expand \scheme{...} ; - insert quotes where needed ; 3. produce output ; a. print \index{ ; b. for each level, if output text is same as output sort key, ; print . ; otherwise print @ ; c. separate levels with ! ; d. print | if present in input ; e. print } (define strip-sort-key ; presently strips only \scheme{ and matching } (let ([buf (open-output-string)]) (lambda (ip) (state-case (c (read-char ip)) [(#\\) (let ([cmd (read-command ip)]) (case cmd [(scheme) (read-open-brace ip) (display (read-bracketed-text ip 1) buf) (strip-sort-key ip)] [else (unexpected-command cmd)]))] [(eof) (get-output-string buf)] [else (write-char c buf) (strip-sort-key ip)])))) (call-with-values (lambda () (parse-index ip #t)) (lambda (levels page-format) (let ([keys (map (lambda (s) (insert-quotes (open-input-string s) #f)) (map (lambda (level) (if (car level) (car level) ; strip text to create sort key (strip-sort-key (open-input-string (cdr level))))) levels))] [texts (map (lambda (level) (insert-quotes (open-input-string (expand-entry (open-input-string (cdr level)))) #f)) levels)]) (let f ([keys keys] [texts texts] [delim #\{]) (unless (null? keys) (write-char delim op) (let ([key (car keys)] [text (car texts)]) (if (string=? key text) (display text op) (fprintf op "~a@~a" key text))) (f (cdr keys) (cdr texts) #\!))) (unless (string=? page-format "") (fprintf op "|~a" page-format)) (write-char #\} op))))) (define expand-entry ; expands \scheme{} forms (let ([buf (open-output-string)]) (lambda (ip) (state-case (c (read-char ip)) [(#\\) (let ([cmd (read-command ip)]) (case cmd [(scheme) (read-open-brace ip) (display "\\scheme{" buf) (sscheme ip buf) (write-char #\} buf) (expand-entry ip)] [else (fprintf buf "\\~a" cmd) (expand-entry ip)]))] [(eof) (get-output-string buf)] [else (write-char c buf) (expand-entry ip)])))) (define insert-quotes (let ([buf (open-output-string)]) ; if proper-nesting? is true, the characters ", @, !, and | lose their ; special meaning within nested groups. (lambda (ip proper-nesting?) (let loop () (state-case (c (read-char ip)) [(#\" #\@ #\! #\|) (write-char #\" buf) (write-char c buf) (loop)] [(#\\) (state-case (c (peek-char ip)) [(#\@ #\! #\|) (write-char #\" buf)] [else (void)]) (write-char c buf) (loop)] [(#\{) (if proper-nesting? (fprintf buf "{~a}" (read-bracketed-text ip 1)) (write-char c buf)) (loop)] [(eof) (get-output-string buf)] [else (write-char c buf) (loop)]))))) (define-syntactic-monad P ip ; current input port op ; current output port ips ; input port stack; does not include ip ops ; output port stack; does not include op ifiles ; stack of input files [(cons ip ips) w/o string ports] eofconts ; stack of continuations to call on eof sout ; output port for code within schemedisplay or #f ) (define process-string (P lambda (s k) (P s0 ([ip (open-input-string s)] [ips (cons ip ips)] [eofconts (cons (P lambda () (P k ([op (car ops)] [ops (cdr ops)]) (get-output-string op))) eofconts)] [op (open-output-string)] [ops (cons op ops)])))) (define s0 (P lambda () (state-case (c (read-char ip)) [(#\\) (let ([cmd (read-command ip)]) (cond [(get-def cmd '()) => (lambda (proc) (unless (or (command-symbol? cmd) (eq? cmd 'schemedisplay) (eq? cmd 'schemeinit) (eq? cmd 'transcript)) (suppress-white-space ip)) (P proc))] [else (fprintf op "\\~a" cmd) (P s0)]))] [(#\%) (write-char #\% op) (copy-through-newline ip op) (P s0)] [(eof) (close-port ip) (if (null? ips) (when sout (close-port sout)) (P (car eofconts) ([ip (car ips)] [ips (cdr ips)] [ifiles (if (eq? ip (car ifiles)) (pop-ifile ifiles) ifiles)] [eofconts (cdr eofconts)])))] [else (write-char c op) (P s0)]))) ;-------------------------------------------------------------------------- (define go (lambda (fn) (let ([ip (open-input-file (format "~a.stex" fn))]) (let ([op (open-output-file (format "~a.tex" fn) 'replace)]) (fprintf op "%%% DO NOT EDIT THIS FILE~%") (fprintf op "%%% Edit the .stex version instead~%~%") ; preplib parameters (parameterize ([current-ifile #f] [genlab-prefix "s"] [genlab-counters '()]) (P s0 ([ip ip] [op op] [ips '()] [ops '()] [ifiles (push-ifile ip '())] [eofconts (list s0)] [sout #f])) (close-port op)))))) (global-def genlab (P lambda () (display (genlab) op) (P s0))) (global-def hindex (P lambda () (P process-string () (read-bracketed-text ip) (P lambda (lab) (fprintf op "\\hindex{~a}" lab) (read-open-brace ip) (sindex ip op) (P s0))))) (global-def index (P lambda () (let ([lab (genlab)]) (fprintf op "\\label{~a}\\hindex{~a}" lab lab)) (read-open-brace ip) (sindex ip op) (P s0))) (global-def raw (P lambda () (display (read-bracketed-text ip) op) (P s0))) (global-def scheme (P lambda () (read-open-brace ip) (display "\\scheme{" op) (sscheme ip op) (write-char #\} op) (P s0))) (global-def schemedisplay (P lambda () (display "\\schemedisplay\n" op) (let loop ([options '()] [labels '()]) ; currently a bit sloppy on the grammar (state-case (c (read-char ip)) [(#\\) ; use read-alpha-command instead of read-command to avoid ; improper handling of special characters that follow a slash (let ([cmd (read-alpha-command ip)]) (case cmd [(label) (loop options (cons (read-bracketed-text ip) labels))] [(raw) (fprintf op "\\raw{~a}~%" (read-bracketed-text ip)) (loop options labels)] [else (input-error "invalid command \\~s following \\schemedisplay" cmd)]))] [(#\newline) (P sschemedisplay () (memq 'number-lines options) labels)] [(#\[) (unread-char c ip) (let ([opt (read-optional-arg ip)]) (if (equal? opt "number-lines") (loop (cons 'number-lines options) labels) (input-error "unexpected optional argument ~a to \\schemedisplay" opt)))] [else (input-error "expected newline after \\schemedisplay")])) (P s0))) (global-def schemeoutput (P lambda () (let* ([mode (if (equal? (read-optional-arg ip) "append") 'append 'replace)] [filename (read-bracketed-text ip)]) (when sout (close-port sout)) (if (eq? filename "") (P s0 ([sout #f])) (P s0 ([sout (open-output-file filename mode)])))))) (global-def var (P lambda () (display "\\scheme{" op) (dovar ip op) (write-char #\} op) (P s0))) (global-def def (P lambda () (let* ([cmd (state-case (c (read-char ip)) [(#\\) (read-command ip)] [else (input-error "invalid \\def syntax")])] [pattern (read-def-pattern ip)] [template (read-bracketed-text ip)]) (fprintf op "\\def\\~a" cmd) (for-each (lambda (x) (cond [(char? x) (write-char x op)] [(number? x) (fprintf op "#~a" x)] [else (errorf #f "unexpected parsed pattern element ~s" x)])) pattern) (fprintf op "{~a}" template) (P s0)))) (global-def xdef (P lambda () (let* ([cmd (state-case (c (read-char ip)) [(#\\) (read-command ip)] [else (input-error "invalid \\xdef syntax")])] [pattern (read-def-pattern ip)] [template (read-bracketed-text ip)]) (set-def! cmd '() #f (P lambda () (P s0 ([ip (open-input-string (expand-template template (read-args ip pattern cmd) cmd))] [ips (cons ip ips)] [eofconts (cons s0 eofconts)])))) (P s0)))) (global-def xedef (P lambda () (let* ([cmd (state-case (c (read-char ip)) [(#\\) (read-command ip)] [else (input-error "invalid \\xedef syntax")])] [pattern (read-def-pattern ip)] [template (read-bracketed-text ip)]) (P process-string () template (P lambda (template) (set-def! cmd '() #f (P lambda () (P s0 ([ip (open-input-string (expand-template template (read-args ip pattern cmd) cmd))] [ips (cons ip ips)] [eofconts (cons s0 eofconts)])))) (P s0)))))) (global-def schemeverbatim (P lambda () (display "\\begin{verbatim}\n" op) (let f () (state-case (c (read-char ip)) [(#\\) (let ([cmd (read-command ip)]) (case cmd [(endschemeverbatim) (void)] [else (write-char c op) (display cmd op) (f)]))] [(eof) (unexpected-eof "after \\schemeverbatim")] [else (write-char c op) (f)])) (display "\\end{verbatim}\n" op) (P s0))) (global-def timestamp (P lambda () (display (date-and-time) op) (P s0))) ;-------------------------------------------------------------------------- (let () (define-syntax define-enumeration (lambda (x) (define iota (case-lambda [(n) (iota 0 n)] [(i n) (if (= i n) '() (cons i (iota (+ i 1) n)))])) (syntax-case x () [(_ name (enum ...)) (and (identifier? #'name) (andmap identifier? #'(enum ...))) (with-syntax ([len (length #'(enum ...))]) (with-syntax ([(i ...) (iota #'len)]) #'(begin (define enum i) ... (define name len))))]))) (define-record tag (markup entity)) (define make-tag-port (lambda (ip) ; To preserve the indentation of Scheme expressions in the .stex source, ; we have to add the leading whitespace the user would have entered to ; compensate for the indentation---due to the prompt---of the first line. ; We compute the current indentation level when writing non-echo output. ; We indent subsequent input lines after we read the first line that ; follows some output. (define-enumeration num-modes (writing reading indenting)) (define mode writing) (define indent 0) (define adjust-indent ; called by output routine (lambda (x) (define do-char (lambda (c) (set! indent (if (char=? c #\newline) 0 (fx+ indent 1))))) ; shouldn't do this if we're printing on behalf of the repl (begin ; unless (use-interaction-window) (unless (fx= mode writing) (set! indent 0)) (set! mode writing) (if (char? x) (do-char x) (let ([len (string-length x)]) (do ([i 0 (fx+ i 1)]) ((fx= i len)) (do-char (string-ref x i)))))))) (define whitespace? (lambda (x) (if (char? x) (char-whitespace? x) (let loop ([i (fx- (string-length x) 1)]) (or (fx< i 0) (and (char-whitespace? (string-ref x i)) (loop (fx- i 1)))))))) (let ([line '()] [bline '()] [buffer '()] [ip ip]) (define (handler msg . args) (record-case (cons msg args) [char-ready? (p) (critical-section (or (not (null? line)) (char-ready? ip)))] [peek-char (p) (define read-line (lambda () (when (fx= mode writing) (set! mode reading)) (when (fx= mode indenting) (unless (fx= indent 0) (set! buffer (cons (make-tag #f (make-string indent #\space)) buffer)))) (let loop () (let ([c (read-char ip)]) (if (eof-object? c) '() (let ([x (make-tag #f c)]) (set! buffer (cons x buffer)) (if (eqv? c #\newline) (begin (set! mode indenting) (list x)) (cons x (loop))))))))) (critical-section (if (null? line) (let ([old bline]) (set! line (read-line)) (set! bline '()) (if (null? line) (begin ; When the last expression in a transcript calls read ; and then prints something in the transcript window, ; we have to be sure that the newline character that ; sent the line of buffered text is properly tagged as ; having been read via the transcript input port since ; read simply peeks at the whitespace character and the ; subsequent repl read (returning #!eof) will usurp the ; newline unless we patch it up here. (when (and (> (length old) 1) (eqv? (tag-entity (car old)) #\newline) (eq? (tag-markup (cadr old)) 'transin)) (set-tag-markup! (car old) 'transin)) #!eof) (tag-entity (car line)))) (tag-entity (car line))))] [unread-char (c p) (critical-section (when (null? bline) (errorf 'unread-char "too many consecutive unreads from ~s" p)) (let ([x (car bline)]) (set! bline (cdr bline)) (set-tag-markup! x #f) (set-tag-entity! x c) (set! line (cons x line))))] [clear-input-port (p) (critical-section (set! line '()) (set! bline '()))] [clear-output-port (p) (void)] [close-port (p) (mark-port-closed! p)] [flush-output-port (p) (void)] [file-position (p . pos) (if (null? pos) (most-negative-fixnum) (errorf 'transcript-port "cannot reposition"))] [port-name (p) "tag-port"] ; intentionally missing block-read and read-char [tag-read-char (markup p) (critical-section (let ([c (peek-char p)]) (unless (null? line) (let ([x (car line)]) (set! line (cdr line)) (set-tag-markup! x markup) (set! bline (cons x bline)))) c))] [tag-write-entity (markup x p) (critical-section (adjust-indent x) (set! buffer (cons (make-tag markup x) buffer)))] [tag-get-repl-interaction-strings () (let ([repl (open-output-string)] [intr (open-output-string)]) (define maxcols (interaction-window-width)) (define col 0) (define col-display (lambda (entity p) (define col-write-char (lambda (c p) (cond [(char=? c #\newline) (set! col 0)] [(= col maxcols) (newline p) (set! col 0)]) (write-char c p) (set! col (+ col 1)))) (if (char? entity) (col-write-char entity p) (for-each (lambda (c) (col-write-char c p)) (string->list entity))))) (define choose-port (lambda (mkup) (case mkup [(#f transerr traceout) repl] [(transin transout) intr] [else (errorf 'scheme-prep.ss "unexpected markup ~s" mkup)]))) (define reclaim-first-newline ; the newline that we entered after the expression in the repl window should ; be charged to the repl window, not the interaction window. ; (misattributed as being read by transin since the repl's read just peeks at ; the newline, and subsequent read during eval phase claims the newline) (lambda (ls) (let f ([ls ls]) (if (null? ls) '() (let ([x (car ls)]) (case (tag-markup x) [(transin) (when (eqv? (tag-entity x) #\newline) (set-tag-markup! x #f))] [(transout) (void)] [else (f (cdr ls))])))) ls)) (let loop ([ls (reclaim-first-newline (reverse buffer))] [markup #f]) (if (null? ls) (begin (set! buffer '()) (when markup (fprintf (choose-port markup) "\\raw{\\end~s{}}" markup)) (values (get-output-string repl) (let ([x (get-output-string intr)]) (if (eq? x "") #f x)))) (let ([x (car ls)]) (let ([new (tag-markup x)] [entity (tag-entity x)]) (unless (eq? new markup) (when markup (fprintf (choose-port markup) "\\raw{\\end~s{}}" markup)) (when new (fprintf (choose-port new) "\\raw{\\~s{}}" new))) (let ([p (choose-port new)]) (if (eq? p repl) (display entity p) (col-display entity p))) (loop (cdr ls) new))))))] [tag-get-output-string () (let ([op (open-output-string)]) (let loop ([ls (reverse buffer)] [markup #f]) (if (null? ls) (begin (set! buffer '()) (when markup (fprintf op "\\raw{\\end~s{}}" markup)) (get-output-string op)) (let ([x (car ls)]) (let ([new (tag-markup x)] [entity (tag-entity x)]) (unless (eq? new markup) (when markup (fprintf op "\\raw{\\end~s{}}" markup)) (when new (fprintf op "\\raw{\\~s{}}" new))) (display entity op) (loop (cdr ls) new))))))] [delete-last-line-if-unmarked () ; clean up the "\n> \n" at the end of the transcript ; by deleting everything from the last newline upto, but ; not including the second newline. (let trim ([ls buffer] [n? #f]) (if (or (null? ls) (tag-markup (car ls))) (set! buffer ls) (let foo ([first (tag-entity (car ls))]) (cond [(string? first) (let scan ([i (- (string-length first) 1)] [n? n?]) (cond [(fx< i 0) (trim (cdr ls) n?)] [(char=? (string-ref first i) #\newline) (if (not n?) (scan (fx- i 1) #t) (begin (set-tag-entity! (car ls) (substring first 0 i)) (set! buffer ls)))] [else (scan (fx- i 1) n?)]))] [(char=? first #\newline) (if (not n?) (trim (cdr ls) #t) (set! buffer (cdr ls)))] [else (trim (cdr ls) n?)])))) ; trim the last newline at the end of the transcript ; since transcript env will insert some vspace of its own (unless (null? buffer) (let ([first (car buffer)]) (when (eqv? (tag-entity first) #\newline) (set! buffer (cdr buffer)))))] [else (errorf 'tag-port "operation ~s not handled" msg)])) (make-input/output-port handler "" "")))) (define make-markup-port (lambda (tag-p imarkup omarkup) (define (handler msg . args) (record-case (cons msg args) [block-read (p str cnt) (critical-section (let ([c (peek-char p)]) (if (eof-object? c) c (if (= cnt 0) 0 (begin (read-char p) (string-set! str 0 c) 1)))))] [char-ready? (p) (char-ready? tag-p)] [clear-input-port (p) (clear-input-port tag-p)] [clear-output-port (p) (clear-output-port tag-p)] [close-port (p) (mark-port-closed! p) (close-port tag-p)] [flush-output-port (p) (flush-output-port tag-p)] [file-position (p . pos) (if (null? pos) (most-negative-fixnum) (errorf 'transcript-port "cannot reposition"))] [port-name (p) "markup"] [peek-char (p) (peek-char tag-p)] [read-char (p) ((port-handler tag-p) 'tag-read-char imarkup tag-p)] [unread-char (c p) (unread-char c tag-p)] [write-char (c p) ((port-handler tag-p) 'tag-write-entity omarkup c tag-p)] [block-write (p str cnt) ((port-handler tag-p) 'tag-write-entity omarkup (substring str 0 cnt) tag-p) cnt] [else (errorf 'markup-port "operation ~s not handled" msg)])) (make-input/output-port handler "" ""))) (define scheme-transcript (P lambda (console-input labels) (let ([tp (make-tag-port (open-input-string console-input))]) (let ([normal (make-markup-port tp #f #f)] [trace (make-markup-port tp #f 'traceout)] [effect (make-markup-port tp 'transin 'transout)] [errors (make-markup-port tp #f 'transerr)] [handler (port-handler tp)]) (handler 'tag-write-entity #f "\\schemedisplay" tp) (for-each (lambda (l) (handler 'tag-write-entity #f (format "\\label{~a}" l) tp)) labels) (handler 'tag-write-entity #f "\n" tp) (parameterize ([console-input-port normal] [console-output-port normal] [console-error-port normal] [current-input-port effect] [current-output-port effect] [current-error-port effect] [trace-output-port trace]) (new-cafe (lambda (x) (with-exception-handler default-exception-handler (lambda () (eval x)))))) ; We could do this with string bashing. I modified the port. (handler 'delete-last-line-if-unmarked tp) (handler 'tag-write-entity #f "\\endschemedisplay\n" tp) (if (use-interaction-window) (let-values ([(repl interaction) (handler 'tag-get-repl-interaction-strings tp)]) (P s0 ([ip (if (not interaction) (open-input-string repl) (open-input-string (string-append "\\startrepl{}" repl "\\endrepl{}\\startinteraction{}\\schemedisplay\n" interaction "\\endschemedisplay\\endinteraction{}")))] [ips (cons ip ips)] [eofconts (cons s0 eofconts)]))) (let ([transcript (handler 'tag-get-output-string tp)]) (P s0 ([ip (open-input-string transcript)] [ips (cons ip ips)] [eofconts (cons s0 eofconts)])))))))) (define make-string-evaluator (lambda (start-mark evaluator) (P lambda () (define text-upto (let ([op (open-output-string)]) (lambda (endmark) (state-case (c (read-char ip)) [(#\\) (let ([mk (read-alpha-command ip)]) (if (eq? mk endmark) (get-output-string op) (begin (write-char #\\ op) (display mk op) (text-upto endmark))))] [(eof) (unexpected-eof (format "after \\~a" start-mark))] [else (write-char c op) (text-upto endmark)])))) (let loop ([endmark #f] [labels '()]) (state-case (c (read-char ip)) [(#\[) ;] (when endmark (input-error "expected newline after \\~a[~a]" start-mark endmark)) (unread-char c ip) (let ([ls (string->list (read-optional-arg ip))]) (when (null? ls) (input-error "empty optional argument to \\~a" start-mark)) (when (not (char=? (car ls) #\\)) (input-error "\\~a terminator must begin with \\" start-mark)) (let ([rest (cdr ls)]) (when (or (null? rest) (not (andmap char-alphabetic? (cdr ls)))) (input-error "\\~a terminator must be \\ followed by alphabetic character(s)" start-mark)) (loop (string->symbol (list->string rest)) labels)))] [(#\\) ; currently a bit sloppy on the grammar ; could require all labels one after the other ; use read-alpha-command instead of read-command to avoid ; improper handling of special characters that follow a slash (let ([cmd (read-alpha-command ip)]) (case cmd [(label) (loop endmark (cons (read-bracketed-text ip) labels))] [else (input-error "invalid command \\~s following \\~a" cmd start-mark)]))] [(#\newline) (let ([endmark (or endmark (string->symbol (string-append "end" start-mark)))]) (P evaluator () (text-upto endmark) endmark (reverse labels)))] [(#\space #\tab) (loop endmark labels)] [else (let ([txt (format "expected newline after \\~a" start-mark)]) (input-error (if endmark (string-append txt (format "[~a]" endmark)) txt)))]))))) (global-def schemeinit ; whitespace has not suppressed when we are invoked (make-string-evaluator "schemeinit" (P lambda (s endmark labels) (unless (null? labels) (input-error "what on earth do you mean putting \\label after \\schemeinit ???")) ; We could perhaps make this easier by not trying to share the ; make-string-evaluator code with \transcript and instead let ; the code simply read from the true ip instead, so that input-error ; does its job without our assistance. Unfortunately, I just thought ; of that and don't have the heart to do any more than document the ; possibility. (let ([real-abort-handler (abort-handler)]) (let ([sip (open-input-string s)]) ; nesting is not an issue. (let f () ; scan ahead to first non-whitespace character, if any (let skip-whitespace () (let ([c (peek-char sip)]) (when (and (char? c) (char-whitespace? c)) (read-char sip) (skip-whitespace)))) ; record the current file position so we adjust the true ; file-position based on the string-input-port's file position ; if we run into an error (let ([last-sip-pos (file-position sip)]) (define scout ; be prepared (lambda (thunk) (parameterize ([abort-handler (lambda args (let ([end (file-position ip)] [endmark-len (+ 1 (string-length (symbol->string endmark)))]) (file-position ip (- end endmark-len (- (string-length s) last-sip-pos)))) (parameterize ([abort-handler real-abort-handler]) (input-error "previous error occurred within \\schemeinit")))]) (thunk)))) (let ([x (scout (lambda () (read sip)))]) (unless (eof-object? x) (scout (lambda () (eval x))) (f))))))) (P s0 ())))) (global-def generated (P lambda () (let ([sop (open-output-string)]) (let loop () (state-case (c (peek-char ip)) [(#\space #\tab #\newline) (read-char ip) (loop)] [(#\\) (read-char ip) (let ([cmd (read-alpha-command ip)]) (case cmd [(endgenerated) (P s0 ([ip (open-input-string (get-output-string sop))] [ips (cons ip ips)] [eofconts (cons s0 eofconts)]))] [else (input-error "unexpected command \\~s following \\generated" cmd)]))] [else (parameterize ([current-output-port sop]) (eval (read ip))) ; should protect against errors (loop)]))))) (global-def transcript ; whitespace has not suppressed when we are invoked (make-string-evaluator "transcript" (P lambda (s endmark labels) (P scheme-transcript () s labels)))) (global-def useinteractionwindow (P lambda () (use-interaction-window #t) (P s0 ()))) (global-def enduseinteractionwindow (P lambda () (use-interaction-window #f) (P s0 ()))) (global-def interactionwindowwidth (P lambda () (let ([s (read-bracketed-text ip)]) (let ([n (string->number s)]) (unless n (errorf #f "expected numeric argument to \\interactionwindowwidth")) ; should be more clever here to make it work in bgroup ... egroup fashion (interaction-window-width n) (P s0 ()))))) ) (populate-source-directories) (command-line-case (command-line) [((keyword --help)) (usage)] [(filename* ...) (for-each go (let ([found (find-filename "scheme-prep.tex")]) (if found (cons found filename*) filename*)))]) stex-1.2.1+git20171204.g5e4f0ca/src/script.ss000066400000000000000000000741611321130544300200420ustar00rootroot00000000000000;;; script.ss ;;; ;;; Copyright (c) 2005 R. Kent Dybvig ;;; ;;; Permission is hereby granted, free of charge, to any person obtaining a ;;; copy of this software and associated documentation files (the "Software"), ;;; to deal in the Software without restriction, including without limitation ;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, ;;; and/or sell copies of the Software, and to permit persons to whom the ;;; Software is furnished to do so, subject to the following conditions: ;;; ;;; The above copyright notice and this permission notice shall be included in ;;; all copies or substantial portions of the Software. ;;; ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ;;; DEALINGS IN THE SOFTWARE. #!chezscheme (library (script) (export command-line-case run-script) (import (chezscheme)) #| (command-line-case command-line [() ]*) -> (keyword * ]) | (flags [ * ]*) | -> | $ -> | ( ) | ( ) -> * * | * * ... -> | ( ) -> (optional ) | (optional ) | (optional ) -> | (+) -> -> -> -> Each must be unique. If any is not specified, it defaults to string. If any is not specified, it defaults to #f. Each is scoped outside of the command-line-case form. Command-line arguments are processed from left to right. Command-line elements must appear in the order specified by , except that each the flags in a single flags section may appear in any order and any flag may occur more than once. For kewyword and flag clauses, the value of the , if specified, is evaluated for effect. Each is scoped where each of the s is visible and each 's current value is based on the specified or implicit defaults and the arguments seen so far. If a flag occurs more than once on a command line, the final value of each corresponding is its last specified value. If is not string, the procedure string-> is applied to the string argument to cast the string argument the actual value; it should return #f if the cast fails, in which case the clause doesn't match. A string-> routine should not cause side effects since it may be called even for clauses that don't match. For flag clauses, variable ?id, where = id or = (id id1 ...), is bound to #t if the argument is specified at least once, otherwise #f. Within each , the variable usage is bound to a thunk that prints usage information. usage information is also printed if a command line cannot be parsed to fit any of the clauses. consider: * instead of one keyword, have multiple keywords ALL of which must be provided in some order. use syntax (all (keyword ...) ...), and use (some (keyword ...) ...) instead of current "flags" syntax. * add a prefix before in flags section to allow multiple occurrences of the given flag and listification of the flag arguments * option to print more verbose information when certain matches fail, for example, when a keyword or flag argument requires more additional arguments than are provided. * allowing optional arguments after keywords and flags. leads to ambiguity in some cases. Testing: scheme (import (script)) (define (exit . args) (void)) > (command-line-case '("a" "-q" "-v" "-v" "-b" "c") [((flags [-b c] [-q $ (write-char #\q)] [-v $ (write-char #\v)])) (list ?-b c)]) qvv(#t "c") > (let () (define (bar cl) (command-line-case cl [((keyword --foo (number n)) (flags [-b (number b)] [-q $ (write-char #\q)] [-v $ (write-char #\v)])) (pretty-print (list ?-b b))])) (bar '("a" "--foo" "32" "-q" "-v" "-v" "-b" "45")) (bar '("a" "--foo" "foo" "-q" "-v" "-v" "-b" "45")) (bar '("a" "--foo" "32" "-q" "-v" "-v" "-b" "b"))) qvv(#t 45) usage: a --foo n [ -b b ] [ -q ] [ -v ] usage: a --foo n [ -b b ] [ -q ] [ -v ] (define (foo cl) (define compact? #t) (define (register-boot-file x) (printf "registering boot file ~s\n" x)) (define (register-heap-file x) (printf "registering boot file ~s\n" x)) (command-line-case cl [((keyword --version)) (print-version)] [((keyword --help (number helplevel))) (printf "here's your help: ~s\n" helplevel)] [((keyword --help)) (print-help)] [((flags [(--boot -b) bootpath $ (register-boot-file bootpath)] [(--compact -c) $ (set! compact? (not compact?))] [(--heap -h) heappath $ (register-heap-file heappath)] [(--quiet -q)] [(--saveheap -s) (number level 0) savepath] [--verbose]) (flags [--]) a (optional b) (optional number c 666) (number d) ...) (let-syntax ([pr (syntax-rules () [(_ x ...) (begin (printf " ~s = ~s\n" 'x x) ...)])]) (pr ?--boot bootpath ?--compact ?--heap heappath ?--quiet ?--saveheap level savepath ?--verbose ?-- compact? a b c d))])) > (foo '("/usr/local/bin/foo" "--help" "3")) here's your help: 3 > (foo '("/usr/local/bin/foo" "aaa")) ?--boot = #f bootpath = #f ?--compact = #f ?--heap = #f heappath = #f ?--quiet = #f ?--saveheap = #f level = 0 savepath = #f ?--verbose = #f ?-- = #f compact? = #t a = "aaa" b = #f c = 666 d = () > (foo '("/usr/local/bin/foo" "aaa" "bbb")) ?--boot = #f bootpath = #f ?--compact = #f ?--heap = #f heappath = #f ?--quiet = #f ?--saveheap = #f level = 0 savepath = #f ?--verbose = #f ?-- = #f compact? = #t a = "aaa" b = "bbb" c = 666 d = () > (foo '("/usr/local/bin/foo" "aaa" "bbb" "#xccc")) ?--boot = #f bootpath = #f ?--compact = #f ?--heap = #f heappath = #f ?--quiet = #f ?--saveheap = #f level = 0 savepath = #f ?--verbose = #f ?-- = #f compact? = #t a = "aaa" b = "bbb" c = 3276 d = () > (foo '("/usr/local/bin/foo" "aaa" "bbb" "#xccc" "3" "4" "5")) ?--boot = #f bootpath = #f ?--compact = #f ?--heap = #f heappath = #f ?--quiet = #f ?--saveheap = #f level = 0 savepath = #f ?--verbose = #f ?-- = #f compact? = #t a = "aaa" b = "bbb" c = 3276 d = (3 4 5) > (foo '("/usr/local/bin/foo" "aaa" "bbb" "ccc")) usage: foo --version foo --help helplevel foo --help foo [ --boot|-b bootpath ] [ --compact|-c ] [ --heap|-h heappath ] [ --quiet|-q ] [ --saveheap|-s level savepath ] [ --verbose ] [ -- ] a [ b ] [ c ] d ... > (foo '("/usr/local/bin/foo" "aaa" "bbb" "#xccc" "3" "4" "5" "ddd")) usage: foo --version foo --help helplevel foo --help foo [ --boot|-b bootpath ] [ --compact|-c ] [ --heap|-h heappath ] [ --quiet|-q ] [ --saveheap|-s level savepath ] [ --verbose ] [ -- ] a [ b ] [ c ] d ... > (foo '("/usr/local/bin/foo" "-q" "--boot" "foo.boot" "aaa")) registering boot file "foo.boot" ?--boot = #t bootpath = "foo.boot" ?--compact = #f ?--heap = #f heappath = #f ?--quiet = #t ?--saveheap = #f level = 0 savepath = #f ?--verbose = #f ?-- = #f compact? = #t a = "aaa" b = #f c = 666 d = () > (foo '("/usr/local/bin/foo" "-q" "--boot" "foo.boot" "-b" "--heap" "-h" "foo.heap" "-s" "7" "foo7.heap" "-c" "-c" "-c" "--verbose" "aaa")) registering boot file "foo.boot" registering boot file "--heap" registering boot file "foo.heap" ?--boot = #t bootpath = "--heap" ?--compact = #t ?--heap = #t heappath = "foo.heap" ?--quiet = #t ?--saveheap = #t level = 7 savepath = "foo7.heap" ?--verbose = #t ?-- = #f compact? = #f a = "aaa" b = #f c = 666 d = () (command-line-case (cons "/usr/local/bin/foo" (command-line-arguments)) [((keyword --build ifn) (flags [--verify] [(--output -o) (string ofn "a.out")]) lib* ...) ---] [((keyword (--query -q) ifn)) ---] [((flags [(--verify -v)] [(--output -o) (string ofn "a.out")]) (string x*) ...) ---] [((flags [(--verify -v)] [(--output -o) ofn]) (flags [--]) x* ...) ---] [(x (optional integer y 0)) ---] [(x (optional integer y) x* ...) ---] ) |# (define-syntax command-line-case (lambda (x) ;; Internal representation: ;; ({ keyword | flags }* reqarg* optarg* restarg?) ;; kwd's are strings ;; vars's are syntax objects (identifiers) ;; defaults are syntax objects ;; actions are syntax objects or #f (define-record pkeyword ((immutable kwd*) (immutable reqarg*) (immutable action))) (define-record pflags ((immutable flag*))) (define-record pflag ((immutable kwd*) (immutable ?var) (immutable optarg*) (immutable action))) (define-record preqarg ((immutable type) (immutable var))) (define-record poptarg ((immutable type) (immutable var) (immutable default))) (define-record prestarg ((immutable reqarg))) (define-record pend ()) (module (parse-cmdspec) (define (parse-cmdspec cmdspec) (unless (syntax-case cmdspec () [(x ...) #t] [_ #f]) (syntax-error cmdspec "improper argument declaration list")) (let parse-cmdspec ([cmdspec cmdspec]) (syntax-case cmdspec (keyword flags $) [((keyword kwd reqarg ... $ actionexpr) . cmdspec) (cons (make-pkeyword (map id->string (parse-kwd #'kwd)) (map parse-reqarg (syntax->list #'(reqarg ...))) #'actionexpr) (parse-cmdspec #'cmdspec))] [((keyword kwd reqarg ...) . cmdspec) (cons (make-pkeyword (map id->string (parse-kwd #'kwd)) (map parse-reqarg (syntax->list #'(reqarg ...))) #f) (parse-cmdspec #'cmdspec))] [((keyword . ignore1) . ignore2) (syntax-error (syntax-case cmdspec () [(x . r) #'x]) "invalid keyword declaration")] [((flags flagdecl ...) . cmdspec) (cons (make-pflags (map (lambda (flagdecl) (syntax-case flagdecl ($) [(kwd flagarg ... $ actionexpr) (let ([kwd* (parse-kwd #'kwd)]) (make-pflag (map id->string kwd*) (make-?var (car kwd*)) (map parse-flagarg (syntax->list #'(flagarg ...))) #'actionexpr))] [(kwd flagarg ...) (let ([kwd* (parse-kwd #'kwd)]) (make-pflag (map id->string kwd*) (make-?var (car kwd*)) (map parse-flagarg (syntax->list #'(flagarg ...))) #f))] [_ (syntax-error flagdecl "invalid flag declaration")])) (syntax->list #'(flagdecl ...)))) (parse-cmdspec #'cmdspec))] [((flags . ignore1) . ignore2) (syntax-error (syntax-case cmdspec () [(x . r) #'x]) "invalid flags declaration")] [argspec (parse-argspec #'argspec)]))) (define (parse-kwd kwd) (syntax-case kwd () [id (identifier? #'id) (list #'id)] [(id1 id2 ...) (syntax->list #'(id1 id2 ...))] [_ (syntax-error kwd "invalid kwd specifier")])) (define (parse-argspec argspec) (define (dots? x) (and (identifier? x) (literal-identifier=? x #'(... ...)))) (syntax-case argspec () [() (list (make-pend))] [(reqarg dots) (dots? #'dots) (list (make-prestarg (parse-reqarg #'reqarg)))] [(arg . argspec) (cons (parse-arg #'arg) (parse-argspec #'argspec))] [(x . r) (syntax-error #'x "invalid argument declaration")])) (define (parse-arg arg) (syntax-case arg (optional) [(optional . stuff) (parse-optarg arg)] [_ (parse-reqarg arg)])) (define (parse-reqarg reqarg) (syntax-case reqarg () [var (identifier? #'var) (make-preqarg #'string #'var)] [(type var) (and (identifier? #'type) (identifier? #'var)) (make-preqarg #'type #'var)] [x (syntax-error reqarg "invalid argument specifier")])) (define (parse-optarg optarg) (syntax-case optarg (optional) [(optional var) (identifier? #'var) (make-poptarg #'string #'var #'#f)] [(optional type var) (and (identifier? #'type) (identifier? #'var)) (make-poptarg #'type #'var #'#f)] [(optional type var default) (and (identifier? #'type) (identifier? #'var)) (make-poptarg #'type #'var #'default)] [x (syntax-error optarg "invalid optional argument specifier")])) (define (parse-flagarg flagarg) (syntax-case flagarg () [var (identifier? #'var) (make-poptarg #'string #'var #'#f)] [(type var) (and (identifier? #'type) (identifier? #'var)) (make-poptarg #'type #'var #'#f)] [(type var default) (and (identifier? #'type) (identifier? #'var)) (make-poptarg #'type #'var #'default)] [x (syntax-error flagarg "invalid flag argument specifier")])) (define (id->string x) (symbol->string (syntax-object->datum x))) (define (make-?var x) (datum->syntax-object x (string->symbol (format "?~a" (id->string x)))))) (module (usage-printer) (define (usage-printer cmdspec+) #`(lambda (cl) (let ([who (path-last (car cl))]) #,(usage-cmdspec "usage:" (car cmdspec+)) #,@(map (lambda (cmdspec) (usage-cmdspec " " cmdspec)) (cdr cmdspec+))))) (define (usage-cmdspec leader cmdspec) (define cmdspec-printer (lambda (s*) #`(printf #,(format "~a ~~a~~a\n" leader) who #,(apply string-append s*)))) (let-values ([(s* flag**) (usage-cmdspec-helper #t cmdspec)]) (assert (null? flag**)) (if (< (apply + (string-length leader) (map string-length s*)) 80) (cmdspec-printer s*) (let-values ([(s* flag**) (usage-cmdspec-helper #f cmdspec)]) (fold-left (lambda (expr flag*) (let ([flag-header (car flag*)] [flag* (cdr flag*)]) #`(begin #,expr (display-string #,(format " where each ~a is one of:\n~{ ~a\n~}" flag-header (map (lambda (kwd* optarg*) (format " ~a~{~a~}" (usage-kwd* kwd*) (map usage-optarg optarg*))) (map pflag-kwd* flag*) (map pflag-optarg* flag*))))))) (cmdspec-printer s*) flag**))))) (define (usage-cmdspec-helper inline-flags? cmdspec) (let loop ([cmdspec cmdspec] [rs* '()] [rflag** '()] [flagsno (and (not inline-flags?) (cond [(memp pflags? cmdspec) => (lambda (cmdspec) (memp pflags? (cdr cmdspec)))] [else #f]) 1)]) (if (null? cmdspec) (values (reverse rs*) (reverse rflag**)) (let ([x (car cmdspec)]) (if (pflags? x) (if inline-flags? (loop (cdr cmdspec) (cons (let ([flag* (pflags-flag* x)]) (format "~{~a~}" (map (lambda (kwd* optarg*) (format " [ ~a~{~a~} ]" (usage-kwd* kwd*) (map usage-optarg optarg*))) (map pflag-kwd* flag*) (map pflag-optarg* flag*)))) rs*) rflag** flagsno) (let ([flag-header (if flagsno (format "flag~s" flagsno) "flag")]) (loop (cdr cmdspec) (cons (format " ~a ..." flag-header) rs*) (cons (cons flag-header (pflags-flag* x)) rflag**) (and flagsno (+ flagsno 1))))) (loop (cdr cmdspec) (cons (cond [(pkeyword? x) (format " ~a~{~a~}" (usage-kwd* (pkeyword-kwd* x)) (map usage-reqarg (pkeyword-reqarg* x)))] [(preqarg? x) (usage-reqarg x)] [(poptarg? x) (format " [~a ]" (usage-optarg x))] [(prestarg? x) (format "~a ..." (usage-reqarg (prestarg-reqarg x)))] [(pend? x) ""] [else (errorf 'usage-cmdspec "unrecognized cmdspec ~s" x)]) rs*) rflag** flagsno)))))) (define (usage-kwd* kwd*) (format "~a~{|~a~}" (car kwd*) (cdr kwd*))) (define (usage-reqarg x) (format " ~a" (syntax-object->datum (preqarg-var x)))) (define (usage-optarg x) (format " ~a" (syntax-object->datum (poptarg-var x))))) (define (xmap p ls tail) (if (null? ls) tail (p (car ls) (xmap p (cdr ls) tail)))) (module (findvars) (define (findvars cmdspec) (findvars-cmdspec cmdspec '())) (define (findvars-cmdspec cmdspec tail) (xmap (lambda (x tail) (cond [(pkeyword? x) (xmap findvars-reqarg (pkeyword-reqarg* x) tail)] [(pflags? x) (xmap (lambda (flag tail) (cons (pflag-?var flag) (xmap findvars-optarg (pflag-optarg* flag) tail))) (pflags-flag* x) tail)] [(preqarg? x) (findvars-reqarg x tail)] [(poptarg? x) (findvars-optarg x tail)] [(prestarg? x) (findvars-reqarg (prestarg-reqarg x) tail)] [(pend? x) tail] [else (errorf 'findvars-cmdspec "unrecognized cmdspec ~s" x)])) cmdspec tail)) (define (findvars-reqarg x tail) (cons (preqarg-var x) tail)) (define (findvars-optarg x tail) (cons (poptarg-var x) tail))) (module (finddefaults) (define (finddefaults cmdspec) (finddefaults-cmdspec cmdspec '())) (define (finddefaults-cmdspec cmdspec tail) (xmap (lambda (x tail) (cond [(pkeyword? x) (xmap finddefaults-reqarg (pkeyword-reqarg* x) tail)] [(pflags? x) (xmap (lambda (flag tail) (cons #'#f (xmap finddefaults-optarg (pflag-optarg* flag) tail))) (pflags-flag* x) tail)] [(preqarg? x) (finddefaults-reqarg x tail)] [(poptarg? x) (finddefaults-optarg x tail)] [(prestarg? x) (cons #''() tail)] [(pend? x) tail] [else (errorf 'finddefaults-cmdspec "unrecognized cmdspec ~s" x)])) cmdspec tail)) (define (finddefaults-reqarg x tail) (cons #'(void) tail)) (define (finddefaults-optarg x tail) (cons (poptarg-default x) tail))) (module (build-clause) (define (type->converter x) (if (and x (not (literal-identifier=? x #'string))) (datum->syntax-object x (string->symbol (format "string->~a" (syntax-object->datum x)))) #'values)) (define (build-clause-body var* cmdspec body) (with-syntax ([(var ...) var*]) (let ([x (car cmdspec)]) (cond [(pkeyword? x) (let ([reqarg* (pkeyword-reqarg* x)]) (with-syntax ([(kwd ...) (pkeyword-kwd* x)] [(reqvar ...) (map preqarg-var reqarg*)] [(convert ...) (map type->converter (map preqarg-type reqarg*))] [action (or (pkeyword-action x) #'(#2%void))] [finish (build-clause-body var* (cdr cmdspec) body)] [n (length reqarg*)]) #'(cond [(and (> (length cl) n) (member (car cl) '(kwd ...))) (let ([cl (cdr cl)]) (apply (lambda (reqvar ... . ignore) ; performs unnecessary tests if convert ; is values; doesn't shortcut out as ; soon as one convert returns false (let ([reqvar (convert reqvar)] ...) (if (and reqvar ...) (let ([cl (list-tail cl n)] [act! (lambda () (act!) action)]) finish) (next orig-cl)))) cl))] [else (next orig-cl)])))] [(pflags? x) (let* ([flag* (pflags-flag* x)] [optarg** (map pflag-optarg* flag*)]) (with-syntax ([((kwd ...) ...) (map pflag-kwd* flag*)] [(?var ...) (map pflag-?var flag*)] [((optvar ...) ...) (map (lambda (optarg*) (map poptarg-var optarg*)) optarg**)] [((convert ...) ...) (map (lambda (optarg*) (map type->converter (map poptarg-type optarg*))) optarg**)] [(action ...) (map (lambda (flag) (or (pflag-action flag) #'(#2%void))) flag*)] [finish (build-clause-body var* (cdr cmdspec) body)] [(n ...) (map length optarg**)]) #'(let ([t (lambda (cl act! ?var ... optvar ... ...) finish)]) (let f ([cl cl] [act! act!] [?var ?var] ... [optvar optvar] ... ...) (cond [(null? cl) (t cl act! ?var ... optvar ... ...)] [(and (> (length cl) n) (member (car cl) '(kwd ...))) (let ([cl (cdr cl)]) (apply (lambda (optvar ... . ignore) ; performs unnecessary tests if convert ; is values; doesn't shortcut out as ; soon as one convert returns false (let ([optvar (convert optvar)] ...) (if (and optvar ...) (let ([?var #t]) (f (list-tail cl n) (lambda () (act!) action) ?var ... optvar ... ...)) (next orig-cl)))) cl))] ... [else (t cl act! ?var ... optvar ... ...)])))))] [(preqarg? x) (with-syntax ([reqvar (preqarg-var x)] [convert (type->converter (preqarg-type x))] [finish (build-clause-body var* (cdr cmdspec) body)]) #'(cond ; performs unnecessary test if convert is values [(and (not (null? cl)) (convert (car cl))) => (lambda (reqvar) (let ([cl (cdr cl)]) finish))] [else (next orig-cl)]))] [(poptarg? x) (with-syntax ([optvar (poptarg-var x)] [convert (type->converter (poptarg-type x))] [finish (build-clause-body var* (cdr cmdspec) body)]) #'(let ([t (lambda (optvar cl) finish)]) (cond [(null? cl) (t optvar cl)] ; performs unnecessary test if convert is values [(convert (car cl)) => (lambda (optvar) (t optvar (cdr cl)))] [else (next orig-cl)])))] [(prestarg? x) (let ([reqarg (prestarg-reqarg x)]) (with-syntax ([restvar (preqarg-var reqarg)] [convert (type->converter (preqarg-type reqarg))] [body body]) #'(let f ([cl cl] [rrestvar '()]) (cond [(null? cl) (let ([restvar (reverse rrestvar)]) (let () (act!) . body))] ; performs unnecessary test if convert is values [(convert (car cl)) => (lambda (x) (f (cdr cl) (cons x rrestvar)))] [else (next orig-cl)]))))] [(pend? x) (with-syntax ([body body]) #'(if (null? cl) (let () (act!) . body) (next orig-cl)))] [else (errorf 'build-clause-body "unrecognized cmdspec ~s" x)])))) (define (build-clause cmdspec body next-expr) (let ([var* (findvars cmdspec)]) (with-syntax ([next-expr next-expr] [(var ...) var*] [(default ...) (finddefaults cmdspec)] [clause-body (build-clause-body var* cmdspec body)]) #'(let ([next next-expr]) (lambda (orig-cl) (let ([cl (cdr orig-cl)] [act! #2%void] [var default] ...) clause-body))))))) (syntax-case x () [(k clexpr [cmdspeca b1a b2a ...] [cmdspec b1 b2 ...] ...) (let ([all-cmdspec* (map parse-cmdspec (cons #'cmdspeca (syntax->list #'(cmdspec ...))))] [body* #'((b1a b2a ...) (b1 b2 ...) ...)]) (with-implicit (k usage) #`(let ([usage-proc #,(usage-printer all-cmdspec*)] [cl clexpr]) (let ([usage (lambda () (usage-proc cl))]) #,(with-syntax ([p (let f ([cmdspec* all-cmdspec*] [body* body*]) (if (null? cmdspec*) #'(lambda (cl) (usage-proc cl) (exit 1)) (build-clause (car cmdspec*) (car body*) (f (cdr cmdspec*) (cdr body*)))))]) #'(p cl))))))]))) ;;; (run-script script arg ...) runs named script in same process (define (run-script script . arg*) (command-line-arguments arg*) (load script)) )