feat: 9.5.9

This commit is contained in:
tmtt 2022-07-29 15:12:07 +02:00
parent cb1753732b
commit 35f43a7909
1084 changed files with 558985 additions and 0 deletions

3
stex/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
*~
.*.sw?
.sw?

58
stex/Makefile Normal file
View file

@ -0,0 +1,58 @@
VERSION=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

35
stex/Makefile.template Normal file
View file

@ -0,0 +1,35 @@
VERSION=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:

150
stex/Mf-stex Normal file
View file

@ -0,0 +1,150 @@
# 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)

39
stex/ReadMe Normal file
View file

@ -0,0 +1,39 @@
stex: 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.

32
stex/doc/Makefile Normal file
View file

@ -0,0 +1,32 @@
# 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:

35
stex/doc/stex.css Normal file
View file

@ -0,0 +1,35 @@
BODY {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}

967
stex/doc/stex.html Normal file
View file

@ -0,0 +1,967 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd"><!-- DO NOT EDIT THIS FILE-->
<!-- Edit the .tex version instead-->
<html>
<head>
<title>Introduction to stex</title>
<link href="stex.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>Introduction to stex</h1>
<h2>R. Kent Dybvig and Oscar Waddell</h2>
<h3>April 2016</h3>
<p>
<table cellpadding=0 cellspacing=0>
<tr><td align="right"><b>1.&nbsp;</b><td><b><a class=plain href="./stex.html#g0">Overview</a></b></td></tr>
<tr><td align="right"><b>2.&nbsp;</b><td><b><a class=plain href="./stex.html#g1">Installation</a></b></td></tr>
<tr><td align="right"><b>3.&nbsp;</b><td><b><a class=plain href="./stex.html#g2">Usage notes</a></b></td></tr>
<tr><td align="right"><b>4.&nbsp;</b><td><b><a class=plain href="./stex.html#g3">Basic stex commands</a></b></td></tr>
<tr><td></td><td><table cellpadding=0 cellspacing=0>
<tr><td><b>4.1.&nbsp;</b></td><td><b><a class=plain href="./stex.html#g4">Inline code</a></b></td></tr>
<tr><td><b>4.2.&nbsp;</b></td><td><b><a class=plain href="./stex.html#g5">Code displays</a></b></td></tr>
<tr><td><b>4.3.&nbsp;</b></td><td><b><a class=plain href="./stex.html#g6">Variables</a></b></td></tr>
<tr><td><b>4.4.&nbsp;</b></td><td><b><a class=plain href="./stex.html#g7">Raw text in code</a></b></td></tr>
<tr><td><b>4.5.&nbsp;</b></td><td><b><a class=plain href="./stex.html#g8">Generated output</a></b></td></tr>
<tr><td><b>4.6.&nbsp;</b></td><td><b><a class=plain href="./stex.html#g9">Verbatim Scheme displays</a></b></td></tr>
</table></td></tr>
<tr><td align="right"><b>5.&nbsp;</b><td><b><a class=plain href="./stex.html#g10">Scheme transcripts</a></b></td></tr>
<tr><td></td><td><table cellpadding=0 cellspacing=0>
<tr><td><b>5.1.&nbsp;</b></td><td><b><a class=plain href="./stex.html#g11">Automatic transcript generation</a></b></td></tr>
<tr><td><b>5.2.&nbsp;</b></td><td><b><a class=plain href="./stex.html#g12">Loading initialization code</a></b></td></tr>
</table></td></tr>
<tr><td align="right"><b>6.&nbsp;</b><td><b><a class=plain href="./stex.html#g13">html-prep support for the <tt>tabular</tt> environment</a></b></td></tr>
</table>
<p>
<p>
<a name="g0"></a>
<h3><a name="./stex:h0"></a>1. Overview</h3>
<p>
The <i>stex</i> 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 <b>scheme-prep</b> and <b>html-prep</b>.
<b>scheme-prep</b> performs a conversion from "stex"-formatted files
into latex-formatted files, while <b>html-prep</b> converts (some)
latex-formatted files into html-formatted files.
<p>
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.
<p>
The subset of latex-formatted files <b>html-prep</b> 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
(<i>The Scheme Programming Language</i>, 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.
<p>
<a name="g1"></a>
<h3><a name="./stex:h1"></a>2. Installation</h3>
<p>
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.
<p>
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:
<p>
<p><tt>make&nbsp;BIN=<i>bindir</i></tt>
<p>where <tt><i>bindir</i></tt> is the directory where make will find the scheme or
petite executables.
<p>
This will create a subdirectory, named for the installed Chez Scheme
machine type, containing binary versions of the programs.
<p>
You can also use "make install" to make stex available for other users.
<p>
<p><tt>sudo&nbsp;make&nbsp;install&nbsp;BIN=<i>bindir</i>&nbsp;LIB=<i>libdir</i></tt>
<p>where <tt><i>bindir</i></tt> is as described above, and <tt><i>libdir</i></tt> is the
directory where the stex library directory should be installed.
<p>
<a name="g2"></a>
<h3><a name="./stex:h2"></a>3. Usage notes</h3>
<p>
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.
<p>
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 <tt>x&nbsp;=&nbsp;stex</tt>, to reflect the name
of your document.
<p>
The make is orchestrated by Mf-stex, which knows how to run
<b>scheme-prep</b>, <b>html-prep</b>, <b>pdflatex</b> (multiple
times), and various other commands to produce both pdf and html versions
of the stex document.
<p>
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.
<p>
<a name="g3"></a>
<h3><a name="./stex:h3"></a>4. Basic stex commands</h3>
<p>
<a name="g4"></a>
<h4><a name="./stex:h4"></a>4.1. Inline code</h4>
<p>
An stex document includes inline Scheme (or other) code via the
<tt>\scheme</tt> command, e.g.:
<p>
<blockquote>
<pre>
When called with two arguments, \scheme{cons} creates a pair of the two
arguments, e.g., \scheme{(cons 3 4)} produces \scheme{(3 . 4)}.
</pre>
<p>
</blockquote>
<p>
produces:
<p>
<blockquote>
When called with two arguments, <tt>cons</tt> creates a pair of the two
arguments, e.g., <tt>(cons&nbsp;3&nbsp;4)</tt> produces <tt>(3&nbsp;.&nbsp;4)</tt>.
</blockquote>
<p>
<a name="g5"></a>
<h4><a name="./stex:h5"></a>4.2. Code displays</h4>
<p>
An stex document includes out-of-line Scheme (or other) code via
<tt>\schemedisplay</tt> and <tt>\endschemedisplay</tt>, e.g.:
<p>
<blockquote>
<pre>
\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
</pre>
<p>
</blockquote>
<p>
produces:
<p>
<blockquote>
<p><tt>(define&nbsp;fact<br>
&nbsp;&nbsp;(lambda&nbsp;(x)<br>
&nbsp;&nbsp;&nbsp;&nbsp;"a&nbsp;light&nbsp;year&nbsp;is&nbsp;a&nbsp;measure&nbsp;of&nbsp;distance"))
<br>
<br>
(define&nbsp;fib<br>
&nbsp;&nbsp;(lambda&nbsp;(x)<br>
&nbsp;&nbsp;&nbsp;&nbsp;"a&nbsp;light&nbsp;year&nbsp;is&nbsp;a&nbsp;measure&nbsp;of&nbsp;time"))</tt>
<p></blockquote>
<p>
Within a Scheme display, <tt>;=&gt;</tt> is converted into a double right arrow
(<img src="math/stex/0.gif" alt="<graphic>">), <tt>;-&gt;</tt> into a single right arrow (<img src="math/stex/1.gif" alt="<graphic>">), and
<tt>;==</tt> into a phantom of the same size.
This is useful for showing what a piece of code translates or evaluates to,
e.g.:
<p>
<blockquote>
<pre>
A \scheme{let} expression expands into a call to a \scheme{lambda}
expression, e.g.:
\schemedisplay
(let ([a 17]) ;-&gt; ((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]) ;=&gt; 17
(+ a a))
\endschemedisplay
</pre>
<p>
</blockquote>
<p>
produces
<p>
<blockquote>
A <tt>let</tt> expression expands into a call to a <tt>lambda</tt>
expression, e.g.:
<p><tt>(let&nbsp;([a&nbsp;17])&nbsp;<img src="math/stex/1.gif" alt="<graphic>">&nbsp;((lambda&nbsp;(a)&nbsp;(+&nbsp;a&nbsp;a))<br>
&nbsp;&nbsp;(+&nbsp;a&nbsp;a))&nbsp;&nbsp;&nbsp;&nbsp;<img src="gifs/ghostRightarrow.gif">&nbsp;&nbsp;17)</tt>
<p>A <tt>let</tt> 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.:
<p><tt>(let&nbsp;([a&nbsp;17])&nbsp;<img src="math/stex/0.gif" alt="<graphic>">&nbsp;17<br>
&nbsp;&nbsp;(+&nbsp;a&nbsp;a))</tt>
<p></blockquote>
<p>
<a name="g6"></a>
<h4><a name="./stex:h6"></a>4.3. Variables</h4>
<p>
Code can include emphasized variables via the <tt>\var</tt> command, e.g.:
<p>
<blockquote>
<pre>
\scheme{(let ([\var{x} \var{e}]) \var{body})} binds the variable \var{x} to
the value of \var{e} in \var{body}.
</pre>
<p>
</blockquote>
<p>
produces:
<p>
<blockquote>
<tt>(let&nbsp;([<i>x</i>&nbsp;<i>e</i>])&nbsp;<i>body</i>)</tt> binds the variable <tt><i>x</i></tt> to
the value of <tt><i>e</i></tt> in <tt><i>body</i></tt>.
</blockquote>
<p>
If the text within a <tt>\var</tt> form contains an underscore, the
following character or bracketed subform is converted into a subscript,
e.g., <tt>\var&#123;abc_3&#125;</tt>
produces <tt><i>abc<sub>3</sub></i></tt>, and <tt>\var&#123;7e5_16&#125;</tt>
produces <tt><i>7e5<sub>16</sub></i></tt>.
<p>
<tt>\var</tt> forms may appear within a <tt>\scheme</tt> form, within a Scheme display
formed by <tt>\schemedisplay</tt> and <tt>\endschemedisplay</tt> commands,
or by itself outside of either.
<p>
<a name="g7"></a>
<h4><a name="./stex:h7"></a>4.4. Raw text in code</h4>
<p>
Raw text can be included in code via the <tt>\raw</tt> command.
For example:
<p>
<blockquote>
<pre>
\schemedisplay
(sqrt \raw{$x$}) \is \raw{$\sqrt{x}$}.
\endschemedisplay
</pre>
<p>
</blockquote>
<p>
produces:
<p>
<blockquote>
<p><tt>(sqrt&nbsp;<i>x</i>)&nbsp;<img src="math/stex/0.gif" alt="<graphic>">&nbsp;<img src="math/stex/2.gif" alt="<graphic>">.</tt>
<p></blockquote>
<p>
<a name="g8"></a>
<h4><a name="./stex:h8"></a>4.5. Generated output</h4>
<p>
Output generated by a Scheme program can be inserted into the output via
<tt>\generated</tt> and <tt>\endgenerated</tt> commands, e.g.:
<p>
<blockquote>
<pre>
\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
</pre>
<p>
</blockquote>
<p>
produces:
<p>
<blockquote>
first five primes: 0, 1, 1, 2, 3
<p>
</blockquote>
<p>
<a name="g9"></a>
<h4><a name="./stex:h9"></a>4.6. Verbatim Scheme displays</h4>
<p>
When special features, like <tt>\var</tt> forms, need to be
suppressed within a Scheme display, a document can use
<tt>\schemeverbatim</tt> and <tt>\endschemeverbatim</tt> instead of
<tt>\schemedisplay</tt> and <tt>\endschemedisplay</tt>.
This document makes extensive use of this feature.
<p>
<a name="g10"></a>
<h3><a name="./stex:h10"></a>5. Scheme transcripts</h3>
<p>
<a name="g11"></a>
<h4><a name="./stex:h11"></a>5.1. Automatic transcript generation</h4>
<p>
The <b>scheme-prep</b> package supports a
<tt>\transcript</tt> command for automatically generating Scheme transcripts
from input supplied in the document source.
All text from the <tt>\transcript</tt> marker up to and including the
<tt>\endtranscript</tt> marker is replaced with a transcript generated
by supplying the intervening text as the input to a Scheme caf&eacute; (REPL).
If the Scheme transcript needs to contain the sequence
<tt>\endtranscript</tt>, a different terminator may be specified as an
optional argument to <tt>\transcript</tt>.
The terminator must be a backslash followed by one or more alphabetic
characters, and is specified without the backslash in the optional argument.
<p>
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 <tt>\transerr</tt>
and <tt>\endtranserr</tt>.
To modify the typesetting of user input read from the current input port
of the caf&eacute;, redefine <tt>\transin</tt> and <tt>\endtransin</tt>.
To modify the typesetting of program output written to the current
output port of new caf&eacute;, redefine <tt>\transout</tt> and
<tt>\endtransout</tt>.
<p>
For example, the following:
<p>
<blockquote>
<pre>
\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
</pre>
<p>
</blockquote>
<p>
produces:
<p>
<blockquote>
<p><tt>&gt;&nbsp;(define&nbsp;f<br>
&nbsp;&nbsp;&nbsp;&nbsp;(lambda&nbsp;(x)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;indentation&nbsp;and&nbsp;comments&nbsp;are<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(zero?&nbsp;x)&nbsp;&nbsp;&nbsp;;&nbsp;preserved&nbsp;in&nbsp;the&nbsp;transcript<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*&nbsp;x&nbsp;(f&nbsp;(-&nbsp;x&nbsp;1))))))<br>
&gt;&nbsp;(values&nbsp;f&nbsp;(f&nbsp;0)&nbsp;(f&nbsp;5)&nbsp;(f&nbsp;20))<br>
#&lt;procedure&nbsp;f&gt;<br>
1<br>
120<br>
2432902008176640000<br>
&gt;&nbsp;(trace&nbsp;f)<br>
(f)<br>
&gt;&nbsp;(f&nbsp;4)<br>
<font color="#0000ff">|(f&nbsp;4)<br>
|&nbsp;(f&nbsp;3)<br>
|&nbsp;|(f&nbsp;2)<br>
|&nbsp;|&nbsp;(f&nbsp;1)<br>
|&nbsp;|&nbsp;|(f&nbsp;0)<br>
|&nbsp;|&nbsp;|1<br>
|&nbsp;|&nbsp;1<br>
|&nbsp;|2<br>
|&nbsp;6<br>
|24<br>
</font>24</tt>
<p></blockquote>
<p>
The following example shows how to specify a different transcript
terminator and shows the default formatting imposed by <tt>\transerr</tt>,
<tt>\transin</tt>, and <tt>\transout</tt>.
<p>
<blockquote>
<pre>
\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
</pre>
<p>
</blockquote>
<p>
produces:
<p>
<blockquote>
<p><tt>&gt;&nbsp;#e4.5<br>
9/2<br>
&gt;&nbsp;(begin&nbsp;(display&nbsp;"Enter&nbsp;a&nbsp;character:&nbsp;")&nbsp;(read-char))<font color="#ff0000"><br>
</font><font color="#0000ff">Enter&nbsp;a&nbsp;character:&nbsp;</font>#\newline<br>
&gt;&nbsp;(begin&nbsp;(display&nbsp;"Enter&nbsp;a&nbsp;character:&nbsp;")&nbsp;(read-char))<font color="#ff0000">Z</font><br>
<font color="#0000ff">Enter&nbsp;a&nbsp;character:&nbsp;</font>#\Z<br>
&gt;&nbsp;(begin&nbsp;(clear-input-port)&nbsp;(display&nbsp;"Enter&nbsp;a&nbsp;character:&nbsp;")&nbsp;(read-char))<br>
<font color="#0000ff">Enter&nbsp;a&nbsp;character:&nbsp;</font><font color="#ff0000">Z</font><br>
#\Z<br>
&gt;&nbsp;(list&nbsp;(read-char)&nbsp;(read-char)&nbsp;(read-char))<font color="#ff0000">abc</font>&nbsp;def<br>
(#\b&nbsp;#\c&nbsp;#\a)<br>
&gt;&nbsp;<br>
Exception:&nbsp;variable&nbsp;def&nbsp;is&nbsp;not&nbsp;bound<br>
Type&nbsp;(debug)&nbsp;to&nbsp;enter&nbsp;the&nbsp;debugger.<br>
&gt;&nbsp;(define&nbsp;silly-repl<br>
&nbsp;&nbsp;&nbsp;&nbsp;(lambda&nbsp;(prompt)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(display&nbsp;prompt)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;([x&nbsp;(read)])<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(unless&nbsp;(eof-object?&nbsp;x)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;([result&nbsp;(eval&nbsp;x)])<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(unless&nbsp;(eq?&nbsp;result&nbsp;(void))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(pretty-print&nbsp;result))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(silly-repl&nbsp;prompt))))))<br>
&gt;&nbsp;(silly-repl&nbsp;"Enter&nbsp;a&nbsp;Scheme&nbsp;expression:&nbsp;")<font color="#ff0000"><br>
</font><font color="#0000ff">Enter&nbsp;a&nbsp;Scheme&nbsp;expression:&nbsp;</font><font color="#ff0000">(list&nbsp;1<br>
</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br>
</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3)<br>
</font><font color="#0000ff">(1&nbsp;2&nbsp;3)<br>
Enter&nbsp;a&nbsp;Scheme&nbsp;expression:&nbsp;</font><font color="#ff0000">(silly-repl&nbsp;"Now&nbsp;what?&nbsp;")<br>
</font><font color="#0000ff">Now&nbsp;what?&nbsp;</font><font color="#ff0000">(define&nbsp;interview<br>
</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">&nbsp;&nbsp;(lambda&nbsp;()<br>
</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">&nbsp;&nbsp;&nbsp;&nbsp;(let*&nbsp;([fname&nbsp;(begin&nbsp;(display&nbsp;"First&nbsp;name:&nbsp;")&nbsp;(read))]<br>
</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[lname&nbsp;(begin&nbsp;(display&nbsp;"Last&nbsp;name:&nbsp;")&nbsp;(read))])<br>
</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff0000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(printf&nbsp;"Hello&nbsp;~a&nbsp;~a!~%"&nbsp;fname&nbsp;lname))))<br>
</font><font color="#0000ff">Now&nbsp;what?&nbsp;</font><font color="#ff0000">(interview)<br>
</font><font color="#0000ff">First&nbsp;name:&nbsp;</font><font color="#ff0000">john<br>
</font><font color="#0000ff">Last&nbsp;name:&nbsp;</font><font color="#ff0000">&nbsp;&nbsp;doe<br>
</font><font color="#0000ff">Hello&nbsp;john&nbsp;doe!<br>
Now&nbsp;what?&nbsp;</font><font color="#ff0000">#!eof<br>
</font><font color="#0000ff">Enter&nbsp;a&nbsp;Scheme&nbsp;expression:&nbsp;</font><font color="#ff0000">(printf&nbsp;"good&nbsp;to&nbsp;be&nbsp;back~%")<br>
</font><font color="#0000ff">good&nbsp;to&nbsp;be&nbsp;back<br>
Enter&nbsp;a&nbsp;Scheme&nbsp;expression:&nbsp;</font><font color="#ff0000">#!eof</font></tt>
<p></blockquote>
<p>
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:
<p>
<blockquote>
<pre>
\transcript
(begin (display "&gt; \n") (exit))
\endtranscript
</pre>
<p>
</blockquote>
<p>
should leave the apparent prompt alone since it is generated as program
output.
<p>
<blockquote>
<p><tt>&gt;&nbsp;(begin&nbsp;(display&nbsp;"&gt;&nbsp;\n")&nbsp;(exit))<br>
<font color="#0000ff">&gt;&nbsp;<br>
</font></tt>
<p></blockquote>
<p>
Prompt suppression works even with
changes to <tt>waiter-prompt-string</tt>.
For example:
<p>
<blockquote>
<pre>
\transcript
(waiter-prompt-string "antelope? ")
"no thanks"
\endtranscript
</pre>
<p>
</blockquote>
<p>
produces no trailing "antelope? " prompt:
<p>
<blockquote>
<p><tt>&gt;&nbsp;(waiter-prompt-string&nbsp;"antelope?&nbsp;")<br>
antelope?&nbsp;&nbsp;"no&nbsp;thanks"<br>
"no&nbsp;thanks"</tt>
<p></blockquote>
<p>
<a name="g12"></a>
<h4><a name="./stex:h12"></a>5.2. Loading initialization code</h4>
<p>
The <tt>stex</tt> commands <tt>\schemeinit</tt> and <tt>\endschemeinit</tt>
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 <tt>\schemeinit</tt> and a
transcript showing how the solutions behave can be generated using the
<tt>\transcript</tt> command.
<p>
For example, the following text:
<p>
<blockquote>
<pre>
\schemeinit
(waiter-prompt-string "&gt;") ; 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
</pre>
<p>
</blockquote>
<p>
produces the output shown below.
<p>
<blockquote>
<p>
<i>The <tt>compute-length</tt> procedure behaves as follows:</i>
<p><tt>&gt;&nbsp;(compute-length&nbsp;'())<br>
0<br>
&gt;&nbsp;(compute-length&nbsp;'(a&nbsp;b&nbsp;c))<br>
3<br>
&gt;&nbsp;(compute-length&nbsp;"abcd")<br>
4<br>
&gt;&nbsp;(compute-length&nbsp;(vector&nbsp;1&nbsp;2&nbsp;3&nbsp;4&nbsp;5&nbsp;6))<br>
6<br>
&gt;&nbsp;(compute-length&nbsp;compute-length)
<br>
<br>
Exception&nbsp;in&nbsp;compute-length:&nbsp;cannot&nbsp;handle&nbsp;#&lt;procedure&nbsp;compute-length&gt;<br>
Type&nbsp;(debug)&nbsp;to&nbsp;enter&nbsp;the&nbsp;debugger.</tt>
<p></blockquote>
<p>
the last line of input intentionally causes an error, which is
displayed just as it would be displayed in a caf&eacute;.
<p>
<a name="g13"></a>
<h3><a name="./stex:h13"></a>6. html-prep support for the <tt>tabular</tt> environment</h3>
<p>
Support for tables comes with a few caveats:
<p>
<ol>
<a name="g14"></a><li><tt>@&#123;&#125;</tt> directives within <tt>tabular</tt>
column specifiers are flat-out ignored for the time being.
<a name="g15"></a><li><tt>|</tt> directives within <tt>tabular</tt>
column specifiers are essentially ignored. Their only effect is
to globally enable borders for the entire HTML table.
<a name="g16"></a><li><tt>\hrule</tt> and <tt>\cline</tt> are not yet implemented.
<a name="g17"></a><li>no warranty is expressed or implied.
</ol>
<p>
<p>
The following code:
<p>
<blockquote>
<pre>
\begin{tabular}{rcl|r}
y &amp;=&amp; f(x) &amp; without loss of generality \\
z &amp; \multicolumn{2}{r}{whee} &amp; this is fun? \\
\multicolumn{4}{c}{
\begin{tabular}{cc}
1 &amp; 2 \\
3 &amp; 4
\end{tabular}
} \\
a &amp; b &amp; c &amp; d \\
12345 &amp; z &amp; \multicolumn{2}{l}{\scheme{(define~x~"foo")}}
\end{tabular}
</pre>
</blockquote>
<p>
generates this table:
<p>
<blockquote>
<TABLE border="1"><TR><TD nowrap align="right">
y </TD><TD nowrap align="center">=</TD><TD nowrap align="left"> f(x) </TD><TD nowrap align="right"> without loss of generality </TD></TR><TR><TD nowrap align="right">
z </TD><TD nowrap colspan="2" align="right"> whee </TD><TD nowrap align="left"> this is fun? </TD></TR><TR><TD nowrap colspan="4" align="center">
<TABLE><TR><TD nowrap align="center">
1 </TD><TD nowrap align="center"> 2 </TD></TR><TR><TD nowrap align="center">
3 </TD><TD nowrap align="center"> 4
</TD></TR></TABLE>
</TD></TR><TR><TD nowrap align="right">
a </TD><TD nowrap align="center"> b </TD><TD nowrap align="left"> c </TD><TD nowrap align="right"> d </TD></TR><TR><TD nowrap align="right">
12345 </TD><TD nowrap align="center"> z </TD><TD nowrap colspan="2" align="left"> <tt>(define&nbsp;x&nbsp;"foo")</tt>
</TD></TR></TABLE>
</blockquote>
<p>
&copy;&nbsp;1998-2016 R. Kent Dybvig and Oscar Waddell</body>
</html>

BIN
stex/doc/stex.pdf Normal file

Binary file not shown.

603
stex/doc/stex.stex Normal file
View file

@ -0,0 +1,603 @@
\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}

54
stex/gifs/Makefile Normal file
View file

@ -0,0 +1,54 @@
gifs = 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

5
stex/gifs/Rightarrow.tex Normal file
View file

@ -0,0 +1,5 @@
\documentclass[12pt]{article}
\begin{document}
\pagestyle{empty}
$\Rightarrow$
\end{document}

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 B

View file

@ -0,0 +1,2 @@
\xdef\selfstudy#1{%
\xedef\studylab{\genlab}\raw{\selfstudy}{#1}{\studylab}\label{\studylab}}

1119
stex/inputs/assignment.bst Normal file

File diff suppressed because it is too large Load diff

233
stex/inputs/assignment.cls Normal file
View file

@ -0,0 +1,233 @@
%%% 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&#1.&\multispan{2}{#2~}\lead&~#3\cr
&&\multispan{2}{\hphantom{#2~\hspace{2em}}}\hfil&\cr
}
\def\l@subsubxection#1\calvin#2\hobbes#3{%
\strut&&#1.&\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

173
stex/inputs/assignment.hcls Normal file
View file

@ -0,0 +1,173 @@
%%% assignment.hcls
\newif\iflatex\latexfalse
\newif\ifhtml\htmltrue
% should be built in
\newenvironment{center}
{\raw{<center>}}
{\raw{</center>}}
\def\copyrightnotice{\ifauthor\par\raw{<hr>}\copyright~\year~\theauthor\par\fi}
\let\trueenddocument=\enddocument
\def\enddocument{
\theselfstudy
\begin{divertoutput}[toc]
\ifsubsubsec\raw{</table></td></tr>}\fi
\ifsubsec\raw{</table></td></tr>}\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{<h1>}\thetitle\raw{</h1>}\fi
\ifauthor
\ifdate
\raw{<h2>}\theauthor\\\thedate\raw{</h2>}%
\else
\raw{<h2>}\theauthor\raw{</h2>}%
\fi
\else
\ifdate\raw{<h2>}\thedate\raw{</h2>}\fi
\fi}
%%% table of contents
\newif\ifsubsec\subsecfalse
\newif\ifsubsubsec\subsubsecfalse
\newcommand{\tableofcontents}{
\raw{<table cellpadding=0 cellspacing=0>}
\rawinput{\jobname.htoc}
\raw{</table>}
\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{<h3><br>}\label{\templabel}\thesection. #1\raw{</h3>}
\begin{divertoutput}[toc]
\ifsubsubsec\raw{</table></td></tr>}\fi
\subsubsecfalse
\ifsubsec\raw{</table></td></tr>}\fi
\subsecfalse
\raw{<tr><td align="right">}\textbf{\thesection.~}\raw{<td>}\textbf{\href[plain]{\templabel}{{\let\label=\nolabel #1}}}\raw{</td></tr>}
\end{divertoutput}
}
%%% \subsection
\newcounter{subsection}[section]
\renewcommand{\thesubsection}{\thesection.\arabic{subsection}}
\newcommand{\subsection}[1]{
\refstepcounter{subsection}
\edef\templabel{\genlab}
\raw{<h4><br>}\label{\templabel}\thesubsection. #1\raw{</h4>}
\begin{divertoutput}[toc]
\ifsubsubsec\raw{</table></td></tr>}\fi
\subsubsecfalse
\ifsubsec\else\raw{<tr><td></td><td><table cellpadding=0 cellspacing=0>}\fi
\subsectrue
\raw{<tr><td>}\textbf{\thesubsection.~}\raw{</td><td>}\textbf{\href[plain]{\templabel}{{\let\label=\nolabel #1}}}\raw{</td></tr>}
\end{divertoutput}
}
%%% \subsubsection
\newcounter{subsubsection}[subsection]
\renewcommand{\thesubsubsection}{\thesubsection.\arabic{subsubsection}}
\newcommand{\subsubsection}[1]{
\refstepcounter{subsubsection}
\edef\templabel{\genlab}
\raw{<h4><br>}\label{\templabel}\thesubsubsection. #1\raw{</h4>}
\begin{divertoutput}[toc]
\ifsubsubsec\else\raw{<tr><td></td><td><table cellpadding=0 cellspacing=0>}\fi
\subsubsectrue
\raw{<tr><td>}\textbf{\thesubsubsection.~}\raw{</td><td>}\textbf{\href[plain]{\templabel}{{\let\label=\nolabel #1}}}\raw{</td></tr>}
\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{<hr>}
\textbf{Exercise \theexercise. }}
\newenvironment{exercise}
{\begingroup\def\newexercise{\@startexercise}\newexercise}
{\raw{<hr>}}
\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{<p>}\textbf{##3.} ##1 [see \hyperlink{######2}{here}]\raw{</p>}}
\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{</td></tr>}}%
\stepcounter{alphalist}%
\raw{<tr valign=top><td>}\alph{alphalist}.\raw{</td><td>}}
\raw{<table>}}
\def\endalphalist{\endalphalistitem\raw{</table>}\endgroup}
%%% define our own (compact) description environment
\def\description{\begingroup
\renewcommand{\item}[1][]{\raw{<dt>}##1\raw{<dd>}}\raw{<dl compact>}}
\def\enddescription{\raw{</dl>}\endgroup}
%%% index
\newcommand{\see}[2]{\emph{see} #1}
\newenvironment{theindex}
{\begingroup\newcommand{\itemindent}{\raw{<tt>&nbsp;&nbsp;&nbsp;</tt>}}
\renewcommand{\item}{\raw{<br>}}
\newcommand{\subitem}{\raw{<br>}\itemindent}
\newcommand{\subsubitem}{\raw{<br>}\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{<sup>+</sup>}}
\def\kstar{\raw{*}}
\def\ang#1{\raw{&lt;}#1\raw{&gt;}}
\def\mbox#1{#1}
%%% hyperlink support
\newcommand{\hyperlink}[3][]{\raw{<a #1 href="}\url{#2}\raw{">}#3\raw{</a>}}

92
stex/inputs/exam.cls Normal file
View file

@ -0,0 +1,92 @@
%%% 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

29
stex/inputs/fullpage.sty Normal file
View file

@ -0,0 +1,29 @@
% 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

15
stex/inputs/grammar.hsty Normal file
View file

@ -0,0 +1,15 @@
%%% grammar support
\newenvironment{grammar}
{\begingroup
\def\orbar{\raw{</td><td align=center>|</td><td nowrap>}}
\def\nobar{\raw{</td><td align=center></td><td nowrap>}}
\def\longis{\raw{</td><td align=center>}$\longrightarrow$\raw{</td><td nowrap>}}
\def\\{\raw{</td></tr><tr><td nowrap>}}
\raw{<table><tr><td nowrap>}}
{\raw{</td></tr></table>}\endgroup}
\def\bar{\raw{|}}
\def\kplus{\raw{<sup>+</sup>}}
\def\kstar{\raw{*}}
\def\ang#1{\raw{&lt;}#1\raw{&gt;}}

12
stex/inputs/grammar.sty Normal file
View file

@ -0,0 +1,12 @@
\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{+}}}

49
stex/inputs/html-prep.tex Normal file
View file

@ -0,0 +1,49 @@
%%% html-prep.tex
%%% /* these don't handle nesting properly, i.e., nested \emph */
\def\emph#1{\raw{<i>}#1\raw{</i>}}
\def\textit#1{\raw{<i>}#1\raw{</i>}}
\def\textsl#1{\raw{<i>}#1\raw{</i>}} % really want slant font
\def\textbf#1{\raw{<b>}#1\raw{</b>}}
\def\texttt#1{\raw{<tt>}#1\raw{</tt>}}
\def\copyright{\raw{&copy;}}
\def\protect{}
\def\bigskip{\raw{<p>}}
\def\medskip{\raw{<p>}}
\def\smallskip{\raw{<p>}}
\def\nobreak{}
\def\noindent{}
\def\_{\raw{_}}
\def\par{\raw{
<p>}}
\def\dots{\raw{...}}
\def\vdots{$\vdots$}
\def\null{}
\def\${\raw{$}}
\def\&{\raw{&amp;}}
\def\%{\raw{%}}
\def\#{\raw{##}}
\newcommand{\item}[1][]{\itemoutsideoflist}
\def\itemize{\begingroup
\renewcommand{\item}[1][]{\raw{<li>}##1}\raw{<ul>}}
\def\enditemize{\raw{</ul>}\endgroup\par}
\newcounter{enumeratecounter}
\def\enumerate{\begingroup\setcounter{enumeratecounter}{0}%
\renewcommand{\item}[1][]{\refstepcounter{enumeratecounter}\raw{<li>}##1}\raw{<ol>}}
\def\endenumerate{\raw{</ol>}\endgroup\par}
\def\description{\begingroup
\renewcommand{\item}[1][]{\raw{<dt>}##1\raw{<dd>}}\raw{<dl>}}
\def\enddescription{\raw{</dl>}\endgroup\par}
\newenvironment{flushleft}{}{}
\newenvironment{thebibliography}[1]
{\begingroup\def\newblock{}}
{\endgroup}
\newenvironment{quotation}
{\raw{<blockquote>}}
{\raw{</blockquote>}}

158
stex/inputs/monograph.cls Normal file
View file

@ -0,0 +1,158 @@
%%% 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

149
stex/inputs/monograph.hcls Normal file
View file

@ -0,0 +1,149 @@
%%% monograph.hcls
\newif\iflatex\latexfalse
\newif\ifhtml\htmltrue
% should be built in
\newenvironment{center}
{\raw{<center>}}
{\raw{</center>}}
\def\copyrightnotice{\ifauthor\par\raw{<hr>}\copyright~\year~\theauthor\par\fi}
\let\trueenddocument=\enddocument
\def\enddocument{
\begin{divertoutput}[toc]
\ifsubsubsec\raw{</table></td></tr>}\fi
\ifsubsec\raw{</table></td></tr>}\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{<h1>}\thetitle\raw{</h1>}\fi
\ifauthor\raw{<h2>}\theauthor\raw{</h2>}\fi
\ifdate\raw{<h3>}\thedate\raw{</h3>}\fi
}
%%% table of contents
\newif\ifsubsec\subsecfalse
\newif\ifsubsubsec\subsubsecfalse
\newcommand{\tableofcontents}{
\raw{<table cellpadding=0 cellspacing=0>}
\rawinput{\jobname.htoc}
\raw{</table>}
\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{</table></td></tr>}\fi
\subsubsecfalse
\ifsubsec\raw{</table></td></tr>}\fi
\subsecfalse
\raw{<tr><td align="right">}\textbf{\thesection.~}\raw{<td>}\textbf{\href[plain]{\templabel}{#1}}\raw{</td></tr>}
\end{divertoutput}
}
\newcommand{\sectionstar}[1]{
\raw{<h3>}#1\raw{</h3>}
}
%%% \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{</table></td></tr>}\fi
\subsubsecfalse
\ifsubsec\else\raw{<tr><td></td><td><table cellpadding=0 cellspacing=0>}\fi
\subsectrue
\raw{<tr><td>}\textbf{\thesubsection.~}\raw{</td><td>}\textbf{\href[plain]{\templabel}{#1}}\raw{</td></tr>}
\end{divertoutput}
}
\newcommand{\subsectionstar}[1]{
\raw{<h4>}#1\raw{</h4>}
}
%%% \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{<tr><td></td><td><table cellpadding=0 cellspacing=0>}\fi
\subsubsectrue
\raw{<tr><td>}\textbf{\thesubsubsection.~}\raw{</td><td>}\textbf{\href[plain]{\templabel}{#1}}\raw{</td></tr>}
\end{divertoutput}
}
\newcommand{\subsubsectionstar}[1]{
\raw{<h4>}#1\raw{</h4>}
}
%%% 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{<hr>}
\textbf{Exercise \theexercise. }}
\newenvironment{exercise}
{\begingroup\def\newexercise{\@startexercise}\newexercise}
{\raw{<hr>}}
\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{</td></tr>}}%
\stepcounter{alphalist}%
\raw{<tr valign=top><td>}\alph{alphalist}.\raw{</td><td>}}
\raw{<table>}}
\def\endalphalist{\endalphalistitem\raw{</table>}\endgroup}
%%% define our own (compact) description environment
\def\description{\begingroup
\renewcommand{\item}[1][]{\raw{<dt>}##1\raw{<dd>}}\raw{<dl compact>}}
\def\enddescription{\raw{</dl>}\endgroup}
%%% index
\newcommand{\see}[2]{\emph{see} #1}
\newenvironment{theindex}
{\begingroup\newcommand{\itemindent}{\raw{<tt>&nbsp;&nbsp;&nbsp;</tt>}}
\renewcommand{\item}{\raw{<br>}}
\newcommand{\subitem}{\raw{<br>}\itemindent}
\newcommand{\subsubitem}{\raw{<br>}\itemindent\itemindent}}
{\par\endgroup}
\newcommand{\parheader}[2][. ]{\medskip\noindent{\bf #2#1}}
\def\mbox#1{#1}
%%% hyperlink support
\newcommand{\hyperlink}[3][ref]{\raw{<a class=#1 href="#2">}#3\raw{</a>}}

94
stex/inputs/quiz.cls Normal file
View file

@ -0,0 +1,94 @@
%%% 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

42
stex/inputs/scheme.hsty Normal file
View file

@ -0,0 +1,42 @@
\def\transerr#1{\raw{<i>}}
\def\transin#1{\raw{<font color="##ff0000">}}
\def\transout#1{\raw{<font color="##0000ff">}}
\def\traceout#1{\raw{<font color="##0000ff">}}
\def\endtranserr#1{\raw{</i>}}
\def\endtransin#1{\raw{</font>}}
\def\endtransout#1{\raw{</font>}}
\def\endtraceout#1{\raw{</font>}}
\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{<table><tr width=20><td>}#1\raw{</td></tr></table>}}
\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{<img src="gifs/ghostRightarrow.gif">}}
\def\var#1{\emph{#1}}
% frame="border" rules="all" makes mozilla do it right
% border="1" makes konqueror do it right
\def\startrepl{\raw{<table width="95%"><tr valign=top><td>}}
\def\endrepl{\raw{</td>}}
\def\startinteraction{\raw{<td align="right"><table rules="all" border="1"><tr><td>}}
\def\endinteraction{\raw{</td></tr></table></td></tr></table>}}

56
stex/inputs/scheme.sty Normal file
View file

@ -0,0 +1,56 @@
\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}

88
stex/inputs/website.cls Normal file
View file

@ -0,0 +1,88 @@
%%% 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

93
stex/inputs/website.hcls Normal file
View file

@ -0,0 +1,93 @@
%%% 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{<h1} \thetitleattributes\raw{>}\thetitle\raw{</h1>}}
\newcommand{\hr}[1][]{\raw{<hr #1>}}
\def\copyright{\raw{&copy;}}
\newcommand{\copyrightnotice}{}
\let\trueenddocument=\enddocument
\def\enddocument{
\endwebpage
\trueenddocument}
%%% \section{title}
\newcommand{\section}[1]{
\raw{<h2>}#1\raw{</h2>}
}
%%% \subsection{title}
\newcommand{\subsection}[1]{
\raw{<h3>}#1\raw{</h3>}
}
%%% \subsection{title}
\newcommand{\subsubsection}[1]{
\raw{<h4>}#1\raw{</h4>}
}
\newenvironment{DIV}[1]
{\raw{<div #1>}}
{\raw{</div>}}
\def\span#1#2{\raw{<span #1>}#2\raw{</span>}}
\newcommand{\img}[3][]{\raw{<img alt="#2" #1 src="#3">}}
%%% \parheader{title}
\def\parheader#1 {\medskip\noindent{\bf #1.}~~}
%%% center: should be built in
\newenvironment{center}
{\raw{<div align=center>}}
{\raw{</div>}}
%%% alphalist
\newcounter{alphalist}
\def\alphalist{\begingroup\setcounter{alphalist}{0}
\def\endalphalistitem{}%
\renewcommand{\item}{\endalphalistitem
\def\endalphalistiem{\raw{</td></tr>}}%
\stepcounter{alphalist}%
\raw{<tr valign=top><td>}\textit{~~\alph{alphalist}}.\raw{</td><td>}}
\raw{<table>}}
\def\endalphalist{\endalphalistitem\raw{</table>}\endgroup}
%%% define our own (compact) description environment
\def\description{\begingroup
\renewcommand{\item}[1][]{\raw{<dt>}##1\raw{<dd>}}\raw{<dl compact>}}
\def\enddescription{\raw{</dl>}\endgroup}
%%% hyperlink support
\newcommand{\hyperlink}[3][]{\raw{<a #1 href="}\url{#2}\raw{">}#3\raw{</a>}}
%%% \mailto{id}{name}
\newcommand{\mailto}[3][]{\raw{<a #1 href="/cgi-bin/tomail.cgi?name=#2">}{#3}\raw{</a>}}
%%% colors
\def\textcolor#1#2{\raw{<span style="color: #1;">}#2\raw{</span>}}
%%% forms
\newenvironment{form}[1]{\raw{<form #1>}}{\raw{</form>}}
\newcommand{\formtextarea}[2]{\raw{<textarea #1>}#2\raw{</textarea>}}
\newcommand{\forminput}[1]{\raw{<input #1>}}
\newcommand{\formselect}[2]{\raw{<select #1>}#2\raw{</select>}}
\newcommand{\formoption}[2][]{\raw{<option #1>}#2\raw{</option>}}

26
stex/math/Makefile Normal file
View file

@ -0,0 +1,26 @@
include 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

21
stex/math/mathmacros Normal file
View file

@ -0,0 +1,21 @@
\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}

73
stex/sbin/install Executable file
View file

@ -0,0 +1,73 @@
#! /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

54
stex/src/dsm.ss Normal file
View file

@ -0,0 +1,54 @@
;;; 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 ())])))]))
)

34
stex/src/fixbibtex.ss Executable file
View file

@ -0,0 +1,34 @@
#! /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 <filename>\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))))

1942
stex/src/html-prep.ss Executable file

File diff suppressed because it is too large Load diff

469
stex/src/preplib.ss Normal file
View file

@ -0,0 +1,469 @@
;;; 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))))
)

1166
stex/src/scheme-prep.ss Executable file

File diff suppressed because it is too large Load diff

710
stex/src/script.ss Normal file
View file

@ -0,0 +1,710 @@
;;; 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 [(<cmdspec>) <body>]*)
<cmdspec> -> (keyword <kwd> <required-arg>* <possible-action>]) <cmdspec>
| (flags [<kwd> <flag-arg>* <possible-action>]*) <cmdspec>
| <argspec>
<possible-action> -> <empty> | $ <action>
<flag-arg> -> <var> | (<type> <var>) | (<type> <var> <default>)
<argspec> -> <required-arg>* <optional-arg>*
| <required-arg>* <optional-arg>* <required-arg> ...
<required-arg> -> <var> | (<type> <var>)
<optional-arg> -> (optional <var>)
| (optional <type> <var>)
| (optional <type> <var> <default>)
<kwd> -> <id> | (<id>+)
<var> -> <id>
<type> -> <id>
<action> -> <expr>
<default> -> <expr>
Each <var> must be unique.
If any <type> is not specified, it defaults to string.
If any <default> is not specified, it defaults to #f. Each <default>
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 <cmdspec>,
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 <action>, if specified,
is evaluated for effect. Each <action> is scoped where each of the <var>s
is visible and each <var>'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 <var> is its last specified value.
If <type> is not string, the procedure string-><type> 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-><type> routine should not cause side effects since it may be
called even for clauses that don't match.
For flag clauses, variable ?id, where <kwd> = id or <kwd> = (id id1 ...),
is bound to #t if the argument is specified at least once, otherwise #f.
Within each <body>, 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 <kwd> 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))
)