summaryrefslogtreecommitdiff
path: root/web/noweb
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /web/noweb
Initial commit
Diffstat (limited to 'web/noweb')
-rw-r--r--web/noweb/CHANGES394
-rw-r--r--web/noweb/COPYRIGHT24
-rw-r--r--web/noweb/CTAN28
-rw-r--r--web/noweb/DATE1
-rw-r--r--web/noweb/DEBIAN19
-rw-r--r--web/noweb/DEBIAN.asc16
-rw-r--r--web/noweb/LICENSE26
-rw-r--r--web/noweb/Makefile66
-rw-r--r--web/noweb/README244
-rw-r--r--web/noweb/contrib/Makefile13
-rw-r--r--web/noweb/contrib/README9
-rw-r--r--web/noweb/contrib/avs/email2
-rw-r--r--web/noweb/contrib/avs/filelist.txt59
-rw-r--r--web/noweb/contrib/avs/ftpsites.txt65
-rw-r--r--web/noweb/contrib/avs/generate.ksh114
-rw-r--r--web/noweb/contrib/avs/howto386.txt254
-rw-r--r--web/noweb/contrib/avs/icon.1330
-rw-r--r--web/noweb/contrib/avs/jrtex12a.avs1054
-rw-r--r--web/noweb/contrib/avs/make_ico.awk50
-rw-r--r--web/noweb/contrib/avs/make_lib.awk12
-rw-r--r--web/noweb/contrib/avs/make_src.awk72
-rw-r--r--web/noweb/contrib/avs/make_xdo.awk14
-rw-r--r--web/noweb/contrib/avs/mks42bug.0d128
-rw-r--r--web/noweb/contrib/avs/mksfixes.ksh15
-rw-r--r--web/noweb/contrib/avs/myenv.ksh38
-rw-r--r--web/noweb/contrib/avs/norman1.txt136
-rw-r--r--web/noweb/contrib/avs/nw_c.bat63
-rw-r--r--web/noweb/contrib/avs/nwicon.bat43
-rw-r--r--web/noweb/contrib/avs/nwinst.ksh9
-rw-r--r--web/noweb/contrib/avs/readme39
-rw-r--r--web/noweb/contrib/avs/report1.bug97
-rw-r--r--web/noweb/contrib/conrado/Makefile15
-rw-r--r--web/noweb/contrib/conrado/README38
-rw-r--r--web/noweb/contrib/conrado/algoritmos.sty169
-rwxr-xr-xweb/noweb/contrib/conrado/d2tex144
-rw-r--r--web/noweb/contrib/conrado/email1
-rw-r--r--web/noweb/contrib/conrado/hospital.nw165
-rw-r--r--web/noweb/contrib/conrado/keywords.tex59
-rw-r--r--web/noweb/contrib/davelove/Makefile6
-rw-r--r--web/noweb/contrib/davelove/README2
-rw-r--r--web/noweb/contrib/davelove/email1
-rw-r--r--web/noweb/contrib/davelove/subref.doc235
-rw-r--r--web/noweb/contrib/fischer/README40
-rwxr-xr-xweb/noweb/contrib/fischer/noscript-0.1/noscript15
-rw-r--r--web/noweb/contrib/fischer/noscript-0.1/test-none.nw8
-rw-r--r--web/noweb/contrib/fischer/noscript-0.1/test-py.nw23
-rw-r--r--web/noweb/contrib/fischer/noscript-0.1/test-sh.nw10
-rw-r--r--web/noweb/contrib/gregory/README2
-rw-r--r--web/noweb/contrib/gregory/dots.nw154
-rw-r--r--web/noweb/contrib/gregory/email1
-rw-r--r--web/noweb/contrib/jobling/Makefile34
-rw-r--r--web/noweb/contrib/jobling/README21
-rw-r--r--web/noweb/contrib/jobling/correct-refs.bbl36
-rw-r--r--web/noweb/contrib/jobling/correct-refs.nw391
-rw-r--r--web/noweb/contrib/jobling/email1
-rw-r--r--web/noweb/contrib/jonkrom/Makefile15
-rw-r--r--web/noweb/contrib/jonkrom/README4
-rw-r--r--web/noweb/contrib/jonkrom/email1
-rw-r--r--web/noweb/contrib/jonkrom/noxref.nw491
-rw-r--r--web/noweb/contrib/kaelin/README19
-rw-r--r--web/noweb/contrib/kaelin/email1
-rw-r--r--web/noweb/contrib/kaelin/pp.nw616
-rw-r--r--web/noweb/contrib/kostas/C++_translation_table64
-rw-r--r--web/noweb/contrib/kostas/C_translation_table55
-rw-r--r--web/noweb/contrib/kostas/Makefile75
-rw-r--r--web/noweb/contrib/kostas/Makefile.gnu75
-rw-r--r--web/noweb/contrib/kostas/Makefile.make75
-rw-r--r--web/noweb/contrib/kostas/README14
-rw-r--r--web/noweb/contrib/kostas/WHATS_NEW46
-rw-r--r--web/noweb/contrib/kostas/defns.nw33
-rw-r--r--web/noweb/contrib/kostas/email1
-rw-r--r--web/noweb/contrib/kostas/icon_translation_table140
-rw-r--r--web/noweb/contrib/kostas/math_translation_table68
-rw-r--r--web/noweb/contrib/kostas/mathdefs.nw24
-rw-r--r--web/noweb/contrib/kostas/oot_translation_table137
-rw-r--r--web/noweb/contrib/kostas/ootdefs.nw198
-rw-r--r--web/noweb/contrib/kostas/pp.nw541
-rw-r--r--web/noweb/contrib/leew/Makefile6
-rw-r--r--web/noweb/contrib/leew/README12
-rw-r--r--web/noweb/contrib/leew/custom-code/README.custom-code17
-rwxr-xr-xweb/noweb/contrib/leew/custom-code/custom-code12
-rw-r--r--web/noweb/contrib/leew/custom-code/example.nw101
-rw-r--r--web/noweb/contrib/leew/custom-code/example.pdfbin0 -> 46036 bytes
-rw-r--r--web/noweb/contrib/leew/custom-code/example.tex105
-rw-r--r--web/noweb/contrib/leew/custom-code/n20
-rw-r--r--web/noweb/contrib/leew/email2
-rw-r--r--web/noweb/contrib/leew/nobrace.nw321
-rw-r--r--web/noweb/contrib/leew/nocond.nw375
-rw-r--r--web/noweb/contrib/leew/strhack.nw32
-rw-r--r--web/noweb/contrib/leyn/README23
-rw-r--r--web/noweb/contrib/leyn/email1
-rwxr-xr-xweb/noweb/contrib/leyn/notangleall27
-rwxr-xr-xweb/noweb/contrib/leyn/ttroots41
-rw-r--r--web/noweb/contrib/norman/Makefile10
-rw-r--r--web/noweb/contrib/norman/README6
-rw-r--r--web/noweb/contrib/norman/cleanchunks.nw42
-rw-r--r--web/noweb/contrib/norman/email1
-rwxr-xr-xweb/noweb/contrib/norman/generate-to24
-rw-r--r--web/noweb/contrib/norman/htmlgif/htmlgif.icn54
-rw-r--r--web/noweb/contrib/norman/htmlgif/newer.c19
-rwxr-xr-xweb/noweb/contrib/norman/htmlgif/pstopbm86
-rw-r--r--web/noweb/contrib/norman/moddate.nw79
-rw-r--r--web/noweb/contrib/norman/numarkup/Makefile37
-rw-r--r--web/noweb/contrib/norman/numarkup/numarkup.bbl58
-rw-r--r--web/noweb/contrib/norman/numarkup/numarkup.nw1264
-rw-r--r--web/noweb/contrib/norman/pp/mkfile24
-rw-r--r--web/noweb/contrib/norman/pp/pp.nw314
-rw-r--r--web/noweb/contrib/norman/scopehack.icn44
-rw-r--r--web/noweb/contrib/partingr/README148
-rwxr-xr-xweb/noweb/contrib/partingr/TeXthings52
-rw-r--r--web/noweb/contrib/partingr/addscore.nw183
-rw-r--r--web/noweb/contrib/partingr/email2
-rwxr-xr-xweb/noweb/contrib/partingr/mm2mx63160
-rwxr-xr-xweb/noweb/contrib/partingr/mm2mx64173
-rwxr-xr-xweb/noweb/contrib/partingr/mm2mx65179
-rwxr-xr-xweb/noweb/contrib/partingr/mm2tex41
-rwxr-xr-xweb/noweb/contrib/partingr/mx2tex31130
-rw-r--r--web/noweb/contrib/partingr/nwindex.tex134
-rwxr-xr-xweb/noweb/contrib/partingr/nwnweave2
-rwxr-xr-xweb/noweb/contrib/partingr/nwtangle2
-rwxr-xr-xweb/noweb/contrib/partingr/nwweave2
-rwxr-xr-xweb/noweb/contrib/partingr/xpand20
-rw-r--r--web/noweb/contrib/rsc/README1
-rw-r--r--web/noweb/contrib/rsc/email1
-rw-r--r--web/noweb/contrib/rsc/rc/cpif.nw47
-rw-r--r--web/noweb/contrib/rsc/rc/emptydefn.nw10
-rw-r--r--web/noweb/contrib/rsc/rc/mkfile28
-rw-r--r--web/noweb/contrib/rsc/rc/noidx.nw432
-rw-r--r--web/noweb/contrib/rsc/rc/noindex.nw194
-rw-r--r--web/noweb/contrib/rsc/rc/noroots.nw16
-rw-r--r--web/noweb/contrib/rsc/rc/notangle.nw51
-rw-r--r--web/noweb/contrib/rsc/rc/nountangle.nw93
-rw-r--r--web/noweb/contrib/rsc/rc/noweave.nw594
-rw-r--r--web/noweb/contrib/rsc/rc/noweave.simple56
-rw-r--r--web/noweb/contrib/rsc/rc/noweb.nw63
-rw-r--r--web/noweb/contrib/rsc/rc/toascii.nw279
-rw-r--r--web/noweb/contrib/rsc/rc/tohtml.nw362
-rw-r--r--web/noweb/contrib/rsc/rc/totex.nw312
-rw-r--r--web/noweb/contrib/rsc/rc/unmarkup.nw53
-rw-r--r--web/noweb/contrib/ydirson/Makefile11
-rw-r--r--web/noweb/contrib/ydirson/README32
-rw-r--r--web/noweb/contrib/ydirson/email1
-rwxr-xr-xweb/noweb/contrib/ydirson/enscript-html150
-rwxr-xr-xweb/noweb/contrib/ydirson/guesslang57
-rwxr-xr-xweb/noweb/contrib/ydirson/inheritlang76
-rwxr-xr-xweb/noweb/echo27
-rw-r--r--web/noweb/examples/Makefile55
-rw-r--r--web/noweb/examples/Makefile.awk58
-rw-r--r--web/noweb/examples/README49
-rw-r--r--web/noweb/examples/README.h72
-rw-r--r--web/noweb/examples/breakmodel.nw459
-rw-r--r--web/noweb/examples/compress.nw1637
-rw-r--r--web/noweb/examples/dag.nw163
-rw-r--r--web/noweb/examples/graphs.nw244
-rw-r--r--web/noweb/examples/mipscoder.nw1118
-rw-r--r--web/noweb/examples/multicol.sty525
-rw-r--r--web/noweb/examples/primes.bbl13
-rw-r--r--web/noweb/examples/primes.nw186
-rw-r--r--web/noweb/examples/scanner.nw444
-rwxr-xr-xweb/noweb/examples/sharpline31
-rw-r--r--web/noweb/examples/test.nw17
-rw-r--r--web/noweb/examples/tree.nw326
-rw-r--r--web/noweb/examples/wc.bbl14
-rw-r--r--web/noweb/examples/wc.nw372
-rw-r--r--web/noweb/examples/wc.nw2html370
-rw-r--r--web/noweb/examples/whitespace10
-rw-r--r--web/noweb/nwsrcfilter.icn60
-rw-r--r--web/noweb/src/COPYRIGHT21
-rw-r--r--web/noweb/src/FAQ501
-rw-r--r--web/noweb/src/FAQ.html676
-rw-r--r--web/noweb/src/HPUX29
-rw-r--r--web/noweb/src/INSTALL92
-rw-r--r--web/noweb/src/INSTALL.DOS43
-rw-r--r--web/noweb/src/Makefile222
-rw-r--r--web/noweb/src/Makefile.nw228
-rw-r--r--web/noweb/src/README20
-rw-r--r--web/noweb/src/VERSIONS11
-rw-r--r--web/noweb/src/awk/Makefile47
-rwxr-xr-xweb/noweb/src/awk/noidx362
-rw-r--r--web/noweb/src/awk/noidx.nw477
-rwxr-xr-xweb/noweb/src/awk/noindex155
-rw-r--r--web/noweb/src/awk/noindex.nw187
-rwxr-xr-xweb/noweb/src/awk/tohtml237
-rw-r--r--web/noweb/src/awk/tohtml.nw331
-rwxr-xr-xweb/noweb/src/awk/totex175
-rw-r--r--web/noweb/src/awk/totex.nw287
-rw-r--r--web/noweb/src/awk/totex.nw.bad292
-rwxr-xr-xweb/noweb/src/awkmake10
-rwxr-xr-xweb/noweb/src/awkname30
-rw-r--r--web/noweb/src/c/Makefile112
-rw-r--r--web/noweb/src/c/columns.c37
-rw-r--r--web/noweb/src/c/columns.h6
-rw-r--r--web/noweb/src/c/columns.nw53
-rw-r--r--web/noweb/src/c/doc.bbl8
-rw-r--r--web/noweb/src/c/doc.nw49
-rw-r--r--web/noweb/src/c/errors.c53
-rw-r--r--web/noweb/src/c/errors.h10
-rw-r--r--web/noweb/src/c/errors.nw94
-rw-r--r--web/noweb/src/c/fakepretty.nw85
-rw-r--r--web/noweb/src/c/finduses.c137
-rw-r--r--web/noweb/src/c/finduses.nw159
-rw-r--r--web/noweb/src/c/getline.c69
-rw-r--r--web/noweb/src/c/getline.h6
-rw-r--r--web/noweb/src/c/getline.nw94
-rw-r--r--web/noweb/src/c/main.c75
-rw-r--r--web/noweb/src/c/main.nw94
-rw-r--r--web/noweb/src/c/markmain.c406
-rw-r--r--web/noweb/src/c/markmain.nw588
-rw-r--r--web/noweb/src/c/markup.c123
-rw-r--r--web/noweb/src/c/markup.h13
-rw-r--r--web/noweb/src/c/markup.nw227
-rw-r--r--web/noweb/src/c/markup.ps1748
-rw-r--r--web/noweb/src/c/match.c26
-rw-r--r--web/noweb/src/c/match.h4
-rw-r--r--web/noweb/src/c/match.nw38
-rw-r--r--web/noweb/src/c/mnt.c172
-rw-r--r--web/noweb/src/c/mnt.nw171
-rw-r--r--web/noweb/src/c/modtrees.c77
-rw-r--r--web/noweb/src/c/modtrees.h4
-rw-r--r--web/noweb/src/c/modtrees.nw100
-rw-r--r--web/noweb/src/c/modules.c226
-rw-r--r--web/noweb/src/c/modules.h37
-rw-r--r--web/noweb/src/c/modules.nw326
-rw-r--r--web/noweb/src/c/notangle.c189
-rw-r--r--web/noweb/src/c/notangle.h2
-rw-r--r--web/noweb/src/c/notangle.nw184
-rwxr-xr-xweb/noweb/src/c/nwmktempbin0 -> 5612 bytes
-rw-r--r--web/noweb/src/c/nwmktemp.c43
-rw-r--r--web/noweb/src/c/nwmktemp.nw54
-rw-r--r--web/noweb/src/c/pretty.nw259
-rw-r--r--web/noweb/src/c/readme.nw61
-rw-r--r--web/noweb/src/c/recognize.c215
-rw-r--r--web/noweb/src/c/recognize.h6
-rw-r--r--web/noweb/src/c/recognize.nw322
-rw-r--r--web/noweb/src/c/strsave.c17
-rw-r--r--web/noweb/src/c/strsave.h1
-rw-r--r--web/noweb/src/c/strsave.nw21
-rwxr-xr-xweb/noweb/src/csmake3
-rw-r--r--web/noweb/src/elisp/noweb-mode.el995
-rw-r--r--web/noweb/src/icon/Makefile151
-rw-r--r--web/noweb/src/icon/asdldefs.icn85
-rw-r--r--web/noweb/src/icon/asdldefs.nw46
-rw-r--r--web/noweb/src/icon/cdefs.icn180
-rw-r--r--web/noweb/src/icon/cdefs.nw132
-rw-r--r--web/noweb/src/icon/defns.nw40
-rw-r--r--web/noweb/src/icon/disambiguate.icn67
-rw-r--r--web/noweb/src/icon/disambiguate.nw80
-rw-r--r--web/noweb/src/icon/docs2comments.icn180
-rw-r--r--web/noweb/src/icon/docs2comments.nw192
-rw-r--r--web/noweb/src/icon/elide.icn71
-rw-r--r--web/noweb/src/icon/elide.nw112
-rw-r--r--web/noweb/src/icon/htmltoc.icn218
-rw-r--r--web/noweb/src/icon/htmltoc.nw264
-rw-r--r--web/noweb/src/icon/icondefs.icn77
-rw-r--r--web/noweb/src/icon/icondefs.nw37
-rw-r--r--web/noweb/src/icon/l2h.icn2237
-rw-r--r--web/noweb/src/icon/l2h.nw2898
-rw-r--r--web/noweb/src/icon/lrtldefs.icn99
-rw-r--r--web/noweb/src/icon/lrtldefs.nw60
-rw-r--r--web/noweb/src/icon/mmixdefs.icn71
-rw-r--r--web/noweb/src/icon/mmixdefs.nw32
-rw-r--r--web/noweb/src/icon/noidx.icn465
-rw-r--r--web/noweb/src/icon/noidx.nw479
-rw-r--r--web/noweb/src/icon/noindex.icn98
-rw-r--r--web/noweb/src/icon/noindex.nw106
-rw-r--r--web/noweb/src/icon/noxref.nw119
-rw-r--r--web/noweb/src/icon/nwl2h.nw79
-rw-r--r--web/noweb/src/icon/pascaldefs.icn96
-rw-r--r--web/noweb/src/icon/pascaldefs.nw55
-rw-r--r--web/noweb/src/icon/pdcached.icn238
-rw-r--r--web/noweb/src/icon/pdcached.nw248
-rw-r--r--web/noweb/src/icon/pipedocs.icn65
-rw-r--r--web/noweb/src/icon/pipedocs.nw69
-rw-r--r--web/noweb/src/icon/promeladefs.icn97
-rw-r--r--web/noweb/src/icon/promeladefs.nw56
-rw-r--r--web/noweb/src/icon/sl2h.icn2167
-rw-r--r--web/noweb/src/icon/smldefs.icn84
-rw-r--r--web/noweb/src/icon/smldefs.nw44
-rw-r--r--web/noweb/src/icon/texdefs.icn73
-rw-r--r--web/noweb/src/icon/texdefs.nw32
-rw-r--r--web/noweb/src/icon/tohtml.icn489
-rw-r--r--web/noweb/src/icon/tohtml.nw534
-rw-r--r--web/noweb/src/icon/totex.icn456
-rw-r--r--web/noweb/src/icon/totex.nw450
-rw-r--r--web/noweb/src/icon/xchunks.icn142
-rw-r--r--web/noweb/src/icon/xchunks.nw186
-rw-r--r--web/noweb/src/icon/yaccdefs.icn67
-rw-r--r--web/noweb/src/icon/yaccdefs.nw26
-rw-r--r--web/noweb/src/lib/Makefile38
-rwxr-xr-xweb/noweb/src/lib/btdefn16
-rwxr-xr-xweb/noweb/src/lib/emptydefn9
-rwxr-xr-xweb/noweb/src/lib/h2a17
-rw-r--r--web/noweb/src/lib/noxref.nw215
-rw-r--r--web/noweb/src/lib/noxref.sh65
-rwxr-xr-xweb/noweb/src/lib/nwmtime32
-rwxr-xr-xweb/noweb/src/lib/pipedocs23
-rwxr-xr-xweb/noweb/src/lib/toascii131
-rw-r--r--web/noweb/src/lib/toascii.nw262
-rwxr-xr-xweb/noweb/src/lib/unmarkup48
-rwxr-xr-xweb/noweb/src/limake3
-rw-r--r--web/noweb/src/nwmake3
-rwxr-xr-xweb/noweb/src/rhmake3
-rw-r--r--web/noweb/src/shell/Makefile35
-rw-r--r--web/noweb/src/shell/cpif32
-rw-r--r--web/noweb/src/shell/detangle73
-rwxr-xr-xweb/noweb/src/shell/htmltoc66
-rw-r--r--web/noweb/src/shell/luddite46
-rwxr-xr-xweb/noweb/src/shell/nocount24
-rw-r--r--web/noweb/src/shell/nodefs28
-rwxr-xr-xweb/noweb/src/shell/nonu41
-rw-r--r--web/noweb/src/shell/noroff98
-rw-r--r--web/noweb/src/shell/noroots15
-rw-r--r--web/noweb/src/shell/notangle27
-rw-r--r--web/noweb/src/shell/notangle.nw30
-rw-r--r--web/noweb/src/shell/nountangle69
-rw-r--r--web/noweb/src/shell/noweave292
-rw-r--r--web/noweb/src/shell/noweave.hpux63
-rw-r--r--web/noweb/src/shell/noweave.nr77
-rw-r--r--web/noweb/src/shell/noweave.nw564
-rw-r--r--web/noweb/src/shell/noweave.sgi74
-rw-r--r--web/noweb/src/shell/noweave.simple48
-rw-r--r--web/noweb/src/shell/noweb34
-rw-r--r--web/noweb/src/shell/noweb.nw74
-rw-r--r--web/noweb/src/shell/nuweb2noweb7
-rw-r--r--web/noweb/src/shell/roff.nw731
-rw-r--r--web/noweb/src/shell/tmac.w171
-rw-r--r--web/noweb/src/shell/toroff135
-rw-r--r--web/noweb/src/shell/toroff.nw617
-rw-r--r--web/noweb/src/shell/unmarkup34
-rwxr-xr-xweb/noweb/src/solmake3
-rw-r--r--web/noweb/src/testmake3
-rw-r--r--web/noweb/src/tex/Makefile28
-rw-r--r--web/noweb/src/tex/multlang.nw1785
-rw-r--r--web/noweb/src/tex/n.sty159
-rw-r--r--web/noweb/src/tex/noweb.sty969
-rw-r--r--web/noweb/src/tex/nwkernel.tex83
-rw-r--r--web/noweb/src/tex/nwmac.tex240
-rw-r--r--web/noweb/src/tex/support.nw1993
-rw-r--r--web/noweb/src/tex/support.nw.orig1301
-rw-r--r--web/noweb/src/tex/support.pdfbin0 -> 79954 bytes
-rw-r--r--web/noweb/src/tex/support.ps6156
-rw-r--r--web/noweb/src/xdoc/Makefile110
-rw-r--r--web/noweb/src/xdoc/chicago.bst1653
-rw-r--r--web/noweb/src/xdoc/chicago.sty264
-rw-r--r--web/noweb/src/xdoc/cpif.138
-rw-r--r--web/noweb/src/xdoc/cpif.txt33
-rw-r--r--web/noweb/src/xdoc/docdate.nw13
-rwxr-xr-xweb/noweb/src/xdoc/doversion2
-rw-r--r--web/noweb/src/xdoc/guide.bbl26
-rw-r--r--web/noweb/src/xdoc/guide.tex1162
-rw-r--r--web/noweb/src/xdoc/htmltoc.142
-rw-r--r--web/noweb/src/xdoc/htmltoc.nw34
-rw-r--r--web/noweb/src/xdoc/htmltoc.txt43
-rw-r--r--web/noweb/src/xdoc/ieee.tex901
-rw-r--r--web/noweb/src/xdoc/manpage.nw681
-rw-r--r--web/noweb/src/xdoc/nodefs.154
-rw-r--r--web/noweb/src/xdoc/nodefs.nw46
-rw-r--r--web/noweb/src/xdoc/nodefs.txt37
-rw-r--r--web/noweb/src/xdoc/noindex.1171
-rw-r--r--web/noweb/src/xdoc/noindex.nw163
-rw-r--r--web/noweb/src/xdoc/noindex.txt103
-rw-r--r--web/noweb/src/xdoc/noroff.157
-rw-r--r--web/noweb/src/xdoc/noroff.nw49
-rw-r--r--web/noweb/src/xdoc/noroff.txt42
-rw-r--r--web/noweb/src/xdoc/noroots.130
-rw-r--r--web/noweb/src/xdoc/noroots.nw22
-rw-r--r--web/noweb/src/xdoc/noroots.txt30
-rw-r--r--web/noweb/src/xdoc/notangle.1641
-rw-r--r--web/noweb/src/xdoc/notangle.txt361
-rw-r--r--web/noweb/src/xdoc/noweb.1221
-rw-r--r--web/noweb/src/xdoc/noweb.txt123
-rw-r--r--web/noweb/src/xdoc/nowebfilters.7211
-rw-r--r--web/noweb/src/xdoc/nowebfilters.nw203
-rw-r--r--web/noweb/src/xdoc/nowebfilters.txt131
-rw-r--r--web/noweb/src/xdoc/nowebstyle.7180
-rw-r--r--web/noweb/src/xdoc/nowebstyle.txt123
-rw-r--r--web/noweb/src/xdoc/nuweb2noweb.128
-rw-r--r--web/noweb/src/xdoc/nuweb2noweb.txt30
-rw-r--r--web/noweb/src/xdoc/onepage.tex197
-rw-r--r--web/noweb/src/xdoc/representation.tex90
-rw-r--r--web/noweb/src/xdoc/sl2h.140
-rw-r--r--web/noweb/src/xdoc/sl2h.nw32
-rw-r--r--web/noweb/src/xdoc/sl2h.txt39
-rw-r--r--web/noweb/src/xdoc/techrep.bbl68
-rw-r--r--web/noweb/src/xdoc/techrep.tex901
-rwxr-xr-xweb/noweb/test/regression82
386 files changed, 74430 insertions, 0 deletions
diff --git a/web/noweb/CHANGES b/web/noweb/CHANGES
new file mode 100644
index 0000000000..9f01a042d2
--- /dev/null
+++ b/web/noweb/CHANGES
@@ -0,0 +1,394 @@
+CHANGES FOR VERSION 2.12
+l2h and sl2h now support rules from booktabs package
+l2h and sl2h now deal with \suspend and \resume from package mdwlist
+l2h and sl2h now deal with \verbatiminput package verbatim
+note to FAQ about \usepackage[T1]{fontenc}
+root Makefile now has a default target that complains bitterly (Allan Adler)
+get xchunks to track source locations
+fix bogon in Hacker's Guide: @index nl takes no argument
+totex didn't handle @line
+improved German text from Pascal Schmitt
+l2h and sl2h now make -- &ndash; and --- &mdash;
+brace fix for 2.11 broke [[}]]; now fixed
+improved German text from Johannes Wiedersich (closes Debian #418892)
+\usepackage{vmargin} not \usepackage{vpage} (Hubert Chan; closes Debian #420614)
+added an optional argument to Emacs noweb-mode to support desktop-read (NR)
+added an option to l2h/sl2h to convert LaTeX double-quote ligatures to HTML 4 entities
+NR has a new address
+changes to noweb-mode.el to make font-lock work better (Christian-Lynbeck)
+C code now compiles with gcc -Wall -Werror, though tricks with rcsid make me blush
+awkname script needed to update roff scripts and lib/pipedocs (Chloe Lopez)
+Partial support for Icelandic (Johann Oskarsson <johann@myrkraverk.com>)
+added Lee Wittenberg's custom-code filter to contrib/leew
+the noweb-mode command now sets noweb-chunk-vector when run
+fix nountangle script to support multiple filters (Anon Sricharoenchai)
+noscript shell-script trick by Greyson Fischer (added to contrib)
+'getline' renamed (now part of POSIX standard) (Brad Larsen)
+added missing control sequences to nwmac.tex (Sergio Spina)
+Aharon Robbins is now Arnold Robbins <arnold@skeeve.com>
+Point to Jim Pettigrew's installation instructions for Windows 7
+noweb & other 25 yo scripts now quote shell variables correctly (Francky Leyn)
+eliminated deprecated tmpnam() in favor of tmpfile(3)
+Makefile now uses mkdir -p (to keep GNU Make from bleating)
+added BSD-2 license (H/T Jonas Stein, Gentoo project)
+Scripts no longer use insecure names in /tmp/; instead using mktemp
+
+CHANGES FOR VERSION 2.11b - released 12 Jun 2006
+Make noroff use -mm by default (Debian 218050)
+Fixed flagrant errors in noweave -x -troff (but bad formatting remains)
+
+CHANGES FOR VERSION 2.11a - released 20 May 2006
+Clarify instructions for $PATH and $MANPATH (B Pierce)
+Create examples/Makefile.awk (B Pierce)
+Clarify documentation: unescaped << and >> not OK in docs chunk (R Hemmecke)
+Add -lua option to docs2comments filter
+
+CHANGES FOR VERSION 2.11 - released 6 April 2006
+Braces did not render correctly in [[<<$\{a_i\}$>>]] (Albert Reiner)
+From Kevin Quick, Windows hints and a new NOTANGLE.BAT
+Generate postscript with -P cmz for better PDF (Francky Leyn)
+Clarify for noweave -delay that the first doco chunk is before the first @
+extended xchunks with -summary argument
+Line in a code chunk opening with unclosed, unescaped << is OK (Ralf Hemmecke)
+
+UNDO ME! Make docs2comments filter tolerate embedded @xref stuff..
+Added Windows XP help to FAQ (David Lemmon)
+Noidx now calculates labels for a code chunk using the number of preceding
+ definitions from the same @file, not the overall number
+Change wording for \noweboptions{german} (Christian Lindig)
+Need to insert \leavevmode in \sublabel so that new \@bsphack will work right
+From Yann Dirson, new filters in contrib/ydirson.
+From Fr'ed'eric Lin'e, some improvements in French translation (apologies to Moli`ere)
+
+CHANGES FOR VERSION 2.10c - released 17 Jul 2002
+
+Bug in noidx.nw caused tag NWD1 etc to be used in multiple files.
+Cleaned up alignment tags in tables emitted by l2h.nw (Federico Di Gregorio)
+Fixed some bugs in the HTML markup for the hacker's guide
+Goes back to iconc, except for noidx.nw, which can't be compiled because
+ of the 32-bit polynomial arithmetic
+
+CHANGES FOR VERSION 2.10b - released 15 Jul 2002
+
+Bug in xchunks.nw, around line 100 -- db never initialized (Stephen Edwards)
+In local identifier cross-reference, enable breaks between pages
+ of multiply defined identifiers (option breakdefs)
+Create a secret \noweboptions{breakcode} for those who want their
+ code chunks broken across page boundaries
+German is `Benutzt' not `Benutztt' (Johannes Huesing)
+No longer suggests iconc; compiling with icont is now the default.
+
+CHANGES FOR VERSION 2.10a - released 30 Mar 2001
+
+Fixed problem in src/Makefile -- FAQ should be built by `source' not `all'
+
+CHANGES FOR VERSION 2.10 - released 16 Jun 2000, but not officially
+
+Added -matlab to nountangle (Uwe Brauer)
+Added \nwblindhyperanchor to \weblabel (Andrew Swann)
+Changed one more 'char c' to 'unsigned char c' in recognize.nw (Gilles ANDRE)
+Change noweb.sty to support more than 26 code chunks on a page (F. Leyn)
+l2h skips optional arguments with \includegraphics
+fixed bugs in htmltoc having to do with nested anchors on one line
+Added capacity for two more filters to noweave script
+Fixed bug in autodefs.sml (including spaces in symbol chars)
+Added autodefs.mmix
+Added autodefs.asdl
+Scripts for Plan 9 rc (Russ Cox)
+Tinkered with noidx sortkey
+Added \mbox{} to \nwnewline, so that spaces won't be eaten (John Cummings)
+Added xchunks filter, per request of Mike Smith & Glenn Holloway
+Replaced FORTH uniqueid heuristic with 32-bit CRC
+Added pipedocs filter to pipe documentation chunks through commands
+Added h2a (convert html to ascii) for use with pipedoces
+Added docs2comments filter, with pipedocs and h2a, to replace nountangle
+Added nwmtime filter; helps derive Zephyr web pages
+Moved the official FAQ to html
+Added multiple-language support to noweb.sty (Miguel Filgueiras)
+notangle -L initial newline is a bug and will never be fixed (Harald Soleng)
+Added \noweboptions{noxref}, intended for temporary use inside documents.
+
+CHANGES FOR VERSION 2.9a - released 16 Feb 1999
+
+Fixed bug in htmltoc that left multiple toc anchors
+
+
+CHANGES FOR VERSION 2.9
+
+Good support for hypertext using the `hyperref' package
+noweave now finds uses in quoted code, the better to exploit hypertext
+added support for emacs font-lock highlighting as comments to noweb-mode (Adnan Yaqub)
+Document common -L options on notangle man page (Brett Presnell)
+Fixed incompatibility with verbatim package (Rafael Laboissiere)
+added contrib/leyn from Francky Leyn
+noweb-mode.el no longer treats @x as chunk end for non-white x (Chris Milner)
+Don't use signed char to index array of 256 in recognize.nw (Michael Herrmann)
+Added explanation for WNT to FAQ.
+Support \ quoting in argument to elide
+Support multiple -R options on the same notangle command line.
+Change tohtml so that noweave -latex+html doesn't protect anchor texts
+ in a rawhtml environment (???)
+Added to /usr/doc/noweb for Slackware binary distribution
+Slackware binary distribution now includes emacs noweb mode.
+Updated internal docs in support.nw to explain the great \nwlbrace trouble
+Use gcc -ansi -pedantic in Makefiles.
+Remove multicols environment from examples/wc.nw (Yotam Medini)
+Change noweave and totex to support subscripting identifiers used in quoted code
+Fixed bug in l2h (bad conversion of tables).
+Make l2h of \section use CPS (for newline between \section and {)
+Added letenv to l2h, and changed verbatim to use environment name as terminator
+
+
+CHANGES FOR VERSION 2.8a
+
+noweave complains if you use -x with -index or -indexfrom
+installation now includes noweb-mode.el
+noroots no longer treats uses in quoted code as real uses (David Bruce)
+file INSTALL now notes that 'awkname' is always needed (Robert Solovay)
+file INSTALL now notes that texhash(1) may be needed (Robert Solovay)
+mnt (noweb script) now complains about chunks named <<*>> (Robert Solovay)
+lots of rcs identifiers and names everywhere
+all man pages should carry version numbers
+Use Stephen Parker's htmltoc, with many bug fixes and improvements.
+
+
+CHANGES FOR VERSION 2.8
+
+fixed unbalanced brace in support.nw for nwmac.tex (Hartmut Henkel)
+changed notangle script so notangle -L preserves tabs (Saul London, NR)
+changed uniqueid in noidx to avoid everything except letters, digits,
+ and a few known special chars. fixes the Norwegian bug (Hans
+ Husum) and also the non-Posix regexp (Christian Wagner)
+update recognizer.nw to use 128-node recognizer for larger character sets
+ as per Christian Wagner
+$arkopts -> $markopts for noweave -v
+noweave now uses \documentclass for headers
+fixed a bug in tohtml ``impossible character to skip''
+hacked \catcode \other for " in \setupcode,
+ which is better for german.sty even though \setupmodname is still wrong
+added support for @fatal to all pipeline stages;
+ noweave and notangle now detect pipeline errors and exit nonzero
+added Lee Wittenberg's changes to support.nw and totex.nw to support
+ printing of index identifiers in different fonts
+updated documentation to be consisten with latex2e, e.g., talk about
+ the noweb 'package' not the 'document-style option'.
+ Kept nowebstyle(1) for backward compatability.
+added \nextchunklabel to support dotNoweb (replaces its \chunklabel)
+massive improvements to l2h, including support for tables
+moved nowebstyle and nowebfilters man pages to section 7
+noweave -v shows @header and @trailer
+
+
+CHANGES FOR VERSION 2.7d
+
+noweb.sty steals \{ and \} in chunk names. Bad dog! No biscuit!
+Forgot to include [noweb] style in numarkup.nw
+changed <- to &lt;- in tohtml and l2h, and similarly for ->
+HTML output of noweb tools is now weblint-clean
+didn't properly skip <!-- ...> in tohtml
+bug fix for bad indentation when chunk starts at beginning of line
+added many more control sequences to l2h
+added % l2h closure, makes nr's \secn, \fig, and the like possible.
+
+
+
+CHANGES FOR VERSION 2.7c
+
+Fixed bug in l2h, wasn't treating quotes in @use correctly.
+Added -autodefs pascal (a hack)
+Fixed bug in tohtml, with noweave -option longxref was showing uses twice
+Fixed ``black magic'' claim in man page to refer to -option longxref...
+Fixed tohtml to make placement of anchors nest properly when possible
+Underscores in filenames are now in FAQ
+Added the htmltoc command
+
+
+CHANGES FOR VERSION 2.7b
+
+Changed module->chunk in error message 'undefined module name'
+Added touch to `make source' in a forlorn attempt to eliminate once
+ and for all the problem of sources and derived sources with
+ identical timestamps
+Added `make touch' in case CTAN screws up timestamps, and updated FAQ.
+Disabled assertions in lexer (markmain.nw)
+Added pointer to noweb home page to README
+Mention sharpline in the man page entry for notangle -L
+@@ in column 1 now stands for a single @ sign.
+Change my address from Bellcore to Purdue.
+Preliminary support for hypertext with hyper.sty.
+
+CHANGES FOR VERSION 2.7a
+
+Move @xrev prevdef and @xref nextdef to appear before @defn, to
+ support navigational aids as in Fraser and Hanson's book.
+ Requires changes in totex and tohtml to delay xref output.
+ Support.nw now makes long vs short a noweb option.
+Hack noweave to pass -shortxref to backend on seeing `-option shortxref'
+Offer shortxref support in tohtml.
+Changed noidx to avoid putting anchor labels in empty documentation chunks.
+Fixed bug in l2h; was treating saved ignore flag as text fun after copying bracket.
+tohtml dumped core if it tried to warn of bad tag with null arg
+Botched local definitions in autodefs files
+SHELL=/bin/sh in Makefiles
+Improvements in l2h, including multiple citations.
+Fixed Makefile in xdoc to build techrep with wc.tex now that examples have moved
+Fix bugs in awkname; thanks to Steven Ooms for the bug report and the fix.
+In INSTALL, noted special awk problems for HP-UX users.
+Change noweb.sty to use \textwidth, not \hsize, to place use/def markup
+Fixed bug in -autodefs.c (confusion around static storage class)
+Quoted code no longer makes l2h forget what mode it was in ($[[x]]+1$)
+Uses in quoted code (e.g., [[<<exported functions>>]]) are now
+ formatted sensibly and with proper cross-reference. As a side effect,
+ lexical analysis is faster.
+
+CHANGES FOR VERSION 2.7
+
+New directory structure, new Makefiles.
+Distributing gzipped tar file instead of compressed shell archive.
+Added l2h filter to convert latex to HTML.
+Added -markup option to tools
+contrib/norman now has a numarkup, which is markup for nuweb
+Fixed unmarkup to handle nuweb chunks, which don't end in newlines.
+The awk versions of filters are even more inferior to the Icon versions,
+ and they are barely tested. I will fix bugs as they are reported.
+
+CHANGES FOR VERSION 2.6d (which never left Bellcore)
+
+New copyright, intended to make it possible to sell CD-ROMs containing noweb
+Revisions to the Noweb Hacker's Guide
+Added 'elide' filter to icon directory.
+Changed totex to turn a reference to ??? into one to nw@notdef
+Commented out references to \code and \edoc in support.nw
+ (too chicken to eliminate them completely)
+Changed lib/tohtml not to use the awk 'length' variable --- mawk barfs
+ (thanks to Bill Trost for bug report)
+Changed tohtml not to plant anchor on < or & because that
+ could start an SGML tag (thanks to Bill Trost for bug report)
+Awk version of tohtml used && in patterns; some awks couldn't handle it.
+ (thanks to Mark Smucker for bug report)
+Changed \filename to \nwfilename to avoid conflicts with some latex2e packages
+Help for the most frequent problems now in INSTALL.
+Fixed a bug that bit noweave -index when there are multiple definitions
+ of an identifier; tag of first defn was repeated instead of
+ getting all tags (thanks to Michael Norrish for bug report).
+noweave -html -x was producing local index stuff, but it shouldn't.
+Decided -html shouldn't disable -noindex in noweave script
+Improved tohtml so it needn't insert * for an anchor so often.
+Changed notangle internally so it doesn't complain
+ if a chunk doesn't end with a newline (possible with nufront)
+changed noweave so -index no longer forces a latex wrapper
+Changed noidx so it won't use HTML specials in unique ids
+Changes tohtml not to quote HTML in chunk names
+
+
+CHANGES FOR VERSION 2.6c
+
+Added -v option to noweave to show the pipeline.
+A preliminary Noweb Hacker's Guide.
+
+CHANGES FOR VERSION 2.6b
+
+Added -autodefs c
+
+Changed installation procedure so that source is no longer distributed
+with contributed software --- you now must install noweb, then build
+contributed software.
+
+Bug fixes:
+
+ - Makefile didn't create .../man/man1
+ - noweave botched -x option, emitted index info anyway
+ - markup complained, incorrectly, about [[<<]] in documentation.
+ - noidx died if it tripped over an identifier used only in quoted code
+ - tohtml wasn't inserting doc anchor into above_defns, so some xrefs
+ that should have read `above' were coming out `below'
+ - when one identifier was a prefix of another, as in
+ Class and Class::member, finduses duplicated the prefix.
+
+
+CHANGES FOR VERSION 2.6a
+
+Fix bug in finduses that bit on the HP snake.
+
+CHANGES FOR VERSION 2.6
+
+For the HTML support
+ - Invented lots of new @xref markup to support cross-referencing and
+ indexing in a formatter-independent way.
+ - Rewrote noidx and totex to push cross-reference and index support into
+ the back end.
+ - Adapted an HTML back end contributed by Bill Trost
+Dave Love provided the bug fixes for latex2e.
+
+CHANGES FOR VERSION 2.5:
+
+Improved Source Code
+
+Several parts of the source code have been rewritten in noweb. I
+especially call your attention to the contents of the shell, lib, and
+tex directories. Reading tex/support.nw will help you tinker with
+formatting.
+
+
+Enhanced Latex Support
+
+Includes INCOMPATIBLE changes to options accepted by noweave (and
+noweave's default behavior). noweb now supports an index of
+identifiers and identifier cross-reference in a language-independent
+way. For more information, see the man page for noweave, especially
+the -index option. The man page for noindex tells how to build
+indexes for large, multi-file documents.
+
+I have added a `noweb' command that acts much like Preston Briggs's
+`nuweb'; it extracts all the source programs and also writes a LaTeX
+document with full cross-referencing. See the man page for details.
+
+latex support has been improved by changes to noweave, the noweave
+cross-referencer, and the noweb document-style option. Dave Love and
+Jon Krom provided impetus for some of these changes in the best
+possible way; they sent code. Improvements include:
+ -- noweave now generates latex headers by default.
+ -- Code chunks are broken across pages only when they are more than
+ a page long. (Thanks to Dave Love.)
+ -- Thanks to Dave Love, cross-referenced definitions that appear on
+ the same page are now numbered 7a, 7b, 7c, etc. (optionally 7.1,
+ 7.2, 7.3, or just plain 7; see the noweave man page).
+ -- There is a `noweb' pagestyle, which puts source-file names and
+ dates on the header line. It is the default page style for noweave.
+ -- noweave inserts no extra newlines, so the line numbers are the
+ same in the .tex and .nw files (Dave Love's suggestion; a major win).
+ -- By using noweave -delay, you can put a latex preamble in the
+ first documentation chunk, and noweave will delay \filename and
+ \begindocs until after the preamble, which becomes a WEB-like
+ ``limbo'' area (suggested by Dave Love, Jon Krom, and others).
+ -- noweave now has a -filter option that lets you name a
+ cross-referencer or prettyprinter on the command line.
+ You can try Jon Krom's cross-referencer by using
+ noweave -filter $LIB/noxref.krom
+ -- notangle has a -filter option that you can use to implement
+ slightly different semantics, such as Knuth's ``...''
+ abbreviation convention.
+ -- The awk version of the cross-referencer is now almost as good as
+ the Icon version; the sole remaining difference is that the Icon
+ version ignores case when sorting; the awk version does not.
+ -- Bug fixes in noweave's handling of special characters in chunk names.
+ -- Many of the shell and awk scripts are now noweb files.
+ -- \chunklist is now \nowebchunks, and it need not appear on a line
+ by itself. \nowebindex provides an index.
+ -- The TeX support is now somewhat documented; see tex/support.nw
+ -- Support for latex's New Font Selection Scheme (whatever that is),
+ thanks again to Dave Love.
+
+Finally, Kostas Oikonomou has contributed a simple prettyprinter for
+Icon programs, and Conrado Martinez-Parra has contributed a
+prettyprinter for Dijkstra's language of guarded commands. I have
+made both suitable for use with noweave -filter.
+
+
+Bug Fix
+
+The code that was supposed to prevent a chunk from including itself
+didn't work at all. So
+<<*>>=
+Forever <<*>>
+@ made notangle very unhappy.
diff --git a/web/noweb/COPYRIGHT b/web/noweb/COPYRIGHT
new file mode 100644
index 0000000000..61fae52cca
--- /dev/null
+++ b/web/noweb/COPYRIGHT
@@ -0,0 +1,24 @@
+Noweb is copyright 1989-2018 by Norman Ramsey. All rights reserved.
+
+Noweb is protected by copyright. It is not public-domain
+software or shareware, and it is not protected by a ``copyleft''
+agreement like the one used by the Free Software Foundation.
+It may be used and/or redistributed using *either* the terms
+stated here *or* by the 2-clause BSD license found in file LICENSE.
+
+Noweb is available free for any use in any field of endeavor. You may
+redistribute noweb in whole or in part provided you acknowledge its
+source and include this COPYRIGHT file. You may modify noweb and
+create derived works, provided you retain this copyright notice, but
+the result may not be called noweb without my written consent.
+
+You may sell noweb if you wish. For example, you may sell a CD-ROM
+including noweb.
+
+You may sell a derived work, provided that all source code for your
+derived work is available, at no additional charge, to anyone who buys
+your derived work in any form. You must give permisson for said
+source code to be used and modified under the terms of this license.
+You must state clearly that your work uses or is based on noweb and
+that noweb is available free of change. You must also request that
+bug reports on your work be reported to you.
diff --git a/web/noweb/CTAN b/web/noweb/CTAN
new file mode 100644
index 0000000000..f034f1b9fc
--- /dev/null
+++ b/web/noweb/CTAN
@@ -0,0 +1,28 @@
+Administrative notes for CTAN upload:
+
+ - The distribution contains 7 .bbl files, which are there to enable
+ users to build documentation or examples.
+
+ - The distribution contains many files with duplicate basenames,
+ e.g., noidx.nw, noindex.nw, noroots.nw, and so on. These
+ different files have identical basenames because they provide
+ identical functionality on different platforms, or because they
+ provide documentation of that functionality. For example,
+
+ src/awk/noindex.nw Index building on Unix using Awk
+ src/icon/noindex.nw Index building on Unix using Icon
+ contrib/rsc/rc/noindex.nw Index building using the Plan 9 shell RC
+ xdoc/noindex.nw Man page for index building
+
+ None of these files is ever exposed to kpathsea or to TeX, so name
+ clashes should not be a problem.
+
+ - The distribution includes TeX source for two papers about Noweb: a
+ 1991 technical report and a 1993 submission to IEEE Software.
+ Both .tex files refer to information that is no longer current,
+ including the obsolete FTP server ftp.tex.ac.uk. Because the
+ intent of the distribution is to provide interested readers with
+ access to these documents as they were published, these references
+ will not be changed.
+
+
diff --git a/web/noweb/DATE b/web/noweb/DATE
new file mode 100644
index 0000000000..97856accd9
--- /dev/null
+++ b/web/noweb/DATE
@@ -0,0 +1 @@
+Version 2.12 of Wed Jun 20 12:21:27 EDT 2018
diff --git a/web/noweb/DEBIAN b/web/noweb/DEBIAN
new file mode 100644
index 0000000000..fd1f2a91d7
--- /dev/null
+++ b/web/noweb/DEBIAN
@@ -0,0 +1,19 @@
+Under noweb's original licence, anyone may modify noweb and create
+derived works, provided he or she retains this copyright notice, but
+the result may not be called noweb without my written consent. I
+hereby provide my written consent to the Debian project to call their
+derived work 'noweb'. I do so under the assumption that Debian's
+modifications are normally intended to fix bugs, close security holes,
+and bring the software into compliance with Debian policy. I have a
+great deal of trust in and respect for the Debian project, so I am in
+fact willing for the Debian project to make any modification they deem
+necessary and still call the result 'noweb'. In particular, there is
+no need for the Debian project to consult me about any contemplated
+modification, either now or in the future. I do reserve the right to
+revoke my consent in the unlikely event that, in my opinion, future
+Debian modifications will have made it misleading to call the package
+'noweb'.
+
+Under the BSD license, anyone may create a derived work and to call it
+noweb without my written consent.
+
diff --git a/web/noweb/DEBIAN.asc b/web/noweb/DEBIAN.asc
new file mode 100644
index 0000000000..0788abba25
--- /dev/null
+++ b/web/noweb/DEBIAN.asc
@@ -0,0 +1,16 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAABCAAdFiEEmrzhALHbgoRRr4rgZfoIXblrJmkFAlsr5Q8ACgkQZfoIXblr
+JmmjChAAi23ohCcof9Z8rf6bshdr8gxYPvFuep5YTIJRmi4aw6nMMMCmrEZC9cvk
+C7TjDeg8TY9z/t0VelcMSepxwjTnJ/r4rm33xIkyojPp277YfU4bmdbR+LavvE5o
+g9z745KAUkemAVBSKH4aieJt+XJ6EMKh/AjPjYzZsGZAfcDrmjCQo4gMM781RSq5
+wBTTxmqHstZ9gRiibu9Pxks1zE+zmf/lpKhP8bYNRCRnYzEuVbDzNesVimFnSZkC
+erxGnIGjmVaUBc0B1LYAfOj/vTYx0h/mxXpeq/1oUpEsO0mslrGxKnB/WPjDVRg7
+/R68gFg6+ptk6IIlwzk9eCIXMcXia1ax10S2RysARmHhYwcGaEkfKFfVcwlK0xlU
+0dhcJ8pSZ2aw+/NP5FLqgBfxt2Fg/YVvwOII37azmkxb3BmUO6UpuxObIsMDmOun
+8fPum5+bzyWGUIevWHSt/cw37BLEWKoS+SKV8MLDZjP2qp5vYlIQNGdW0/pypSHC
+qUEghZpTOxTFU7A3qtVO3ksOqTrxIDqc72Qe6f3i8KBT8Nw1xplKygDesYmTJ85t
+aftWYTizQ4QQHk2GzW5UPzxoVzUQYYIANTOu5sESdOjf4a99FvHc6lu9pIWMSqvk
+0nqbxMjODpNaYbHRF3LxZx2Qv1nHgj5n+M4le5zzM2PBpgAo1GE=
+=y3B3
+-----END PGP SIGNATURE-----
diff --git a/web/noweb/LICENSE b/web/noweb/LICENSE
new file mode 100644
index 0000000000..3a62e12067
--- /dev/null
+++ b/web/noweb/LICENSE
@@ -0,0 +1,26 @@
+BSD 2-Clause License
+
+Copyright © 2018, Norman Ramsey
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/web/noweb/Makefile b/web/noweb/Makefile
new file mode 100644
index 0000000000..f2fd5753a6
--- /dev/null
+++ b/web/noweb/Makefile
@@ -0,0 +1,66 @@
+# Copyright 1995-2006 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+#
+# Don't edit this file; you should be editing the Makefiles in the
+# src and contrib directories.
+
+VERSION=2.12
+SHELL=/bin/sh
+CINAME=-Nv`echo $(VERSION) | tr . _`
+CIMSG=-f -m'standard checkin preparing to export version $(VERSION)'
+
+all:
+ @echo "You have no business running 'make' here; please look at the README file"
+ @exit 1
+source: ; for i in src; do (cd $$i; make source); done
+www: ; for i in src/xdoc examples; do (cd $$i; make www); done
+
+clean:
+ for i in src examples contrib; do (cd $$i; make clean); done
+ rm -f nwsrcfilter *~ */*~
+clobber: clean
+ for i in src examples contrib; do (cd $$i; make clobber); done
+
+DATE:
+ (./echo -n "Version $(VERSION) of "; date) > DATE
+
+versioncheck:
+ @if [ -z "$(UPPERVERSION)" ]; then echo "run 'make versioncheck' in the parent directory, not here" 1>&2; exit 1; fi
+ @if [ "$(VERSION)" = "$(UPPERVERSION)" ]; then echo "Version $(VERSION) OK in Makefile"; else echo "Version mismatch in Makefile: upper $(UPPERVERSION) lower $(VERSION)"; exit 1; fi
+ @if [ "$(VERSION)" = "`awk '{print $$2}' DATE`" ]; then echo "Version $(VERSION) OK in DATE"; else ./echo -n "Version mismatch in DATE: "; cat DATE; exit 1; fi
+ @if fgrep -s "This is version $(VERSION) of " README; then echo "Version $(VERSION) OK in README"; else echo "Version mismatch in README"; exit 1; fi
+ @if fgrep -s "CHANGES FOR VERSION $(VERSION)" CHANGES; then echo "Version $(VERSION) OK in CHANGES"; else echo "Version mismatch in CHANGES"; exit 1; fi
+ @if fgrep -s " for version $(VERSION) of" src/README; then echo "Version $(VERSION) OK in src/README"; else echo "Version mismatch in src/README"; exit 1; fi
+ @if fgrep -s "version $(VERSION)" src/xdoc/notangle.txt; then echo "Version $(VERSION) OK in src/xdoc/notangle.txt"; else echo "Version mismatch in src/xdoc/notangle.txt"; exit 1; fi
+
+nwsrcfilter: nwsrcfilter.icn
+ icont nwsrcfilter
+
+tarnames: clean source nwsrcfilter DATE
+ find . -not -type d -not -name FAQ.old -print | ./nwsrcfilter
+
+tar: clean source nwsrcfilter DATE emacscheck
+ chmod +w src/Makefile
+ rm -rf /tmp/noweb-$(VERSION)
+ mkdir /tmp/noweb-$(VERSION)
+ tar cvf - `find . ! -type d -not -name FAQ.old -print | ./nwsrcfilter` | (cd /tmp/noweb-$(VERSION) ; tar xf - )
+ (cd /tmp; tar cf - noweb-$(VERSION) ) | gzip -v > ../noweb-$(VERSION).tgz
+ rm -f ../noweb.tgz
+ (cd .. ; ln -s noweb-$(VERSION).tgz noweb.tgz)
+ chmod -w src/Makefile
+
+ctan: clean source nwsrcfilter DATE emacscheck
+ chmod +w src/Makefile
+ (cd src; make boot)
+ rm -f ../noweb-$(VERSION)-ctan.zip
+ find ./* ! -type d -not -name FAQ.old -not -name '.git*' -print | ./nwsrcfilter | sed 's@^@noweb/@' | ( ln -s . noweb; zip ../noweb-$(VERSION)-ctan.zip -@; rm -f noweb )
+ chmod -w src/Makefile
+
+emacscheck:
+ -echo "Checking to ensure distribution matches personal emacs mode" 1>&2
+ diff src/elisp/noweb-mode.el $(HOME)/emacs/noweb-mode.el
+
+checkin:
+ (cd src; make "CINAME=$(CINAME)" "CIMSG=$(CIMSG)" checkin)
+
+
diff --git a/web/noweb/README b/web/noweb/README
new file mode 100644
index 0000000000..0ba30b32cb
--- /dev/null
+++ b/web/noweb/README
@@ -0,0 +1,244 @@
+This is version 2.12 of ``noweb'', a simple, extensible literate-
+programming tool. noweb is available from the Github repository
+https://github.com/nrnrnr/noweb, and it is mirrored by the
+Comprehensive TeX Archive Network. It is distributed under the BSD-2
+open-souce license. Other helpful information can be found on noweb's
+home page at http://www.cs.tufts.edu/~nr/noweb.
+
+The most convenient way to get noweb is to install it from a package;
+the procedure for building noweb from source dates from 1989, and it is
+both baroque and brittle. If you must build noweb from source, change
+to the `src' directory and follow the instructions in the file INSTALL.
+(Windows users, look for http://www.jim-pettigrew.com/noweb/install.)
+
+
+WHAT'S NEW IN VERSION 2.12
+
+Version 2.12 now has a dual license: in addition to noweb's original
+license, it is licensed under the BSD 2-clause license.
+
+Version 2.12 no longer defines a getline() function, which conflicted
+with a new POSIX standard. And it no longer uses the deprecated
+tempnam(3).
+
+Version 2.12 contains a number of enhancements to the sl2h program and
+l2h filter, which convert from LaTeX to HTML. They now deal with
+\suspend and \resume from \usepackage{mdwlist}, and they also convert
+some TeX ligatures to HTML entities, most notably the -- and ---
+ligatures. Thanks to Christian Lynbeck, 2.12 also has new Emacs Lisp
+code that better supports font-lock. Other than that, 2.12 fixes a
+number of bugs, the most notable of which is that the emacs noweb-mode
+command is now compatible with Emacs 25 desktop-read and desktop-save.
+
+
+INTRODUCTION --- WHAT IS NOWEB, ANYWAY?
+
+noweb is designed to meet the needs of literate programmers while
+remaining as simple as possible. Its primary advantages are
+simplicity, extensibility, and language-independence. noweb uses 5
+control sequences to WEB's 27. The noweb manual is only 3 pages; an
+additional page explains how to customize its LaTeX output. noweb
+works ``out of the box'' with any programming language, and supports
+TeX, latex, and HTML back ends. A back end to support full hypertext
+or indexing takes about 250 lines; a simpler one can be written in 40
+lines of awk. Noweb does not prettyprint natively, but supports
+prettyprinting through such third-party filters as pretzel and dpp.
+
+noweb has been distributed free of charge for thirty years, and it is
+one of the world's most widely used literate-programming tools. It
+has been used for hundreds of thousands of lines of code in such
+languages as awk, C, C++, Haskell, Icon, Lua, Modula-3, Objective
+Caml, PAL, perl, Promela, and Standard ML.
+
+If you already know you want to use noweb, you need only install it
+and read the manual page. If you're just curious about noweb, read
+the paper that appeared in the September 1994 issue of IEEE Software.
+(If you can't get Software, send me a postcard and I'll send you a
+reprint.) A nice, brief tutorial appeared in the October 1997 issue
+of Linux Journal (but beware that chunk syntax is <<name>> and not <<name>).
+
+If you're brand new to literate programming, check out the FAQ for the
+USENET newsgroup comp.programming.literate. There are also some
+resources available through the noweb home page:
+ http://www.cs.tufts.edu/~nr/noweb
+
+
+WHAT YOU GET IN THIS DISTRIBUTION
+
+This distribution contains the following directories:
+ binaries Pre-built distributions containing binaries and documentation
+ contrib software contributed by noweb users
+ examples sample noweb filters and programs in different languages
+ src Source code and documentation (including FAQ) for noweb
+Where appropriate, these directories have README files of their own.
+BINARY DISTRIBUTIONS MAY NOT ALWAYS BE UP-TO-DATE, especially DOS
+distributions.
+
+
+EXTENSIBILITY
+
+noweb provides extensibility by using the Unix toolkit philosophy.
+The ``noweb,'' ``notangle,'' and ``noweave'' commands are built from
+pieces, which are then assembled in pipelines using shell scripts.
+The pieces include:
+
+ markup convert noweb file from human syntax to tool syntax
+ unmarkup inverse of markup
+ totex convert from tool syntax to TeX/latex markup
+ tohtml convert from tool syntax to HTML markup
+ nt `tangle' the tool form of the noweb file
+ mnt discover roots, then act like nt
+ noidx insert indexing and cross-reference information
+ finduses finds uses of identifiers
+
+These pieces are combined by the scripts in the src/shell directory to
+provide more than just weaving and tangling:
+
+ noweb analog of nuweb
+ notangle analog of TANGLE
+ noweave analog of WEAVE
+ nountangle tangle, but keep interleaved documentation in comments
+ noroots print names of all root chunks in a noweb file
+ nocount count number of lines of code and documentation.
+ nodefs extract defined identifiers for noweave -indexfrom
+ noindex build an external index for multi-file documents
+
+
+WEAVING --- A TAR PIT
+
+The worst aspect of literate programming is the enormous amount of
+time wasted wrangling over what ``woven'' output should look like.
+Although noweb does no prettyprinting, it is not entirely immune---
+several people have complained about noweave's output or have sent me
+changes that add more options to noweave. I resisted for years, but
+with version 2.5 I finally succumbed. I let the number of options to
+noweave double, and I have provided for too many options and hooks for
+customizing the latex output. I won't let it happen again.
+
+noweb doesn't try to be all things to all programmers, but it is very
+easy to change. If you don't like noweave's formatting, you can read
+tex/support.nw to learn how to customize it; look for the words
+``style hook.'' (Reading noweb.sty directly is not recommended.) For
+simple formatting, it might be easier to throw away noweave and make
+your own. To help you get started, the shell directory contains
+noweave.simple, a simplified version of noweave that Dave Hanson
+created for use with C programs (it can't handle code with @ signs).
+The Noweb Hacker's Guide (xdoc/guide.tex) explains the intermediate
+language that noweb uses to represent literate programs.
+
+The intermediate language makes it possible to extend noweave with a
+language-dependent prettyprinter, as shown by contributions of an Icon
+prettyprinter by Kostas Oikonomou and a guarded-command prettyprinter
+by Conrado Martinez-Parra. (I haven't written a prettyprinter myself
+because my experience with Spider left me thinking that prettyprinting
+is far more trouble than it's worth.) Further contributions of
+prettyprinters are welcome.
+
+noweb comes with two cross-referencers for use with noweave. The
+standard one is written in Icon, because Icon offers excellent
+functionality and performance. Because Icon is not available on all
+platforms, I profide an alternative, but inferior cross-referencer
+written in awk. See the INSTALL file for details.
+
+Cross-referencing makes formatting even more of a tar pit; the
+cross-referencer itself takes about 300 lines, and extensive LaTeX
+support is also required. I haven't made the attempt to write
+cross-reference code for plain TeX. Anyone who has ideas for reducing
+the number of options or for other ways to restore sanity to the
+situation is urged to write to nr@cs.tufts.edu.
+
+
+INDEX AND IDENTIFIER CROSS-REFERENCE
+
+Noweb creates identifier cross-references so that you can click on an
+identifier and jump to its definition (if you're using printed LaTeX
+output, a footnote gives you the page number of the definition).
+To noweb, any string of nonwhite characters can be an identifier.
+A human being or a language-dependent tool must mark definitions of
+identifiers; noweb finds the uses using a language-independent
+algorithm. The algorithm relies on an idea taken from the lexical
+conventions of Standard ML. Characters are divided into three
+classes: alphanumerics, symbols, and delimiters. If an identifier
+begins with an alphanumeric, it must be delimited on the left by a
+symbol or a delimiter. If it begins with a symbol, it must be
+delimited on the left by an alphanumeric or a delimiter. If it begins
+with a delimiter, there are no restrictions on the character
+immediately to the left. Similar rules apply on the right-hand side.
+The default classifications are chosen to make sense for commonly used
+programming languages, so that noweb will not recognize `zip' when it
+sees `zippy', or `++' when it sees `++:='. This trick works
+surprisingly well, but it does not prevent noweb from spotting
+identifiers in comments or string literals.
+
+The basic assumption in noweb is that a language-dependent filter will
+identify definitions automatically. Filters for Icon, TeX, and yacc
+all take about 30 lines of Icon code and are included in the noweb
+distribution; if you write a filter of your own, you can put it in the
+$LIB directory with a name like `autodefs.pascal'. Try `noweave
+-showautodefs' for a complete list of such filters.
+
+If the automatic filter does not work well for you, or if there is no
+filter available for your language, I recommend that you mark
+definitions using backticks (`) in your source code, and use
+`-filter btdefn' with both noweave and notangle.
+
+noweave -index works well for short programs, but nodefs, noindex, and
+noweave -indexfrom are there for large multi-file programs. See the
+noindex man page for details.
+
+
+NOTES
+
+ src/xdoc/techrep.* contains an early, almost unrecognizable version
+ of a paper describing noweb that appeared in IEEE Software in
+ September, 1994. You are probably better off writing me for a
+ reprint of the Software paper. (Send a postcard!)
+
+ The Noweb Hacker's Guide, which appears in src/xdoc/guide.*,
+ documents the representation of noweb files that is used by the
+ noweb tools, in case you want to write any tools of your own.
+ Simple tools (e.g. count the number of lines of interleaved
+ documentation) are trivial. If you write any tools, or you want
+ tools written (e.g. prettyprinters, index generators), let me know.
+
+ The icon directory contains Icon versions of most pipeline
+ stages. If you want to adapt noweb to work with a text processor
+ other than TeX or latex, they might provide a better starting point.
+ Perhaps the whole system should have been written in Icon from the
+ beginning, but I'm not going to do it over. Icon is available by
+ anonymous ftp from cs.arizona.edu.
+
+
+ Thanks to Preston Briggs for the Aho-Corasick recognizer, and for
+ helpful discussions.
+ Thanks to Dave Hanson for cpif.
+ Thanks to Dave Love for LaTeX wizardry.
+ Thanks to Joseph Reynolds for prodding me to fix [[...]].
+ Thanks to Bill Trost for the original HTML back end.
+ Thanks to Phil Bewig for the troff support.
+ Thanks to Philip Miller and Lee Wittenberg for DOS binaries.
+ Thanks to Paolo Ciccone for the Win32 binaries.
+ Thanks to Hubert Chathi for picking up the Debian distribution.
+
+Send comments or questions to nr@cs.tufts.edu.
+
+I enjoy hearing from noweb users; if you have enjoyed noweb, why not
+send me a local postcard for my collection? My address is:
+
+ Norman Ramsey
+ Department of Computer Science
+ Tufts University
+ 161 College Avenue
+ Medford, MA 02155
+ USA
+
+
+COPYRIGHT
+
+Noweb is copyright 1989-2018 by Norman Ramsey. All rights reserved.
+
+You may use and distribute noweb for any purpose, for free. You may
+modify noweb and create derived works, provided you retain the
+copyright notice, but the result may not be called noweb without my
+written consent. You may not sell noweb itself, but you may do
+anything you like with programs created with noweb.
diff --git a/web/noweb/contrib/Makefile b/web/noweb/contrib/Makefile
new file mode 100644
index 0000000000..0e048da8ea
--- /dev/null
+++ b/web/noweb/contrib/Makefile
@@ -0,0 +1,13 @@
+SHELL=/bin/sh
+LIB=/dev/null # to be overridden
+ICONC=icont # to be overridden
+DIRS=davelove jonkrom leew norman
+
+# don't do kostas; it requires gnu make (ugh)
+
+all: ; for i in $(DIRS); do (cd $$i; make ICONC=$(ICONC) all); done
+install: ; for i in $(DIRS); do (cd $$i; make LIB=$(LIB) BIN=$(BIN) install); done
+source: ; for i in $(DIRS); do (cd $$i; make source); done
+clean: ; for i in $(DIRS); do (cd $$i; make clean); done
+clobber: clean
+
diff --git a/web/noweb/contrib/README b/web/noweb/contrib/README
new file mode 100644
index 0000000000..7b5d7c97ed
--- /dev/null
+++ b/web/noweb/contrib/README
@@ -0,0 +1,9 @@
+These directories contain software that was contributed by users of
+noweb. Each directory contains a file called `email' that has the
+email address of the contributor. I don't pretend to have copyright
+rights, and I don't provide any warranty or any support. If you find
+something useful here, we're both pleased.
+
+Some contributed software contains binaries or is too big to be
+included in the standard noweb distribution. In such cases, the
+directories here may contain only pointers to anonymous ftp sites.
diff --git a/web/noweb/contrib/avs/email b/web/noweb/contrib/avs/email
new file mode 100644
index 0000000000..9c280ceffc
--- /dev/null
+++ b/web/noweb/contrib/avs/email
@@ -0,0 +1,2 @@
+avs@daimi.aau.dk (Alexandre Valente Sousa)
+If this doesn't work (in a couple of years it won't) try avs@monet.inescn.pt
diff --git a/web/noweb/contrib/avs/filelist.txt b/web/noweb/contrib/avs/filelist.txt
new file mode 100644
index 0000000000..73ee43dd75
--- /dev/null
+++ b/web/noweb/contrib/avs/filelist.txt
@@ -0,0 +1,59 @@
+File list for noweb/contrib/avs
+This is not in Noweb 2.7a but it has been proposed to be in the contrib dir
+Thus these files are from ftp.daimi.aau.dk:/pub/empl/avs/avs386_noweb27a.tar.gz
+
+Although the target is Dos I use .tar.gz format instead of .arj or .zip because
+anyhow you need DJGPP (which has gzip) and MKS (which has tar) to use this. For
+your convenience just in case (i.e. you only have MKS yet and will be using
+my instructions to get DJGPP) I supply the file
+ftp.daimi.aau.dk:/pub/empl/avs/gzip386.exe' (you should rename it to gzip.exe)
+
+ CHANGE THIS:
+myenv.ksh --> edit this file for your environment (Korn shell script)
+
+ DOCUMENTATION:
+readme --> brief description
+email --> my contact info
+norman1.txt --> mail sent to Norman Ramsey describing this Dos HOWTO
+filelist.txt --> this file
+howto386.txt --> documentation/troubleshooting/explanation/Dos recipe
+ftpsites.txt --> where to get additional software that might be required
+
+ ADDITIONAL DOCUMENTATION:
+icon.1 --> NROFF processed man file for Icon (because we are using it)
+jrtex12a.avs --> excellent J. Refling's PC386 LaTeX2e HOWTO annotated by me
+mks42bug.0d --> text file with my personal list of MKS 4.2 bugs
+report1.bug --> bug report for noweb 2.7a
+
+ BUILD & INSTALL SCRIPTS (used by myenv.ksh):
+mksfixes.ksh --> fix noweb.ksh and cpif.ksh for the MKS Toolkit 4.2
+generate.ksh --> generates 'automate.bat' (the build/install script)
+nwicon.bat --> Make Icon code (the '\\\\' hack)
+nw_c.bat --> Patch DJGPP bug & Make C code & avoid out of memory errors
+nwinst.ksh --> install Noweb (just to separate install from build)
+make_ico.awk --> patches noweb/src/icon/makefile for Ms-Dos
+make_src.awk --> patches noweb/src/makefile for Ms-Dos
+make_xdo.awk --> patches noweb/src/xdoc/makefile for Ms-Dos
+make_lib.awk --> patches noweb/src/lib/makefile for Ms-Dos
+
+ 2 17 122 email
+ 59 353 2735 filelist.txt
+ 63 412 2978 ftpsites.txt
+ 114 687 4883 generate.ksh
+ 254 2270 13918 howto386.txt
+ 330 1243 10462 icon.1
+ 1054 5692 43470 jrtex12a.avs
+ 50 297 1694 make_ico.awk
+ 12 80 498 make_lib.awk
+ 72 509 2832 make_src.awk
+ 14 104 593 make_xdo.awk
+ 128 1219 7347 mks42bug.0d
+ 14 110 714 mksfixes.ksh
+ 38 321 1923 myenv.ksh
+ 136 1409 8168 norman1.txt
+ 62 288 2077 nw_c.bat
+ 43 201 1411 nwicon.bat
+ 9 33 253 nwinst.ksh
+ 39 302 1807 readme
+ 97 796 4554 report1.bug
+ 2590 16343 112439 total
diff --git a/web/noweb/contrib/avs/ftpsites.txt b/web/noweb/contrib/avs/ftpsites.txt
new file mode 100644
index 0000000000..8abcbd4bdc
--- /dev/null
+++ b/web/noweb/contrib/avs/ftpsites.txt
@@ -0,0 +1,65 @@
+NOTE: The information below is from May 30, 1995. It is likely to be
+obsolete. And to appease the maintainers of CTAN, references to ftp
+dot tex dot ac dot uk have been removed.
+----------------------------------------------------------------
+These are the anonymous ftp sites that I prefer (I am in Europe and these are
+the fastest sites for me)
+
+Noweb 2.7a (only in this site in 29-May-95)
+ftp.shsu.edu:/pub/tex/web
+
+Noweb 2.7
+(No longer available. Try https://github.com/nrnrnr/noweb, tag v2_7,
+or better yet, a version that is up to date.)
+
+How to build Noweb 2.7a for Dos + PC386 + MKS toolkit
+ftp.daimi.aau.dk:/pub/empl/avs/avs386_noweb27a.tar.gz
+(my site, just for completeness, you might also want to look there for a newer
+version in case some bug in my scripts has been reported and fixed)
+
+emTeX 386 3.1415 [3c-beta12], LaTeX2e (1-Dec-94 patch level 1), Dvips 5.54
+(several ftp sites must be used, see the file 'jrtex12a.avs')
+
+Chicago LaTeX package (required by noweb/src/xdoc/guide.tex)
+CTAN
+Assuming that you followed the instructions from the file 'jrtex12a.avs' put
+the 3 files (chicago.bst, chicago.sty, chicagoa.bst) in
+?:/emtex/texinputs/local)
+
+DJGPP (GNU software Dos port for PC 386)
+ftp.funet.fi:/pub/mirrors/oak.oakland.edu/Simtel/msdos/djgpp (empty in
+21-Mar-95 due to disk crash)
+or
+omnigate.clarkson.edu:/pub/msdos/djgpp
+or
+oak.oakland.edu:/pub/msdos/djgpp
+The easiest way is to get the README's and FAQ (readme.1st, readme.dj,
+djgpp.faq), to read them, and then to get the installation program
+(install.exe, install.dat) and the remaining binaries and docs (the minimum set
+of files that you need is the first FAQ entry, you will also need the Make
+module, and if you have a 386 without a coprocessor the 80387 emulator)
+
+Binaries for Icon 9.0 for MsDos 386/486:
+cs.arizona.edu:/icon/packages/msdos/de-386.lzh
+(if you don't have lha.exe to unpack the archive you should also get it from
+there)
+
+The MKS Toolkit for Dos is commercial software (Sorry)
+Don't know which is the last version, I use 4.2 (Oct-93)
+Tel: (519) 884-2251 Mortice Kern Systems Inc.
+Fax: (519) 884-8861 35 King Street North,
+Technical Advice: (519) 884-2270 Waterloo, Ontario,
+Internet: inquiry@mks.com N2J 2W9
+CompuServe User ID: 73260,1043 CANADA
+BIX User Name: mks
+
+GhostScript 3.12
+ftp.funet.fi:/gnu/ghostscript3/aladdin
+If you don't have a PostScript printer you might want to use GhostScript which
+can take PostScript and translate it to your printer (presuming your printer is
+somehow supported). See 'jrtex12a.avs' for a list of the devices in the gs.exe,
+gs386.exe, gswin.exe, and gswin32s.exe binaries. Notice that gs.exe crawls when
+processing noweave output (after intermediate processing by latex and dvips),
+while gs386.exe is about 40 times faster (about 1 page/second in a 486
+DX2-80). This speed difference does not apply to normal PostScript code it is
+caused by something in the noweb code
diff --git a/web/noweb/contrib/avs/generate.ksh b/web/noweb/contrib/avs/generate.ksh
new file mode 100644
index 0000000000..8bf6050166
--- /dev/null
+++ b/web/noweb/contrib/avs/generate.ksh
@@ -0,0 +1,114 @@
+# do not use directly, it is better to edit the file 'myenv.ksh'
+
+if [ -e ../../contrib/avs/$0.ksh -o -e ../../contrib/avs/$0 ]
+then
+else
+ echo Wrong dir, must run \'$0\' from noweb/contrib/avs dir
+ exit 1
+fi
+
+if [ -z "$7" ]
+then
+ echo Usage: $0 BIN LIB MAN TEXINPUTS GMAKEPATH TMP ICONTRANSLATORPATH
+ echo If your environment is OK installs noweb27 in your PC386
+ echo "(icont.exe, iconx.exe, ixhdr.exe in dir e:\\b), e.g."
+ echo " $0 i:/b g:/usr/local/lib/noweb g:/man h:/emtex/texinputs/local j:/djgpp/bin/make.exe d:/tmp e:/b/icont.exe"
+ echo "(the '.exe' in make.exe and icont.exe is not necessary)"
+ exit 1
+fi
+
+cd ../..
+# now one is at ./noweb
+
+echo "Renaming src/makefile src/icon/makefile src/install src/xdoc/makefile src/lib/makefile src/awkname to *.old:"
+for f in src/makefile src/icon/makefile src/install src/xdoc/makefile src/lib/makefile src/awkname
+do
+ if [ -e $f.old ]
+ then
+ echo File \'$f.old\' already exists, skipped
+ else
+ mv $f $f.old
+ fi
+done
+echo Done!
+
+echo "Adding Dos specific makefiles and scripts for the combination MKS/DJGPP/ICONT:"
+awk -f contrib/avs/make_ico.awk src/icon/makefile.old > src/icon/makefile
+awk -f contrib/avs/make_src.awk src/makefile.old > src/makefile
+awk -f contrib/avs/make_xdo.awk src/xdoc/makefile.old > src/xdoc/makefile
+awk -f contrib/avs/make_lib.awk src/lib/makefile.old > src/lib/makefile
+cp -p contrib/avs/nw_c.bat src
+cp -p contrib/avs/nwinst.ksh src
+cp -p contrib/avs/nwicon.bat src
+echo Done!
+
+cd src
+echo "Adapting awkname for Dos and changing the awk name to 'awk' in all scripts:"
+sed "s@new=/tmp/\$\$.new; old=/tmp/\$\$.old@new=$6/\$\$.new; old=$6/\$\$.old@" <awkname.old >awkname
+# because the script has no '.ksh' extension one has to use 'awkname.'
+sh -c "./awkname. awk"
+echo Done!
+
+echo "Touch'ing all *.nw source code to avoid potential date/time problems:"
+echo "(all of it gets dummy date 12:00 23-Feb-95)"
+find . -name "*.nw" -exec touch -t 9502231200 "{}" \;
+echo Done!
+
+echo "Touch'ing all *.1 man pages to avoid potential date/time problems:"
+echo "(all of it gets dummy date 12:00 24-Feb-95)"
+find xdoc -name "*.1" -exec touch -t 9502241200 "{}" \;
+echo Done!
+
+cd ../contrib/avs
+echo "Generating 'contrib/avs/automate.bat' (to avoid out of memory errors):"
+echo "@echo off" >automate.bat
+echo "REM This file was generated by $0" >>automate.bat
+echo "cd ..\\\\..\\\\src" >> automate.bat
+
+echo "echo ***" >>automate.bat
+echo "echo *** Make icon code" >>automate.bat
+echo "echo ***" >>automate.bat
+
+# Trying to get something like:
+# call nwicon i:/b g:/usr/local/lib/noweb j:\djgpp\bin\make.exe e:\\\\b\\\\icont.exe
+# The '\c' arg to echo means not to add a \n at the end
+# Careful not to allow echo to interpret e.g. djgpp\bin as having an embedded backspace (\b)
+# 'sed' adds a \n line to its output, that's why tr was needed
+echo call nwicon $1 $2 \\c >>automate.bat
+echo $5 \\c | sed 's#/#\\#g' | tr -d '\015\012' >>automate.bat
+echo $7 | sed 's#/#\\\\\\\\#g' >>automate.bat
+
+echo if errorlevel 1 goto FAILURE >>automate.bat
+echo "echo ***" >>automate.bat
+echo "echo *** Make C code" >>automate.bat
+echo "echo ***" >>automate.bat
+echo set DJGPPMAKE=$5 >>automate.bat
+echo call nw_c $5 | sed 's@/@\\@g' >>automate.bat
+echo if errorlevel 1 goto FAILURE >>automate.bat
+echo "echo ***" >>automate.bat
+echo "echo *** Installing noweb" >>automate.bat
+echo "echo ***" >>automate.bat
+echo sh -c \"./nwinst.ksh $1 $2 $3 $4\" >>automate.bat
+echo if errorlevel 1 goto FAILURE >>automate.bat
+echo "echo ***" >>automate.bat
+echo "echo *** Fixing $1/cpif.ksh and $1/noweb.ksh as documented in 'howto386.txt'" >>automate.bat
+echo "echo ***" >>automate.bat
+echo "cd ..\\\\contrib\\\\avs" >>automate.bat
+echo sh -c \"./mksfixes.ksh $1 $6\" >>automate.bat
+echo if errorlevel 1 goto FAILURE >>automate.bat
+echo "echo Success, noweb 2.7a built & installed! Now use 'man noweb'" >>automate.bat
+echo 'echo Noweb 2.7| banner -c n | sed' "'s/[ ]$//'" >>automate.bat
+echo goto THEEND >>automate.bat
+echo :FAILURE >>automate.bat
+echo "echo Previous command failed (non 0 exit code), out of memory?" >>automate.bat
+echo echo Aborting... sorry you have to manually fix the problem >>automate.bat
+echo "echo (and after that go to noweb/contrib/avs and rerun automate.bat)" >>automate.bat
+echo :THEEND >>automate.bat
+
+echo "****"
+echo "The file 'automate.bat' has been generated, now LEAVE the Korn shell (to avoid"
+echo "out of memory errors) and run it. If 'automate.bat' fails at some point, e.g."
+echo "out of memory, then you may try to fix the problem by hand e.g. calling the C"
+echo "compiler directly by looking at the previous output from Make, and then to"
+echo "rerun 'automate'. You can run 'automate.bat' as many times as you need until"
+echo "you reach the end with success"
diff --git a/web/noweb/contrib/avs/howto386.txt b/web/noweb/contrib/avs/howto386.txt
new file mode 100644
index 0000000000..49dedea19d
--- /dev/null
+++ b/web/noweb/contrib/avs/howto386.txt
@@ -0,0 +1,254 @@
+** Recipe for building and installing noweb 2.7a in a PC386 running Dos
+** Recipe version 0.3 (30-May-95), report problems to avs@daimi.aau.dk
+
+This recipe assumes its support files are at './noweb/contrib/avs'. If they are
+not (as is the case with the noweb 2.7a distribution) then just unpack
+noweb27a.tar.gz (official distribution) and avs386_noweb27a.tar.gz (my
+contribution) from the same base dir
+
+I'm only doing a minimum patch of the noweb source files and installation
+scripts to get a successful install (binaries plus support files plus man
+pages). I do not patch things that I am not likely to need like support for
+'make clean' or changing the '.nw' files in the sources dir. Also I didn't try
+to install the contributed software from the contrib dir. After noweb is
+successfully installed just remove the distribution files from your system (it
+is better to archive it somewhere, there are some docs, examples and contribs
+that might be useful later)
+
+Bugs/problems with noweb 2.7a: see the file 'report1.bug'
+
+This recipe supports Awk but that option is not thoroughly tested. Why should I
+use Awk if the Noweb distribution explicitly says that the Awk versions of the
+tools are untested and so probably have bugs? Compiling Icon for Ms-Dos is not
+easy but one can ftp the binaries (only 512 KB)
+
+** History:
+
+0.3 recipe for noweb 2.7 (30-May-95)
+0.2 recipe for noweb 2.7 (26-Mar-95), internal use only
+0.1 recipe for noweb 2.6c (12-Dec-94), internal use only
+
+**** Software ****
+
+Requires:
+- MKS Toolkit 4.2 for Dos (older versions of MKS might not work)
+- the DJGPP port of GNU gcc, GNU make, and GNU gzip
+- version 9.0 of Icon for MsDos 386/486,
+- LaTeX (LaTeX 2.09 or LaTeX2e)
+
+LaTeX: I use emTeX 386, the installation is everything except straightforward,
+if you don't already have LaTeX in your PC the best way to get it up and
+running is by using John Refling's jrtex12a.txt ("How I installed emtex,
+latex2e, mf, dvips, on a 386 with postscript or hplaser"). I supply an
+annotated copy of that document with some corrections and some additions
+made by me in the file 'jrtex12a.avs'
+
+Because MKS does not have nroff, a nroff processed man page for Icon is
+provided here. (I also provide mks42bug.0d which has a list of all the MKS 4.2
+bugs that I am aware of, some of them required a fix in this recipe)
+
+See the file 'ftpsites.txt' for download info for the additional software
+
+**** Install ****
+
+NOTE: my MKS installation allows me to switch easily between using the MKS
+Korn-shell (sh.exe) and the Ms-Dos command interpreter (command.com), i.e. I
+boot with command.com and then I run login to get the Korn shell and by logging
+out I am back in command.com. You need the ability to switch between using
+command.com and sh.exe because some software has problems with the MKS pathname
+separator '/'. This is why the steps normally specify if they are to be run
+under command.com or sh.exe. If nothing is said it would work under
+either. Also command.com uses much less memory than sh.exe, for instance I am
+unable to compile the C code when running under sh.exe (this has to do with the
+640KB MsDos limit, I have lots of extended memory and a good memory manager)
+
+Change to some temporary directory (if '.' is that dir then all files will be
+under './noweb') and extract the distribution (the extension .tar.gz was
+changed to .tgz to comply with Ms-Dos filenames, 386avs27.tgz is
+avs386_noweb27.tar.gz):
+
+cd ...
+gzip -dc noweb27.tgz | tar xvf -
+gzip -dc 386avs27.tgz | tar xvf -
+ (my files are not part of noweb 2.7)
+cd ./noweb/contrib/avs
+
+All my files are at ./noweb/contrib/avs, see the file 'filelist.txt'
+
+If you feel lucky edit the site specific line of the file 'myenv.ksh'
+(i.e. specify the paths where things are, and where things will go) and run
+it. Then run the generated file 'automate.bat'. If things work as they ought
+to, you can stop reading.
+
+**** Troubleshooting ****
+
+Print this file and go through it step by step (I'm explaining what 'myenv.ksh',
+'automate.bat' and the scripts called by these are doing)
+
+a) change to ./noweb/src directory and edit 'awkname'
+ (this script uses '/tmp', if your tmp dir is not in the same drive as noweb,
+ replace in line 8
+ new=/tmp/$$.new; old=/tmp/$$.old
+ with e.g.
+ new=c:/tmp/$$.new; old=c:/tmp/$$.old
+ (Notice that although one is using Icon instead of Awk line 26 of
+ noweb.ksh, line 7 of noroots.ksh and line 32 of nountang.ksh use Awk
+ anyway, so it's easier to update the awk name everywhere)
+
+b) run the shell script 'awkname' under the Korn shell with 'awk' as argument
+ (because the Korn shell awk is named awk). Notice that because the awkname
+ script does not have a .ksh extension one has to explicitly supply a '.' as
+ the extension name, otherwise the shell won't find it, e.g.
+ cd ./noweb/src; ./awkname. awk
+
+c) rename src/makefile src/icon/makefile src/install src/xdoc/makefile
+ src/awkname to *.old. And then run the awk scripts to patch the makefiles
+ (each action in each script has a comment explaining what it is doing and
+ why). The file 'install' had to be renamed to avoid confusing MKS make when
+ it tries to run 'make install'.
+ awk -f contrib/avs/make_ico.awk src/icon/makefile.old > src/icon/makefile
+ awk -f contrib/avs/make_src.awk src/makefile.old > src/makefile
+ awk -f contrib/avs/make_xdo.awk src/xdoc/makefile.old > src/xdoc/makefile
+
+d) copy the scripts to the /noweb/src dir (you need to run them from there)
+ cp -p contrib/avs/nw_c.bat src
+ cp -p contrib/avs/nwinst.ksh src
+ cp -p contrib/avs/nwicon.bat src
+
+e) run nwicon.bat under command.com, run it 1st without args to get an usage
+ screen, and then provide the correct args (careful with the number and use
+ of slashes and backslashes). This compiles the icon code
+ (Concerning the location of your icon binaries: if it is d:/bin/icont.exe
+ and d:/bin/ixhdr.exe then use d:\\\\bin\\\\icont, '.exe' extension not
+ necessary. Sorry about the \\\\, but believe me that's the only way I
+ managed for it to work, see below for an explanation. Give also the
+ location of your DJGPP make, and the locations where later on you want to
+ install the noweb LIB and the noweb BIN)
+
+f) run nw_c.bat under command.com without args to get the usage screen, then
+ use the 'set' command and then rerun nw_c.bat. This compiles the C code
+ (if I try to run under the shell instead of command.com and the makefile
+ tries to compile a C program I get out of memory errors, i.e. this is the
+ place where you need more free Ram, 600000 bytes free is enough)
+ (the full pathname of DJGPP Make is given twice, the one with Unix style
+ slashes goes in the environment var and the one with MsDos style
+ backslashes is given as arg. Notice that an environment variable called
+ DJGPPMAKE is set, make sure that you have enough space for it, otherwise
+ increase the value used in the /E:### option of the SHELL command in
+ your config.sys)
+ (nw_c.bat also patches src/c/finduses.c because of a problem with DJGPP
+ tmpfile() in libc.a, the screen will show what is being changed. This
+ might not be necessary under a newer version of DJGPP (I did not yet
+ install the last DJGPP maintenance patches) but it is better to do it
+ anyway because tempnam() uses the environment var TMPDIR, while
+ tmpfile() doesn't)
+
+g) run nwinst.ksh under the Korn shell (sh.exe), there is an usage screen. You
+ can also run it from command.com using 'sh -c "./nwinst.ksh ..."'. This
+ installs the icon based version of noweb (some files will need to be patched
+ afterwards, see below).
+ (because an Unix style shell and MKS make are needed)
+ (make sure that MKS make is the 1st make in your path, see Technical
+ Notes below)
+ (if you prefer to use Awk instead of Icon update the scripts yourself.
+ Notice that although Awk is slower than Icon, MKS has a 32 bits version
+ of Awk which might be good enough, and MKS has also an Awk compiler
+ (awkc, see 'man awkc'), thus by removing from the shell scripts the
+ awk code, puting it into a file, compiling it, and updating the shell
+ scripts to use that executable you might get good performance, I didn't
+ try to use Awk thus I don't know)
+ (in noweb27.tar.gz in the file "install.dos" there are some references
+ to an MKS awk bug in handling backslashes in gsub(), I was unable to find
+ the code that it refered to in the noweb distribution (did it only apply
+ to an older version of noweb?), but anyhow you should check it out if you
+ are going to use awk)
+
+h) fix cpif.ksh and noweb.ksh by running mksfixes.ksh (from noweb/contrib/avs),
+ there is an usage screen. This edits the noweb.ksh in the BIN location
+ specified to nwinst.ksh and removes twice (in lines 20 and 25) the
+ PATH="$PATH:$LIB"
+ which is not necessary and causes the error 'cannot execute go32' at run-time
+ (go32 is the Dos extender used by DJGPP). It also edits cpif.ksh (also in the
+ BIN location) and:
+ - removes the PATH statement in line 8 (because 'PATH=/bin:/usr/bin' is
+ probably wrong for your system)
+ - adds a full pathname (with a drive letter) to "new=/tmp/$$" in line 20
+ (e.g. "new=d:/tmp/$$"), because otherwise the script will fail when run
+ from a drive which has no tmp dir
+ - because of a bug in MKS 4.2 changes line 28 from
+ -eq0|-ne1|*2) cp $new $i
+ to
+ -eq0|-ne1|*2|*3) cp $new $i
+ Maybe you would like to check out if that bug applies to your system,
+ in MKS 4.2 the program cmp ("cmp.exe") gives an exit code of 3 if one of
+ the files to be compared cannot be opened or doesn't exist, this is in
+ contrast with the MKS man page which says that an error code of 2 is
+ given (to fix this bug is very important otherwise e.g. the command noweb
+ will never create the TeX file)
+
+i) copy './noweb/contrib/avs/icon.1' to '.../yourman/cat1' and 'mks42bug.0d' to
+ '.../yourman/cat0' and add '.../yourman' to your MANPATH.
+
+j) test the installation by running noweb/examples/...
+ (you must run noweb under the Korn shell. I have enough free RAM to run
+ everything including the Dos extenders of Icon, DJGPP Emacs, emTeX, etc.
+ Probably this happens because 'mem' run from the Korn Shell reports
+ 590272 free bytes (of the 640 KB), and I have enough free EMS. I use
+ QEMM 7.5 as the memory manager)
+
+**** Technical Notes: ****
+
+- DJGPP Make can be in your path but it can't be 1st otherwise install.ksh does
+not work
+- noweb/install renamed to noweb/install.old to avoid confusing MKS Make when
+ trying to execute 'make install'
+- it is assumed that MKS Make is the 1st Make in your path
+- nw_c.bat does not run coff2exe, thus you CANNOT test the binaries BEFORE
+ you install them, i.e. you don't get the .exe files. This avoids the need to
+ change the src/c/makefile
+ When you run install.ksh, coff2exe will be run for all binaries (i.e. a stub
+ will be added to them which will call the Dos extender go32.exe)
+- if you have problems with the 127 chars PATH limit do:
+ Command.com 6.0 can take a PATH longer than 127 chars by setting it in the
+ config.sys (but it is not possible to change it afterwards from e.g.
+ autoexec.bat or the command line), also some programs might crash with this
+ extra long path and one can only see the 1st 122 chars (although all are used
+ in a search)
+ The Ndos shareware command interpreter can have a PATH 256 chars long.
+
+- main changes made to the Unix noweb/src/makefile to create the Dos Makefile:
+ (see also make_src.awk)
+a) in some places of the makefile quotes had to be removed (e.g. instead of
+ "CFLAGS=$(CFLAGS)" one has to use CFLAGS=$(CFLAGS), this is caused by the
+ use of 'command.com' as the shell while building noweb). Of course if using
+ more than one CFLAGS (i.e. embedded blanks) this won't work (the easiest and
+ dirty fix is to add them directly to the makefile in that case)
+b) MKS strip cannot be used on the DJGPP .exe, otherwise go32 would fail
+c) it is an hybrid makefile, 'make all' only works with DJGPP Make and
+ 'command.com', while 'make install' only works with MKS Make and the MKS
+ Korn Shell
+d) 'SHELL=/bin/sh' had to be disabled (e.g. if MKS $ROOTDIR is not '/')
+e) links (used in the man pages) not supported under MsDos, copy was used
+f) there is also an external 'cd.exe' in the MKS Toolkit (don't ask me what
+ it can be used for, it is just a source of problems). This gives problems
+ that the MKS make will use it instead of the internal Korn-shell cd command
+ unless the line to be executed is such that it requires the Korn-shell to
+ interpret it. This is why:
+ cd c; coff2exe nt markup mnt finduses
+ won't work, but
+ cd "c"; coff2exe nt markup mnt finduses
+ works fine
+
+- main changes made to the noweb/src/icon/makefile (see also make_ico.awk):
+a) cannot run under the Korn shell otherwise icont.exe becomes confused about
+ the current directory
+b) when executing icont.exe if argv[0] has slashes (instead of backslashes)
+ icont.exe runs OK but at the end it is unable to run ixhdr.exe thus it fails
+c) I got several spurious CPU locks when calling make from make while executing
+ icont.exe, that's why only one make is used
+d) icont must be replaced with the full path (with backslashes) to itself,
+e) the option '-I' to the 'icont.exe' is not documented in the Icon man page
+ (see section 3 of document IPD248a from the Icon project), it produces a
+ non-executable icode file (.icx) which can be run by iconx.exe
+
+**** The End ****
diff --git a/web/noweb/contrib/avs/icon.1 b/web/noweb/contrib/avs/icon.1
new file mode 100644
index 0000000000..04c5465e6d
--- /dev/null
+++ b/web/noweb/contrib/avs/icon.1
@@ -0,0 +1,330 @@
+}
+
+
+ IIIICCCCOOOONNNN((((1111)))) IIIICCCCOOOONNNN((((1111))))
+ 11113333 MMMMaaaarrrrcccchhhh 1111999999993333 IIIIPPPPDDDD222211119999
+
+
+
+ NNNNAAAAMMMMEEEE
+ icon - interpret or compile Icon programs
+
+ SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
+ icont [ option ... ] file ... [ -x arg ... ]
+ iconc [ option ... ] file ... [ -x arg ... ]
+
+ DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
+ icont and iconc each convert an Icon source program into executable
+ form. icont translates quickly and provides interpretive execution.
+ iconc takes longer to compile but produces programs that execute
+ faster. icont and iconc for the most part can be used
+ interchangeably.
+
+ This manual page describes both icont and iconc. Where there there are
+ differences in usage between icont and iconc, these are noted.
+
+ FFFFiiiilllleeee NNNNaaaammmmeeeessss:::: Files whose names end in .icn are assumed to be Icon
+ source files. The .icn suffix may be omitted; if it is not present, it
+ is supplied. The character - can be used to indicate an Icon source
+ file given in standard input. Several source files can be given on
+ the same command line; if so, they are combined to produce a single
+ program.
+
+ The name of the executable file is the base name of the first input
+ file, formed by deleting the suffix, if present. stdin is used for
+ source programs given in standard input.
+
+ PPPPrrrroooocccceeeessssssssiiiinnnngggg:::: As noted in the synopsis above, icont and iconc accept
+ options followed by file names, optionally followed by -x and
+ arguments. If -x is given, the program is executed automatically and
+ any following arguments are passed to it.
+
+ icont: The processing performed by icont consists of two phases:
+ _t_r_a_n_s_l_a_t_i_o_n and _l_i_n_k_i_n_g. During translation, each Icon source file is
+ translated into an intermediate language called _u_c_o_d_e. Two ucode files
+ are produced for each source file, with base names from the source
+ file and suffixes .u1 and .u2. During linking, the one or more pairs
+ of ucode files are combined to produce a single _i_c_o_d_e file. The ucode
+ files are deleted after the icode file is created.
+
+ Processing by icont can be terminated after translation by the -c
+ option. In this case, the ucode files are not deleted. The names of
+ .u1 files from previous translations can be given on the icont command
+ line. These files and the corresponding .u2 files are included in the
+ linking phase after the translation of any source files. The suffix
+ .u can be used in place of .u1; in this case the 1 is supplied
+ automatically. Ucode files that are explicitly named are not deleted.
+
+ iconc: The processing performed by iconc consists of two phases: _c_o_d_e
+ _g_e_n_e_r_a_t_i_o_n and _c_o_m_p_i_l_a_t_i_o_n _a_n_d _l_i_n_k_i_n_g. The code generation phase
+
+
+
+ - 1 - Formatted: December 9, 1994
+
+
+
+
+
+
+ IIIICCCCOOOONNNN((((1111)))) IIIICCCCOOOONNNN((((1111))))
+ 11113333 MMMMaaaarrrrcccchhhh 1111999999993333 IIIIPPPPDDDD222211119999
+
+
+
+ produces C code, consisting of a .c and a .h file, with the base name
+ of the first source file. These files are then compiled and linked to
+ produce an executable binary file. The C files normally are deleted
+ after compilation and linking.
+
+ Processing by iconc can be terminated after code generation by the -c
+ option. In this case, the C files are not deleted.
+
+ OOOOPPPPTTTTIIIIOOOONNNNSSSS
+ The following options are recognized by icont and iconc:
+
+ -c Stop after producing intermediate files and do not delete them.
+
+ -e _f_i_l_e
+ Redirect standard error output to _f_i_l_e.
+
+ -m Preprocess each .icn source file with the _m_4(_1) macro processor.
+
+ -o _n_a_m_e
+ Name the output file _n_a_m_e.
+
+ -s Suppress informative messages. Normally, both informative
+ messages and error messages are sent to standard error output.
+
+ -t Arrange for &trace to have an initial value of -1 when the program
+ is executed and for iconc enable debugging features.
+
+ -u Issue warning messages for undeclared identifiers in the program.
+
+ -E Direct the results of preprocessing to standard output and inhibit
+ further processing.
+
+ The following additional options are recognized by iconc:
+
+ -f _s_t_r_i_n_g
+ Enable features as indicated by the letters in _s_t_r_i_n_g:
+
+ a all, equivalent to delns
+
+ d enable debugging features: display(), name(), variable(),
+ error trace back, and the effect of -f n (see below)
+
+ e enable error conversion
+
+ l enable large-integer arithmetic
+
+ n produce code that keeps track of line numbers and file names
+ in the source code
+
+ s enable full string invocation
+
+
+
+
+ - 2 - Formatted: December 9, 1994
+
+
+
+
+
+
+ IIIICCCCOOOONNNN((((1111)))) IIIICCCCOOOONNNN((((1111))))
+ 11113333 MMMMaaaarrrrcccchhhh 1111999999993333 IIIIPPPPDDDD222211119999
+
+
+
+ -n _s_t_r_i_n_g
+ Disable specific optimizations. These are indicated by the letters
+ in _s_t_r_i_n_g:
+
+ a all, equivalent to cest
+
+ c control flow optimizations other than switch statement
+ optimizations
+
+ e expand operations in-line when reasonable (keywords are always
+ put in-line)
+
+ s optimize switch statements associated with operation
+ invocations
+
+ t type inference
+
+ -p _a_r_g
+ Pass _a_r_g on to the C compiler used by iconc
+
+ -r _p_a_t_h
+ Use the run-time system at _p_a_t_h, which must end with a slash.
+
+ -v _i
+ Set verbosity level of informative messages to _i
+
+ -_C _p_r_g
+ Have iconc use the C compiler given by _p_r_g
+
+ EEEENNNNVVVVIIIIRRRROOOONNNNMMMMEEEENNNNTTTT VVVVAAAARRRRIIIIAAAABBBBLLLLEEEESSSS
+ When an Icon program is executed, several environment variables are
+ examined to determine certain execution parameters. Values in
+ parentheses are the default values.
+
+ BLKSIZE (65000)
+ The initial size of the allocated block region, in bytes.
+
+ COEXPSIZE (2000)
+ The size, in words, of each co-expression block.
+
+ DBLIST
+ The location of data bases for iconc to search before the standard
+ one. The value of DBLIST should be a blank-separated string of
+ the form _p_1 _p_2 ... _p_n where the _p_i name directories.
+
+ ICONCORE
+ If set, a core dump is produced for error termination.
+
+ ICONX
+ The location of iconx, the executor for icode files, is built into
+ an icode file when it is produced. This location can be overridden
+
+
+
+ - 3 - Formatted: December 9, 1994
+
+
+
+
+
+
+ IIIICCCCOOOONNNN((((1111)))) IIIICCCCOOOONNNN((((1111))))
+ 11113333 MMMMaaaarrrrcccchhhh 1111999999993333 IIIIPPPPDDDD222211119999
+
+
+
+ by setting the environment variable ICONX. If ICONX is not set
+ and iconx is not found on the built-in path, PATH is searched for
+ it. If this environment variable is set, it specifies the
+ location of iconx to use to execute an icode file.
+
+ IPATH
+ The location of ucode files specified in link declarations for
+ icont. IPATH is a blank-separated list of directories. The
+ current directory is always searched first, regardless of the
+ value of IPATH.
+
+ LPATH
+ The location of source files specified in link declarations for
+ iconc. LPATH is otherwise similar to IPATH.
+
+ MSTKSIZE (10000)
+ The size, in words, of the main interpreter stack for icont.
+
+ NOERRBUF
+ By default, &errout is buffered. If this variable is set, &errout
+ is not buffered.
+
+ QLSIZE (5000)
+ The size, in bytes, of the region used for pointers to strings
+ during garbage collection.
+
+ STRSIZE (65000)
+ The initial size of the string space, in bytes.
+
+ TRACE
+ The initial value of &trace. If this variable has a value, it
+ overrides the translation-time -t option.
+
+ FFFFIIIILLLLEEEESSSS
+ icont Icon translator
+ iconc Icon compiler
+ iconx Icon executor
+
+ SSSSEEEEEEEE AAAALLLLSSSSOOOO
+ _T_h_e _I_c_o_n _P_r_o_g_r_a_m_m_i_n_g _L_a_n_g_u_a_g_e, Ralph E. Griswold and Madge T.
+ Griswold, Prentice-Hall Inc., Englewood Cliffs, New Jersey, Second
+ Edition, 1990. _V_e_r_s_i_o_n _8._1_0 _o_f _I_c_o_n, Ralph E. Griswold, Clinton L.
+ Jeffery, and Gregg M. Townsend, IPD212, Department of Computer
+ Science, The University of Arizona, 1993. _U_s_i_n_g _V_e_r_s_i_o_n _8._1_0 _o_f _t_h_e
+ _I_c_o_n _C_o_m_p_i_l_e_r, Ralph E. Griswold, IPD214, Department of Computer
+ Science, The University of Arizona, 1993. m4(1), icon_vt(1)
+
+ LLLLIIIIMMMMIIIITTTTAAAATTTTIIIIOOOONNNNSSSS AAAANNNNDDDD BBBBUUUUGGGGSSSS
+ The icode files for the interpreter do not stand alone; the Icon run-
+ time system (iconx) must be present. Stack overflow is checked using
+ a heuristic that is not always effective. If the -m option is used,
+
+
+
+ - 4 - Formatted: December 9, 1994
+
+
+
+
+
+
+ IIIICCCCOOOONNNN((((1111)))) IIIICCCCOOOONNNN((((1111))))
+ 11113333 MMMMaaaarrrrcccchhhh 1111999999993333 IIIIPPPPDDDD222211119999
+
+
+
+ line numbers reported in error messages and tracing messages are from
+ the file after, not before, preprocessing.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - 5 - Formatted: December 9, 1994
+
+
+
diff --git a/web/noweb/contrib/avs/jrtex12a.avs b/web/noweb/contrib/avs/jrtex12a.avs
new file mode 100644
index 0000000000..a9d7131aee
--- /dev/null
+++ b/web/noweb/contrib/avs/jrtex12a.avs
@@ -0,0 +1,1054 @@
+**** NOTE: this is the superb document 'jrtex12a' from John Refling. I just
+**** fixed a couple of bugs and added a few comments (for my own use). The
+**** changes are marked with '****'. The biggest problem was that his setup
+**** didn't contemplate installing emTeX in another drive than C, nor did it
+**** contemplate putting the fonts generated on demand on yet another drive
+**** (handy if one wants emTeX to be in a READONLY drive)
+****
+**** If you only have a 386 without coprocessor be careful with some
+**** delete instructions (which assume you have a 387 or a 486DX)
+****
+**** Known problems:
+**** If running under the MKS Toolkit shell, font generation on demand may
+**** fail. I don't have this problem any more (don't know what fixed it,
+**** the new version of emTeX?) but I had it in the past. Just do the font
+**** generation under 'command.com' and then go back to the Korn shell
+**** avs@daimi.aau.dk (18-Mar-95)
+
+How I installed emtex, latex2e, mf, dvips, on a 386 w/ postscript or hplaser
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ John Refling, University of California
+ jprefling@lbl.gov [DO NOT SEND REQUESTS HERE]
+ date: 13 January 1995, Version: 12a
+
+Archivists
+~~~~~~~~~~
+This file should be stored on your machine with a basename of 'jrtex12a'.
+in a place related to tex. A one line description of this guide might be:
+"Describes install of emtex, latex2e, hplj & PS on PC"
+
+How to get latest
+~~~~~~~~~~~~~~~~~
+This will be available at simtel mirrors such as wuarchive.wustl.edu
+and oak.oakland.edu in/or near the /pub/msdos/tex directory, and perhaps
+CTAN machines. A similar file which describes an older
+version of emtex installation (pre latex-2e) has basename jrhelp11.
+
+What is this
+~~~~~~~~~~~~
+This is a short account of my experiences installing emtex on a few different
+computers, with a few different printers.
+
+Hardware you NEED to follow this guide
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+a 386 or greater computer with reasonable (4MB) ram about 35 meg free space
+ peak for the install (for easy installation, although you can get by with
+ much less if you are willing to really work at it), reduced to ~10 MB
+ disk space permanently (less w/o postscript support and the docs),
+ plus fonts (about 5 MB max).
+
+a reasonable dos version (best if you can recall and edit commands)
+
+a laser printer (postscript or pcl hplaserjet or hplaserjet iv, are tested).
+
+What you get
+~~~~~~~~~~~~
+emtex system (tex, latex2e, mf, screen previewer, postscript support)
+dynamically generated fonts if you wish (that's right, I don't generate them
+ until I use `em)
+The emtex system is a great tex / latex system.
+
+A note on the version numbers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The base name of this document is jrtex which takes 5 characters out of 8
+possible. The next two digits correspond to the betatest version of emtex,
+currently 12. Unfortunately, other pieces of the emtex package change without
+notice and so it is hard to pin a version number on the entire package, which
+I could carry over to this document, plus I might have revisions. The final
+character in this help file's name will serve as a minor revision indicator.
+
+Even so, there might be minor discrepancies between what you see here
+and what is on the net. Perhaps one of the best ways to check for
+revisions on the net would be to check the file's size and/or it's date.
+However, I just don't see any good way to build this info into the name
+of this document. I have included the file size of files obtained from
+the net. When the size indicated is different from the size you received,
+you need to be cautious... most likely a new version has been added to the
+distribution, and you need to take that into account. Sometimes in the
+betatest subdirectory there are multiple versions of the same thing... use
+the latest... even if I don't in this document!
+
+How to do it
+~~~~~~~~~~~~
+Print out a copy of this file, and follow along with it. CROSS OFF STEPS
+WHEN COMPLETED. You need to be able to transfer files from the internet
+to your PC. You also need pkunzip, and know how to use it. If you use
+unzip, the options are slightly different.
+
+What you don't get
+~~~~~~~~~~~~~~~~~~
+This worked for me, but I can't guarantee it for you. You take all
+responsibility for implementing this. You are assumed to know enough
+about what is going on to not do something dangerous even if it says to
+do so here. Besides, someone could have changed this before you got it.
+ALSO, I DON'T COVER MIGRATION FROM THE 2.09 VERSION OF LATEX TO THE NEW
+2E VERSION. I ASSUME A NEW INSTALLATION! Also, this is only how I did
+it! and is not an official guideline, or recommendation. It is possible
+that something in here may guide you contrary to some of the published
+or yet to be published standards. This is provided in the hope that it
+may be useful, in the event that you are having trouble with your
+installation. THAT'S IT. You have been warned!
+
+Introduction
+~~~~~~~~~~~~
+The emtex distribution was a little confusing to me at first, since I am
+used to obtaining one compressed distribution archive file and working with
+that. When a new version is distributed, one goes back to the ftp site and
+gets the compressed file with the next higher version number.
+
+With emtex, things are spread across directories, not only in terms of package
+components, but also in terms of revision levels. The most serious drawback
+of this method is that it is difficult to determine the revision level of
+programs, or where a particular revision level is. The simpliest way to
+install it is just to install ALL of the archives in order, and let
+them overwrite [hopefully] older versions. Then, you will have the latest
+versions, and you delete what you don't want.
+
+1. OBTAIN THE DISTRIBUTION AND EXTRACT IT AND ARCHIVE IT FOR LATER
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+a. cd \
+
+b. use ftp to connect to a distribution machine, ftp.dante.de,
+ ftp.shsu.edu, wuarchive.wustl.edu, etc, and get to the emtex directory
+ something like /tex-archive/systems/msdos/emtex. We wish to grab all the
+ files in the disk1, disk2, disk3, disk4, disk5, betatest subdirs.
+ MAKE SURE YOU SET BINARY MODE BEFORE THE TRANSFER OF BINARY FILES.
+ One way to do it all is as follows (assuming that the remote ftp server
+ has on-the-fly compression):
+
+ ftp ftp.shsu.edu
+**** ftp.dante.de is too slow
+ cd /tex-archive/systems/msdos
+ bin
+ hash
+ get emtex.zip [15,173,126]
+**** get emtex.tar.gz [11,859,740]
+
+ This will recursively get everything. Last time I tried it, it ended up
+ being a 14,992,564 byte file, and took 60 minutes via ftp.
+
+ Then, get the latex2e stuff:
+
+ cd /tex-archive/macros/latex
+ get base.zip [771,461]
+ cd packages
+ get tools.zip [221,517]
+**** get graphics.tar.gz [80,020]
+**** 'graphics' has epsfig (allows including Encapsulated PostScript files in LaTeX docs)
+ quit
+
+c. Then on the pc:
+
+ mkdir \emtmp
+ cd \emtmp
+ pkunzip \emtex.zip [or unzip -j \emtex.zip]
+ cd \
+
+ You will need 15 + 15 = 30 MB disk space for this process. Read the
+ readme.tst and note the date in the upper right-hand corner. For my
+ installation it was 12-Dec-94. After success, you may delete \emtex.zip
+ and get 15 MB disk space back. Then goto step d.
+**** version of 03-Feb-95 (includes web.zip with weave, tangle and pooltype)
+
+ If this does not work [because you don't have enough temporary disk space
+ for the one huge file, or if the ftp server can't compress into one huge
+ file], you have to get all the files individually. The ones we are most
+ interested in are listed in item 5 below with their locations in [].
+
+d. Do the following in order [if you use unzip, do not use the -d]:
+
+ pkunzip -d \emtmp\tex1.zip [disk1, 375854]
+ pkunzip -d \emtmp\tex2.zip [disk1, 268240]
+ pkunzip -d \emtmp\latex1.zip [disk2, 248823]
+ pkunzip -d \emtmp\latex2.zip [disk2, 238131]
+ pkunzip -d \emtmp\blatex.zip [disk2, 231677]
+ pkunzip -d \emtmp\makeindx.zip [disk2, 52717]
+ pkunzip -d \emtmp\bmf1.zip [disk3, 266527]
+ pkunzip -d \emtmp\bmf2.zip [disk5, 271791]
+ pkunzip -d \emtmp\texcad.zip [disk3, 120547]
+ pkunzip -d \emtmp\mf1.zip [disk4, 249916]
+ pkunzip -d \emtmp\mf2.zip [disk4, 344463]
+ pkunzip -d \emtmp\mf3.zip [disk4, 278545]
+ pkunzip -d \emtmp\mfware1.zip [disk4, 327215]
+ pkunzip -d \emtmp\mfware2.zip [disk5, 140361]
+ pkunzip -d \emtmp\btex1.zip [disk5, 265159]
+ pkunzip -d \emtmp\btex2.zip [disk5, 274600]
+ pkunzip -d \emtmp\misc_mf.zip [disk5, 36349]
+ pkunzip -d -o \emtmp\mfb5.zip [betatest, 1044415]
+ pkunzip -d -o \emtmp\mfjob11n.zip [betatest, ?]
+ pkunzip -d -o \emtmp\texb12.zip [betatest, 1120943]
+ pkunzip -d -o \emtmp\bibtexb1.zip [betatest, 167593]
+ pkunzip -d -o \emtmp\fontl12a.zip [betatest, 88321]
+ pkunzip -d -o \emtmp\dvid15g1.zip [betatest, 1213323]
+ pkunzip -d -o \emtmp\dvid15g2.zip [betatest, 727077]
+
+ Answer yes to any overwrites.
+
+ move \emtmp\readme.tst \emtex\doc
+ move \emtmp\readme.eng \emtex\doc\english
+
+ Extracting these files generates another 18 MB of files. If this is
+ successful, you may now delete everything in \emtmp, as well as \emtex.zip.
+
+ If you run out of space in the process, you may delete each .zip you
+ have extracted successfully. After extracting ALL the .zips, you may
+ delete \emtex.zip.
+
+e. Get rid of stuff (I save only the 386 stuff):
+ cd \emtex
+ del *.cmd [os/2 stuff]
+ del bmf*.* [big mf]
+ del blatex.bat [big latex]
+ del btex*.* [big tex]
+ del mf.exe [small mf]
+ del mf186.exe [small mf]
+ del mf286.exe [small mf]
+ del tex.exe [small tex]
+ del tex186.exe [small tex]
+ del tex286.exe [small tex]
+ del texp.exe [os/2 stuff]
+ del texfmts [small tex]
+ rmdir texfmts [small tex]
+ del mfbases [small tex]
+ rmdir mfbases [small tex]
+****
+ del remove [intnl files]
+ rmdir remove [intnl files]
+**** Might not be a good idea to remove, tells from where a given file came
+ del mfp*.* [os/2 stuff]
+ del dvipm*.* [os/2 stuff]
+ del mfjob1.ovl [small mfjob]
+ del mfjob2.ovl [small mfjob]
+ del ask.exe
+ del bibtex.exe [small bibt]
+****
+ del book
+ rmdir book
+**** book has subdirs (skip these steps, german subdir will be deleted below)
+
+ IF YOU REALLY ARE GOING TO USE A DOT MATRIX PRINTER, YOU MIGHT KEEP THESE:
+ del dvidot*.* [dot matrix]
+ del gh.*
+ del prtfx*.*
+ del prtitoh.*
+ del prtlq*.*
+ del prtp6*.*
+ del prtsty.bat
+ del pcx*.*
+ del prtaiw.bat
+ del makedot.exe
+
+ I DON'T HAVE LIMITED MEMORY, SO DELETE
+ del vs.bat [ltd memory vers]
+ del dviscrs.exe [ltd memory vers]
+
+ OLD FORMATS FOR FONTS, IF YOU ARE STARTING NEW, YOU DON'T WANT THEM:
+ del chtopx.exe
+ del gftopxl.exe
+ del gftype.exe
+ del pktopx.exe
+ del pxtoch.exe
+ del pxtopk.exe
+
+ I HAVE A COPROCESSOR SO DON'T NEED THE COPROCESSOR-LESS VERSIONS
+ del dviscr.exe
+ del dvihplj.exe
+
+ I DON'T HAVE A VIKING DISPLAY
+ del dvivik.exe
+
+ SAVE SOME MORE SPACE since I regenerate the bases & formats later
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ cd \emtex\bmfbases
+ del *.cmd
+ del *.log
+ del *.bas
+ edit bas.bat and change "bmf" to "\emtex\mf386" in all cases (2)
+**** use only 'mf386' (i.e. ?:/emtex will be in the PATH)
+
+ cd \emtex\btexfmts
+ del *.cmd
+ del *.log
+ del *.fmt
+ edit fmt.bat and change "btex" to "\emtex\tex386" in all cases (2)
+ edit slifmt.bat and change "btex" to "\emtex\tex386" in all cases (1)
+**** use only 'tex386' (i.e. ?:/emtex will be in the PATH)
+
+ I delete some dot-matrix printer configuration files. Actually, all I
+ keep in the \emtex\data\ subdirectory is:
+ dvidrv.err fax.cnf fontlist lj.cnf ljh.cnf newfonts.sub oldfonts.sub
+
+ I choose to get rid of a few of the doc files in German to save space:
+ del \emtex\doc\german
+ rmdir \emtex\doc\german
+ del \emtex\book\german
+ rmdir \emtex\book\german
+
+ and get rid of some more o/s-2 stuff:
+ del \emtex\help
+ rmdir \emtex\help
+
+f. FINALLY, ARCHIVE IT:
+ cd \
+ pkzip -rP em941212 \emtex\*.* [941212 = date in readme.tst]
+ copy em941212.zip [your archive place]
+ copy base.zip [your archive place]
+ copy tools.zip [your archive place]
+
+ These should fit on two 3" floppies. This is what I use to archive the
+ distribution. The em941212.zip will have to be split across the disks. I
+ picked 941212 as the version number since that is the date in the readme.tst
+ file. When the date changes, change the number.
+
+g. This will give you the following software and versions:
+
+ bibtex32.exe 0.99c [3c-beta1, have to dig thru exe to find vers]
+ dvidrv ?
+ dvihplj 1.5g
+**** dvihplj7 1.5g
+ dviscr 1.5g
+**** dviscr 1.5a
+ emx.exe 0.8h (rev 16) [have to dig thru exe to find vers]
+**** emx.exe 0.8h (rev 18)
+ fontlib 1.2a
+ gftodvi.exe 3.0 [1g]
+ gftopk.exe 3.2 [1j]
+**** gftopk.exe 2.3 [1j]
+ makeindx.exe 2.11
+ maketcp.exe 1.1c
+ mf386.exe 2.71 [3c-beta5]
+ mfjob.exe 1.1n
+ mft.exe 2.0 [1e]
+ pktogf.exe 1.0 [1c]
+ pktype.exe 2.3 [1c]
+ tex386.exe 3.1415 [3c-beta12]
+ texcad.exe 2.8
+
+
+2. RESTORING THE ARCHIVE
+~~~~~~~~~~~~~~~~~~~~~~~~
+If you are continuing from above skip to the next section. If you are
+restoring em941212 from the archive you made earlier, do that now, and:
+
+pkunzip -d em941212.zip
+
+3. COMPLETING THE INSTALLATION OF LATEX2e
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Make sure that the following is in \config.sys: (the numbers can be larger)
+
+shell=command.com /e:1024 /p
+buffers=20
+files=20
+
+if tex complains that it can't open an output file, increase the files.
+
+Edit \autoexec.bat and append the following to the path statement:
+;\emtex
+
+also add the following lines
+
+set texinput=c:\emtex\texinput!
+set dvidrvfonts=c:\texfonts
+set dviscr=-s2
+set mfjobopt=-3
+
+You may insert the contents of \emtex\set-tex.bat into your autoexec.bat,
+although it is not necessary, since the default paths are hard coded into
+the .exe files. However, if you change any paths later, you will have to
+edit \emtex\set-tex.bat to reflect them, and execute \emtex\set-tex.bat
+each time you boot, or automatic subdirectory searching will not work.
+Make sure that the ! follows the `texinput' as in the first line above.
+Also, the last two are not in set-tex.bat, so you have to add them anyway.
+
+You should add the following line to your autoexec.bat, with appropriate
+number for the lpt port. This prevents prthplj & prthpljh from aborting when
+you take too long to refill the printer's paper:
+mode lpt1 retry=r
+
+create \emtex\tex.bat in path:
+tex386 &plain %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+create \emtex\latex.bat in path:
+tex386 &latex %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+create \emtex\slitex.bat in path:
+tex386 &splain %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+or add them to a ced-like alias file. If you don't know what that is, don't
+ask. You will now type tex, latex, slitex followed by the filename to
+process a document. If the extension on the filename is .tex, it is optional.
+
+reboot now!
+
+EXTRACT LATEX2E
+~~~~~~~~~~~~~~~
+cd \
+pkunzip -d \base
+cd \base
+\emtex\tex386 /i unpack.ins
+
+replace any existing files in the following (to override them):
+move *.ltx \emtex\btexfmts
+move ltxcheck.tex \emtex\texinput
+move testpage.tex \emtex\texinput
+move docstrip.tex \emtex\texinput
+move *.cls \emtex\texinput
+move *.clo \emtex\texinput
+move *.sty \emtex\texinput
+move *.fd \emtex\texinput
+move *.def \emtex\texinput
+move *.cfg \emtex\texinput
+
+mkdir \emtex\makeindx
+move *.ist \emtex\makeindx
+
+mkdir \emtex\doc\base
+move *.tex \emtex\doc\base [save and read these docs]
+move *.txt \emtex\doc\base [save and read these docs]
+**** move *.err \emtex\doc\base [LaTeX companion & LaTeX book errata]
+
+mkdir \emtex\texinput\local
+**** For local files, will be used by automatic 1 subdir level search ('!')
+
+cd \
+del base.zip
+del base
+rmdir base
+
+BUILD THE CM BASES
+~~~~~~~~~~~~~~~~~~
+cd \emtex\bmfbases
+bas
+
+BUILD THE TEX AND LATEX2e FORMATS
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+cd \emtex\btexfmts
+fmt
+slifmt
+del lplain.* [this is the old 2.09 format replaced later on]
+\emtex\tex386 /i latex.ltx [this is the new latex 2e format file]
+
+cd \
+latex ltxcheck [all should be ok]
+**** Complains about missing AMS fonts (this was to be expected)
+
+
+EXTRACT THE MAINZ TOOLS
+~~~~~~~~~~~~~~~~~~~~~~~
+cd \
+pkunzip -d \tools
+cd tools
+latex tools.ins
+del temp.tex
+mkdir \emtex\texinput\tools
+move *.sty \emtex\texinput\tools
+move *.tex \emtex\texinput\tools
+**** move *.txt \emtex\doc\tools
+
+mkdir \emtex\doc\tools
+move *.dtx \emtex\doc\tools [these are all the docs for tools]
+
+cd \
+del tools.zip
+del tools
+rmdir tools
+
+TESTING THE LATEX INSTALLATION
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+mkdir \test
+cd \test
+
+Make a small file called cm.tex containing:
+
+\documentclass{article}
+\begin{document}
+Hello world...........$\sum$
+\end{document}
+
+and latex it by typing `latex cm'. It should not complain.
+
+
+4. VIEWING THE RESULTS
+~~~~~~~~~~~~~~~~~~~~~~
+By latexing the above test document we have only used brief font info that
+is stored in the TFM files (in \emtex\tfm). You cannot print or view the
+results until you put fonts on your computer and/or printer. The only
+exception to this is postscript printers or viewers which have their fonts
+built in. More on that later.
+
+If you have a postscipt printer, you may use its internal fonts, or you may
+download fonts (e.g. CM [computer modern]), or do a combination of the two).
+You may also choose to use a postscript previewer for screen previewing (e.g.
+ghostscript). OR, you may choose to use the CM fonts that come with latex for
+screen previewing and use a dvi previewer (e.g. dviscr).
+
+If you have a reasonably recent HP pcl laser printer (any of the laser jets
+excluding the laser jet 1 [the laser jet 1+ is ok, although limited memory)
+or a laser printer that emulates an HP laser printer, you will want to use
+the CM fonts.
+
+The new HPLJ IV has its own scaleable fonts, so perhaps you will be able to
+use those internal fonts much like with postscript printers. You would need
+the TFM files describing the fonts inside the printer. I haven't done much
+work with the HP LJ IV so it is possible this has already been done. I don't
+discuss it here.
+
+Moving on in the choices, if you choose to use CM for either printing or
+display, then you need to obtain the actual fonts. You can either get
+them from the net, generate them all at once, or generate them on demand
+and the save them for future use. I do the latter. On a 486-33 MHz
+it only takes a minute or so to generate a font in a particular size.
+All these options are described next.
+
+Pick one, and skip to a), b), c), d), e), or f) below.
+**** Best choice is step c), generate fonts on demand
+
+a. CM fonts from the net, for screen viewing & 300 dpi hplj printing
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ mkdir \texfonts
+ cd \texfonts
+ ftp ftp.shsu.edu [or other site]
+ cd tex-archive/systems/msdos/emtex-fonts
+ bin
+ hash
+ get lj_fonts.zip [this will be about 5 MB]
+ quit
+
+ pkunzip lj_fonts *.fli [or unzip -j lj_fonts *.fli]
+
+ Archive lj_fonts.zip somewhere for future use.
+
+ To display the document on your screen, use v <filename>. v.bat is a batch
+ file in \emtex which calls dviscr. If you have a math coprocessor and
+ deleted dviscr.exe and kept dviscr7.exe, edit v.bat to call dviscr7.exe
+ instead of dviscr.exe. Example:
+
+ cd \test
+ v test
+
+ I add a /pt to \emtex\data\lj.cnf to prevent all the .dlg files.
+
+ You can also put the one line contents of v.bat into a ced-like program. If
+ you don't know what that is, skip it.
+
+ Read the documentation on dvi viewers in \emtex\doc\english\dvidrv.doc
+
+b. CM fonts from the net, for screen viewing & 600 dpi hplj IV printing
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ I haven't tried this, since I couldn't find the .fli files for the HPLJ 4 on
+ the net. They would be rather large (up to 4x larger than the 300dpi---twice
+ in each dimension, 2 dimensions). If you do find them, edit
+ \emtex\v.bat to use @ljh.cnf and follow along similarly to the previous
+ section for 300dpi fonts, but edit \emtex\ljh.cnf, instead.
+
+ Or, You may want to dynamically generate the fonts (below)...
+
+
+c. Dynamically generating the CM fonts on demand, 300 dpi for hplj & screen
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ This is how I do it. Append the following line to \emtex\data\lj.cnf
+ /fb
+
+ I also add a /pt to the file to prevent all the .dlg files.
+
+ You may wish to comment out the /pl line with a %, since you will not be
+ using the font libraries, as was done in 4a.
+
+ Make sure that `set mfjobopt=-3' is in your autoexec.bat, or that it is
+ set before trying to generate the fonts. This tells mfjob to use mf386.exe
+ instead of mf.exe.
+
+ cd \test
+ v test
+
+ should generate 2 fonts and then display the dvi file on your screen. The
+ next time you do `v test' the fonts will already be generated. v.bat is a
+ batch file in \emtex which calls dviscr. If you have a math coprocessor,
+ edit v.bat to call dviscr7.exe. You can also put the one line contents of
+ v.bat into a ced-like line. The fonts go to \texfonts\pixel.lj\300dpi.
+
+
+d. Dynamically generating the CM fonts on demand, 600 dpi for hplj IV & screen
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Append the following lines to \emtex\data\ljh.cnf
+ /fb
+
+ & comment out the /pl line with a %. Also edit v.bat to use ljh.cfg instead
+ of lj.cnf. v.bat is a batch file in \emtex which calls dviscr. If you
+ have a math coprocessor, edit v.bat to call dviscr7.exe. I also add a /pt
+ to the config file to prevent all the .dlg files.
+
+ Make sure that `set mfjobopt=-3' is in your autoexec.bat, or that it is
+ set before trying to generate the fonts. This tells mfjob to use mf386.exe
+ instead of mf.exe.
+
+ cd \test
+ v test
+
+ should generate 2 fonts and display the dvi file on your screen. The fonts
+ go to \texfonts\pixel.ljh\600dpi. Next time, it won't have to generate
+ these fonts.
+
+e. Locally generating all 300dpi fonts for HP
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ cd \emtex\mfjob
+ mfjob all [wait several hours]
+ cd \
+ del \newfonts\tfm
+ rmdir \newfonts\tfm
+ del \newfonts\log
+ rmdir \newfonts\log
+ move newfonts texfonts
+
+f. Locally generating all 600dpi fonts for HP IV
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ cd \emtex\mfjob
+ edit modes.mfj and change `def m=[lj]' to `def m=[ljh]' at end
+ mfjob all [wait several hours]
+ cd \
+ del \newfonts\tfm
+ rmdir \newfonts\tfm
+ del \newfonts\log
+ rmdir \newfonts\log
+ move newfonts texfonts
+
+
+5. Printing using CM fonts and HPLJ or HPLJ IV
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+use prthplj.bat and prthpljh.bat respectively. You may want to edit
+them and change the output file /po=lpt1:, etc. If you have a math coproc,
+edit prthplj.bat and prthpljh.bat to call dvihplj7.exe. If you are using
+the HPLJ IV, add /og=600 to \emtex\prthpljh.bat on the same line.
+
+These routines use the same fonts and config files as the screen previewer,
+so once the fonts are generated by the screen viewer, they are generated for
+the printer too.
+
+IF you have an hp printer you are now done with the installation.
+
+6. PSNFSS & DVIPS for postscript printers (skip if you don't have a PS printer)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+a. Using CM fonts only, and not the internal PS fonts of your printer
+
+ if all you want to do is to use the CM fonts (and not the fonts in your
+ postscript printer), you may stop here. However this is kind of a waste
+ because the extra money you paid for the postscript printer gives you a
+ lot of advanced features and fonts. However, with those features comes
+ more installation difficulties, ie, the rest of this document. So no
+ one would blame you for stopping here.
+
+ If you want to stop here and generate CM fonts and download them to the
+ printer as a bit-map each time you print, do the following:
+
+ cd \
+ ftp wuarchive.wustl.edu
+**** 4.8 KB/s
+ cd /mirrors/msdos/postscript
+**** cd /systems/ibmpc/simtel/msdos/postscrp
+ bin
+ hash
+ get dvips554.zip [592,893 bytes, or latest]
+ quit
+
+ pkzip -d \dvips554.zip *.tfm [delete the .tfm's from the zip]
+ pkzip -d \dvips554.zip *.vf [delete the .vf's from the zip]
+ pkunzip -d \dvips554.zip
+
+ cd \emtex\texinput\dvips
+ del times.sty
+ del palatino.sty
+ del bookman.sty
+ del chancery.sty
+ del avantgar.sty
+ del lucida.sty
+ del ncs.sty
+ del psfonts.sty
+ del psgreek.sty
+
+ The above represent old style files incompatible with latex2e and psnfss2e.
+
+ mkdir \emtex\doc\dvips
+ move dvi*.tex \emtex\doc\dvips
+
+ The fonts for the Apple Laserwriters are the same as for the HP LJ, since
+ the engines are the same [write black]. Choosing dvihplj or dvips formats
+ the bit maps properly in each printer's language. This is where the
+ difference is. Thus CM fonts obtained in 4a, 4b, 4e, or 4f are suitable
+ for dvips. Follow those instructions if you haven't already for the
+ screen fonts. If you have already obtained or generated or set up
+ dynamic (on the fly generation of fonts) for the screen you are already
+ to go:
+**** The problem is that the Dvips config files assume drive C unless
+**** told otherwise (dvips won't find 'tex.pro', see page 37 Dvips manual)
+**** Assuming emTeX in drive D, fonts in drive E:
+**** set texconfig=d:\emtex\ps
+**** set emtexdir=d:\emtex
+**** set dvipsheader=d:\emtex\ps
+**** set texfonts=e:\texfonts
+**** set texpks=e:\texfonts\pixel.lj\%bdpi\%f.pk
+**** (put these in a batch file, remember to use '%%' to mean '%' in the
+**** texpks value)
+
+ cd \test
+ dvips cm
+ copy cm.ps lpt1: [or where ever your printer is]
+
+ You may need an iteration of `mfjob dvips' to generate fonts. You may
+ stop here. Delete dvips.mfj after doing mfjob.
+
+
+b. Using the internal PS fonts of your printer, and CM for occasional math
+
+ IF you wish to take advantage of the native fonts in
+ your postscript printer, continue on.
+
+ Do the steps in a) above.
+
+ To use use native fonts, you will
+ insert one command \usepackage{font} in your latex document after the
+ \documentclass{} command. font=one of times, palatino, helvet, avant,
+ newcent, or bookman. To get these psnfss2e packages:
+
+ cd \
+ ftp ftp.shsu.edu [or other site]
+ cd tex-archive/macros/latex/packages
+ bin
+ hash
+ get psnfss.zip [724,648]
+ quit
+
+ pkunzip -d \psnfss.zip
+ cd \psnfss
+ latex psfonts.ins [installation]
+**** answer y to "do you have the 36 common PS fonts or do you intend to install them"
+ mkdir \emtex\texinput\ps
+ move *.sty \emtex\texinput\ps
+ mkdir \emtex\doc\ps
+ move psnfss2e.tex \emtex\doc\ps
+ move psfonts.dtx \emtex\dec\ps
+ cd \
+ del \psnfss
+ rmdir \psnfss
+
+ get the latex2e tfm, vf, fd and other associated files for adobe ps fonts:
+
+ ftp ftp.shsu.edu [or other site]
+ cd tex-archive/fonts/metrics
+ bin
+ hash
+ get adobe.zip [1,895,291 bytes]
+ quit
+
+ cd \
+ pkunzip -d \adobe.zip
+
+ edit \emtex\ps\config.ps and uncomment (delete the *) & change the line:
+ T c:\emtex\tfm;c:\emtex\tfm\ps;c:\emtex\tfm\local
+**** Change all the following paths (V, P, L, S, H) also because they assume drive C
+
+ there are 6 packages (times, palatino, helvet, avant, newcent, bookman) which
+ you use to select the primary postscript fonts for your document. These in
+ turn call upon the following 7 native postscipt fonts in the printer:
+ Helvetica, AvantGarde, Times, Palatino, NewCenturySchoolbook, Bookman, and
+ Courier. Your printer and screen previewer should have these to work properly
+ with the 6 packages (they are part of the standard 35 fonts). This info came
+ from Table 1 of psnfess2e.tex (page 4). The file adobe.zip that you just
+ obtained contains fd, tfm, and vf data for these and many other postscript
+ fonts. I will only cover the 7 fonts used by the 6 packages.
+
+ move \adobe\helvetic\fd\*.fd \emtex\texinput\ps
+ move \adobe\avantgar\fd\*.fd \emtex\texinput\ps
+**** md emtex\tfm\ps
+**** This requires adding this path to the environment var TEXTFM
+ move \adobe\times\fd\*.fd \emtex\texinput\ps
+ move \adobe\palatino\fd\*.fd \emtex\texinput\ps
+ move \adobe\newcentu\fd\*.fd \emtex\texinput\ps
+ move \adobe\bookman\fd\*.fd \emtex\texinput\ps
+ move \adobe\courier\fd\*.fd \emtex\texinput\ps
+
+ mkdir \texfonts\vf
+ move \adobe\helvetic\vf\*.vf \texfonts\vf
+ move \adobe\avantgar\vf\*.vf \texfonts\vf
+ move \adobe\times\vf\*.vf \texfonts\vf
+ move \adobe\palatino\vf\*.vf \texfonts\vf
+ move \adobe\newcentu\vf\*.vf \texfonts\vf
+ move \adobe\bookman\vf\*.vf \texfonts\vf
+ move \adobe\courier\vf\*.vf \texfonts\vf
+
+ move \adobe\helvetic\tfm\*.tfm \emtex\tfm\ps
+ move \adobe\avantgar\tfm\*.tfm \emtex\tfm\ps
+ move \adobe\times\tfm\*.tfm \emtex\tfm\ps
+ move \adobe\palatino\tfm\*.tfm \emtex\tfm\ps
+ move \adobe\newcentu\tfm\*.tfm \emtex\tfm\ps
+ move \adobe\bookman\tfm\*.tfm \emtex\tfm\ps
+ move \adobe\courier\tfm\*.tfm \emtex\tfm\ps
+
+ move \adobe\helvetic\phv.map \emtex\ps
+ move \adobe\avantgar\pag.map \emtex\ps
+ move \adobe\times\ptm.map \emtex\ps
+ move \adobe\palatino\ppl.map \emtex\ps
+ move \adobe\newcentu\pnc.map \emtex\ps
+ move \adobe\bookman\pbk.map \emtex\ps
+ move \adobe\courier\pcr.map \emtex\ps
+
+ cd \
+ del adobe.zip
+ del adobe
+ rmdir adobe
+
+ cd \emtex\ps
+ del psfonts.map
+ ren *.map *.x
+ copy phv.x + pag.x + ptm.x + ppl.x + pnc.x + pbk.x + pcr.x psfonts.map
+ del *.x
+
+ cd \test and create a file called ps.tex
+ \documentclass{article}
+ \usepackage{times}
+ \begin{document}
+ Hello world...........$\sum$
+ \end{document}
+
+ dvips ps
+
+ this should work. The math needs to use the old CM fonts, a small subset
+ of which may need to be generated on the fly or downloaded. dvips should
+ have created an instruction file for mfjob to create the missing math
+ fonts. If all is well, run
+
+ mfjob dvips
+ dvips ps
+ copy ps.ps to lpt1: [or whatever is your printer port]
+
+ and you should have the complete document. I create everything on demand,
+ when dvips complains, using mfjob dvips as above.
+
+ cd \
+ del adobe
+ rmdir adobe
+
+ Note, as I mentioned before, you can't view postscript on your screen.
+ The missing fonts appear as boxes on the screen, but print fine on a
+ postscript printer.
+
+ You can look at the document on the screen using ghostscript or another
+ postscript previewer, which allows you to look at any included post-
+ script figures too, but involves a few more hours of install time (if you've
+ gotten this far then you can handle anything!).
+
+ Check out gs386.exe on wuarchive.wustl.edu.
+
+
+7. CUSTOM FONTS
+~~~~~~~~~~~~~~~
+to use a custom font, say APL, get the .mf file off the net, and
+put it in a \emtex\mfinput\local subdirectory. As an example, use cmapl10.mf
+from the CTAN archive in /tex-archive/fonts/apl:
+
+cd \emtex\mfinput\local
+mf386 \mode=hplaser; \nonstopmode; mag=1.0; input cmapl10
+
+move cmapl10.tfm \emtex\tfm\local
+
+to look at it, for example, do:
+
+tex testfont
+and reply:
+cmapl10
+\table
+\end
+
+then
+v testfont
+
+and let it generate the fonts and look at them! To use them in a document,
+read the texbook.
+
+you can print out the result on an hp printer:
+dvihplj testfont
+
+you can print out the result on an hp IV printer:
+dvihpljh testfont
+
+you can print out the result on a postscipt printer:
+dvips testfont
+
+(c) 1995 John P. Refling, All rights reserved.
+
+
+ # - # - #
+
+
+
+
+ printing
+ /|\
+/- / | \
+| / | \
+| / | \
+|printer hp / | hpIV \ ps
+| / | \
+| / | \
+\- / | \
+ / | \
+/- / / \ / \
+|font CM / CM / \ HP CM / \ PS /w CM
+|- / / ? / \
+ / / / \
+ prthplj prthpljh dvips1 dvips2
+ 300 600 300 300
+/- |\ /| |\ /|
+| | \ LIB OTF / | | \ LIB OTF / |
+| OTF | \ / | LIB OTF | \ / |
+| | \ / | | \ / |
+|source | \ | | \ |
+| | / \ | | / \ |
+| | / \ | | / \ |
+| | / \ | | / \ |
+\- |/ \| |/ \|
+
+ 4c,4d download=4a or 4b 6a+(4c or 4d) download=6b+(4a or 4b)
+ genall=4e or 4f genall=6b+(4e or 4f)
+
+
+Type of printer
+~~~~~~~~~~~~~~~
+hp = PCL (hplaserjet 1+ through BUT not including the HP Laserjet IV)
+hpIV = PJL (hplaserjet IV, w/o postscript)
+ps = any postscript printer (including hplaserjet IV w/postscript)
+
+Choice of font
+~~~~~~~~~~~~~~
+CM = Computer Modern fonts, freely available, and included with emtex
+ (either generated locally with metafont, or downloaded off the net,
+ see source of CM font below)
+HP = scaleable fonts inside the HP laserjet IV printer
+PS = scaleable postscript fonts inside a postscript printer, however, when
+ you are using math, it will revert to CM for the math fonts. See source
+ of CM fonts below.
+
+Source of CM fonts (for CM or CM for postscript math)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OTF = On the fly font generation (initially slower, small space rqmt)
+LIB = downloaded libraries of all the fonts (faster, large space rqmt ~5 MB)
+
+
+
+What to use
+~~~~~~~~~~~
+prthplj = from emtex
+prthpljh = from emtex
+dvips1 = with OTF CM generation from MakeTeXPK, or PK libraries
+dvips2 = mostly internal postscript fonts, but some of OTF CM generation
+ for fonts missing from postscript.
+? = no solution that I am aware of, but I didn't look very hard
+
+(c) 1995 John P. Refling. All rights reserved.
+
+**** All lines below this one represent my setup, they are not from John Refling:
+**** (they are not all marked with '****' to avoid cluttering)
+
+**** Encapsulated PostScript support:
+To be able to use the epsfig package expand 'graphics.tar.gz' somewhere,
+read the '00readme.txt' and then run:
+('?' is your drive letter, .tgz because .tar.gz is invalid in Ms-Dos)
+
+gzip -dc graphics.tgz | tar xvf -
+latex graphics.ins
+md ?:\emtex\texinputs\graphics
+copy *.def ?:\emtex\texinputs\graphics
+copy *.sty ?:\emtex\texinputs\graphics
+copy 00readme.txt ?:\emtex\texinputs\graphics
+echo \ExecuteOptions{dvips} > ?:\emtex\texinputs\graphics\color.cfg
+echo \ExecuteOptions{dvips} > ?:\emtex\texinputs\graphics\graphics.cfg
+
+**** I put this in my 'autoexec.bat':
+
+rem emTeX, don't change, just update DVIDRVFONTS, EMTEXDRIVE, PATH and edit the
+rem file '?:\emtex\ps\config.ps' and fix its T, V, P, L, S, H paths
+set DVIDRVFONTS=G:\texfonts
+set EMTEXDRIVE=H
+echo Calling %EMTEXDRIVE%:\emtex\set-tex.bat
+if exist %EMTEXDRIVE%:\emtex\set-tex.bat goto SETTEX
+echo File not found!
+pause
+:SETTEX
+call %EMTEXDRIVE%:\emtex\set-tex.bat
+SET MFINPUT=%MFINPUT%;g:\usr\local\lib\tex\mfinput
+
+**** And I put this in the 'set-tex.bat' file in the emtex dir:
+
+rem emTeX env vars setup, see also jrtex12a.txt.
+rem If changing location update:
+rem a) env vars 'EMTEXDRIVE' (emTeX drive) and 'DVIDRVFONTS' (TeX fonts path)
+rem b) edit the file 'emtex\ps\config.ps' and fix the paths T, V, P, L, S, H
+if %DVIDRVFONTS%.==. goto NOENVVAR
+if %emtexdrive%.==. goto NOENVVAR
+rem Append `!' to a directory name to get one-level subdirectory search
+rem Append `!!' to a directory name to let emTeX search all subdirectories
+SET TEXINPUT=%emtexdrive%:\EMTEX\TEXINPUT!
+SET TEXFMT=%emtexdrive%:\EMTEX\TEXFMTS
+SET BTEXFMT=%emtexdrive%:\EMTEX\BTEXFMTS
+SET TEXTFM=%emtexdrive%:\EMTEX\TFM;%emtexdrive%:\EMTEX\TFM\PS
+SET MFINPUT=%emtexdrive%:\EMTEX\MFINPUT
+SET MFBAS=%emtexdrive%:\EMTEX\MFBASES
+SET BMFBAS=%emtexdrive%:\EMTEX\BMFBASES
+SET MFJOB=%emtexdrive%:\EMTEX\MFJOB
+SET BIBINPUT=%emtexdrive%:\EMTEX\BIBINPUT
+SET DVIDRVINPUT=%emtexdrive%:\MYTEX;%emtexdrive%:\EMTEX\DOC
+rem SET DVIDRVGRAPH=C:\MYTEX;%emtexdrive%:\EMTEX\DOC\GR$r
+SET DVIDRVGRAPH=%emtexdrive%:\EMTEX\DOC\GR$r
+set dviscr=-s2
+set mfjobopt=-3
+rem DVIPS 5.54 (also possible to only use TEXCONFIG and to set rest in cfg file)
+set texconfig=%emtexdrive%:\emtex\ps
+set emtexdir=%emtexdrive%:\emtex
+set dvipsheaders=%emtexdrive%:\emtex\ps
+set texfonts=%emtexdrive%:\emtex\tfm;%emtexdrive%:\emtex\tfm\ps
+set texpks=%DVIDRVFONTS%\pixel.lj\%%bdpi\%%f.pk
+goto THEEND
+:NOENVVAR
+echo %0: ERROR, env vars DVIDRVFONTS and EMTEXDRIVE not set!
+pause
+:THEEND
+
+**** GhostScript (PostScript level 2 interpreter/previewer)
+**** The current version is 3.12 (Oct-94)
+**** ftp.funet.fi:/pub/gnu/ghostscript3/aladdin
+There are several Dos/Win binaries:
+ 1) gs.exe was compiled for the following devices:
+ vga ega svga16 vesa atiw tseng tvga deskjet
+ djet500 laserjet ljetplus ljet2p ljet3 ljet4 cdeskjet cdjcolor
+ cdjmono cdj550 pj pjxl bj10e bj200 epson eps9high
+ ibmpro gifmono gif8 pcxmono pcxgray pcx16 pcx256 pcx24b
+ 2) gs386.exe was compiled for the following devices:
+ vga ega svga16 atiw tseng tvga deskjet djet500
+ laserjet ljetplus ljet2p ljet3 ljet4 cdeskjet cdjcolor cdjmono
+ cdj550 paintjet pjetxl epson eps9high ibmpro bj10e bj200
+ gifmono gif8 tiffg3 faxg3 pcxmono pcxgray pcx16 pcx256
+ pcx24b pbm pbmraw pgm pgmraw ppm ppmraw bitcmyk
+ 3) don't know what gswin.exe was compiled for (use the PostScript command
+ 'devicenames ==' to find out, using the option '-h' won't work here)
+ 4) gswin32s.exe was compiled (not by Aladdin) for the following devices:
+ mswin mswinprn deskjet djet500 laserjet ljetplus ljet2p
+ ljet3 ljet4 cdeskjet cdjcolor cdjmono cdj550 paintjet pjetxl epson
+ eps9high ibmpro st800 bj10e bj200 gifmono gif8 tiffg3
+ tiffg4 bmpmono bmp16 bmp256 bmp16m pcxmono
+ pcx16 pcx256 pbm pbmraw pgm pgmraw ppm ppmraw
+If you need something that is not in here you will have to compile GhostScript
+yourself (if the device code already exists just add it to the makefile,
+otherwise you'll have to write it yourself, there is documentation on how to do
+that) or if your printer is supported by Windows to use gswin?.exe with the
+device 'mswinprn')
+
+**** end of this file
diff --git a/web/noweb/contrib/avs/make_ico.awk b/web/noweb/contrib/avs/make_ico.awk
new file mode 100644
index 0000000000..f422176173
--- /dev/null
+++ b/web/noweb/contrib/avs/make_ico.awk
@@ -0,0 +1,50 @@
+# edits noweb/src/icon/makefile for Ms-Dos + PC386 + Icon 386 9.0 + DJGPP + MKS 4.2
+# tested with noweb 2.7a
+
+BEGIN { print "# generated MsDos makefile, original in makefile.old" }
+
+/SHELL=/ { $0 = "# " $0 } # disable SHELL def
+
+/BINEXECS=/ { # add .exe extension
+ s = "";
+ for (k = 1; k <= NF; ++k)
+ s = s sprintf("%s.exe ", $k);
+ $0 = s
+}
+
+function splitLineTooLong() { # appends to strings s1 & s2 (does not initialize them)
+ for (k = 1; k <= NF; ++k)
+ if (match($k, "\\."))
+ s1 = s1 $k " ";
+ else
+ s2 = s2 $k ".exe ";
+ }
+/LIBEXECS=/ { # split in 2 parts (to avoid 128 chars command.com overflow) and add .exe if no extension is provided
+ s1 = ""; s2 = "";
+ if ($NF == "\\") { # tackles problem of a '\' meaning continue in next line
+ $NF = "";
+ NF = NF - 1;
+ splitLineTooLong();
+ getline; # read next line due to '\' continuation char
+ }
+ splitLineTooLong();
+ printf("LIBEXECS2=%s\n", s1);
+ $0 = s2;
+}
+
+/^EXECS=/ { $0 = $0 " $(LIBEXECS2)" } # because now LIBEXECS is split into LIBEXECS and LIBEXECS2
+
+/cp \$\(LIBEXECS\)/ { printf("\tcp $(LIBEXECS2) $(LIB)\n"); } # the new LIBEXECS2 also need to be copied
+
+/\/bin\/rm/ { $1 = "\trm" } # rm might not be at "/bin/rm", remember to add the tab \t
+
+/\$\(ICON.\) -o/ {
+ if (!match($3, "\\.")) { # if no extension add .exe
+ sub(/[a-z0-9]+/, "&.exe", $3);
+ $1 = "\t" $1 " -I" # add -I option to icon translator (see Icon 386 9.0 Ms-Dos docs)
+ }
+ }
+
+/^[a-z0-9]+: [a-z0-9]+\.icn/ && NF == 2 { sub(/[a-z0-9]+/, "&.exe", $1) } # add .exe
+
+{ print $0 } # prints the line (which might have been changed)
diff --git a/web/noweb/contrib/avs/make_lib.awk b/web/noweb/contrib/avs/make_lib.awk
new file mode 100644
index 0000000000..84e2c15bd6
--- /dev/null
+++ b/web/noweb/contrib/avs/make_lib.awk
@@ -0,0 +1,12 @@
+# edits noweb/src/lib/makefile for Ms-Dos + PC386 + Icon 386 9.0 + DJGPP + MKS 4.2
+# tested with noweb 2.7a
+
+BEGIN { print "# generated MsDos makefile, original in makefile.old"; }
+
+/SHELL\=/ { $0 = "# " $0 } # disable SHELL def
+
+/cp unmarkup emptydefn toascii \$/ { # add an extension .ksh) when copying
+ $0 = "\tcp unmarkup $(LIB)/unmarkup.ksh\n\tcp emptydefn $(LIB)/emptydefn.ksh\n\tcp toascii $(LIB)/toascii.ksh"
+}
+
+{ print $0 } # prints the line (which might have been changed)
diff --git a/web/noweb/contrib/avs/make_src.awk b/web/noweb/contrib/avs/make_src.awk
new file mode 100644
index 0000000000..d9dec16af4
--- /dev/null
+++ b/web/noweb/contrib/avs/make_src.awk
@@ -0,0 +1,72 @@
+# edits noweb/src/makefile for Ms-Dos + PC386 + Icon 386 9.0 + DJGPP + MKS 4.2
+# tested with noweb 2.7a
+
+BEGIN { print "# generated MsDos makefile, original in makefile.old" }
+
+/SHELL\=/ { $0 = "# " $0 } # disable SHELL def
+
+/for i in shell lib xdoc tex;/ { # new fix for noweb 2.7a (not needed in 2.7)
+ $0 = "\tcd shell\n\tmake all\n\tcd ..\n\tcd lib\n\tmake all\n\tcd ..\n\tcd xdoc\n\tmake all\n\tcd ..\n\tcd tex\n\tmake all\n\tcd ..\n"
+}
+
+/cd ([a-z]+)|(\$\(LIBSRC\)); make/ { # fix problems with quotes and 'cd' and explode into 3 lines
+ if ($NF == "all") {
+ for (k = 1; k <= NF; ++k) gsub("\"", "", $k); # remove quotes
+ sub(/;/, "", $2); # remove semicolon
+ s = ""; for (k = 4; k <= NF; ++k) s = s " " $k; # group 'Make' args in a single string (for the sprintf)
+ $0 = sprintf("cd %s\n\t$(DJGPPMAKE) %s\n\tcd ..", $2, s);
+ } else
+ if ($NF == "install")
+ sub("^[^;]+", " \"&\"", $2); # add quotes (which need a shell) to force use of shell internal 'cd' instead of bin/cd.exe
+ $0 = "\t" $0;
+}
+
+/\/dev\/null/ { sub(/\/dev\/null/, "NUL") } # Ms-Dos uses NUL to mean /dev/null
+
+/strip/ {
+ sub(/strip/, "# strip"); # remove the strip, MKS strip would ruin the binaries
+ $0 = $0 "\n\tcd \"c\"; coff2exe nt markup mnt finduses"; # and in next line add the coff2exe command (see DJGPP docs)
+}
+
+/chmod \+x/ { $0 = "\t# " $0 } # disable chmod (not necessary and sometimes tries to 'chmod +x foo' instead of 'chmod +x foo.ksh')
+
+/cp / { # add an eventual extension (.exe or .ksh) when copying
+ if (match($2, "^c/")) {
+ $1 = "\t" $1;
+ for (k = 2; k < NF; ++k) # NB: 1st & last field not processed
+ $k = $k ".exe";
+ } else {
+ if ($NF == "$(LIB)") { # add .ksh and split in several lines
+ s = "";
+ for (k = 2; k < NF; ++k) {
+ baseName = substr($k, 1 + match($k, "/"));
+ s = s sprintf("\tcp %s %s/%s.ksh", $k, $NF, baseName);
+ if (k != NF-1)
+ s = s "\n";
+ }
+ $0 = s;
+ }
+ }
+}
+
+/install: install-code install-man install-tex/ { $3 = "install-preformat-man" } # MKS has no NROFF
+
+/sed / { # all files processed by sed require something to be fixed for MsDos
+ if (match($0, "\$\(BIN\)"))
+ $NF = $NF ".ksh" # add .ksh extension
+ else {
+ if (match($0, "gzip")) { # remove gzip of man pages, MKS supports compressed man pages but in .dbz not in .gz format
+ sub("\| gzip", ""); # remove call to gzip
+ sub("\.gz$", "", $NF); # remove .gz extension
+ } else
+ $0 = "#" $0; # Disable because MKS does not support NROFF
+ }
+ $0 = "\t" $0;
+}
+
+/; ln / { # no links in MsDos
+ sub(/; ln /, "; cp -p "); # replace link (ln) with copy (cp)
+ gsub(/\.gz/, ""); # gzip compressed man pages not used
+}
+
+{ print $0 } # prints the line (which might have been changed)
diff --git a/web/noweb/contrib/avs/make_xdo.awk b/web/noweb/contrib/avs/make_xdo.awk
new file mode 100644
index 0000000000..b59ccefb5d
--- /dev/null
+++ b/web/noweb/contrib/avs/make_xdo.awk
@@ -0,0 +1,14 @@
+# edits noweb/src/xdoc/makefile for Ms-Dos + PC386 + Icon 386 9.0 + DJGPP + MKS 4.2
+# tested with noweb 2.7a
+
+BEGIN { print "# generated MsDos makefile, original in makefile.old"; }
+
+/SHELL\=/ { $0 = "# " $0 } # disable SHELL def
+
+/WWW=/ { $0 = "WWW=../.." } # Put World Wide Web files in noweb because the dir $(HOME)/www/noweb might not exist
+
+/\/bin\/rm/ { sub(/\/bin\/rm/, "rm") } # rm might not be at "/bin/rm"
+
+/\.ps\.gz/ { sub(/\.ps\.gz/, ".pgz"); } # MsDos limitation, use extension .pgz instead of .ps.gz
+
+{ print $0 } # prints the line (which might have been changed)
diff --git a/web/noweb/contrib/avs/mks42bug.0d b/web/noweb/contrib/avs/mks42bug.0d
new file mode 100644
index 0000000000..f6ba43e2dd
--- /dev/null
+++ b/web/noweb/contrib/avs/mks42bug.0d
@@ -0,0 +1,128 @@
+ MKS Toolkit 4.2 Dos Bugs
+
+Environment: 486DX2-80 VLbus, 32 MB RAM, 2 EIDE HDs, ATI Mach64 GPT 2048K VLbus
+Sblaster 16 ASP, Logitech serial Mouseman, Ms-Dos6.22, WfW3.11 (32 bits disk
+access/32 bits file access), QEMM7.5, Stacker4.0 for OS/2 & Dos,
+OS/2 boot manager (Dos/Win, Warp, Linux)
+
+1- bin32/diff.exe doesn't do correctly wild card expansion under command.com
+ (i.e. doesn't use glob.exe correctly). It works fine under the Korn shell.
+ No problems with bin/diff.exe
+ (as it can be much faster than the 16 bits diff, e.g. 5s against 18s, I
+ just renamed it to diff32.exe)
+ BUT: it seems that in some cases with QEMM 7.5 diff32 works sometimes with
+ wildcards expansion, and it is diff.exe that crashes when wild card expansion
+ is used and at the same time there are differences (QEMM says invalid ...).
+ Notice that it seems that if the 2 files are identical no problem! Under
+ a clean boot no crash, but again no one can check if invalid statements
+ are used. See the 2 files MOD_FBUS.LST and LIXO for an example of a crash!
+
+2- bin/find.exe with the option -exec doesn't always work correctly under
+ command.com (Ms-Dos 6.2 or Ms-Dos 6.22). The 1st exec works, the 2nd gives a
+ memory allocation error (under Ms-Dos 6.2) or an unspecified error (under
+ Ms-Dos 6.22).
+ E.g.:
+ find . -type f -exec ls -l {} ;
+ always works, but in
+ find . -name "*.zip" -exec ls -l {} ;
+ only the first exec works, the 2nd gives the error message
+ find: cannot execute "ls": not a directory or path not found
+ and find aborts.
+ The same behaviour occurs with executing non MKS commands.
+ No problems if executing under the Korn shell.
+ The find.exe from version 2.3 of the MKS toolkit works fine under
+ command.com, thus this is a new bug.
+
+3- the Korn shell crashes if one presses ctrl-BREAK (even ctrl-alt-del doesn't
+ work). Under windows it "violates system integrity" and windows terminates
+ it and asks one to reboot the machine because it should be unstable. Under
+ Qemm, Qemm also complains in the same way. The setting of 'break' in
+ config.sys/autoexec.bat (i.e. ON/OFF) is not relevant here
+
+4- there are several bugs in bin/pax.exe
+ a) -i never works (i.e. whether one writes a name, presses '.' or
+ presses return it always is unable to create that file)
+ b) -s only works partially, most of the time (using s/.../.../p to see
+ what happens) it does erroneous substitutions. It seems to work if
+ all ocurrences of '.' or '/' on the original name are matched by
+ using a '.' (e.g. never use a regular expression that matches both the
+ basename and the extension)
+ c) using '-f path' if path has a backslash anywhere then it crashes
+ (e.g. using 'pax -f g:\users\foo.tar' from the DOS prompt). The
+ crash looks like an infinite loop. If running in a Dos window then it
+ is possible to kill that window without crashing the system
+ d) this is not really a bug but a thing that would come handy. It would be
+ good if pax discarded the sufix ',v' from the filenames, this because
+ Unix RCS adds that kind of sufix and when extracting it creates an
+ invalid filename. In the current version 'RCS/filename.txt,v' extracts
+ correctly (because it already has a 3 char extension thus the ',v' is
+ discarded) but RCS/filename.c,v doesn't extract at all (and as there
+ are bugs in the option -s it is hard to extract those filenames)
+ (a good thing with tar/pax is that when creating a tar file if one
+ specifies a longer filename or a filename with a mixture of upper/lower
+ case the file will be stored in the tar file with that name, this
+ simplifies going back and forward between Ms-Dos/Unix if after truncation
+ and case convertion no filenames are equal. Thus it would be also good
+ if it did accept ',v' when creating a tar file under Ms-Dos)
+#
+# How to extract RCS files from a tar file if they have ',v' on their name
+#
+# Warning: pax has bugs, -i doesn't work, -s only works if all ocurrences of
+# either '.' or '/' in the expression to match are matched by using '.'
+# Assuming filenames of the type 'cpnauto/RCS/*.*,v', extracts to 'rcs/*.*'
+# BUG: a filename without an extension (e.g. cpnauto/RCS/makefile,v') loses
+# the last char (i.e. becomes 'rcs/makefil')
+#
+# Don't try to automate (e.g. to use args, the bugs in the handling of -s
+# will probably defeat any attempts)
+#
+pax -f /cpnauto.tar >cpnauto.lst
+pax -krvf /cpnauto.tar -s '/cpnauto\(.\)RCS.\([a-z0-9_]*\).\([a-z]*\),v/rcs\1\2.\3/p' `grep RCS cpnauto.lst`
+
+5- bin/tar.exe crashes (infinite loop?) when given wildcards, e.g.
+ 'tar tvf *.tar' from the Dos prompt (command.com) and there is a single
+ file with extension .tar in that dir, no problem if using the full
+ filename [check if it is the same as 4-c)]. It also crashes if a backslash
+ is given in a pathname (infinite loop)
+
+6- there is no online man page for dircmp(1) although 'man tkerrat' says there
+ is. Anyhow dircmp(1) works
+
+ Usage: dircmp [-ds] dir1 dir2
+
+ -d -> works only for text files, shows differences in diff format
+ -s -> silent mode (non verbose, only the differences)
+
+7- 'make -f makefile' doesn't work, it always tries to use makefile.mak as
+ the makefile. Probably because 'whence -v makefile' says that makefile
+ is a function. Not checked any further
+
+8- man who(1) says that login(1) only uses the file $ROOTDIR/etc/utmp if
+ it already exists, this is not true, it is created if it does not exist.
+ Anyhow one can still install MKS in a READONLY drive because if etc/utmp is
+ set to READONLY it is not changed and there is no error message (it is not
+ enough to only have the drive but not the file write protected, in that case
+ one gets an error message: Write protect error writing drive ?)
+
+9- bin/cmp.exe gives an exit code of 3 if one of the files to be compared cannot
+ be open or doesn't exist, this is in contrast with the MKS man page (and with
+ Unix) which says that an error code of 2 is to be given. If only 1 filename
+ or more than 2 filenames are given, an exit code of 2 occurs, if one of the
+ files does not exist (the 1st or the 2nd) an exit code code of 3 occurs
+
+10- the date of the '.' and '..' entries given by 'ls -al' is wrong, it's
+ always 31-Dec-79 (i.e. 0, because the PC time starts at 1-Jan-80). In other
+ words if current dir is 'foo/bar' then to get the creation date of dir
+ 'bar' one has to do 'ls -ld ../bar' instead of just 'ls -ld .'
+
+11- 'vi -x pathname' where pathname is not from the current dir
+ or has dir names (e.g. ./filename.txt)
+ Under command.com do not use '/' but '\' otherwise one gets
+ 0 lines 0 chars (even if the file exists). Under the Korn shell
+ do not use '\\' but use '/' otherwise 0 lines 0 chars.
+ This has something to do with the implicit call to crypt (caused by
+ the -x).
+ This bug is not very serious because usually one uses '\' under
+ command.com and '/' under the korn shell, still all the MKS toolkit
+ commands are supposed to accept both (and I usually use '/' even
+ under command.com)
diff --git a/web/noweb/contrib/avs/mksfixes.ksh b/web/noweb/contrib/avs/mksfixes.ksh
new file mode 100644
index 0000000000..6ca89997de
--- /dev/null
+++ b/web/noweb/contrib/avs/mksfixes.ksh
@@ -0,0 +1,15 @@
+if [ -z "$1" -o -z "$2" ]
+then
+ echo Usage $0 BIN TMP >&2
+ echo Fixes "'BIN/cpif.ksh'" for use with MKS Toolkit "(see 'man mks42bug', cmp entry)" >&2
+ echo "Fixes 'BIN/noweb.ksh' for use with MKS toolkit (the PATH problem, see howto386.txt)" >&2
+ echo TMP is for later use by cpif.ksh i.e. at run-time >&2
+ echo "Changes only line 8 (if it has 'PATH='), line 20 (if it has 'new=') and line 28 (if it has '-eq0')" >&2
+ exit 1
+fi
+
+cat $1/cpif.ksh | sed -e '8s/\(PATH=.*\)/#\1/' -e '20s@\(new=.*\)@new='$2'/$$@' -e '28s/-eq0.*/ -eq0|-ne1|*2|*3) cp $new $i/' > $2/cpif.tmp
+mv $2/cpif.tmp $1/cpif.ksh
+
+cat $1/noweb.ksh | sed '21,26s/PATH="$PATH:$LIB"//' > $2/noweb.tmp
+mv $2/noweb.tmp $1/noweb.ksh \ No newline at end of file
diff --git a/web/noweb/contrib/avs/myenv.ksh b/web/noweb/contrib/avs/myenv.ksh
new file mode 100644
index 0000000000..d390df0c59
--- /dev/null
+++ b/web/noweb/contrib/avs/myenv.ksh
@@ -0,0 +1,38 @@
+# You should only edit the line ' myargs=...', see below
+
+echo Builds and installs Noweb 2.7 from source code
+echo "Full documentation in 'howto386.txt'"
+echo Assumptions:
+echo "1- There is free environment space (between 30 and 40 bytes)"
+echo "2- DJGPP is installed (gcc, go32, coff2exe, make)"
+echo "3- MKS Toolkit 4.2 (or above?) for Dos is installed"
+echo "4- The MKS Toolkit Make is the 1st make in your PATH env var"
+echo "5- Icon 9.0 translator binaries are installed"
+echo "6- You have enough free Ram (around 600000 bytes)"
+echo "7- Your paths are not too long to break some script"
+echo " (i.e. 128 bytes Dos command line limit)"
+echo "8- To fully use Noweb, LaTeX2e already is or WILL be installed"
+echo "9- You are running a not too old Dos version (e.g. 'call batchfile')"
+
+# Edit the 'myArgs=...' line to adapt for your environment:
+# Use always FULLPATHS, i.e. with DRIVE LETTER
+# Use only slashes '/' in pathnames, backslashes won't work
+# BIN is where the noweb binaries will be installed
+# LIB is where the noweb support files will be installed
+# MAN is where to put the man pages (MANPATH env var or Mks ROOTDIR/etc)
+# DJGPPmake is the fullpath to Gnu make (does not have to be in your PATH)
+# TMP is a temporary directory to be used by Noweb at run-time
+# ICON is the fullpath to icont (the Icon translator)
+# (in both DJGPPmake and ICON the '.exe' is not necessary,
+# remove it if you have problems with names too long)
+
+theArgs="BIN LIB MAN TEXINPUTS DJGPPmake TMP ICON"
+ myArgs="i:/b g:/usr/local/lib/noweb g:/man h:/emtex/texinputs/local j:/djgpp/bin/make.exe d:/tmp e:/b/icont.exe"
+
+echo "generate $theArgs"
+echo "generate $myArgs"
+read f?"Check if the line above is OK for your machine, continue (y/n)? "
+if [ "$f" = "y" -o "$f" = "Y" -o "$f" = "yes" -o "$f" = "YES" ]
+then
+ ./generate.ksh $myArgs
+fi
diff --git a/web/noweb/contrib/avs/norman1.txt b/web/noweb/contrib/avs/norman1.txt
new file mode 100644
index 0000000000..5db826cb87
--- /dev/null
+++ b/web/noweb/contrib/avs/norman1.txt
@@ -0,0 +1,136 @@
+Hi Norman
+
+I'm one of your noweb fans (one of these days you'll get a postcard from
+Denmark) since version 2.6c. I use it in several Unix systems (Sun4, Solaris,
+HPUX, Linux) and in a PC running Dos. I am able to use Noweb in the same way
+under both Dos and Unix. This means Dos+Icon+LaTeX2e in all platforms.
+
+When I downloaded Noweb 2.6c I had problems compiling it for Dos. In a way the
+information on how to do it was there (e.g. the 'install.dos' file from Lee
+Wittenburg), but it just gave general guidelines and it used Awk instead of
+Icon. To be able to compile and use Icon took one day's work and several
+machine crashes. So I wrote a kind of HOWTO for my own use when the next
+version came around.
+
+Noweb 2.7 should have been easy, but it took a couple of hours because the
+directory hierarchy had changed. Now there are Dos binaries on the
+distribution, but they have a couple of problems (besides being from 2.6c).
+
+Today I just downloaded Noweb 2.7a. It has binaries for both 2.6c and 2.7, but
+that version 2.7 if for the Watcom compiler (I have it but it is not installed)
+and it uses Perl, which is nice but is risky if you change your code.
+After half an hour I had updated my scripts to cope with version 2.7a and
+after that I just compiled the source and got 2.7a Dos binaries.
+
+So I cleaned up my HOWTO and I'm asking if you would be interested in putting
+it in the next noweb distribution. Here is why you might be interested:
+
+1- no binaries, only text files i.e. reduced space usage. You already have Dos
+binaries in your distribution and you wouldn't want more. For those users that
+don't manage to build it, I offer to supply ftp access to the binaries (all
+they have to do is ask). Another advantage is that my scripts might work
+without changes in the next Noweb version (if you don't change the directory
+hierarchy nor the part of the makefiles that I'm patching nor add anything new
+that requires patching). Gzip compressed the files take about 40 KB, expanded
+about 112 KB. Notice that the scripts have comments and check for errors trying
+to fail gracefully, otherwise they would be one fourth as big. Also more than
+two thirds is documentation files
+
+2- the noweb/src/install.dos doesn't say enough (in my case it required 1 day's
+work), noweb/binaries/dos-2.6c.zip is already two versions behind and
+although it uses Icon it does not use Icon for a PC 386 (or above) thus memory
+problems are to be expected. Also only some of the shell scripts were
+translated to C++, thus using noweb at work (Unix) and home (Dos) wouldn't be
+exactly the same. The same applies to the Dos binaries for version 2.7, using
+Perl might make a difference
+
+3- minimum hardware/software requirements are a PC386 and the MKS Toolkit
+(commercial software). Any user that is thinking about using Noweb in an
+e.g. PC 286 is not doing serious work (or is brave). Thus asking for a 386 as a
+minimum is reasonable. It is a pity that one has to rely on commercial software
+but although there are some shareware Unix shells, I have no experience with
+them thus I don't know how good they are. The MKS toolkit is very popular and
+the price tag is quite reasonable (I think around $250). It closely follows
+Posix, there are versions for Dos, OS/2 and Win NT. It offers a Korn shell and
+all the standard Unix utilities, e.g. find, tar, man, awk, sed, vi, make. The
+only thing missing is multitasking (I manage to get a kind of multitasking by
+unning several Dos boxes under Windows, but that is another story). One can
+even use '/' instead of '\'.
+
+4- if the user has the above then the missing parts can be downloaded. I supply
+ftp sites and directories where to find DJGPP binaries (the PC386 Dos port of
+gcc, gmake, gzip, etc), Icon PC386 binaries, and LaTeX2e PC386 binaries (I
+supply an original document of John Refling annotated by me because the
+installation for a normal user is a nightmare, with that document it is
+straightforward, my annotations only fix some small bugs in that document and
+explain a few more points). As an option GhostScript can also be used
+
+5- after the user has MKS, DJGPP, Icon, and LaTeX2e (latex2e can be installed
+after noweb) properly installed, to get noweb 2.7a up and running all he/she
+has to do is to download it and to edit a one line script (in the same fashion
+as your noweb/src/nwmake) to specify the paths.
+
+6- that one line script works as follows: it supplies the args to another
+script which generates a third script. If the user is lucky running that script
+is enough (it works for me). Otherwise he/she has to look at that script and
+compare it with my document which explains ALL the steps required for fixing
+Noweb to run under Dos limitations. The generated script begins by renaming
+some of your makefiles and replacing them with equivalent makefiles (patched
+with awk scripts to circunvent Dos problems), then it uses GNU Make and Icon to
+compile the Icon sources, GNU Make and gcc to compile the C sources, and MKS
+Make and the Korn shell to install noweb. It might seem contrived but it avoids
+out of memory errors and I want to use your makefiles (i.e. slightly patched
+versions of them), not to supply my own makefiles which would be more sensitive
+to changes in your source code
+
+7- for troubleshooting I supply a document that explains all the steps for
+building Noweb, and I also supply a list of the MKS bugs that I discovered (one
+of them while compiling Noweb). I also discovered a couple of bugs/problems in
+your code, all of them trivial except one (the missing chunk problem, this is
+easy to reproduce in Dos but tough in Unix). See the file
+noweb/contrib/avs/report1.bug
+
+8- notice that the user gets EVERYTHING, e.g. 'cd noweb/src/xdoc; latex guide;
+dvips guide' works (any missing METAFONT fonts will be generated on the
+fly). Then if he/she does not have a PostScript printer he/she can get
+GhostScript (mentioned in the ftpsites.txt) to translate for the printer at
+hand. The same applies to all Noweb commands (they work as in Unix). This
+allows using Noweb for doing serious literate programming on a Dos PC all the
+way down to the printing process.
+
+9- I assume that the next version won't change the directory hierarchy thus my
+scripts might work without change or will need half an hour work to update them
+(I had to update my 2.7 scripts to 2.7a because you changed sensitive parts of
+your makefiles)
+
+10- I don't supply makefiles for commercial C compilers. As noweb is free I'll
+rather use as much free software as possible. MKS is the unfortunate exception.
+
+The tar file (39 KB) ftp.daimi.aau.dk:/pub/empl/avs/avs386_noweb27a.tar.gz
+has files that expand into noweb/contrib/avs (I copied the style of the other
+contributions, e.g. readme, email). By uncompressing noweb27a.tar.gz and
+avs386_noweb27a.tar.gz from the same directory and by editing a single line of
+my script 'noweb/contrib/avs/myenv.ksh' one can compile Noweb 2.7a for Dos.
+Here is what that line looks like in my case:
+ generate i:/bin g:/usr/local/lib/noweb g:/man h:/emtex/texinputs/local j:/djgpp/bin/make.exe d:/tmp e:/bin/icont.exe
+
+If you think this is interesting you might
+a) mention it in comp.programming.literate
+b) add it to the noweb 2.7b distribution, after all now this allows me to build
+ and install Noweb 2.7a from the 2 tar files in just under 3 minutes ;-)
+
+Regards
+/avs
+
+P.S: myself I switched to Linux but up to now Noweb under Dos helped me a
+lot. Although I won't be using Noweb under Dos so much in the future I'm still
+willing to support it (i.e. any eventual updates to my recipe). And if you ever
+give me a prerelease of a new Noweb (with a week's notice) I will supply you
+with either the Dos binaries for incorporating into the official distribution
+or better still with updated patches/scripts
+
+P.S.: if you want the noweb 2.7a Dos binaries just ask
+
+P.S.: remember that the files in avs386_noweb27a.tar.gz were Dos manipulated.
+ To see any of those files under Unix (e.g. report1.bug) remember to do
+ tr -d '\015' < infile > outfile
diff --git a/web/noweb/contrib/avs/nw_c.bat b/web/noweb/contrib/avs/nw_c.bat
new file mode 100644
index 0000000000..d62641151e
--- /dev/null
+++ b/web/noweb/contrib/avs/nw_c.bat
@@ -0,0 +1,63 @@
+@echo off
+if %1.==. goto USAGE
+if %DJGPPMAKE%.==. goto NOENVVAR
+goto DOIT
+
+:NOENVVAR
+echo Aborting, environment var DJGPPMAKE not set
+goto THEEND
+:USAGE
+echo %0 DJGPPmakePath
+echo ** Use backslash path in arg & slash path in DJGPPMAKE env var, e.g.
+echo set DJGPPMAKE=j:/djgpp/bin/make
+echo %0 j:\djgpp\bin\make
+goto THEEND
+
+:FAILURE0
+echo Failed to patch src/c/finduses.c (probably the source lines to patch are
+echo not any more at lines 44 and 65)
+goto THEEND
+:FAILURE2
+echo Failed to patch src/c/finduses.c, reason unknown
+goto THEEND
+
+:DOIT
+rem Requires DJGPP port of GNU gcc (gcc, make)
+rem Beware of the Ms-Dos command line 128 chars limit!
+rem MKS make won't do, use DJGPP make!
+
+rem Use UNIX style pathnames in DJGPPMAKE path, otherwise DJGPP make chokes!
+rem This is used for make to launch submakes assuming that you might have 2
+rem different makes in your path, the MKS make (which we don't want to use)
+rem and the DJGPP make (which we want to use)
+
+rem Avoid using broken tmpfile() function from DJGPP 'libc.a'
+if not exist c\finduses.old cp c/finduses.c c/finduses.old
+if errorlevel 1 goto THEEND
+echo Patching lines 44 and 65 of src/c/finduses.c (DJGPP tmpfile() broken!)
+sed '44s/FILE \*tmp = tmpfile()/char *tmpName;FILE*tmp=fopen(tmpName=tempnam(".",NULL),"w+")/' c/finduses.old>c\finduses.tmp
+diff c/finduses.old c/finduses.tmp
+if errorlevel 2 goto FAILURE2
+if errorlevel 1 goto STEP2
+if errorlevel 0 goto FAILURE0
+:STEP2
+sed '65s/add_use_markers(tmp, stdout);/add_use_markers(tmp, stdout); remove(tmpName);/' c/finduses.tmp > c\finduses.new
+diff c/finduses.tmp c/finduses.new
+if errorlevel 2 goto FAILURE2
+if errorlevel 1 goto STEP3
+if errorlevel 0 goto FAILURE0
+:STEP3
+rm c/finduses.tmp
+if errorlevel 1 goto THEEND
+cmp -s c/finduses.c c/finduses.new
+if errorlevel 1 goto DIFFERENT
+rm c/finduses.new
+goto THEMAKE
+:DIFFERENT
+mv c/finduses.new c/finduses.c
+
+:THEMAKE
+rem Use Ms-Dos style pathnames here, otherwise command.com chokes!
+@echo on
+%1 CC=gcc
+:THEEND
diff --git a/web/noweb/contrib/avs/nwicon.bat b/web/noweb/contrib/avs/nwicon.bat
new file mode 100644
index 0000000000..d416013c2c
--- /dev/null
+++ b/web/noweb/contrib/avs/nwicon.bat
@@ -0,0 +1,43 @@
+@echo off
+if %1.==. goto USAGE
+if %2.==. goto USAGE
+if %3.==. goto USAGE
+if %4.==. goto USAGE
+if not %5.==. goto USAGE
+
+if exist ..\..\noweb\src\%0 goto DOIT
+if exist ..\..\noweb\src\%0.bat goto DOIT
+echo '..\..\noweb\src\%0' not found!
+cd
+echo Bad startup dir? Aborting.
+echo Change to ./noweb/src and run the file installed by msdosfix.bat in there
+echo (you cannot use the original in noweb\contrib\avs\nwicon.bat)
+goto THEEND
+:DOIT
+
+rem This represents 'make iconlib', but only like this I could put it to work
+cd icon
+rem j:\djgpp\bin\make ICONC=e:\\\\b\\\\icont ICONT=e:\\\\b\\\\icont
+%3 ICONC=%4 ICONT=%4
+if errorlevel 1 goto THEEND
+cp -p totex.exe ../lib
+if errorlevel 1 goto THEEND
+cp -p tohtml.exe ../lib
+if errorlevel 1 goto THEEND
+cp -p noidx.exe ../lib
+if errorlevel 1 goto THEEND
+cp -p noindex.exe ../shell
+if errorlevel 1 goto THEEND
+rem j:\djgpp\bin\make ICONC=e:\\\\b\\\\icont ICONT=e:\\\\b\\\\icont LIB=g:/usr/local/lib/noweb BIN=i:/b install
+%3 ICONC=%4 ICONT=%4 LIB=%2 BIN=%1 install
+if errorlevel 1 goto THEEND
+cd ..
+goto THEEND
+
+:USAGE
+if not %1.==. echo Wrong usage: %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
+echo Usage: %0 BIN LIB DJGPPmakeBackslashPath 4BackslashedIconTranslatorPath
+echo e.g. %0 i:/b g:/usr/local/lib/noweb j:\djgpp\bin\make.exe e:\\\\b\\\\icont.exe
+echo If you are running this as part of another script abort with CTRL-C
+pause
+:THEEND
diff --git a/web/noweb/contrib/avs/nwinst.ksh b/web/noweb/contrib/avs/nwinst.ksh
new file mode 100644
index 0000000000..6e11001f5a
--- /dev/null
+++ b/web/noweb/contrib/avs/nwinst.ksh
@@ -0,0 +1,9 @@
+export SHELL=${SHELL:=$ROOTDIR/bin/sh.exe}
+if [ -z "$1" ]
+then
+ echo "Usage: $0 BIN LIB MAN TEXINPUTS"
+ echo "-- Installs noweb using icon"
+ exit 1
+fi
+
+make CC="gcc" BIN=$1 LIB=$2 MAN=$3 TEXINPUTS=$4 LIBSRC=icon install
diff --git a/web/noweb/contrib/avs/readme b/web/noweb/contrib/avs/readme
new file mode 100644
index 0000000000..f284d69d52
--- /dev/null
+++ b/web/noweb/contrib/avs/readme
@@ -0,0 +1,39 @@
+version 0.3 (30-May-95)
+
+How to install noweb 2.7a in a PC386 or above running Dos if you have Mortice
+Kern Systems' MKS Toolkit 4.2 for Dos. The rest of the software can be obtained
+by ftp (GNU DJGPP, Icon binaries, LaTeX2e, GhostScript). Complete details on
+how to get and install everything are provided
+
+ a) Look at filelist.txt, and if you need something look at ftpsites.txt
+ b) To install noweb if you are lucky you just have to edit 'myenv.ksh' and
+ to run it, e.g. from the Ms-Dos command.com prompt do:
+ cd noweb\contrib\avs
+ edit myenv.ksh
+ sh -c ./myenv.ksh
+ automate
+ c) Test the installation by doing (from the Korn shell prompt):
+ cd noweb/src/tex
+ noweb support.nw
+ latex support
+ latex support
+ latex support
+ v support
+ (assuming your dvi viewer is a batch file called v.bat)
+ dvips -o support.ps support
+ d) See if you have the same problem as I do. If section 2.2 is missing
+ from page 7, chunk 9b from page 9 and chunk 28b from page 28 then
+ you also have that problem that some code/doc chunks come out as white
+ space. The current fix is to add a newline at the start/end of the chunk
+ to make a paragraph. See report1.bug
+ e) Further technical details on howto386.txt
+
+If using this recipe you still run into trouble contact me. As a last resort
+I'm willing to supply you by anonymous ftp with everything you need to run
+noweb 2.7a (except the MKS toolkit which is commercial software, i.e. I can
+supply binaries for LaTeX2e, Icon 9.0 and Noweb 2.7 that fit in 4 * 1.44 MB
+floppies)
+
+My recipe has only been tested in my machine (which is heavily loaded, dozens
+of TSR's and has recent versions of most software). I will appreciate receiving
+comments that allow it to run smoothly in other environments
diff --git a/web/noweb/contrib/avs/report1.bug b/web/noweb/contrib/avs/report1.bug
new file mode 100644
index 0000000000..c19c2abcd4
--- /dev/null
+++ b/web/noweb/contrib/avs/report1.bug
@@ -0,0 +1,97 @@
+Noweb 2.7a bug report (avs@daimi.aau.dk, 29-May-95)
+
+*****************
+"strip problem in hpux8"
+
+In noweb/src/Makefile the strip command in an HPUX8 machine causes the make to
+fail. Commenting out the 'strip' fixes the problem
+
+*****************
+\n problem in -option output of 'noweave -h'
+
+The 'Add \noweboptions{opt} to ...' should be 'Add noweboptions{opt} to ...'
+
+*****************
+Dates problem in source code distribution (as of 29-May-95)
+
+I used ftp get with on the fly compression of the noweb dir to a .tar.gz file
+thus I got the original dates (I didn't cause the dates problem)
+
+The .nw files are not always older than the generated files and the same
+applies to the man page files (regarding the nroff processed man pages). The
+problem seems to be that the dates are identical instead of say 1 second older.
+A simple fix is:
+
+cd noweb/src
+find . -name "*.nw" -exec touch -t 9502231200 "{}" \;
+find xdoc -name "*.1" -exec touch -t 9502241200 "{}" \;
+
+*****************
+Style hook in 'src/tex/support.nw' page 21
+
+The margin note style hook in page 21 is wrong handed (should have come on the
+right instead of on the left)
+
+*****************
+There is a problem with noweb 2.7a/LaTeX: some chunks might disappear from the
+LaTeX output, i.e. they are in the output .tex file but in the .dvi file they
+come out as white space (sometimes this is noticed because it seems strange
+that a page has a big block of white space in the middle, but if it is in the
+end of the page the disappearance might go unnoticed)
+
+A similar problem was found with noweb 2.6c and 2.7 (I didn't report it
+before). I was once able under Unix (HPUX8) to see the problem, but
+unfortunately I'm unable to reproduce it (sorry!). I can see it under Dos with
+e.g in 2.7a
+ cd noweb/src/tex
+ noweb support.nw
+ latex support
+ latex support
+ latex support
+ v support
+ (v is the Dos equivalent of xdvi)
+The section 2.2 in page 7 and the chunks 9b and 28b come out as a white
+rectangle in the middle of the page. If you want I can send you the .dvi files
+(Dos generated) that show the disappearance. This is a subtle problem
+
+The problem can always be solved by adding an empty newline (to make a
+paragraph). In my noweb source file the problem causes a chunk of documentation
+to disappear. A doc chunk comes after a code chunk and if I started with '@
+...', i.e. a '@' followed by a blank followed by the text the chunk came out as
+white space, but if I added a newline to the '@' (i.e. started the text in the
+next line) everything was OK (the lost chunk could be seen in the .tex file, it
+just didn't make to the .dvi file). This didn't happen everywhere or always
+only in some doc or code chunks and only in some particular circunstances,
+i.e. adding a couple of lines several pages before (which changed the page
+layout in the problematic page) made the problem disappear
+
+Using diff to compare the .tex outputs I noticed that the only difference is
+that the \n makes its way to the .tex output thus the problem does not seem to
+be with the noweb scripts but with the noweb LaTeX support code (nwmac.tex or
+noweb.sty)
+
+Or maybe it's a LaTeX bug (it is NOT only a bug in the emTeX Dos port because
+the first time I saw this it was in an Unix machine running Latex 2.09)
+
+Other symptoms:
+ a) using the .dvi file (Dos generated) and seeing it under Linux
+ caused a crash (floating point exception) when viewing the affected
+ pages (7, 9, 28). No problem if those pages were skipped (i.e. never
+ displayed on the screen). When with a now lost .nw file
+ I saw chunks disappearing under HPUX8 I also got floating point
+ exceptions and core dumps (until I made a slight change in the page
+ layout which caused the core dumps to disappear, still the missing
+ chunks hapenned still later on). Seeing the .dvi file under Dos does
+ not cause any crashes, only a white rectangle in the affected area
+ b) using the .tex file (Dos generated) caused no problem under Linux
+
+My tentative diagnostic:
+ - it is not a LaTeX2e specific problem (I saw it under LaTeX)
+ - it is not a Dos specific problem (I saw it under HPUX8)
+ - it is not a noweb/noweave problem (if the .tex output is manipulated
+ under another machine it works fine)
+ - it is either in the LaTeX support file noweb.sty or in LaTeX, still
+ it is a machine dependent problem rare under Unix frequent under Dos
+
+If I manage to pinpoint the problem, or reproduce it under Unix I'll let you
+know
diff --git a/web/noweb/contrib/conrado/Makefile b/web/noweb/contrib/conrado/Makefile
new file mode 100644
index 0000000000..f7a9ee59e2
--- /dev/null
+++ b/web/noweb/contrib/conrado/Makefile
@@ -0,0 +1,15 @@
+LIB=/dev/null # to be overridden by install
+
+.SUFFIXES: .nw .icn
+.nw.icn: ; notangle -L'#line %-1L "%F"%N' $*.nw | cpif $*.icn
+
+all: d2tex
+source: d2tex
+install:
+ cp d2tex $(LIB)/dijkstra.filter
+
+# TeX files.
+hospital.tex: hospital.nw d2tex
+ noweave -delay -filter ./d2tex hospital.nw > hospital.tex
+clean:
+ /bin/rm -f hospital.tex *.dvi *.aux *.log *.blg *.bbl *~
diff --git a/web/noweb/contrib/conrado/README b/web/noweb/contrib/conrado/README
new file mode 100644
index 0000000000..c21ed85589
--- /dev/null
+++ b/web/noweb/contrib/conrado/README
@@ -0,0 +1,38 @@
+This is the README file for the collection of files related to d2tex.
+These files are:
+
+- algoritmos.sty:
+defines the 'code' environment and several other
+related environments (code*, algorithm, ...); the implementation is
+not documented and can be difficult to understand, but I have
+documented the main features of the environments.
+- d2tex:
+an noweb filter (written in awk) that prettyprints; for instance,
+ /* this is a comment */ is replaced by \COMMENT{this is a comment}
+ <= is replaced by \le
+ PROCEDURE initialize is replaced by \PROCEDURE |initialize|
+
+this script does not parse the input; it only uses pattern-matching,
+but produces reasonable output if some thumb rules are followed.
+d2tex has a list of keywords built in.
+
+- keywords.tex:
+
+contains TeX macro definitions for producing keywords in boldface,
+special simbols (as the boxes between guarded commands), etc.; most of
+the macros include indentation macros \tab and \untab; \tab is sets a
+tab and moves the margin tab to the right, while \untab removes a tab
+stop and moves to the left the margin tab. Since the 'code'
+environment is based upon the tabbing environment, it is useful for
+the keyword macros (such as \WHILE) to include these tab/untab
+macros. \tab and \untab can be used inside the 'code' environment when
+needed, for instance, to override the default indentation or to
+correct minor mistakes.
+
+- hospital.nw:
+a weird example of the type of code that d2tex is 'able' to
+prettyprint; the documentation is not written in english (several
+paragraphs and comments in the code are written in catalan) and the
+code is not complete.
+
+
diff --git a/web/noweb/contrib/conrado/algoritmos.sty b/web/noweb/contrib/conrado/algoritmos.sty
new file mode 100644
index 0000000000..23bbc711f3
--- /dev/null
+++ b/web/noweb/contrib/conrado/algoritmos.sty
@@ -0,0 +1,169 @@
+\catcode`@=11
+%
+% \listofalgorithms
+%
+% this macro is like \listoffigures or \listoftables; it prepares a
+% list of algorithms/programs using an auxiliary file (.lop)
+% CUSTOMIZATION: the banner of the list is a string defined by \listalgorithmsname;
+% the default value is ``List of Algorithms''
+
+\def\listofalgorithms{\@restonecolfalse\if@twocolumn\@restonecoltrue\onecolumn
+ \fi\chapter*{\listalgorithmsname\@mkboth
+ {\uppercase{\listalgorithmsname}}{\uppercase{\listalgorithmsname}}}
+ \addcontentsline{toc}{chapter}{\listalgorithmsname}
+ {\ssp\@starttoc{lop}}\if@restonecol
+ \twocolumn\fi}
+\let\l@algorithm\l@figure
+
+\def\listalgorithmsname{List of Algorithms}
+
+% \begin{algorithm} ... \end{algorithm}
+%
+% the 'algorithm' environment encloses a float object (like figure or table)
+% algorithm's get their own numbering; captions begin with
+% ``Algorithm'', then the number, and then the text;
+% and there is an entry in the .lop file for each 'algorithm'
+% CUSTOMIZATION: the first word in a caption is given by \algorithmname
+
+\newcounter{algorithm}
+\def\thealgorithm{\@arabic\c@algorithm}
+\def\fps@algorithm{tbp}
+\def\ftype@algorithm{4}
+\def\ext@algorithm{lop}
+\def\fnum@algorithm{\algorithmname\ \thealgorithm}
+\def\algorithm{\@float{algorithm}}
+\def\endalgorithm{\end@float}
+\@namedef{algorithm*}{\@dblfloat{algorithm}}
+\@namedef{endalgorithm*}{\end@dblalgorithm}
+
+\def\algorithmname{Algorithm}
+
+% \begin{code} ... \end{code}
+%
+% this environment is a slight modification of the tabbing environment.
+% the specific characteristics are:
+% 0) it has a parameter from xref information
+% 1) there is a small skip between the paragraph above and the first
+% line of the code.
+% 2) a rule is drawn at the beginning and at the end of the code.
+% 3) all lines are typeset in math mode
+% 4) |<something>| prints <something> in \rm if issued inside math
+% mode (for instance, inside this environment);
+% and in \sl if issued outside math mode
+% 5) _ can be used instead of \_ inside the code environments and in
+% text; it produces subscripts in math mode as usual
+% 6) <return>'s are obeyed; if you want to break lines in the source
+% but not in the final document terminate the line with a comment char %
+% 7) you can leave a blank line using \\
+%
+% it also introduces a command \numberlines that has no effect in this
+% environment, but it has in the *-form of code
+% CUST: \algosep and \algoruleheight are the length parameters that
+% give the amount of skip between the previous paragraph and the
+% beginning of code, and the width of the rule.
+% Both have default value 0pt. \algofontsize allows changing the font size
+% of the text written inside a code environment. The default is \footnotesize
+
+
+\def\numberlines{}
+\newlength{\algosep}
+\newlength{\algoruleheight}
+\def\rulecode{\rule{\textwidth}{\algoruleheight}}
+\def\sepcode{\vspace{\algosep}}
+\def\algofontsize{\footnotesize}
+\newif\ifinsidecode
+\insidecodefalse
+
+\def\@programcr{$\@tabcr$}
+
+{\catcode`\;=\active \gdef;{\semicolon\;}}
+\mathchardef\semicolon="603B
+
+\catcode`\_=\active \gdef_{\ifinsidecode\_\else\ifmmode\sb\else\_\fi\fi}
+
+\catcode`\|=12\relax
+\def\origbar{|}
+\catcode`\|=\active
+
+\def|{\ifx\@sharp\relax\origbar\else\@dovar\fi}
+\def\@dovar#1#2|{#1\ifmmode{\mbox{\rm #2}}\else{\sl #2}\fi}
+
+
+\def\@tabcommandson{% activate tabbing commands:
+ % \tab sets a tab stop and adds one to the margin tab:
+ \def\tab{$\=\+$}
+ % Must finish current field before testing if at margin:
+ \def\@finishfield{\@stopfield\@addfield\@startfield}
+ % \untab removes one tab stop and moves left if at the beginning of a line:
+ \def\untab{$\@finishfield\@ifatmargin\@ltab\else\relax\fi\-$}
+ % \@marginspace adds an extra space unless there is no text on the line:
+ \def\@marginspace{$\@finishfield$\@ifatmargin\relax\else\ \fi}}
+
+\def\@tabcommandsoff{% deactivate tabbing commands:
+ \let\tab=\relax
+ \let\@finishfield=\relax
+ \let\untab=\relax
+ \let\@marginspace=\ % never at margin thus always a space
+}
+\@tabcommandsoff
+
+\def\code#1{\par\sepcode
+\noindent\rulecode\algofontsize\numberlines\insidecodetrue
+\@tabcommandson \obeycr
+\lineskip \z@\let\>\@rtab\let\<\@ltab\let\=\@settab
+ \let\+\@tabplus\let\-\@tabminus\let\t\tab\let\u\untab
+\let\\=\@programcr
+\global\@hightab\@firsttab \global\@nxttabmar\@firsttab
+\dimen\@firsttab\@totalleftmargin \global\@tabpush0
+\global\@rjfieldfalse \trivlist
+\item[]\if@minipage\else\vskip\parskip\fi
+\setbox\@tabfbox\hbox{\rlap{\indent\hskip\@totalleftmargin
+\the\everypar}}\def\@itemfudge{\box\@tabfbox}\@startline\ignorespaces
+$\@gobblecr
+}
+
+\def\endcode{$\@stopline\ifnum\@tabpush > 0 \@badpoptabs
+\fi\endtrivlist\noindent\@tabcommandsoff
+\rulecode
+\sepcode
+}
+
+% \begin{code*} ... \end{code*}
+%
+% the *-form of code numbers sequentially each line of the code (lines
+% are separated by \\'s)
+% CUST: the label of each line can be easily changed, by redefining
+% the macro \codelinelabel and/or the macro \thecodeline; the counter
+% is codeline.
+
+\newcounter{codeline}
+\def\thecodeline{\arabic{codeline}}
+\def\codelinelabel{\thecodeline.\ \ }
+
+\@namedef{code*}{\def\numberlines{\setcounter{codeline}{0}
+\def\@stopline{\addtocounter{codeline}{1}
+\unskip\@stopfield\if@rjfield \global\@rjfieldfalse
+ \@tempdima\@totalleftmargin \advance\@tempdima\linewidth
+\hbox to\@tempdima{\@itemfudge\codelinelabel\hskip\dimen\@curtabmar
+ \box\@curline\hfil\box\@curfield}\else\@addfield
+ \hbox{\@itemfudge\codelinelabel\hskip\dimen\@curtabmar\box\@curline}\fi}
+}\code}
+\@namedef{endcode*}{\endcode}
+
+\catcode`@=12
+
+% \begin{cntcode} ... \end{cntcode}
+%
+% a slight variation of the code environment, cntcode centers its
+% contents; it should be used only if there is no page break in
+% the middle of the code; that means that its usefulness is limited to
+% small chunks of code, specifications, short declarations, ...
+\newlength{\codewidth}
+\setlength{\codewidth}{0.7\textwidth}
+\newenvironment{cntcode}{\def\sepcode{}\def\rulecode{}\centering
+\begin{minipage}[t]{\codewidth}
+\begin{code}}{\end{code}\end{minipage}
+\par}
+
+
+
diff --git a/web/noweb/contrib/conrado/d2tex b/web/noweb/contrib/conrado/d2tex
new file mode 100755
index 0000000000..5b807b7ce0
--- /dev/null
+++ b/web/noweb/contrib/conrado/d2tex
@@ -0,0 +1,144 @@
+#! /bin/sh
+KEYGEN=$(mktemp)
+trap "rm -f $KEYGEN; exit 1" 1 2 3 15
+cat > $KEYGEN <<END_OF_FILE
+COMMENT#1
+ASSERT#1
+PROGRAM
+ENDPROGRAM
+USES
+ENDUSES
+MODULE
+ENDMODULE
+SPECIFICATION
+ENDSPECIFICATION
+IMPLEMENTATION
+ENDIMPLEMENTATION
+IMPORT
+ENDIMPORT
+TYPE
+ENDTYPE
+VAR
+ENDVAR
+CONST
+ENDCONST
+ARRAY
+RECORD
+ENDRECORD
+BEGIN
+IF
+ELSE
+ENDIF
+THEN
+SKIP
+WHILE
+ENDWHILE
+DO
+DDO
+ENDDO
+FORALL
+FOR
+ENDFOR
+ENDFORALL
+PARALLEL
+REPEAT
+UNTIL
+AND
+OR
+NOT
+CAT
+OF
+IN
+DIV
+MOD
+PROCEDURE
+ENDPROCEDURE
+FUNCTION
+ENDFUNCTION
+RETURNS
+INP
+OUTP
+INOUTP
+PRIVATE
+@@@
+END_OF_FILE
+
+nawk '
+BEGIN { code=0 ; quoting=0 ; inside_comm=0
+ while ((getline kw < "'"$KEYGEN"'") >0)
+ keywords[kw]++
+ }
+/^@begin code/ {
+ printf "@literal \\begin{code}{%s}\\let\\maybehbox=\\hbox\n", substr($0, 13)
+ code=1; next
+}
+/^@end code/ { code=0 ; printf "@literal \\end{code}\n"; next}
+/^@quote$/ { quoting = 1 }
+/^@endquote$/ { quoting = 0 }
+/^@text / { if (code) { print_code(substr($0, 7)) }
+ else { print }
+ next
+ }
+{print}
+function print_code(line) {
+ temp = line;
+ comm = "";
+ if (temp ~ /\/\*/)
+ { r = index(temp, "/*");
+ inside_comm = 1; comm = "\\COMMENT{" substr(temp, r+3);
+ if (comm ~ /\*\//) { inside_comm = 0; comm = comm "}"; temp = ""; }
+ }
+ if (temp ~ /\*\//)
+ { comm = temp "}"; temp = ""; inside_comm = 0; }
+
+ sub(/\*\//,"",comm);
+ sub(/\/\*.*/,"",temp);
+
+ if (temp != "" && inside_comm == 0)
+ {
+ temp = operators(temp);
+ temp = substitute_keywords(temp);
+ temp = mark_vars_types(temp);
+ }
+ line = temp comm;
+ print "@literal " line;
+}
+
+function substitute_keywords(s, kw) {
+ for (kw in keywords)
+ if (s ~ kw)
+ {
+ gsub("(^|[ \\t]+)" kw "($|[ \\t]+)", " \\" kw " ", s);
+ gsub("(^|[ \\t]+)" kw ";", " \\" kw ";", s);
+ gsub("(^|[ \\t]+)" kw "\\.", " \\" kw ".", s);
+ gsub("[(]" kw, "(\\" kw, s);
+ gsub("," kw, ",\\" kw, s);
+ }
+ return s
+}
+
+function mark_vars_types(s ) {
+ gsub(/\\OF[ \t\n]*[a-zA-Z_]+/,"|&|", s);
+ gsub(/\\RETURN[ \t\n]*[a-zA-Z_]+/,"|&|", s);
+ gsub(/[a-zA-Z_]+[ \t\n]*=[ \t\n](\\RECORD|\\ARRAY)/,"|&|", s);
+ gsub(/[a-zA-Z_]+[ \t\n]*=[ \t\n]\\{/,"|&|",s);
+ gsub(/:[\t\n ]*[a-zA-Z_]+/, "|&|" ,s);
+ gsub(/[a-zA-Z_]+[ \\t\\n]*\(/,"|&|",s);
+ gsub(/\(\|/, "|(", s);
+ gsub(/\|:[ \t\n]*/, ":|", s);
+ gsub(/\|\\de[ \t\n]*/, "\\de |", s);
+ gsub(/\|\\RETURN[ \t\n]*/, "\\RETURN |", s);
+ gsub(/\=[\t\n ]*\\ARRAY\|/, "| = \\ARRAY", s);
+ gsub(/\=[\t\n ]*\\RECORD\|/, "| = \\RECORD", s);
+ gsub(/\=[\t\n ]*\\{\|/, "| = \\{", s);
+ return s
+}
+
+function operators(s ) {
+ gsub(/ >= /," \\ge ", s);
+ gsub(/ <= /, " \\le ", s);
+ gsub(/ != /, " \\not= ", s);
+ return s;
+}
+' "$@"
+rm -f $KEYGEN
diff --git a/web/noweb/contrib/conrado/email b/web/noweb/contrib/conrado/email
new file mode 100644
index 0000000000..ef96d5bb44
--- /dev/null
+++ b/web/noweb/contrib/conrado/email
@@ -0,0 +1 @@
+conrado@moon.upc.es (Conrado Martinez-Parra)
diff --git a/web/noweb/contrib/conrado/hospital.nw b/web/noweb/contrib/conrado/hospital.nw
new file mode 100644
index 0000000000..46b5d9fe1f
--- /dev/null
+++ b/web/noweb/contrib/conrado/hospital.nw
@@ -0,0 +1,165 @@
+\documentstyle[noweb,algoritmos]{article}
+\input{keywords}
+\title{Hospital General}
+\author{Conrado Mart\'{\i}nez-Parra}
+\pagestyle{plain}
+\begin{document}
+\maketitle
+
+@ The problem.
+
+
+An hospital has $np$ floors ($1\le np\le |MAX_PISOS|$),
+the $i$-th floor has $nh_i$ rooms
+($1\le nh_i\le |MAX_HAB|$) and the $j$-th room of the $i$-th floor
+has $nll_{i,j}$ beds ($1\le nll_{i,j}\le |MAX_LLITS|$). The number of
+beds that are occupied by patients in the $j$-th room of the $i$-th
+floor in a given moment is denoted by $oc_{i,j}$.
+
+\smallskip
+
+The patients are distributed in the hospital according to one of the
+following three cathegories: {\tt child}, {\tt men}, {\tt women}.
+All the patients in a given room must belong to the same cathegory.
+
+Consider the following type definitions:
+<<definicio de tipus>>=
+TYPE operation_class = { ingress, dismin, null };
+ cathegory = { child, women, men };
+
+ id_llit = RECORD
+ pis, hab, llit : integer;
+/* any bed can be identified by a tuple
+(floor number, room number, bed number) */
+ ENDRECORD;
+
+ operation = RECORD
+ class : operation_class;
+ cat_ingress_patient : categhory;
+/* used only in ingress operations */
+ vacant_bed : id_llit;
+/* used only for dismin operations */
+ ENDRECORD;
+
+ENDTYPE
+@
+
+
+@ The solution.
+<<definicio de tipus>>=
+TYPE hospital = RECORD
+ nr_pisos : integer;
+ pisos : ARRAY [1..MAX_PISOS] OF pis;
+ /* com que el tipus 'taula [...] de pis' es
+ totalment accesori, no ho definim per separat; fem el
+ mateix en la definicio del tipus 'pis' */
+ ENDRECORD;
+ pis = RECORD
+ nr_habitacions : integer;
+ habs : ARRAY [1..MAX_HABIT] OF pis;
+ ENDRECORD;
+
+ENDTYPE
+
+@
+Pel que fa a cadascuna de les habitacions, ens caldr\`a saber: 1)
+quants llits hi ha; 2) quants llits estan ocupats; 3) la categoria
+dels pacients (buida, si no n'hi ha cap); 4) l'estat de cadascun dels
+llits. Nom\'es ens caldr\`a saber la categoria d'un pacient, ja que
+tots els pacients dins una habitaci\'o tenen la mateixa categoria.
+Aix\'{\i} doncs, proposem la seg\"uent definici\'o:
+
+<<inicialitzar hospital>>=
+PROCEDURE inicialitzar(OUTP H : hospital)
+VAR i,j,k : enter
+ENDVAR
+
+ llegir(H.nr_pisos);
+
+ /* hem obtingut el nombre de pisos del hospital */
+
+ i:= 1;
+
+ WHILE i <= H.nr_pisos DO
+
+ llegir(H.pisos[i].nr_nabitacions);
+ i:= i + 1
+
+ ENDWHILE;
+
+ /* hem obtingut el nombre d'habitacions per a cada pis */
+
+ i:= 1;
+
+ WHILE i <= H.nr_pisos DO
+
+ j:= 1;
+ WHILE j <= H.pisos[i].nr_habitacions DO
+
+ llegir(H.pisos[i].habs[j].nr_llits;
+ /* hem obtingut el nombre de llits per a cada habitacio */
+ H.pisos[i].habs[j].nr_ocupats:= 0;
+ H.pisos[i].habs[j].cat_pacients:= buida;
+
+ k:= 1;
+ WHILE k <= H.pisos[i].habs[j].nr_llits DO
+
+ H.pisos[i].habs[j].ocupat[k]:= false;
+ k:= k + 1
+
+ ENDWHILE;
+
+ /* hem fet les definicions que indiquen que l'habitacio es
+ buida */
+ j:= j + 1
+
+ ENDWHILE;
+
+ i:= i + 1
+
+ ENDWHILE
+
+ENDPROCEDURE
+@
+
+<<*>>=
+PROGRAM Hospital
+
+<<definicio de tipus>>
+
+VAR op : operacio;
+ H : hospital;
+ENDVAR
+
+ inicialitzar_hospital(H);
+
+ llegir_operacio(op);
+
+ WHILE op.classe != nul DO
+
+ tractar_operacio(op,H);
+ llegir_operacio(op)
+
+ ENDWHILE
+
+ENDPROGRAM.
+
+@
+
+<<tractar l'operacio en curs $op$, modificant l'estat de l'hospital $H$>>=
+PROCEDURE tractar_operacio(INP op : operacio; INOUTP H : hospital)
+VAR ll_asgn: id_llit;
+ENDVAR
+
+ IF op.classe = ingres THEN ingres(op,cat_pacient_ingressat, H, ll_asgn);
+ escriure("Ingres:",ll_asgn.pis,ll_asgn.hab,
+ ll_asgn.llit);
+
+ ELSE op.classe = baixa THEN donar_baixa(op.llit_abandonat,H);
+
+ ENDIF
+
+ENDPROCEDURE;
+
+@
+\end{document}
diff --git a/web/noweb/contrib/conrado/keywords.tex b/web/noweb/contrib/conrado/keywords.tex
new file mode 100644
index 0000000000..7dc7c2968c
--- /dev/null
+++ b/web/noweb/contrib/conrado/keywords.tex
@@ -0,0 +1,59 @@
+\def\COMMENT#1{\{\parbox[t]{\codewidth}{\rm #1\}}}
+\def\ASSERT#1{\{\mbox{\rm #1}\}}
+\def\PROGRAM{{\bf pro}\tab{\bf gram\ }}
+\def\ENDPROGRAM{\untab{\bf end}}
+\def\USES{{\bf uses\ }\tab}
+\def\ENDUSES{\untab{\bf end}}
+\def\MODULE{{\bf mod}\tab{\bf ule\ }}
+\def\ENDMODULE{\untab{\bf end}}
+\def\SPECIFICATION{{\bf spe}\tab{\bf cification\ }}
+\def\ENDSPECIFICATION{\untab{\bf end}}
+\def\IMPLEMENTATION{{\bf imp}\tab{\bf lementation\ }}
+\def\ENDIMPLEMENTATION{\untab{\bf end}}
+\def\IMPORT{{\bf imp}\tab{\bf orts\ }}
+\def\ENDIMPORT{\untab{\bf end}}
+\def\TYPE{{\bf type\ }\tab}
+\def\ENDTYPE{\untab}
+\def\VAR{{\bf var\ }\tab}
+\def\ENDVAR{\untab}
+\def\CONST{{\bf const\ }\tab}
+\def\ENDCONST{\untab}
+\def\ARRAY{{\bf array\ }}
+\def\RECORD{\tab{\bf rec}\tab{\bf ord\ }}
+\def\ENDRECORD{\untab{\bf end}$\-$}
+\def\BEGIN{}
+\def\IF{{\bf if }\tab\ \ \tab}
+\def\ELSE{\untab\untab [\!]$\>$}
+\def\ENDIF{\untab\untab {\bf fi}}
+\def\THEN{\ \longrightarrow\ \ \tab}
+\def\SKIP{\emptyset}
+\def\WHILE{{\bf whi}\tab{\bf le\ }}
+\def\ENDWHILE{\untab{\bf end}}
+\def\DO{{\bf\ do\ }}
+\def\DDO{{\bf do\ }\tab}
+\def\ENDDO{\untab{\bf end}}
+\def\FORALL{{\bf for}\tab{\bf\ all\ }}
+\def\FOR{{\bf for}\tab\ }
+\def\ENDFOR{\untab{\bf end}}
+\def\ENDFORALL{\untab{\bf end}}
+\def\PARALLEL{{\bf\ parallel\ }}
+\def\REPEAT{{\bf rep}\tab{\bf eat\ }}
+\def\UNTIL{\untab{\bf until\ }}
+\def\AND{\mathbin{\hbox{\bf and}}}
+\def\OR{\mathbin{\hbox{\bf or}}}
+\def\NOT{\mathop{\hbox{\bf not}}}
+\def\CAT{\mathbin{\&}}
+\def\OF{{\bf\ of\ }}
+\def\IN{{\bf\ in\ }}
+\def\DIV{\mathbin{\hbox{\bf div}}}
+\def\MOD{\mathbin{\hbox{\bf mod}}}
+\def\PROCEDURE{{\bf pro}\tab{\bf cedure\ }}
+\def\ENDPROCEDURE{\untab{\bf end}}
+\def\FUNCTION{{\bf fun}\tab{\bf ction\ }}
+\def\ENDFUNCTION{\untab{\bf end}}
+\def\RETURNS{{\bf return\ }}
+\def\INP{{\bf in\ }}
+\def\OUTP{{\bf out\ }}
+\def\INOUTP{{\bf in/out\ }}
+\def\PRIVATE{{\bf private\ }}
+
diff --git a/web/noweb/contrib/davelove/Makefile b/web/noweb/contrib/davelove/Makefile
new file mode 100644
index 0000000000..5a349d23c1
--- /dev/null
+++ b/web/noweb/contrib/davelove/Makefile
@@ -0,0 +1,6 @@
+SHELL=/bin/sh
+all:
+source:
+install:
+clean:
+ /bin/rm -f *.dvi *.log *.aux
diff --git a/web/noweb/contrib/davelove/README b/web/noweb/contrib/davelove/README
new file mode 100644
index 0000000000..2ca66a6bac
--- /dev/null
+++ b/web/noweb/contrib/davelove/README
@@ -0,0 +1,2 @@
+subref.doc is a literate version of the code that noxref uses to
+number definitions 7a, 7b, 7c, and so on.
diff --git a/web/noweb/contrib/davelove/email b/web/noweb/contrib/davelove/email
new file mode 100644
index 0000000000..eeaf4fb95f
--- /dev/null
+++ b/web/noweb/contrib/davelove/email
@@ -0,0 +1 @@
+d.love@daresbury.ac.uk
diff --git a/web/noweb/contrib/davelove/subref.doc b/web/noweb/contrib/davelove/subref.doc
new file mode 100644
index 0000000000..93a5c48d8d
--- /dev/null
+++ b/web/noweb/contrib/davelove/subref.doc
@@ -0,0 +1,235 @@
+%<*x> ^^A -*-latex-*-
+% [Standard D. Carlisle boilerplate.]
+% This file may be used without modification as a style (.sty) file.
+%
+% If you have Mittelbach's doc.sty, this file may be formatted with a
+% command like:
+% latex subref.sty
+%
+% If you have the Mittelbach/Duchier/Braams docstrip utility, you may
+% produce a faster loading .sty file.
+% Rename this file to: subref.doc
+% Then run this file through *plain* TeX:
+% tex subref.doc
+% This should produce the file subref.sty.
+% If you do not have plain TeX on your system, you can trick LaTeX into
+% doing the work as follows:
+% latex \def\fmtname{plain} \input subref.doc
+% Note that you may need to quote the arguments here to stop your
+% operating system treating the \ characters incorrectly.
+%
+% latex subref.doc
+% Will produce a typeset version of the documentation, as above.
+%
+% [Although this is a fairly trivial style, it is for a literate
+% programming task, so it better be written literately, i.e. with the
+% `doc' option.]
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\plain{plain}\ifx\fmtname\plain\csname fi\endcsname
+ \def\batchfile{subref.doc}
+ \input docstrip
+ \preamble
+
+ Copyright D.Love, SERC Daresbury Laboratory, 1993
+ The `doc' version of this style is re-distributable and usable
+ under conditions of the GNU copyleft, but please mark any changes,
+ list them here and report any major enhancements to the author.
+ Do not distribute the stripped version of this file.
+
+ \endpreamble
+ \generateFile{subref.sty}{t}{\from{subref.doc}{}}
+ \endinput
+\fi
+%
+\ifcat a\noexpand @\let\next\relax\else\def\next{%
+ \documentstyle[doc%,a4
+ ,subref]{article}\MakePercentIgnore}\fi\next
+%
+%\def\eatmodule<#1>{}\eatmodule
+%</x>
+% \def\fileversion{1.0}
+% \def\filedate{7/7/93}
+% \def\docdate {7/7/93}
+% \CheckSum{113}
+%% \CharacterTable
+%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+%%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% \textwidth=355pt ^^A Allow macrocode text with 72 columns.
+% \CodelineIndex ^^A Code lines numbered.
+% \DisableCrossrefs ^^A No Cross references.
+% \MakeShortVerb{\"} ^^A "\foo" works like \verb+\foo+
+%
+% \title{{\tt subref.sty}:\\Counting references on pages\thanks{This
+% file has version number \fileversion{} dated \filedate{}. The
+% documentation was last revised on \docdate.}}
+% \author{Dave Love}
+% \date{}
+% \begin{document}
+% \maketitle
+% \begin{abstract}
+% \noindent This \LaTeX{} style option
+% provides a mechanism for defining `page
+% sub-references' using "\sublabel{foo}" referenced with
+% "\subpageref{foo}". Sub-references will be numbered like these real
+% examples: \subpageref{ref:foo}, \subpageref{ref:bar},
+% \subpageref{ref:baz}\sublabel{ref:foo}\sublabel{ref:bar}\sublabel{ref:baz}
+% etc.\ unless there is only one on the page, in which case the letter
+% will be dropped like this: \subpageref{ref:fred}.
+% \end{abstract}
+%
+% \subsection*{Usage}
+%
+% For use in "noweb", Norman Ramsey requires:\DescribeMacro{\subpageref}
+% \begin{quote}
+% What's wanted is a latex macro "\subpageref{quux}" that produces
+% either a page number (for a page containing only one definition) or
+% a page number followed by a, b, c, etc\dots
+% \end{quote}
+% To be able to use "\subpageref" we must define the label with
+% "\sublabel"\DescribeMacro{\sublabel}, used like label. (Using
+% "\ref" \DescribeMacro{\ref} with a label defined by "\sublabel" will
+% produce the sub-reference number, by the way, and "\pageref"
+% \DescribeMacro{\pageref} works as expected.) Note that
+% "\subpageref" is robust and "\ref" and "\pageref" are defined to be
+% robust also, as they will be in future \LaTeX{} releases.
+% Incidentally, these expand to the relevant text plus "\null"---you
+% might want to strip this off, e.g.\ for sorting lists.
+%
+% \StopEventually
+%
+% \subsection*{Code}
+%
+% There are various ways we could attack this task (which is made
+% non-trivial by the well-known asynchrony of (La)\TeX's output
+% routine). There are various ways we might tackle the problem, but
+% they all must depend on hacks in the ".aux" file or a similar one.
+% Joachim Schrod's "fnpag.sty" does the same sort of thing differently
+% to this \LaTeX-specific approach. See "latex.tex" for enlightenment
+% on the cross-referencing mechanism and the \LaTeX{} internals used
+% below.
+% \begin{macro}{\subpageref}
+% The "\subpageref" macro first does a normal "\pageref". If the
+% reference is actually defined, it then goes on to check whether the
+% control sequence "2on"\meta{page referenced} is defined and sets the
+% "\ref" value to get "a" etc.\ if so. The magic, of course, is in
+% defining the "2on" bit appropriately.
+% \begin{macrocode}
+\newcommand{\subpageref}[1]{%
+ \pageref{#1}%
+ \@ifundefined{r@#1}%
+ {}%
+ {\@ifundefined{2on\@pageref{#1}}%
+ {}%
+ {\ref{#1}}}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@pageref}
+% This is like "\pageref", but expands to "\relax" without a warning
+% if the reference is undefined.
+% \begin{macrocode}
+\def\@pageref#1{\expandafter\expandafter\expandafter
+ \@cdr\csname r@#1\endcsname\@nil}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\sublabel}
+% This is like the usual "\label" command, except that it writes
+% "\newsublabel" onto the ".aux" file rather than "\newlabel".
+% \begin{macrocode}
+\newcommand{\sublabel}[1]{%
+ \@bsphack\if@filesw {\let\thepage\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string
+ \newsublabel{#1}{{}{\thepage}}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\newsublabel}
+% This is the macro that does the important work. It is called with the
+% same sort of arguments as "\newlabel": the first argument is the
+% label name and the second is "{"\meta{ref value}"}{"\meta{page
+% number}"}". (Note that the only definition here which needs to be
+% global is the one which is, and that "\global" is redefined by
+% "\enddocument", which will bite you if you use it\dots.)
+%
+% First we extract the page number into "\this@page".
+% \begin{macrocode}
+\newcommand{\newsublabel}[2]{%
+ \edef\this@page{\@cdr#2\@nil}%
+% \end{macrocode}
+% Then we see whether it's greater than the value of "\last@page"
+% which was stashed away by the last "\newsublabel" (or is zero if
+% this is the first one). If the page has changed, we reset the
+% counter "\sub@page" telling us how many sub-labels there have been
+% on the page.
+% \begin{macrocode}
+ \ifnum\this@page>\last@page
+ \sub@page=0\relax
+ \fi
+ \last@page=\this@page
+ \advance\sub@page by 1
+% \end{macrocode}
+% If we've had at least two on the page, we define the "2on"\meta{page
+% no.} macro to indicate the fact.
+% \begin{macrocode}
+ \ifnum\sub@page=2
+ \global\@namedef{2on\this@page}{}%
+ \fi
+% \end{macrocode}
+% Then we write a normal "\newlabel" with the sub-reference as the
+% normal reference value in the second argument.
+% \begin{macrocode}
+ \edef\@tempa{\noexpand\newlabel{#1}%
+ {{\@alph{\number\sub@page}}{\this@page}}}%
+ \@tempa}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\last@page}
+% \begin{macro}{\sub@page}
+% We need to define these counters. "\last@page" could be a
+% suitably-initialised macro instead.
+% \begin{macrocode}
+\newcount\last@page
+\newcount\sub@page
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\pageref}
+% \begin{macro}{\ref}
+% Let's use Rainer's new expandable definitions of "\ref" and
+% "\pageref" to minimise the risk of nasty surprises.
+% \begin{macrocode}
+%% RmS 92/08/14: made \ref and \pageref robust
+\def\ref#1{\@ifundefined{r@#1}{{\reset@font\bf ??}\@warning
+ {Reference `#1' on page \thepage \space
+ undefined}}{\expandafter\expandafter\expandafter
+ \@car\csname r@#1\endcsname
+ \@nil\null}}
+\def\pageref#1{\@ifundefined{r@#1}{{\reset@font\bf ??}\@warning
+ {Reference `#1' on page \thepage \space
+ undefined}}{\expandafter\expandafter\expandafter
+ \@cdr\csname r@#1\endcsname
+ \@nil\null}}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}\sublabel{ref:fred}
+% \Finale
+% \end{document}
+%
+\endinput
diff --git a/web/noweb/contrib/fischer/README b/web/noweb/contrib/fischer/README
new file mode 100644
index 0000000000..12150874a3
--- /dev/null
+++ b/web/noweb/contrib/fischer/README
@@ -0,0 +1,40 @@
+Date: Wed, 23 Feb 2011 23:02:00 -0500
+From: Greyson Fischer <greyson@foosoft.us>
+To: nr@cs.tufts.edu
+Subject: noweb + interpreter line = noscript
+
+
+Dear Norman,
+
+I have been a literate programmer for a few years now. Although I must
+limit my use of it most of the time due to corporate pressure, it comes
+in extremely handy for particularly new or challenging tasks. Of course
+I use noweb for many of my literate programs, preferring it over even
+cweb for C and C++ (sure, 'int' isn't bold, but at least it's indented
+the way I like to read).
+
+I found myself repeating a pattern when it came to writing in
+interpreted languages; specifically those that use a shebang to specify
+their interpreter. I write the literate script, tangle it, and then copy
+the result off to be used. The problem with this approach comes when I
+want, or need, to edit the script again later. Although I know it came
+from noweb (usually because of the complete lack of comments) I couldn't
+always track down the original source in a timely manner, leading me to
+make changes to the derived script, rather than the source.
+
+So, I came up with a simple fix. noscript tangles a document on the fly
+(assuming the first line has %!) and executes it inline with the
+specified interpreter.
+
+To use it, take a noweb document (for example: myscript.nw) which
+tangles <<*>> into, for example, a shell script. Add a "%!/bin/sh" at
+the top of the file. Run 'noscript myscript.nw'. Done, the script has
+been executed.
+
+I've attached my version 0.1 in case your interested (along with some
+trivial test documents). It's made it quite a bit easier for me to keep
+the document and the script together. Perhaps you, or one of your users,
+might find it of use.
+
+Cheers,
+Greyson Fischer
diff --git a/web/noweb/contrib/fischer/noscript-0.1/noscript b/web/noweb/contrib/fischer/noscript-0.1/noscript
new file mode 100755
index 0000000000..7b2a559005
--- /dev/null
+++ b/web/noweb/contrib/fischer/noscript-0.1/noscript
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+SCRIPT="$1"; shift
+INTERP=`sed -ne '
+ s!/bin/sh!/bin/sh -s!;
+ 1s/^%!//p
+ ' "$SCRIPT"`
+
+case "$INTERP" in
+ '')
+ echo 'No interpreter line (%!) found!' >&2
+ exit 1
+ ;;
+ *) notangle "$SCRIPT" | exec $INTERP - "$@" ;;
+esac
diff --git a/web/noweb/contrib/fischer/noscript-0.1/test-none.nw b/web/noweb/contrib/fischer/noscript-0.1/test-none.nw
new file mode 100644
index 0000000000..eb54b3864a
--- /dev/null
+++ b/web/noweb/contrib/fischer/noscript-0.1/test-none.nw
@@ -0,0 +1,8 @@
+@ This is a test script which displays the ability of my new noweb-script to
+actually execute a script which is embedded in a noweb styled file. This test
+case ensures that nothing is run when there is no interpreter specified.
+
+<<*>>=
+/bin/false -- nothing here.
+
+@ And that should do it.
diff --git a/web/noweb/contrib/fischer/noscript-0.1/test-py.nw b/web/noweb/contrib/fischer/noscript-0.1/test-py.nw
new file mode 100644
index 0000000000..113b5a8e0f
--- /dev/null
+++ b/web/noweb/contrib/fischer/noscript-0.1/test-py.nw
@@ -0,0 +1,23 @@
+%!/usr/bin/env python
+
+@ This is a test script which displays the ability of my new noweb-script to
+actually execute a script which is embedded in a noweb styled file.
+
+<<*>>=
+<<imports>>
+
+print "Hello Python World!"
+print "Args:", sys.argv[1:]
+for n in xrange( 0, 10 ):
+ <<Do something with numbers>>
+print
+
+@ And that should do it, now we just need to do something with the numbers:
+
+<<Do something with numbers>>=
+print n,
+
+@ Oh yeah, I need to import [[sys]] as well
+
+<<imports>>=
+import sys
diff --git a/web/noweb/contrib/fischer/noscript-0.1/test-sh.nw b/web/noweb/contrib/fischer/noscript-0.1/test-sh.nw
new file mode 100644
index 0000000000..18f29b2efd
--- /dev/null
+++ b/web/noweb/contrib/fischer/noscript-0.1/test-sh.nw
@@ -0,0 +1,10 @@
+%!/bin/sh
+
+@ This is a test script which displays the ability of my new noweb-script to
+actually execute a script which is embedded in a noweb styled file.
+
+<<*>>=
+echo "Hello Bourne World!"
+echo "Args: $*"
+
+@ And that should do it.
diff --git a/web/noweb/contrib/gregory/README b/web/noweb/contrib/gregory/README
new file mode 100644
index 0000000000..ae55232fb7
--- /dev/null
+++ b/web/noweb/contrib/gregory/README
@@ -0,0 +1,2 @@
+dots.nw enables the use of trailing dots in chunk names. It does the same
+job as the example program `disambiguate.nw', but it is written in perl.
diff --git a/web/noweb/contrib/gregory/dots.nw b/web/noweb/contrib/gregory/dots.nw
new file mode 100644
index 0000000000..b7d1f650dc
--- /dev/null
+++ b/web/noweb/contrib/gregory/dots.nw
@@ -0,0 +1,154 @@
+\section*{Resolving trailing dots\ldots}
+Gregory Tucker-Kellogg\\
+gtk@walsh.med.harvard.edu
+\subsection*{Introduction}
+
+Unlike \verb|WEB|, \verb|noweb| does not allow the use of trailing
+dots in chunk (section) names. \verb|Dots| corrects for this. It is
+similar but not identical to \verb|disambiguate|, an \verb|Icon|
+program to accomplish the same task. \verb|Dots| is written in
+\verb|perl|.
+
+Before it does much else, \verb|noweb| creates a markup description of
+a source file. That markup description is passed along (in both
+\verb|noweave| and \verb|notangle|) to other programs in the pipeline
+(\verb|totex| for \verb|noweave| and \verb|nt| for \verb|notangle|).
+\verb|Dots| intervenes after the markup stage as a filter. The chunk
+name references are passed in the form described in Ramsey's paper,
+i.e.,
+\begin{quote}
+\leavevmode\rlap{\begin{tabular}{ll}
+\tt @defn {\rm\it name}&The code chunk named {\rm\it name} is being defined\\
+\tt @use {\rm\it name}&A reference to code chunk named {\rm\it name}\\
+\end{tabular}}
+\end{quote}
+If trailing dots are used in a chunk name, they will be passed along
+at the markup stage verbatim without any attempt at resolution.
+That's where \verb|dots| comes in.
+
+We require two passes over the noweb code as passed through
+\verb|markup|. The first pass picks out all of the unambigious chunk
+names and stores them in associative arrays. In between the passes,
+we expand the ambigious names and do some simple error checking. The
+second pass does a simple replace on incomplete names and writes
+output to the next stage of the pipeline.
+
+The choices for handling the input stream seems to be between sucking
+the whole markup into memory at once (as \verb|disambiguate| does) or storing
+the markup as a temporary file between the passes. The second is
+slower but will not break as the file gets bigger. We'll choose the
+first for now.
+
+\subsection*{Program outline}
+<<*>>=
+#!/usr/local/bin/perl
+while (<>) { # the first pass takes the input from STDIN
+ <<create lists of identifiers>>
+}
+<<resolve ambiguities in identifier names>>
+<<printout while replacing those with trailing dots>>
+@
+
+\subsection*{Representation}
+
+What's the best structure for the list of chunk names? It could just be a
+normal array, except we would have to check if a given name is already
+defined before adding it too the list. We could make an associative
+array, except we really don't have a key to associate. On the other
+hand, we could make a single associative array of names with
+associations ``complete'' and ``incomplete'' depending on the
+presence of dots. This would require no checking on predefinitions,
+and a key sorted list brings up each full chunk name as the {\em next}
+member of the list for which [[$completion{$identifier}=$complete]].
+
+<<create lists of identifiers>>=
+if (/^@(defn|use)\s(.*)$/) { # we've found a name of some sort
+ if (($truncated = $2) =~ s/\.\.\.$//) { # this one ends in dots.
+ $completion{$truncated} ="incomplete";
+ $truncations{$.-1} = $truncated;
+ $usage_type{$.-1} = $1;
+ }
+ else {$completion{$2} ="complete";}
+ }
+ push(lines,$_);
+
+@
+
+\subsection*{Chunkname resolution}
+The associative array [[%completion]] contains all of the names. The
+associative array [[%truncation_table]] contains the line numbers of the
+names with trailing dots. We can change the values of [[%completion]]
+from ``complete'' and ``incomplete'' to a number representing the
+index of the appropriate completion. If there is more than one, we
+can print out a warning but still resolve on the closest name.
+
+<<resolve ambiguities in identifier names>>=
+@namelist = sort(keys(%completion));
+$j = $i = 0;
+while ($i < $#namelist) { #collect all the ambiguities in a row
+ while ($completion{$namelist[$j]} eq "incomplete") {
+ $ambiguity_found = 1;
+ $j = $i + 1;
+ }
+ <<check for remaining ambiguity>>
+ foreach $name (@namelist[$i..$j]) {
+ $completion{$name} = $namelist[$j];
+ }
+ $j=$i=$j + 1;
+ undef($ambiguity_found);
+}
+@
+
+
+After we've gotten the expansions of abbreviated chunk names, we still
+might run into a problem. First, if no correct expansion was
+established, we might just missassign the abbreviation. The expansion
+might still be ambiguous if more than one complete expansion can give
+the same abbreviation. The first case is a fatal error. The second
+can be resolved by seeing if a complete chunkname immediately
+following the first completion is a solution. If so, we take the
+first completion anyway but print a warning for the user.
+
+<<check for remaining ambiguity>>=
+if (defined $ambiguity_found) {
+ $suggested = $namelist[$j];
+ $nextchance = $namelist[$j+1];
+ foreach $name (@namelist[$i..$j-1]) {
+ if (substr($suggested,0,length($name)) ne $name) {
+ die "FATAL ERROR: can't resolve @<<$name...>>\n"
+ }
+ }
+ if ($completion{$nextchance} eq "complete") {
+ foreach $name (@namelist[$i..$j-1]) {
+ if (substr($nextchance,0,length($name)) eq $name) {
+ print STDERR "WARNING--Ambiguous chunkname:\n";
+ print STDERR "\t<<${name}...@>> could be either\n";
+ print STDERR "\t<<$suggested@>> or\n\t<<$nextchance@>>\n";
+ print STDERR "I will use <<$suggested@>>\n"
+ }
+ }
+ }
+}
+@
+
+
+\subsection*{Printout}
+Finally, the [[%truncations]] and [[%usage_type]] arrays are put to
+work. We use the line numbers (as [[keys()]]) to pull up the
+truncations, and then associate truncations with completed names.
+Since we found everything on the first pass we don't have to scan
+each line for a [[@defn]] or [[@use]] statement. Note: this part of
+the program, analogous to {\em pass2} in \verb|disambiguate|, is
+different from \verb|disambiguiate|, which went through a search on
+the second pass. If we decided to store the markup in a temporary
+file after the first pass to save memory, we would change this section
+for blockwise printout. We still would not be forced to scan each
+line.
+
+<<printout while replacing those with trailing dots>>=
+foreach $trunc_line (sort(keys(%truncations))) {
+ $lines[$trunc_line] =
+ "\@$usage_type{$trunc_line} $completion{$truncations{$trunc_line}}\n";
+}
+print @lines;
+@
diff --git a/web/noweb/contrib/gregory/email b/web/noweb/contrib/gregory/email
new file mode 100644
index 0000000000..04b61f60a9
--- /dev/null
+++ b/web/noweb/contrib/gregory/email
@@ -0,0 +1 @@
+gtk@walsh.med.harvard.edu (Gregory Tucker-Kellogg)
diff --git a/web/noweb/contrib/jobling/Makefile b/web/noweb/contrib/jobling/Makefile
new file mode 100644
index 0000000000..5f91558927
--- /dev/null
+++ b/web/noweb/contrib/jobling/Makefile
@@ -0,0 +1,34 @@
+PROG = correct-refs
+DOCSRC = $(PROG).tex
+PROGSRC = $(PROG).csh
+SCRIPTS = list-anchors.awk awk-scripts.awk
+
+all: correct-refs.tex correct-refs.csh all-scripts
+
+correct-refs.tex: correct-refs.nw
+ noweave -delay -index $< > $@
+
+correct-refs.csh: correct-refs.nw
+ notangle -Rcorrect-refs.csh $< | cpif $@
+ chmod +x $@
+
+all-scripts: correct-refs.nw
+ notangle -Rlist-anchors.awk $< | cpif list-anchors.awk
+ notangle -Rawk-scripts.awk $< | cpif awk-scripts.awk
+ touch all-scripts
+
+install:
+ cp correct-refs.csh $(HOME)/bin
+ cp *.awk $(HOME)/lib
+
+tidy:
+ -rm *~ *% *.bak *.log *.blg
+
+clean: tidy
+ -rm *.ps *.dvi *.toc *.aux *.bbl *.dep $(PROG).shar
+
+realclean: clean
+ -rm $(DOCSRC) $(PROGSRC) $(SCRIPTS)
+
+shar:
+ shar README Makefile $(PROG).nw > $(PROG).shar
diff --git a/web/noweb/contrib/jobling/README b/web/noweb/contrib/jobling/README
new file mode 100644
index 0000000000..c522c48295
--- /dev/null
+++ b/web/noweb/contrib/jobling/README
@@ -0,0 +1,21 @@
+Correct-refs:
+============
+
+A set of awk scripts and to correct the internal anchors and links
+produced by noweave -latex+html followed by latex2html.
+
+This is necessary because the design of the html back-ends for
+noweave assume that the resulting HTML file will be the single
+document produced by latex2html -split 0 but this is not such
+a good idea if the document is large (e.g. the nuweb example).
+By default latex2html will split documents into nodes at
+section boundaries --- but if the document contains links,
+the names have to be changed from "#name" to "noden.html#name".
+
+The full documentation is contained in correct-refs.nw. Comments
+to
+
+Chris P. Jobling, University of Wales, Swansea
+C.P.Jobling@Swansea.ac.uk
+
+
diff --git a/web/noweb/contrib/jobling/correct-refs.bbl b/web/noweb/contrib/jobling/correct-refs.bbl
new file mode 100644
index 0000000000..dbeac6d068
--- /dev/null
+++ b/web/noweb/contrib/jobling/correct-refs.bbl
@@ -0,0 +1,36 @@
+\begin{thebibliography}{1}
+
+\bibitem{awk-book}
+Alfred~V. Aho, Brain~W. Kernighan, and Peter~J. Weinberger.
+\newblock {\em The {AWK} Programming Language}.
+\newblock Addison Wesley, Reading, MA, USA, 1988.
+
+\bibitem{gawk-manual}
+Diane~Barlow Close, Arnold~D. Robbins, Paul~H. Rubin, and Richard Stallman.
+\newblock {\em The {GAWK} Manual}.
+\newblock Free Software Foundation, 675 Massachusetts Avenue, Cambridge, MA
+ 02139, USA, version 0.11 beta edition, October 1989.
+
+\bibitem{nutshell-unix}
+Daniel Gilly.
+\newblock {\em UNIX in a Nutsell}.
+\newblock O'Reilly \& Associates, Sebastopol, CA, USA, {System V} edition,
+ 1992.
+
+\bibitem{ramsey94}
+Norman Ramsey.
+\newblock Literate programming simplified.
+\newblock {\em IEEE Software}, pages 97--105, September 1994.
+
+\bibitem{perl-llama}
+Randal~L. Schwartz.
+\newblock {\em Learning perl}.
+\newblock O'Reilly \& Associates, Sebastopol, CA, USA, 1993.
+
+
+\bibitem{perl-camel}
+Larry Wall and Randal~L. Schwartz.
+\newblock {\em Programming perl}.
+\newblock O'Reilly \& Associates, Sebastopol, CA, USA, 1991.
+
+\end{thebibliography}
diff --git a/web/noweb/contrib/jobling/correct-refs.nw b/web/noweb/contrib/jobling/correct-refs.nw
new file mode 100644
index 0000000000..6ab051e9a1
--- /dev/null
+++ b/web/noweb/contrib/jobling/correct-refs.nw
@@ -0,0 +1,391 @@
+%========================================================================%
+% @noweb-file{
+% author = "C.P. Jobling",
+% version = "$Revision: 1.5 $",
+% date = "$Date: 1995/04/01 13:54:43 $,
+% filename = "correct-refs.nw",
+% address = "Control and computer aided engineering
+% Department of Electrical and Electronic Engineering
+% University of Wales, Swansea
+% Singleton Park
+% Swansea SA2 8PP
+% Wales, UK",
+% telephone = "+44-792-295580",
+% FAX = "+44-792-295686",
+% checksum = "",
+% email = "C.P.Jobling@Swansea.ac.uk",
+% codetable = "ISO/ASCII",
+% keywords = "",
+% supported = "yes",
+% abstract = "Postprocessing routines to correct link
+% errors introduced by \verb|rawhtml| when
+% anchors are moved into sub-nodes of the
+% main HTML document.",
+% docstring = "The checksum field above contains a CRC-16
+% checksum as the first value, followed by the
+% equivalent of the standard UNIX wc (word
+% count) utility output of lines, words, and
+% characters. This is produced by Robert
+% Solovay's checksum utility.",
+% }
+%========================================================================
+\documentclass[a4paper]{article}
+\usepackage{noweb,html,multicol}
+
+\newcommand{\noweb}{\texttt{noweb}}
+\newcommand{\command}{\texttt{correct-xref}}
+
+\title{\command \\
+ Correct HTML In-Document Anchors and Hyperlinks}
+\author{C.P. Jobling \\
+University of Wales, Swansea \\
+(C.P.Jobling@Swansea.ac.uk)}
+\date{$Date: 1995/04/01 13:54:43 $ \\
+Version $Revision: 1.5 $}
+
+\begin{document}
+\maketitle
+\begin{abstract}
+Postprocessing routines to correct link
+errors introduced by \verb|rawhtml| when
+anchors are moved into sub-nodes of the
+main HTML document.
+\end{abstract}
+
+\tableofcontents
+<<Copyright>>=
+# This file is part of the correct-refs.nw package which is
+# Copyright (C) C.P. Jobling, 1995
+#
+# The code may be freely used for any purpose whatever
+# provided that it distributed with
+# the noweb source correct-refs.nw and that this copyright
+# notice is kept intact.
+#
+# Please report any problems, errors or suggestions to
+# Chris Jobling, University of Wales, Swansea
+# email: C.P.Jobling@Swansea.ac.uk
+# www-home page: http://faith.swan.ac.uk/chris.html/cpj.html
+#
+# $Id: correct-refs.nw,v 1.5 1995/04/01 13:54:43 eechris Exp $
+@
+
+\section{Purpose}
+When a \LaTeX $+$ HTML document is processed by \LaTeX 2HTML the
+resulting HTML document consists of a set of smaller documents, called
+``nodes''. Cross-referencing between nodes, works well if \LaTeX{}
+\verb|\label| and \verb|\ref| commands have been used to establish
+them. However, if the \verb|rawhtml| environment is used to create
+HTML anchors, e.g.
+\begin{verbatim}
+I want
+\begin{rawhtml}
+<a name="anchor">this</a>
+\end{rawhtml}
+to be an anchor.
+ :
+ :
+And now I want to go back to the anchor:
+follow this
+\begin{rawhtml}
+<a href="#anchor">link</a>
+\end{rawhtml}
+\end{verbatim}
+will only work if the link and the anchor happen to be in the same
+document. This can only be guaranteed when the \verb|-split 0| option
+is used.
+
+Why is this a problem? The answer is that I am interested in
+``literate programming'' using \noweb{} \cite{ramsey94} which has an
+option to create a \LaTeX{} file for its support of fancy mathematics, tables
+and figures with code-chunks, code and variable crossreferences
+formatted using \verb|rawhtml|. And the cross-references are exactly
+as described above. For largeish programs, particularly those that make
+heavy use of mathematics, tables and figures in the documentation sections
+(exactly the kind that I write!), it is inconvenient to have a single
+HTML file so I want to have the document split into pieces. Hence, I
+have to postprocess the resulting HTML files changing links so that
+the node-name of the anchor is included.
+
+For the previous example, say
+\begin{verbatim}
+I want
+\begin{rawhtml}
+<a name="anchor">this</a>
+\end{rawhtml}
+to be an anchor.
+\end{verbatim}
+ends up as:
+\begin{verbatim}
+I want
+<a name="anchor">this</a>
+to be an anchor.
+\end{verbatim}
+in \texttt{node1.html}
+
+Then any links to this anchor which are of the form
+\begin{verbatim}
+And now I want to go back to the anchor:
+follow this
+<a href="#anchor">link</a>
+\end{verbatim}
+Have to be changed to:
+\begin{verbatim}
+And now I want to go back to the anchor:
+follow this
+<a href="node1.html#anchor">link</a>
+\end{verbatim}
+in every node (except node1.html itself).
+
+In best UNIX, and \noweb{} tradition, the tools to achieve this are
+written in a mixture of \texttt{csh} \cite[Chapter 5]{nutshell-unix},
+\texttt{awk} \cite{awk-book,gawk-manual} and \texttt{awk}
+\cite[Chapter 10]{nutshell-unix} although one day I might redo them in
+\texttt{perl} \cite{perl-llama,perl-camel} for better portability.
+
+\section{Usage}
+The command to correct the cross-references is
+\begin{quote}
+\command{} {\it html-dir}
+\end{quote}
+where {\it html-dir} is the document directory created by \LaTeX 2HTML
+from {\it html-dir.tex}.
+
+\section{The Code}
+
+\subsection{Finding the anchors}
+On examining the HTML created by \LaTeX 2HTML, I noticed that all
+anchors created from \LaTeX{} \verb|\ref|, \verb|\tableofcontents|,
+\verb|\index| and by the cross-referencing done by \LaTeX 2HTML itself
+are of the form
+\begin{verbatim}
+<a name=sometext>blah, blah</a>
+\end{verbatim}
+That is the label name is not enclosed in double quotes. So, providing
+that the anchors that you create in your \verb|rawhtml| environments
+are of the form
+\begin{verbatim}
+<a name="sometext">Blah, blah</a>
+\end{verbatim}
+\command{} will be able to distinguish between anchors and links
+created by \LaTeX 2HTML and anchors and links created by \noweb{} or
+by the author of the original \LaTeX{} document.
+
+Here is an \texttt{awk} script to extract all the anchors from a
+series of documents and to output them in a list in the form
+\begin{verbatim}
+filename:anchor-name1
+filename:anchor-name2
+\end{verbatim}
+
+<<list-anchors.awk>>=
+# list-anchors.awk --- process a set of .html files and list
+# anchors in form filename:anchor-name
+# usage: [gn]awk -f list-anchors.awk *.html
+#
+<<Copyright>>
+{ <<Throw away [[<meta name=""]] stuff>>
+ for (i = 1; i <= NF; i++)
+ <<Find and print anchors>>
+}
+@
+
+\LaTeX 2HTML adds \verb|<meta name="">| tags to the head of all nodes.
+These could confuse the anchor finder, so we have to throw them away.
+
+<<Throw away [[<meta name=""]] stuff>>=
+if ($1 != "<meta")
+@
+
+
+This code just compares each field in the line with the pattern
+\verb|^name=".*"$| and when it finds one, strips it to leave just the
+anchor name and writes the filename and anchor name on {\it stdout}.
+<<Find and print anchors>>=
+if ($i ~ /^(name|NAME)\=\".*\".*$/) {
+ anchor = $i
+ sub(/^(name|NAME)\=\"/,"",anchor)
+ sub(/\".*$/,"",anchor)
+ printf("%s:%s\n",FILENAME,anchor)
+}
+@
+
+To use this program to create the anchor list:
+<<Create the list of anchors>>=
+cd $DOC
+echo Creating list of anchors
+gawk -f $LIB/list-anchors.awk *.html | sort -u >! anchor-list
+@
+
+\subsection{Generating link editing scripts}
+
+In order to correct the links in the HTML files, we now use the {\it
+ anchor-list} to control the creation of a set of \texttt{awk}
+scripts, one per html file, which will edit the links and replace
+\begin{verbatim}
+<a href="#anchor">link</a>
+\end{verbatim}
+by
+\begin{verbatim}
+<a href="node.html#anchor">link</a>
+\end{verbatim}
+unless the anchor and link happen to be in the same file.
+
+The processing is again done with a \texttt{[gn]awk} script.
+
+<<awk-scripts.awk>>=
+# awk-scripts.awk --- process a file conatining node:anchor
+# information to create a set of awk
+# scripts to correct the links in the nodes.
+# usage: [gn]awk -f awk-scripts.awk anchor-list
+#
+<<Copyright>>
+BEGIN {FS = ":"}
+{
+ <<Collect file names and anchors>>
+}
+END {
+ <<produce \texttt{awk} scripts>>
+}
+@
+
+The first part of this script just reads the entry in the {\it
+ anchor-list} and stores the information in arrays for use later.
+
+<<Collect file names and anchors>>=
+if (! ($1 in files)) {
+ files[$1] = NR
+}
+prefix[NR] = $1
+anchor[NR] = $2
+@
+
+To produce the \texttt{awk} scripts we loop over each unique file name
+encountered:
+<<produce \texttt{awk} scripts>>=
+for (file in files) {
+ <<Open new \texttt{awk} script>>
+ <<Write \texttt{awk} commands for each anchor>>
+}
+@
+
+To create a new \texttt{awk} script:
+<<Open new \texttt{awk} script>>=
+<<Create file name for \texttt{awk} script>>
+<<Open file>>
+@
+
+The first thing we need to is
+to get the root of the HTML file and append awk.
+
+<<Create file name for \texttt{awk} script>>=
+filename = file
+sub(/\..*$/,".awk",filename)
+@
+
+Next we open the file using redirection
+<<Open file>>=
+printf("# awk script to correct HTML links in %s\n",file) > filename
+@
+
+To create the \texttt{awk} code, we have to loop over each item in the
+list of anchor names. We throw away any that have the same filename as
+the currently open file. It will be ok to leave these as
+\begin{verbatim}
+<a href="#anchor">link</a>
+\end{verbatim}
+because the anchor is in the same file as the link. The rest get the
+file-name prepended onto each use of the anchor name in all links.
+When this is run, the output will be:
+\begin{verbatim}
+{ gsub(/href=\"#anchor-1\"/,"href=\"node1.html#anchor-1\"") }
+{ gsub(/href=\"#anchor-2\"/,"href=\"node1.html#anchor-2\"") }
+ :
+ :
+{ gsub(/href=\"#anchor-n\"/,"href=\"nodem.html#anchor-n\"") }
+{ print $0 }
+\end{verbatim}
+The actual string printing command doesn't look much like this because
+of all the escaping that has to be done.
+
+<<Write \texttt{awk} commands for each anchor>>=
+for (i=1; i < NR; i++) {
+ <<Reject links to anchors in current file>>
+ printf("{ gsub(/href=\\\"#%s\\\"/,\"href=\\\"%s#%s\\\"\") }\n",
+ anchor[i],prefix[i],anchor[i]) >> filename
+}
+printf("{ print $0 }") >> filename
+close(filename)
+@
+
+<<Reject links to anchors in current file>>=
+if (prefix[i] != file)
+@
+
+To create the \texttt{awk} scripts
+<<Create \texttt{awk} scripts for HTML files>>=
+echo Creating awk scripts
+gawk -f $LIB/awk-scripts.awk anchor-list
+@
+
+<<Use the \texttt{awk} scripts to correct HTML nodes>>=
+echo Processing HTML nodes
+foreach f (*.awk)
+ set root=$f:r
+ set tmpfile=`mktemp --suffix=.html`
+ echo -n Processing $root.html
+ gawk -f $f < $root.html >! $tmpfile
+ echo "..." Done
+ cp $root.html $root.html.bak
+ cp $tmpfile $root.html
+end
+
+@
+
+\subsection{\texttt{csh} Script to do anchor correction}
+<<correct-refs.csh>>=
+#!/usr/bin/csh
+# correct-refs.csh - CSH script file to correct HTML links and anchors
+# usage: correct-refs HTMLDIR
+<<Copyright>>
+unalias rm
+set LIB = $HOME/lib
+set DOC = $argv[1]
+echo Correcting anchors in HTML dir $DOC
+<<Create the list of anchors>>
+<<Create \texttt{awk} scripts for HTML files>>
+<<Use the \texttt{awk} scripts to correct HTML nodes>>
+<<Clean up>>
+@
+
+<<Clean up>>=
+rm *.awk
+rm anchor-list
+echo Done!
+@
+
+\bibliographystyle{plain}
+\bibliography{refs}
+
+\section*{Code Chunks}
+\nowebchunks
+
+\section*{Revision History}
+
+\begin{description}
+\item[1.3 to 1.4] The {\tt sed} script didn't work for \noweb{}
+ generated long anchor and link names. The substitute command string
+ was too long apparently! I changed the {\tt sed} scripts to {\tt awk
+ scripts}. Also tidied a few bits of the documentation.
+\end{description}
+\end{document}
+
+
+
+
+
+
+
+
+
+
diff --git a/web/noweb/contrib/jobling/email b/web/noweb/contrib/jobling/email
new file mode 100644
index 0000000000..4d70f5cc4b
--- /dev/null
+++ b/web/noweb/contrib/jobling/email
@@ -0,0 +1 @@
+C.P.Jobling@Swansea.ac.uk
diff --git a/web/noweb/contrib/jonkrom/Makefile b/web/noweb/contrib/jonkrom/Makefile
new file mode 100644
index 0000000000..12485906bc
--- /dev/null
+++ b/web/noweb/contrib/jonkrom/Makefile
@@ -0,0 +1,15 @@
+LIB=/dev/null # override for installation
+SHELL=/bin/sh
+all: noxref.krom
+ chmod +x noxref.krom
+
+install:
+ cp noxref.krom $(LIB)
+
+source: noxref.krom
+
+noxref.krom: noxref.nw
+ notangle -Rnoxref noxref.nw > noxref.krom
+
+clean:
+ /bin/rm -f *.tex *.dvi *.ilg *.idx *.aux *.log *.blg *.bbl *~ *.ind noxref.krom
diff --git a/web/noweb/contrib/jonkrom/README b/web/noweb/contrib/jonkrom/README
new file mode 100644
index 0000000000..8d294db2b9
--- /dev/null
+++ b/web/noweb/contrib/jonkrom/README
@@ -0,0 +1,4 @@
+An altered version of noxref (written in awk) that claims to support
+the same \chunklist semantics as the Icon version, plus boilerplate
+for supporting DOS.
+
diff --git a/web/noweb/contrib/jonkrom/email b/web/noweb/contrib/jonkrom/email
new file mode 100644
index 0000000000..1b7699c64c
--- /dev/null
+++ b/web/noweb/contrib/jonkrom/email
@@ -0,0 +1 @@
+jgk@jet.uk
diff --git a/web/noweb/contrib/jonkrom/noxref.nw b/web/noweb/contrib/jonkrom/noxref.nw
new file mode 100644
index 0000000000..06480117a8
--- /dev/null
+++ b/web/noweb/contrib/jonkrom/noxref.nw
@@ -0,0 +1,491 @@
+%=============================================================================
+% ----------------------------------------------------------------------------
+% Noxref, the cross referencing program for Noweb
+
+\documentstyle[noweb]{article}
+%\RCSdef $Id: noxref.nw,v 1.2 1993/05/06 18:15:40 jgk Exp $
+
+% ----------------------------------------------------------------------------
+%\title{{\tt Noxref\thanks{\RCSId},}
+\title{{\tt Noxref\thanks{Id: noxref.nw,v 1.2 1993/05/06 18:15:40 jgk Exp},}
+ the cross referencing program for {\tt Noweb}}
+\author{\setcounter{footnote}{6}%
+ JG Krom\thanks{JET Joint Undertaking, e-mail address: jgk@jet.uk}}
+
+\date{Printed: \today}
+
+% ----------------------------------------------------------------------------
+\makeindex
+\begin{document}
+\maketitle
+
+% ----------------------------------------------------------------------------
+% A bit of jargon:
+\newcommand{\noweb}{{\tt noweb}}
+\newcommand{\noweave}{{\tt noweave}}
+\newcommand{\notangle}{{\tt notangle}}
+\newcommand{\noxref}{{\tt noxref}} \newcommand{\Noxref}{{\tt Noxref}}
+\newcommand{\markup}{{\tt markup}}
+\newcommand{\awk}{{\rm awk}}
+\newcommand{\unix}{{\sc unix}}
+\newcommand{\dos}{{\sc msdos}}
+\newcommand{\chklist}{{$\setminus$\tt nowebchunks}}
+%----------------------------------------------------------------------------
+\section{Introduction}
+
+N Ramsey presents in [2] a clean, language independent system for
+literate programming, called \noweb. One of the components of
+\noweave, the ``weave'' program for this system, is the \noxref\ program.
+
+This system has been been ported to \dos\ by L Wittenberg.
+
+The author of this paper customised this \noxref\ program. The purpose
+of this paper is to describe these customisations. In order to
+implement these cutomisations in a ``literate Programming'' style, the
+codes written by the above mentioned authors are included in this
+document.
+
+% ----------------------------------------------------------------------------
+\section{Problem Definition}
+
+The \noxref\ program consists of an \awk\ [1] program, driven by an
+\unix\ shell script or, as appropriate, by an \dos\ batch file. This
+\noxref\ program adds page number references to the usage and
+definitions of the code chunks in a ``woven'' printing of a literate
+program.
+
+A feature that is available in other implementations of the \noxref\
+program, the alphabetical chunk list, was missing from the \awk\
+implementation of this program. As this feature seemed useful, it is
+implemented as an addition to the existing \noxref\ \awk\ program.
+
+This noxref program is the proper place to create this chunk list,
+since all information required for this list is already collected by
+this program.
+
+The chunk list should take a form, similar to a table of contents:
+chunk names, in the ``\LA{chunk name}\RA{}'' format, on the left hand
+side of the page, a list of page numbers on the right hand side of the
+page and leaders between the two. The list of page numbers should first
+contain the pages on which the chunk is defined and then the pages on
+which the chunk is used. Root chunks are to be indicated with the word
+``Root''. Chunks that are used, but not defined, are marked with the
+word ``Undefined''.
+
+This whole chunk list, formatted using \LaTeX\ commands, replaces any
+line, in the original source, containing only the word ``\chklist''.
+
+\Noxref\ was, and still is, intended as a stage in the \noweave\
+pipeline. This means that it will receive input in the ``marked-up''
+format generated by the \markup\ program. The output of \noxref\
+should also be in this format.
+
+% ----------------------------------------------------------------------------
+\pagebreak
+\section{Web Structure}
+This document describes three different files for two different environments:
+\begin{enumerate}
+\item [[noxref]] The executable shell script for use under \unix.
+ This file includes the awk script.
+\item [[noxref.bat]] The executable shell script for use under \dos.
+ This file calls upon the following file.
+\item [[noxref.awk]] The awk source code used or included by the
+ files above.
+\end{enumerate}
+Each of these can be generated by specifying the required filename as
+the root chunk name when executing the \notangle\ program on this web.
+To obtain the \dos\ batch file the following command should be executed:
+\begin{center}
+[[notangle -Rnoxref.bat noxref.nw > noxref.bat]]
+\end{center}
+Users of these shell scripts might have to adapt the [[awk]] program
+name in these scripts to match their local system configuration.
+<<noxref>>=
+#!/bin/sh
+# $Id: noxref.nw,v 1.2 1993/05/06 18:15:40 jgk Exp $
+nawk '<<noxref.awk>>'
+<<noxref.bat>>=
+@echo off
+REM # $Id: noxref.nw,v 1.2 1993/05/06 18:15:40 jgk Exp $
+REM The NOWEB environment variable must be set to the directory
+REM where NOXREF.AWK is. It must end in '/' or '\' as required
+REM by the AWK interpreter in use.
+awk -f %NOWEB%noxref.awk
+<<noxref.awk>>=
+# $Id: noxref.nw,v 1.2 1993/05/06 18:15:40 jgk Exp $
+<<Noxref awk source>>
+<<Noxref awk chunk list additions>>
+@
+% ----------------------------------------------------------------------------
+\section{The AWK Source Code}
+This is mostly Ramsey's original code. The fragment that has been
+changed is included as the chunk: \LA{Find and process the \chklist\
+request}\RA. Module label generation has been upgraded to the
+algorithm used in N~Ramsey's last release of the \noweb\ system.
+<<Noxref awk source>>=
+BEGIN { defns[0] = 0 ; uses[0] = 0 ; dcounts[0] = 0 ; firstdef[0] = 0;
+ ucounts[0] = 0 ; idtable[0] = 0 ; keycounts[0] = 0 ;
+ firstdefnout[0] = 0; filetable[0] = 0 }
+{ lines[nextline++] = $0 }
+/^@defn / { logname("DEFN", defns, dcounts, substr($0, 7)) }
+/^@use / { logname("USE", uses, ucounts, substr($0, 6)) }
+/^@file / { curfile = modid(substr($0, 7) substr($0, 10, 3)) }
+<<Noxref awk source>>=
+function logname(which, tbl, counts, name, id) {
+ counts[name] = counts[name] + 1
+ id = which curfile "-" modid(name) "-" counts[name]
+ tbl[name] = tbl[name] id " "
+ lines[nextline++] = "@literal \\label{" id "}"
+ if (which == "DEFN" && firstdef[name] == "") firstdef[name] = id
+}
+<<Noxref awk source>>=
+function modid(name, key) {
+ if (idtable[name] == "") {
+ key = name
+ gsub(/[\[\]\\{} -]/, "*", key)
+ if (length(key) > 6) key = substr(key,1,3) substr(key, length(key)-2, 3)
+ keycounts[key] = keycounts[key] + 1
+ idtable[name] = key "-" keycounts[key]
+ }
+ return idtable[name]
+}
+<<Noxref awk source>>=
+END {
+ for (i=0; i < nextline; i++) {
+ name = substr(lines[i], 2)
+ name = substr(name, 1, index(name, " ")-1)
+ arg = substr(lines[i], length(name)+3)
+ if (name == "defn") {
+ thischunk = arg
+ printf "@defn %s~{\\footnotesize\\rm\\pageref{%s}}\n", arg, firstdef[arg]
+ } else if (name == "use") {
+ if (firstdef[arg] != "")
+ printf "@use %s~{\\footnotesize\\rm\\pageref{%s}}\n", arg, firstdef[arg]
+ else
+ printf "@use %s~{\\footnotesize\\rm (never defined)}\n", arg
+ } else if (name == "end") {
+ if (substr(arg, 1, 4) == "code" && firstdefnout[thischunk] == 0) {
+ firstdefnout[thischunk] = 1
+ n = split(defns[thischunk], a)
+ if (n > 1) {
+ printf "@literal \\nwalsodefined{"
+ for (j = 2; j <= n; j++)
+ printf "\\\\{%s}", a[j]
+ printf "}\n@nl\n"
+ }
+ if (uses[thischunk] != "") {
+ printf "@literal \\nwused{"
+ n = split(uses[thischunk], a)
+ for (j = 1; j <= n; j++)
+ printf "\\\\{%s}", a[j]
+ printf "}\n@nl\n"
+ } else
+ printf "@literal \\nwnotused\n@nl\n"
+ }
+ print lines[i]
+ }
+ <<Find and process the \chklist\ request>>
+ else
+ print lines[i]
+ delete lines[i]
+ }
+}
+@ Finding the \chklist\ command is straight forward, it must be on a
+\verb+@text+ line. The unclean way of using a chunk to insert an
+[[else]]~[[if]] clause in a larger [[if -- else if -- else]]
+structure should be noted.
+<<Find and process the \chklist\ request>>=
+else if (name == "text") {
+ if (arg == "\\nowebchunks")
+ printChunkList()
+ else
+ print lines[i]
+}
+@ If the keyword has been found the function [[printChunkList()]] is
+called to do the actual printing.
+% ----------------------------------------------------------------------------
+\section{The Chunk List Additions}
+These additions consist, except for the chunk \LA{Find and process the
+\chklist\ request}\RA\ mentioned above, of two functions: one to sort
+the list of chunks, and one to print this list.
+
+<<Noxref awk chunk list additions>>=
+<<Sort chunk list>>
+<<Print chunk list>>
+@
+% ----------------------------------------------------------------------------
+\subsection{The Sorting Routine}
+This function implements essentially a simple insertion sort. If
+performance becomes a problem, some effort could be invested to use a
+better algorithm, but that seems unnecessary at the moment.
+
+\subsubsection{The Sorting Function Framework}
+Two global variables, [[nextFreeIdx]] and [[sortedNames]], carry the
+results of this function.
+
+The [[sortedNames]] array is empty to start with, except for the
+first element, which contains the null string as a sentinel; no
+string compares to less than the null string. The invariant on this
+array is that it will always contain chunk names in sorted order,
+with the lowest (according to the awk comparison rules) coming first.
+
+The invariant on [[nextFreeIdx]] is that it always contains the index
+number of the next free element in the array.
+<<Sort chunk list>>=
+function sortChunkNames( <<Sort --- Local Variables>>)
+{
+ sortedNames[0] = ""
+ nextFreeIdx=1; # The next index to use (range 1--N)
+ <<Run through the [[chunkname]]s as stored in [[defns]] array>>
+ <<Run through the [[chunkname]]s as stored in [[uses]] array>>
+}
+@
+\subsubsection{Scan the Arrays}
+All chunk names have been stored in the [[defns]] array when they were
+defined. Using the ``{\tt for \em xyz \tt in \em arrayname}'' feature of
+awk, it is possible to step through all elements of the array. The
+zero element in the arrays would confuse the sorting algorithm, so these
+elements have to be discarded.
+<<Run through the [[chunkname]]s as stored in [[defns]] array>>=
+for (chunkname in defns) {
+ if (chunkname != 0) {
+ <<Insert in proper place in sorted array>>
+ }
+}
+<<Sort --- Local Variables>>=
+chunkname,
+@ All names that have been used are stored in the array [[uses]]. This
+array has to be scanned for chunk names that might have been used, but
+that were not defined. Such chunks should also be included in the chunk
+list, so they are inserted in the [[sortedNames]] array.
+<<Run through the [[chunkname]]s as stored in [[uses]] array>>=
+for (chunkname in uses) {
+ if ((chunkname != 0) && !(chunkname in defns)) {
+ <<Insert in proper place in sorted array>>
+ }
+}
+@
+\subsubsection{Insert into the Sorted Array}
+The proper place for the insertion is found by scanning the sorted
+array from the end to the beginning. The local variable [[idx]] is
+used for this scan, it will always point at a possible insertion
+location. [[nextFreeIdx]] is incremented, since it is now known that
+there is another element which will be inserted.
+
+If the element before the current scan location is greater than the
+chunkname to be inserted, then the chunkname will be inserted before
+that element. The scanned element should be moved one position up (to
+the current insertion location) at this point.
+
+Otherwise, the chunk name should come after the element before the
+scan location, ie. it should be inserted at the current position.
+[[idx]] is pushed to the end condition, to stop the scan over the
+sorted array and to get a new chunk name.
+<<Insert in proper place in sorted array>>=
+for ( idx = nextFreeIdx++ ; idx>0 ; idx-- ) {
+ if ( sortedNames[idx-1] > chunkname )
+ sortedNames[idx] = sortedNames[idx-1] ;
+ else {
+ sortedNames[idx] = chunkname ;
+ idx = -1 ;
+ }
+}
+<<Sort --- Local Variables>>=
+idx
+@
+% ----------------------------------------------------------------------------
+\subsection{Print the Chunk List}
+The function to print the chunk list, first calls upon the sorting
+function to get the names in order. It then inserts, if required,
+some heading material and lastly prints the names.
+<<Print chunk list>>=
+function printChunkList( <<Print --- Local Variables>> )
+{
+ sortChunkNames() ;
+ <<Optional Header material>>
+ <<Header material>>
+ <<Print Loop>>
+ <<Closing Material>>
+}
+@
+% ----------------------------------------------------------------------------
+\subsubsection{The Printing Loop}
+This loops steps through the indices of the sorted names array, up to
+the next free index number. It prints each name, using the \markup\
+\verb+@use+ directive, followed by a row of dots. The printing of the
+page numbers, root markers etc. is delegated to the chunk \LA{print page
+numbers etc.}\RA.
+<<Print Loop>>=
+for (idx=1; idx<nextFreeIdx; idx++) {
+ print "@use " sortedNames[idx] ;
+ print "@literal \\dotfill" ;
+ <<Print page numbers etc.>>
+ print "@nl" ;
+}
+<<Print --- Local Variables>>=
+idx,
+@ When printing the page references, the following cases should be considered.
+\begin{itemize}
+\item If a name does not appear in the [[uses]] array, it must have been
+ in the [[defns]] arrray. It is therefore a root chunk.
+\item If a name does not appear in the [[defns]] array, it is undefined in
+ the source file currently processed.
+\item If a name is defined, print the page references of the definitions.
+\item If a name is used, print the usage page references.
+\end{itemize}
+<<Print page numbers etc.>>=
+if (uses[sortedNames[idx]] == "") {
+ print "@literal { \\rm Root}," ;
+}
+if (defns[sortedNames[idx]] == "") {
+ print "@literal { \\rm Undefined}" ;
+}
+else {
+ <<Print definition page numbers>>
+}
+if (uses[sortedNames[idx]] != "") {
+ <<Print usage page numbers>>
+}
+@
+\paragraph{Definition References.}
+Definition page references are derived from the [[defns]] arrays, by
+splitting them into fields with the [[split]] function. The first one
+should not be preceded by a ``,'' (comma character), but all subsequent
+numbers (if any) should have a comma in front of them. Page references
+for the definitions are printed underlined.
+<<Print definition page numbers>>=
+n = split(defns[sortedNames[idx]], a)
+print "@literal { \\underline{\\pageref{" a[1] "}}}";
+if (2 <= n)
+ for (j = 2; j <= n; j++)
+ print "@literal {, \\underline{\\pageref{" a[j] "}}}";
+<<Print --- Local Variables>>=
+n, a, j
+@
+\paragraph{Usage References.}
+The page references for the places where the chunks are used are
+obtained from the [[uses]] array. These always have
+preceding text (definition page references or the word ``Undefined''),
+so these should always have a ``,'' in front of them.
+<<Print usage page numbers>>=
+n = split(uses[sortedNames[idx]], a)
+for (j = 1; j <= n; j++)
+ print "@literal {\\rm, \\pageref{" a[j] "}}";
+@
+\paragraph{A Small Test.}
+Both chunk names should appear in the chunk list: one
+marked as ``Root'', the other as ``Undefined''.
+<<An unused (therefore root) chunk>>=
+<<An undefined chunk>>
+@
+\pagebreak
+\subsubsection{List Opening and Closing Definitions}
+If required, some commands could be included to generate a chapter or
+section heading above the chunk list. However, the author of this
+code prefers to have such sectioning commands under the control of the
+final document source file.
+
+Users who prefer to have these section commands automatically
+generated (like the Icon implementation of the \noxref\ program does)
+can redefine \LA{Optional Header material}\RA\ to be equal to the
+current definition of \LA{Not used header material}\RA.
+<<Optional Header material>>=
+<<Not used header material>>=
+print "@literal \\ifx\\chapter\\undefined\\section*"
+print "@literal {Alphabetical List of Chunk Names}" ;
+print "@literal \\else\\chapter"
+print "@literal {Alphabetical List of Chunk Names}" ;
+print "@literal \\fi"
+print "@nl" ;
+@ The following header material is required, it sets up the
+environment for the list.
+<<Header material>>=
+print "@literal {\\obeylines" ;
+print "@literal \\setlength{\\parindent}{0mm}" ;
+print "@literal \\setlength{\\parskip}{1.4ex}" ;
+print "@nl" ;
+<<Closing Material>>=
+print "@literal }" ;
+@
+% ----------------------------------------------------------------------------
+\newpage
+\section{References}
+% This is faked (ie, not a real LaTeX bibliography), since this file
+% is likely to get included in other files, with other bibliographies.
+{
+\begin{description}
+\sfcode`\.=1000\relax
+
+\item[{\rm [1]~~~}]
+Aho AV., Kernighan BW., Weinberger PJ. 1988,
+{\sl The AWK Programming Language,}
+Addison-Wesley.
+
+\item[{\rm [2]~~~}]
+Ramsey N. 1992--1993,
+``Literate Programming Tools Need Not Be Complex,''
+To be published in {\sl IEEE Software.} 1993.
+
+\end{description}
+}
+
+
+% ----------------------------------------------------------------------------
+% This should go in RCS.sty!
+\newenvironment{RCSlog}%
+{\begin{trivlist} \item[]%
+\setlength{\parindent}{0mm}%
+\setlength{\parskip}{3ex}%
+\catcode`\$=12%
+\hbadness=10000\ignorespaces\obeycr}%
+{\end{trivlist}}
+
+\section{RCS Maintained Log}
+\begin{RCSlog}
+$Log: noxref.nw,v $
+Revision 1.2 1993/05/06 18:15:40 jgk
+Moved from using bold to underlining for the page references
+of definitions. (On advice of Lee Wittenberg.)
+A few linguistic improvements. RCS ID strings included in progs.
+
+Revision 1.1 1993/05/01 21:08:21 JG~Krom
+Initial revision
+
+A version with the same code, but some errors and typos
+in the documentation text was known as:
+Revision 1.1 1993/04/28 17:03:23 jgk
+Initial revision
+
+This file was derived from:
+``NOXREF.BAT'' by L~Wittenberg and ``noxref'' By N~Ramsey.
+(No change log was available for these files.)
+
+And from:
+Log: noxref.awk
+Revision 1.5 1993/04/23 12:52:16 JG~Krom
+On advice of Lee Wittenberg, used the new way of label generation.
+
+Revision 1.4 1993/04/20 22:41:44 JG~Krom
+Improved layout of chunklist.
+
+Revision 1.3 1993/04/11 17:47:38 JG~Krom
+Indicate root chunks in the chunklist.
+
+Revision 1.2 1993/04/11 15:52:53 JG~Krom
+First stab at the chunklist command.
+
+Revision 1.1 1992/10/21 17:00:00 LEEW
+checked in with -k by JG~Krom at 1993/04/10 16:53:28
+
+Which in turn was also derived from: ``noxref'' By N~Ramsey.
+\end{RCSlog}
+% ----------------------------------------------------------------------------
+\newpage
+\section{Alphabetical List of Chunk Names}
+\nowebchunks
+% ----------------------------------------------------------------------------
+\input{noxref.ind}
+% ----------------------------------------------------------------------------
+\end{document}
+% End of noweb code
+%=============================================================================
diff --git a/web/noweb/contrib/kaelin/README b/web/noweb/contrib/kaelin/README
new file mode 100644
index 0000000000..f8be279ff9
--- /dev/null
+++ b/web/noweb/contrib/kaelin/README
@@ -0,0 +1,19 @@
+Prettyprinters for Icon and C++ based on Kostas's work, but using Computer Modern fonts.
+Prettyprinters for Icon and C++ based on Kostas's work, but using Computer Mode
+rn fonts.
+
+Theres is no Makefile
+Type
+> noweave -x -delay pp.nw > pp.tex < /* creates pp.tex */
+> latex pp.tex < /* creates pp.dvi and warnings */
+> latex pp.tex < /* creates final pp.dvi */
+to get documentation and
+> noweb -t pp.nw < /* creates cnw.icn and inw.icn */
+> iconc cnw.icn < /* creates cnw */
+> iconc inw.icn < /* creates inw */
+to get filters named cnw and inw.
+(Maybe you have to use full path-names for noweave, noweb, latex and iconc)
+
+For installation: Look at the other Makefiles in contrib/*
+
+Cleaning up is trivial: Remove pp.aux, pp.log, pp.tex, inw.icn and cnw.icn
diff --git a/web/noweb/contrib/kaelin/email b/web/noweb/contrib/kaelin/email
new file mode 100644
index 0000000000..8790d4fd1f
--- /dev/null
+++ b/web/noweb/contrib/kaelin/email
@@ -0,0 +1 @@
+Kaelin Colclasure <kaelin@bridge.com>
diff --git a/web/noweb/contrib/kaelin/pp.nw b/web/noweb/contrib/kaelin/pp.nw
new file mode 100644
index 0000000000..dd06757340
--- /dev/null
+++ b/web/noweb/contrib/kaelin/pp.nw
@@ -0,0 +1,616 @@
+% For LaTeX input: noweave -x -delay filename.nw > filename.tex
+% For source code: noweb -t filename.nw
+\documentstyle[noweb,11pt]{article}
+\pagestyle{noweb}
+\noweboptions{longchunks,smallcode}
+
+\newcommand{\CEE}{{\sc C\spacefactor1000}}
+\newcommand{\CPP}{{\sc C\PP\spacefactor1000}}
+\newcommand{\ICON}{{\sc Icon\spacefactor1000}}
+\newcommand{\PP}{\kern.5pt\raisebox{.4ex}
+ {$\scriptscriptstyle+\kern-1pt+$}\kern.5pt}
+
+\begin{document}
+\title{Beyond the {\tt \symbol{"5C}tt} Font\\{\large A {\tt noweb} Extension}}
+\author{Kaelin L. Colclasure \\ {\tt kaelin@bridge.com}}
+\date{Preliminary Draft}
+\maketitle
+
+\section{Introduction}
+This document contains two filters for {\tt noweave}, written in \ICON,
+which add basic pretty-printing for \CPP\ and \ICON\ code to {\tt noweb}'s
+repetoir of functionality. The bulk of the code herein is derived from
+\cite{kostas}, and at least a nodding familiarity with that work is assumed
+by this documentation. A working knowledge of \ICON\ is, of course, a must.
+Refer to \cite{griswold} as necessary.
+
+\subsection{Design philosophy}
+While I relish the idea of inflicting my own code formatting
+preferences on the unsuspecting masses, I was less enthusiastic
+towards the prospect of writing a scanner for each target language.
+Besides (I adeptly rationalized), so doing would violate one of the
+fundamental tenets of {\tt noweb}-- that the programmer maintain
+control over the formatting of code.
+
+Thus, this implementaion does not address indentation or line-breaking
+within code chunks. Like its predecessor, it is limited bolding target
+language keywords, operator substitution and other such in-line markup
+generation. However, even these restricted transformations can have a
+marked effect on the clarity of exposition of the source code.\footnote{This
+is particularly true for languages like Icon which have a plethora of
+multi-character operators.}
+
+\subsection{Why a new implementation?}
+While \cite{kostas} provides an easily-extensible implementation, it also
+has one unfortunate limitation-- the technique used to distinguish between
+operators and comment delimiters relies upon those categories consisting of
+disjoint character sets\footnote{More precisely, it relies upon the {\em
+start sets} of those two categories of tokens being disjoint.} in the target
+language. While true for the target languages Kostas implemented, this
+assertion does not hold for a large class of commonly used languages. The
+\CEE\ lagnuage, for instance, uses \verb|/*| \ldots \verb|*/| to bracket
+comments when both \verb|/| and \verb|*| are operators as well.
+
+While obviously a problem for me, since my first target language was \CPP,
+this could undoubtably have been redressed with relatively minor surgery to
+\cite{kostas}. However, once I'd familiarized myself with Kostas' code, I
+felt compelled to add some additional tweaks and features of my own. The
+principle enhancements provided are as follows:
+\begin{itemize}
+\item A more versatile scheme for handling token recognition. This not only
+addresses the problem outlined above, but makes it possible to do target
+language dependent processing during scanning as well as during
+initialization.
+\item More robust handling of string constants. Kostas did not deal with
+escaped embedded quoting characters at all.
+\item Pretty-printing of [[[[quoted]]]] code as well as code in {\tt noweb}
+chunks.
+\item Use of \ICON s conditional compilation facilities to allow all the code
+for different targets to reside in one file.\footnote{Well, {\em I} like it
+better this way\ldots}
+\end{itemize}
+Along the way, there have been some steps backwards as well:
+\begin{itemize}
+\item I make no provisions for multi-line comments at all. I
+personally use them only for commenting out code regions, and in that
+context special treatment is undesirable.\footnote{This does not
+preclude other target language implementations based upon this work
+from using target language dependent code to deal with multi-line
+comments.}
+\item Font utilization has been restricted to the Computer Modern fonts
+provided with all implementations of \TeX\ (primarily because my
+site has only those fonts).
+\item Due to my ignorance of ``vanilla'' \TeX, the markup code generated
+is \LaTeX\ dependent (I was tempted to add this as an item to the list
+above, but decided to refrain from provoking any nasty EMail).
+\end{itemize}
+No doubt I have introduced some new bugs as well, but discovering those is
+left as an excercise for the reader.
+
+\section{Implementation}
+Like Kostas, I have split the implementation of each target filter into a
+common part and a target dependent part. However, in contrast with
+\cite{kostas}, I have kept all the pieces together in one {\tt noweb} input
+file. Readers interested only in adding a new target should read \S
+\ref{reqs} and then skim \S \ref{c} and \S \ref{icon} for complete examples.
+
+\subsection{Target requirements\label{reqs}}
+\paragraph{Minimal implementation:}
+Each target implementation must provide at least the following:\footnote{In
+point of fact, the list of keywords could be left null. It merely provides
+a convenient way to populate the [[translation]] table with the
+language's reserved words, which will likely all receive the same markup
+treatment. However, here again, Icon is an exception\ldots}
+\begin{itemize}
+\item A root chunk which generates the \ICON\ source file for the target
+language filter.
+\item A table containing all of the target languages ``interesting''
+character sequences and either their typographic translation {\em or an \ICON\
+procedure for deriving it}.
+\item A list of keywords.
+\item A list of operators. For our purposes here, comment-delimiting
+punctuation marks are considered operators.
+\end{itemize}
+Variables to hold the required table and lists exist at global scope.
+<<Global declarations>>=
+global translation # Table of typographic translations
+global keyword_list, operator_list # List of keywords, operators
+@
+
+\paragraph{The [[translation]] table:} The table of typographic substitutions
+is built by the following code chunk during program initialization:
+<<Define the [[translation]] table>>=
+translation := table();
+<<Keywords>>
+<<Operators>>
+@
+
+\paragraph{Initial character sets:}
+The {\em start sets} for the two classes of tokens are defined globally in
+the following two chunks. Note that [[op_chars]] is automatically derived
+from the list of operators already defined above. However, some target
+languages will require adjustments to the definition of
+[[id_chars]].\footnote{Note that the Icon implementation does {\em not}
+add $\&$ to this list even though it prefixes some identifiers. We treat
+it always as an operator instead.}
+<<Global declarations>>=
+global id_chars, op_chars
+@
+<<Define initial character sets>>=
+id_chars := &letters ++ &digits ++ '_'
+op_chars := ''
+every op := !operator_list do op_chars ++:= cset(op[1])
+@
+
+\paragraph{The [[begin_token]] character set:}
+The next two chunks globally define the {\em start set} for {\bf all}
+interesting tokens. In general this will be \mbox{[[id_chars]] $\cup$
+[[op_chars]]}, but in some cases it may be desirable to add additional
+elements to this set.
+<<Global declarations>>=
+global begin_token
+@
+<<Define the [[begin_token]] character set>>=
+begin_token := id_chars ++ op_chars
+@
+
+\paragraph{Procedures:}
+\ICON\ procedures referenced in the [[translation]] table must, of
+course, be defined by the target implementation. When invoked, such a
+procedure will receive one argument-- the token which caused it to be
+invoked.
+
+Additionally, the [[TeXify]] procedure's [[case]] statement includes a
+target language dependent chunk which may be used to implement anything I've
+forgotten or neglected (like multi-line comments). The \CEE/\CPP
+implementation provides a skeletal example of how this might be used to
+process \CEE preprocessor directives.\footnote{It takes the trouble to find
+them, but then merely writes them verbatim to the output with no special
+formatting. This could have been more easily accomplished with a [[procedure]]
+entry in the [[translation]] table.}
+
+\subsection{Target independent code}
+
+\subsubsection{The [[main]] procedure}
+
+<<Procedure [[main]]>>=
+procedure main()
+ <<Define the [[translation]] table>>
+ <<Define initial character sets>>
+ <<Define the [[begin_token]] character set>>
+
+ <<Emit special \LaTeX\ definitions>>
+ <<Process each input line through the [[filter]] procedure>>
+ return
+end
+@
+<<Emit special \LaTeX\ definitions>>=
+write("@literal \\def\\begcom{\\begingroup\\rm" ||
+ "\\catcode`\\$=3\\catcode`\\^=7\\catcode`\\_=8{}}")
+write("@literal \\def\\endcom{\\endgroup}")
+@
+<<Process each input line through the [[filter]] procedure>>=
+while line := read() do
+ line ? (="@" & filter(tab(upto(' ') | 0), if =" " then tab(0) else &null))
+@
+
+\subsubsection{The [[filter]] procedure}
+
+<<Procedure [[filter]]>>=
+procedure filter(name, arg)
+static kind
+static whitespace
+static code_in_line
+ initial {
+ whitespace := ' \t'
+ }
+ case name of {
+ "begin": {
+ arg ? kind := tab(many(&letters))
+ copyline(name, arg)
+ }
+ "defn" | "literal" | "use": {
+ code_in_line := 1
+ copyline(name, arg)
+ }
+ "endquote": {
+ kind := "docs"
+ copyline(name, arg)
+ }
+ "nl": {
+ if \kind == "code" & /code_in_line then
+ write("@literal \\smallskip\\eatline")
+ copyline(name, arg)
+ code_in_line := &null
+ }
+ "quote": {
+ kind := "code"
+ copyline(name, arg)
+ }
+ "text": {
+ if \kind == "code" then {
+ if *(cset(arg) -- whitespace) > 0 then code_in_line := 1
+ TeXify(arg)
+ }
+ else copyline(name, arg)
+ }
+ default: copyline(name, arg)
+ }
+ return
+end
+@
+<<Procedure [[copyline]]>>=
+procedure copyline(name, arg)
+ return write("@", name, (" " || \arg) | "")
+end
+@
+
+\subsubsection{The [[TeXify]] procedure}
+
+<<Procedure [[TeXify]]>>=
+procedure TeXify(arg)
+ writes("@literal ")
+ arg ? {
+ while writes(preTeX(tab(upto(begin_token)))) do case &pos + 1 of {
+ <<Language-dependent \TeX ify chunk>>
+ any(id_chars): <<Identifier or numeric constant>>
+ any(op_chars): <<Operator>>
+ default: stop("\n** Error at input pos ", &pos)
+ }
+ writes(preTeX(tab(0)))
+ }
+ write()
+ return rval
+end
+@
+<<Identifier or numeric constant>>=
+{
+ token := tab(many(id_chars))
+ <<Write [[token]] or its typographic translation>>
+}
+@
+<<Operator>>=
+{
+ token := tab(match(!operator_list) | &pos + 1)
+ <<Write [[token]] or its typographic translation>>
+}
+@
+<<Write [[token]] or its typographic translation>>=
+trans := translation[token]
+case type(trans) of {
+ "procedure": writes(trans(token))
+ "null": writes(preTeX(token))
+ default: writes("\\mbox{" || trans || "}")
+}
+@
+<<Procedure [[preTeX]]>>=
+procedure preTeX(arg)
+static TeX, hex
+ initial {
+ TeX := '\\${}&#^_%'
+ hex := table();
+ hex["\\"] := "5C"; hex["$"] := "24"; hex["{"] := "7B"; hex["}"] := "7D"
+ hex["&"] := "26"; hex["#"] := "23"; hex["^"] := "5E"; hex["_"] := "5F"
+ hex["%"] := "25"
+ }
+ str := ""
+ every c := !arg do
+ str ||:= if *(cset(c) ** TeX) > 0 then "\\symbol{\"" || hex[c] || "}"
+ else c
+ return str
+end
+@
+
+\subsubsection{Target utility procedures}
+
+<<Procedure [[comment_eol]]>>=
+procedure comment_eol(arg)
+ return "\\begcom" || arg || tab(0) || "\\endcom"
+end
+@
+
+\paragraph{The [[quoted_c_string]] procedure:}
+This procedure matches a \CEE/\CPP-style
+string constant which may contain embedded quotes escaped by a backslash
+(\verb|\|) character. We want string constants to be typeset with
+\verb|\verb*| (ala {\tt CWEB}). The result looks like
+\verb*|"a string constant"| which makes counting multiple embedded spaces
+{\em much} easier.
+<<Procedure [[quoted_c_string]]>>=
+procedure quoted_c_string(arg)
+local c, str
+ c := cset(arg)
+ str := tab(upto(c))
+ if \str then while str[-1] == "\\" & (*str < 2 | str[-2] ~== "\\") do
+ str ||:= tab(&pos + 1) || tab(upto(c))
+ else str := ""
+ str ||:= tab(&pos + 1) # Pick up closing quote
+ return "\\verb*\^K" || arg || str || "\^K"
+end
+@ Note the use of ASCII {\tt VT} control characters to bracket the
+\verb|\verb*| environment. Any target implementation which utilizes this
+procedure must include [[write("@literal \\catcode`^^K=3")]] in the \LaTeX\
+special definitions chunk. This is a gross hack, but it's made necessary by
+the fact that a string literal could conceiveably contain {bf all} of the
+printable ASCII characters. We therefore arbitrarily choose a control
+character which we deem unlikely to be found in a string
+literal.\footnote{Incidently, my original choice was NUL, but this proved
+problematic for {\tt vi} users because that editor stripped the NULs away
+when the {\tt .tex} file was edited by hand.}
+
+\subsection{\protect\CEE/\protect\CPP\ code markup\label{c}}
+
+<<cnw.icn>>=
+$define LANG_CPLUSPLUS
+<<Global declarations>>
+<<Procedure [[main]]>>
+<<Procedure [[filter]]>>
+<<Procedure [[copyline]]>>
+<<Procedure [[preTeX]]>>
+<<Procedure [[TeXify]]>>
+
+<<Procedure [[comment_eol]]>>
+<<Procedure [[quoted_c_string]]>>
+@
+<<Keywords>>=
+$ifdef LANG_CPLUSPLUS
+keyword_list := [
+ "asm","auto","break","case","catch","char","class","const",
+ "continue","default","delete","do","double","else","enum","extern",
+ "float","for","friend","goto","if","inline","int","long",
+ "new","operator","private","protected","public","register","return","short",
+ "signed","sizeof","static","struct","switch","template","this","throw",
+ "try","typedef","union","unsigned","virtual","void","volatile","while"
+]
+every key := !keyword_list do translation[key] := "{\\bf{}" || key || "}"
+$endif
+@
+<<Operators>>=
+$ifdef LANG_CPLUSPLUS
+operator_list := [
+ "<\<=",">>=","->","++","--","<\<",">>","<=",">=","==","!=","&&","||",
+ "*=","/=","%=","+=","-=","&=","^=","|=","()","[]","//","/*","*/",
+ "!","%","^","&","*","(",")","-","+","=","{","}","|","~","[","]","<",">",
+ "?","/","'","\""
+]
+translation["<\<="] := "\\protect\\OPASSIGN{\\ll}"
+translation[">>="] := "\\protect\\OPASSIGN{\\gg}"
+translation["->"] := "\^K\\rightharpoonup\^K"
+translation["++"] := "\\protect\\PP"
+translation["--"] := "\\protect\\MM"
+translation["<\<"] := "\^K\\ll\^K"
+translation[">>"] := "\^K\\gg\^K"
+translation["<="] := "\^K\\leq\^K"
+translation[">="] := "\^K\\geq\^K"
+translation["=="] := "\^K\\equiv\^K"
+translation["!="] := "\^K\\neq\^K"
+translation["&&"] := "\^K\\wedge\^K"
+translation["||"] := "\^K\\vee\^K"
+translation["*="] := "\\protect\\OPASSIGN{\\ast}"
+translation["/="] := "\\protect\\OPASSIGN{\\div}"
+translation["%="] := "\\protect\\OPASSIGN{" || preTeX("%") || "}"
+translation["+="] := "\\protect\\OPASSIGN{+}"
+translation["-="] := "\\protect\\OPASSIGN{-}"
+translation["&="] := "\\protect\\OPASSIGN{" || preTeX("&") || "}"
+translation["^="] := "\\protect\\OPASSIGN{\\oplus}"
+translation["|="] := "\\protect\\OPASSIGN{\\mid}"
+translation["()"] := "\^K(\\;)\^K"
+translation["[]"] := "\^K[\\;]\^K"
+translation["//"] := comment_eol
+
+translation["!"] := "\^K\\neg\^K"
+translation["%"] := "\^K" || preTeX("%") || "\^K"
+translation["^"] := "\^K\\oplus\^K"
+translation["&"] := "\^K" || preTeX("&") || "\^K"
+translation["*"] := "\^K\\ast\^K"
+translation["="] := "\^K\\leftarrow\^K"
+translation["{"] := "\\boldmath\^K\\{\^K"
+translation["}"] := "\\boldmath\^K\\}\^K"
+translation["|"] := "\^K\\mid\^K"
+translation["~"] := "\^K\\sim\^K"
+translation["/"] := "\^K\\div\^K"
+translation["'"] := quoted_c_string
+translation["\""] := quoted_c_string
+
+every op := !operator_list do /translation[op] := "\^K" || op || "\^K"
+$endif
+@
+<<Language-dependent \TeX ify chunk>>=
+$ifdef LANG_CPLUSPLUS
+any(cpp_mark): writes(preTeX(tab(0)))
+$endif
+@
+<<Global declarations>>=
+$ifdef LANG_CPLUSPLUS
+global cpp_mark
+$endif
+@
+<<Define initial character sets>>=
+$ifdef LANG_CPLUSPLUS
+cpp_mark := '#'
+$endif
+@
+<<Define the [[begin_token]] character set>>=
+$ifdef LANG_CPLUSPLUS
+begin_token ++:= cpp_mark
+$endif
+@
+<<Emit special \LaTeX\ definitions>>=
+$ifdef LANG_CPLUSPLUS
+write("@literal \\catcode`^^K=3")
+write("@literal \\newcommand{\\MM}{\\kern.5pt\\raisebox{.4ex}" ||
+ "{\^K\\scriptscriptstyle-\\kern-1pt-\^K}\\kern.5pt}")
+write("@literal \\newcommand{\\PP}{\\kern.5pt\\raisebox{.4ex}" ||
+ "{\^K\\scriptscriptstyle+\\kern-1pt+\^K}\\kern.5pt}")
+write("@literal \\newcommand{\\OPASSIGN}[1]{\\raisebox{-.4ex}" ||
+ "{\^K\\stackrel{\\scriptscriptstyle\\,#1}{\\leftarrow}\^K}}")
+$endif
+@
+
+\subsection{\protect\ICON\ code markup\label{icon}}
+
+<<inw.icn>>=
+$define LANG_ICON
+<<Global declarations>>
+<<Procedure [[main]]>>
+<<Procedure [[filter]]>>
+<<Procedure [[copyline]]>>
+<<Procedure [[preTeX]]>>
+<<Procedure [[TeXify]]>>
+
+<<Procedure [[comment_eol]]>>
+<<Procedure [[quoted_c_string]]>>
+<<\ICON\ [[prefixed_keyword_check]] procedure>>
+@
+<<Global declarations>>=
+$ifdef LANG_ICON
+global an_word_list, ss_word_list
+$endif
+@
+<<Keywords>>=
+$ifdef LANG_ICON
+keyword_list := [
+ "by","break","case","create","default","do","else","end",
+ "every","fail","global","if","initial","link","local","next",
+ "not","of","procedure","record","repeat","return","static","suspend",
+ "to","then","while","until"
+]
+an_word_list := [
+ "ascii","clock","collections","cset","current","date","dateline","digits",
+ "error","errornumber","errortext","errorvalue","errout","fail","features",
+ "file","host","input","lcase","letters","level","line","main","null",
+ "output","pos","random","regions","source","storage","subject","time",
+ "trace","ucase","version",
+# Added in Version 8.10
+ "allocated","e","phi","pi","progname",
+# Added by X interface
+ "col","control","interval","ldrag","lpress","lrelease","mdrag","meta",
+ "mpress","mrelease","resize","rdrag","row","rpress","rrelease","shift",
+ "window","x","y"
+]
+ss_word_list := [
+# Translator directives for Version 8.10
+ "define","else","endif","ifdef","ifndef","include","line","undef",
+]
+every key := !keyword_list do translation[key] := "{\\bf{}" || key || "}"
+$endif
+@
+
+<<Operators>>=
+$ifdef LANG_ICON
+operator_list := [
+ "#","~===:=","<\<=:=",">>=:=","~==:=","|||:=","===:=","~===","<=:=",
+ ">=:=","~=:=","++:=","--:=","**:=","||:=","<\<:=","==:=",">>:=",
+ "<\<=",">>=","~==","|||",":=:","<->","===","+:=","-:=","*:=","/:=","%:=",
+ "^:=","<:=","=:=",">:=","@:=","&:=","?:=","()","[]",
+ "<=",">=","~=","++","--","**","||","<\<","==",">>",":=","<-","{","}","|",
+ "+","-","?","~","=","!","@","^","*",".","/","\\","%","<","&","$","'","\""
+]
+
+translation["#"] := comment_eol
+translation["~===:="] := "\\protect\\OPASSIGN{\\not\\equiv}"
+translation["<\<=:="] := "\\protect\\OPASSIGN{\\preceq}"
+translation[">>=:="] := "\\protect\\OPASSIGN{\\succeq}"
+translation["~==:="] := "\\protect\\OPASSIGN{\\not\\approx}"
+translation["|||:="] := "\\protect\\LONGOPASSIGN{[\\:]\\Join}"
+translation["===:="] := "\\protect\\OPASSIGN{\\equiv}"
+translation["~==="] := "\^K\\not\\equiv\^K"
+translation["<=:="] := "\\protect\\OPASSIGN{\\leq}"
+translation[">=:="] := "\\protect\\OPASSIGN{\\geq}"
+translation["~=:="] := "\\protect\\OPASSIGN{\\neq}"
+translation["++:="] := "\\protect\\OPASSIGN{\\uplus}"
+translation["--:="] := "\\protect\\OPASSIGN{\\ni}"
+translation["**:="] := "\\protect\\OPASSIGN{\\in}"
+translation["||:="] := "\\protect\\OPASSIGN{\\Join}"
+translation["<\<:="] := "\\protect\\OPASSIGN{\\prec}"
+translation["==:="] := "\\protect\\OPASSIGN{\\approx}"
+translation[">>:="] := "\\protect\\OPASSIGN{\\succ}"
+
+translation["<\<="] := "\^K\\preceq\^K"
+translation[">>="] := "\^K\\succeq\^K"
+translation["~=="] := "\^K\\not\\approx\^K"
+translation["|||"] := "\\protect\\OPSTACK{[\\:]}{\\Join}"
+translation[":=:"] := "\^K\\leftrightarrow\^K"
+translation["<->"] := "\^K\\Leftrightarrow\^K"
+translation["==="] := "\^K\\equiv\^K"
+translation["+:="] := "\\protect\\OPASSIGN{+}"
+translation["-:="] := "\\protect\\OPASSIGN{-}"
+translation["*:="] := "\\protect\\OPASSIGN{\\ast}"
+translation["/:="] := "\\protect\\OPASSIGN{\\div}"
+translation["%:="] := "\\protect\\OPASSIGN{" || preTeX("%") || "}"
+translation["^:="] := "\\protect\\OPASSIGN{\\uparrow}"
+translation["<:="] := "\\protect\\OPASSIGN{<}"
+translation["=:="] := "\\protect\\OPASSIGN{=}"
+translation[">:="] := "\\protect\\OPASSIGN{>}"
+translation["@:="] := "\\protect\\OPASSIGN{\\partial}"
+translation["&:="] := "\\protect\\OPASSIGN{\\wedge}"
+translation["?:="] := "\\protect\\OPASSIGN{\\wr}"
+translation["()"] := "\^K(\\;)\^K"
+translation["[]"] := "\^K[\\;]\^K"
+translation["<="] := "\^K\\leq\^K"
+translation[">="] := "\^K\\geq\^K"
+translation["~="] := "\^K\\neq\^K"
+translation["++"] := "\^K\\uplus\^K"
+translation["--"] := "\^K\\ni\^K"
+translation["**"] := "\^K\\in\^K"
+translation["||"] := "\^K\\Join\^K"
+translation["<\<"] := "\^K\\prec\^K"
+translation["=="] := "\^K\\approx\^K"
+translation[">>"] := "\^K\\succ\^K"
+translation[":="] := "\^K\\leftarrow\^K"
+translation["<-"] := "\^K\\Leftarrow\^K"
+translation["{"] := "\\boldmath\^K\\{\^K"
+translation["}"] := "\\boldmath\^K\\}\^K"
+translation["|"] := "\^K\\vee\^K"
+translation["?"] := "\^K\\wr\^K"
+translation["~"] := "\^K\\ni\^K"
+translation["!"] := "\^K\\forall\^K"
+translation["^"] := "\^K\\uparrow\^K"
+translation["*"] := "\^K\\ast\^K"
+translation["\\"] := "\^K\\exists\^K"
+translation["%"] := "\^K" || preTeX("%") || "\^K"
+translation["&"] := prefixed_keyword_check
+translation["$"] := prefixed_keyword_check
+translation["'"] := quoted_c_string
+translation["\""] := quoted_c_string
+
+every op := !operator_list do /translation[op] := "\^K" || op || "\^K"
+$endif
+@
+<<\ICON\ [[prefixed_keyword_check]] procedure>>=
+procedure prefixed_keyword_check(arg)
+local keyword_list, keyword, result
+ keyword_list := (arg == "&", an_word_list) | ss_word_list
+ keyword := tab(match(!keyword_list)) | &null
+ if \keyword then result := "{\\bf{}" || preTeX(arg) || keyword || "}"
+ else result := "\^K" || ((arg == "&", "\\wedge") | preTeX(arg)) || "\^K"
+ return result
+end
+@
+<<Emit special \LaTeX\ definitions>>=
+$ifdef LANG_ICON
+write("@literal \\catcode`^^K=3")
+write("@literal \\newcommand{\\LONGOPASSIGN}[1]{\\raisebox{-.4ex}" ||
+ "{\^K\\stackrel{\\scriptscriptstyle\\,#1}{\\longleftarrow}\^K}}")
+write("@literal \\newcommand{\\OPASSIGN}[1]{\\raisebox{-.4ex}" ||
+ "{\^K\\stackrel{\\scriptscriptstyle\\,#1}{\\leftarrow}\^K}}")
+write("@literal \\newcommand{\\OPSTACK}[2]{\\raisebox{-.4ex}" ||
+ "{\^K\\stackrel{\\scriptscriptstyle#1}{#2}\^K}}")
+$endif
+@
+
+\section{Chunks}
+\nowebchunks
+
+\begin{thebibliography}{Mmoo}
+\bibitem[Gris]{griswold}Ralph E. Griswold and Madge T. Griswold. {\em
+The Icon Programming Language}. Prentice-Hall, Englewood Cliffs, New
+Jersey, 1983.
+\bibitem[Oiko]{kostas}Kostas N. Oikonomou. {\em Extending Noweb With
+Some Typesetting}. Unpublished. Included in {\tt contrib} directory
+of the standard {\tt noweb} distribution.
+\end{thebibliography}
+\end{document}
+% Local Variables:
+% outline-regexp: "\\([\\\]\\(sub\\)*sec\\)\\|\\(<[^>]+>>=\\)"
+% End:
diff --git a/web/noweb/contrib/kostas/C++_translation_table b/web/noweb/contrib/kostas/C++_translation_table
new file mode 100644
index 0000000000..1653f51057
--- /dev/null
+++ b/web/noweb/contrib/kostas/C++_translation_table
@@ -0,0 +1,64 @@
+# This file defines translations into \TeX\ code for keywords of C++. It also defines
+# translations for special tokens, such as <=.
+
+# Initialize the translation table to contain nulls.
+translation := table()
+
+# Reserved words.
+translation["asm"] := "{\\ttb{}asm}"
+translation["auto"] := "{\\ttb{}auto}"
+translation["break"] := "{\\ttb{}break}"
+translation["case"] := "{\\ttb{}case}"
+translation["char"] := "{\\ttb{}char}"
+translation["class"] := "{\\ttb{}class}"
+translation["const"] := "{\\ttb{}const}"
+translation["continue"] := "{\\ttb{}continue}"
+translation["default"] := "{\\ttb{}default}"
+translation["delete"] := "{\\ttb{}delete}"
+translation["do"] := "{\\ttb{}do}"
+translation["double"] := "{\\ttb{}double}"
+translation["else"] := "{\\ttb{}else}"
+translation["enum"] := "{\\ttb{}enum}"
+translation["extern"] := "{\\ttb{}extern}"
+translation["float"] := "{\\ttb{}float}"
+translation["for"] := "{\\ttb{}for}"
+translation["friend"] := "{\\ttb{}friend}"
+translation["goto"] := "{\\ttb{}goto}"
+translation["if"] := "{\\ttb{}if}"
+translation["inline"] := "{\\ttb{}inline}"
+translation["int"] := "{\\ttb{}int}"
+translation["long"] := "{\\ttb{}long}"
+translation["new"] := "{\\ttb{}new}"
+translation["operator"] := "{\\ttb{}operator}"
+translation["overload"] := "{\\ttb{}overload}"
+translation["private"] := "{\\ttb{}private}"
+translation["protected"] := "{\\ttb{}protected}"
+translation["public"] := "{\\ttb{}public}"
+translation["register"] := "{\\ttb{}register}"
+translation["return"] := "{\\ttb{}return}"
+translation["short"] := "{\\ttb{}short}"
+translation["sizeof"] := "{\\ttb{}sizeof}"
+translation["static"] := "{\\ttb{}static}"
+translation["struct"] := "{\\ttb{}struct}"
+translation["switch"] := "{\\ttb{}switch}"
+translation["this"] := "{\\ttb{}this}"
+translation["typedef"] := "{\\ttb{}typedef}"
+translation["union"] := "{\\ttb{}union}"
+translation["unsigned"] := "{\\ttb{}unsigned}"
+translation["virtual"] := "{\\ttb{}virtual}"
+translation["void"] := "{\\ttb{}void}"
+translation["while"] := "{\\ttb{}while}"
+
+# Translations for operators.
+translation["{"] := "\\{"
+translation["}"] := "\\}"
+translation["<"] := "\\(<\\)"
+translation[">"] := "\\(>\\)"
+translation["<<"] := "\\(\\ll\\)"
+translation[">>"] := "\\(\\gg\\)"
+translation["!="] := "\\(\\neq\\)"
+translation["&&"] := "\\(\\land\\)"
+translation["||"] := "\\(\\lor\\)"
+translation["<="] := "\\(\\le\\)"
+translation[">="] := "\\(\\ge\\)"
+translation["->"] := "\\(\\to\\)"
diff --git a/web/noweb/contrib/kostas/C_translation_table b/web/noweb/contrib/kostas/C_translation_table
new file mode 100644
index 0000000000..a283eb89ce
--- /dev/null
+++ b/web/noweb/contrib/kostas/C_translation_table
@@ -0,0 +1,55 @@
+# This file defines translations into \TeX\ code for keywords of C. It also defines
+# translations for special tokens, such as <=.
+
+# Initialize the translation table to contain nulls.
+translation := table()
+
+# Reserved words.
+translation["auto"] := "{\\ttb{}auto}"
+translation["break"] := "{\\ttb{}break}"
+translation["case"] := "{\\ttb{}case}"
+translation["char"] := "{\\ttb{}char}"
+translation["continue"] := "{\\ttb{}continue}"
+translation["default"] := "{\\ttb{}default}"
+translation["do"] := "{\\ttb{}do}"
+translation["double"] := "{\\ttb{}double}"
+translation["else"] := "{\\ttb{}else}"
+translation["enum"] := "{\\ttb{}enum}"
+translation["extern"] := "{\\ttb{}extern}"
+translation["float"] := "{\\ttb{}float}"
+translation["for"] := "{\\ttb{}for}"
+translation["goto"] := "{\\ttb{}goto}"
+translation["if"] := "{\\ttb{}if}"
+translation["int"] := "{\\ttb{}int}"
+translation["long"] := "{\\ttb{}long}"
+translation["register"] := "{\\ttb{}register}"
+translation["return"] := "{\\ttb{}return}"
+translation["short"] := "{\\ttb{}short}"
+translation["sizeof"] := "{\\ttb{}sizeof}"
+translation["static"] := "{\\ttb{}static}"
+translation["struct"] := "{\\ttb{}struct}"
+translation["switch"] := "{\\ttb{}switch}"
+translation["typedef"] := "{\\ttb{}typedef}"
+translation["union"] := "{\\ttb{}union}"
+translation["unsigned"] := "{\\ttb{}unsigned}"
+translation["void"] := "{\\ttb{}void}"
+translation["while"] := "{\\ttb{}while}"
+
+# Pre-processor directives
+translation["#define"] := "{#\\ttb{}define}"
+translation["#include"] := "{#\\ttb{}include}"
+
+# Translations for operators.
+translation["{"] := "\\{"
+translation["}"] := "\\}"
+translation["<"] := "\\(<\\)"
+translation[">"] := "\\(>\\)"
+translation["<<"] := "\\(\\ll\\)"
+translation[">>"] := "\\(\\gg\\)"
+translation["!="] := "\\(\\neq\\)"
+translation["&&"] := "\\(\\land\\)"
+translation["||"] := "\\(\\lor\\)"
+translation["<="] := "\\(\\le\\)"
+translation[">="] := "\\(\\ge\\)"
+translation["->"] := "\\(\\to\\)"
+
diff --git a/web/noweb/contrib/kostas/Makefile b/web/noweb/contrib/kostas/Makefile
new file mode 100644
index 0000000000..27bbffad71
--- /dev/null
+++ b/web/noweb/contrib/kostas/Makefile
@@ -0,0 +1,75 @@
+# Only works with Gnu make.
+
+LIB=/opt/noweb/lib
+ICONC=icont
+# This is supposed to be the defns.nw file in the icon directory of the distribution.
+defns=defns.nw
+TANGLE=notangle
+WEAVE=noweave -delay -filter icon.filter -index
+
+.SUFFIXES: .nw .icn .tex .dvi
+
+
+all: C.filter C++.filter icon.filter oot.filter math.filter\
+ autodefs.oot autodefs.math
+
+install:
+ mv *.filter $(LIB)
+ mv autodefs.* $(LIB)
+
+
+# TeX files.
+%.tex : %.nw
+ $(WEAVE) $< > $@
+pp.tex: pp.nw
+ noweave -delay -autodefs icon -filter icon.filter -index pp.nw > pp.tex
+%.dvi : %.tex
+ latex $<
+# Don't delete the intermediate .tex file.
+.PRECIOUS : %.tex
+
+
+# Icon files.
+C.icn: pp.nw C_translation_table
+ $(TANGLE) -R"C" pp.nw > $@
+C++.icn: pp.nw C++_translation_table
+ $(TANGLE) -R"C++" pp.nw > $@
+icon.icn: pp.nw icon_translation_table
+ $(TANGLE) -R"Icon" pp.nw > $@
+oot.icn: pp.nw oot_translation_table
+ $(TANGLE) -R"OOT" pp.nw > $@
+math.icn: pp.nw math_translation_table
+ $(TANGLE) -R"Mathematica" pp.nw > $@
+
+ootdefs.icn: ootdefs.nw
+ $(TANGLE) $< $(defns) > $@
+mathdefs.icn: mathdefs.nw
+ $(TANGLE) $< $(defns) > $@
+
+
+# Executables: filters.
+%.filter : %.icn
+ $(ICONC) -o $@ $<
+
+# Executables: autodefs.
+autodefs.oot: ootdefs.icn
+ $(ICONC) -o autodefs.oot ootdefs.icn
+autodefs.math: mathdefs.icn
+ $(ICONC) -o autodefs.math mathdefs.icn
+
+
+# Cleaning: remove all files that can be recreated from noweb sources.
+nowebs := $(wildcard *.nw)
+rem := $(nowebs:.nw=.icn)
+rem := $(rem) $(nowebs:.nw=.tex)
+rem := $(rem) $(nowebs:.nw=.log)
+rem := $(rem) $(nowebs:.nw=.aux)
+rem := $(rem) $(nowebs:.nw=.toc)
+
+
+# Also remove the Icon files for the filters.
+clean:
+ -rm -f $(rem) C.icn C++.icn icon.icn oot.icn math.icn *.filter autodefs.*
+
+
+
diff --git a/web/noweb/contrib/kostas/Makefile.gnu b/web/noweb/contrib/kostas/Makefile.gnu
new file mode 100644
index 0000000000..27bbffad71
--- /dev/null
+++ b/web/noweb/contrib/kostas/Makefile.gnu
@@ -0,0 +1,75 @@
+# Only works with Gnu make.
+
+LIB=/opt/noweb/lib
+ICONC=icont
+# This is supposed to be the defns.nw file in the icon directory of the distribution.
+defns=defns.nw
+TANGLE=notangle
+WEAVE=noweave -delay -filter icon.filter -index
+
+.SUFFIXES: .nw .icn .tex .dvi
+
+
+all: C.filter C++.filter icon.filter oot.filter math.filter\
+ autodefs.oot autodefs.math
+
+install:
+ mv *.filter $(LIB)
+ mv autodefs.* $(LIB)
+
+
+# TeX files.
+%.tex : %.nw
+ $(WEAVE) $< > $@
+pp.tex: pp.nw
+ noweave -delay -autodefs icon -filter icon.filter -index pp.nw > pp.tex
+%.dvi : %.tex
+ latex $<
+# Don't delete the intermediate .tex file.
+.PRECIOUS : %.tex
+
+
+# Icon files.
+C.icn: pp.nw C_translation_table
+ $(TANGLE) -R"C" pp.nw > $@
+C++.icn: pp.nw C++_translation_table
+ $(TANGLE) -R"C++" pp.nw > $@
+icon.icn: pp.nw icon_translation_table
+ $(TANGLE) -R"Icon" pp.nw > $@
+oot.icn: pp.nw oot_translation_table
+ $(TANGLE) -R"OOT" pp.nw > $@
+math.icn: pp.nw math_translation_table
+ $(TANGLE) -R"Mathematica" pp.nw > $@
+
+ootdefs.icn: ootdefs.nw
+ $(TANGLE) $< $(defns) > $@
+mathdefs.icn: mathdefs.nw
+ $(TANGLE) $< $(defns) > $@
+
+
+# Executables: filters.
+%.filter : %.icn
+ $(ICONC) -o $@ $<
+
+# Executables: autodefs.
+autodefs.oot: ootdefs.icn
+ $(ICONC) -o autodefs.oot ootdefs.icn
+autodefs.math: mathdefs.icn
+ $(ICONC) -o autodefs.math mathdefs.icn
+
+
+# Cleaning: remove all files that can be recreated from noweb sources.
+nowebs := $(wildcard *.nw)
+rem := $(nowebs:.nw=.icn)
+rem := $(rem) $(nowebs:.nw=.tex)
+rem := $(rem) $(nowebs:.nw=.log)
+rem := $(rem) $(nowebs:.nw=.aux)
+rem := $(rem) $(nowebs:.nw=.toc)
+
+
+# Also remove the Icon files for the filters.
+clean:
+ -rm -f $(rem) C.icn C++.icn icon.icn oot.icn math.icn *.filter autodefs.*
+
+
+
diff --git a/web/noweb/contrib/kostas/Makefile.make b/web/noweb/contrib/kostas/Makefile.make
new file mode 100644
index 0000000000..27bbffad71
--- /dev/null
+++ b/web/noweb/contrib/kostas/Makefile.make
@@ -0,0 +1,75 @@
+# Only works with Gnu make.
+
+LIB=/opt/noweb/lib
+ICONC=icont
+# This is supposed to be the defns.nw file in the icon directory of the distribution.
+defns=defns.nw
+TANGLE=notangle
+WEAVE=noweave -delay -filter icon.filter -index
+
+.SUFFIXES: .nw .icn .tex .dvi
+
+
+all: C.filter C++.filter icon.filter oot.filter math.filter\
+ autodefs.oot autodefs.math
+
+install:
+ mv *.filter $(LIB)
+ mv autodefs.* $(LIB)
+
+
+# TeX files.
+%.tex : %.nw
+ $(WEAVE) $< > $@
+pp.tex: pp.nw
+ noweave -delay -autodefs icon -filter icon.filter -index pp.nw > pp.tex
+%.dvi : %.tex
+ latex $<
+# Don't delete the intermediate .tex file.
+.PRECIOUS : %.tex
+
+
+# Icon files.
+C.icn: pp.nw C_translation_table
+ $(TANGLE) -R"C" pp.nw > $@
+C++.icn: pp.nw C++_translation_table
+ $(TANGLE) -R"C++" pp.nw > $@
+icon.icn: pp.nw icon_translation_table
+ $(TANGLE) -R"Icon" pp.nw > $@
+oot.icn: pp.nw oot_translation_table
+ $(TANGLE) -R"OOT" pp.nw > $@
+math.icn: pp.nw math_translation_table
+ $(TANGLE) -R"Mathematica" pp.nw > $@
+
+ootdefs.icn: ootdefs.nw
+ $(TANGLE) $< $(defns) > $@
+mathdefs.icn: mathdefs.nw
+ $(TANGLE) $< $(defns) > $@
+
+
+# Executables: filters.
+%.filter : %.icn
+ $(ICONC) -o $@ $<
+
+# Executables: autodefs.
+autodefs.oot: ootdefs.icn
+ $(ICONC) -o autodefs.oot ootdefs.icn
+autodefs.math: mathdefs.icn
+ $(ICONC) -o autodefs.math mathdefs.icn
+
+
+# Cleaning: remove all files that can be recreated from noweb sources.
+nowebs := $(wildcard *.nw)
+rem := $(nowebs:.nw=.icn)
+rem := $(rem) $(nowebs:.nw=.tex)
+rem := $(rem) $(nowebs:.nw=.log)
+rem := $(rem) $(nowebs:.nw=.aux)
+rem := $(rem) $(nowebs:.nw=.toc)
+
+
+# Also remove the Icon files for the filters.
+clean:
+ -rm -f $(rem) C.icn C++.icn icon.icn oot.icn math.icn *.filter autodefs.*
+
+
+
diff --git a/web/noweb/contrib/kostas/README b/web/noweb/contrib/kostas/README
new file mode 100644
index 0000000000..d26e9c78b5
--- /dev/null
+++ b/web/noweb/contrib/kostas/README
@@ -0,0 +1,14 @@
+This directory contains noweb programs (written in Icon) that extend the basic noweb
+with some pretty-printing capabilities. By this we don't mean formatting, but just
+printing keywords in bold, comments in roman, mathematical operators using special
+symbols, etc. The pretty-printers work as noweb filters.
+
+There are 4 pretty-printers here, all generated from the same file, pp.nw. The
+pretty-printers are for C/C++, Icon, Turing (OOT), and Mathematica. pp.nw contains
+full documentation, and is written in a way that adding another language should be
+easy. (Let me know if you find it isn't so.)
+
+The pretty-printers work only with LaTeX2e, and you must have the cmttb10 font.
+
+There are also filters that write noweb index entries (autodefs) for Turing and
+Mathematica.
diff --git a/web/noweb/contrib/kostas/WHATS_NEW b/web/noweb/contrib/kostas/WHATS_NEW
new file mode 100644
index 0000000000..e08b859d56
--- /dev/null
+++ b/web/noweb/contrib/kostas/WHATS_NEW
@@ -0,0 +1,46 @@
+WHAT'S NEW:
+
+1) Indexing: the pretty-printers now fix up some of the deficiencies of noweb's
+indexing mechanism.
+
+"finduses" generates spurious references to identifiers when it sees a string
+matching an identifier inside a comment or string literal. For example, try
+
+ noweave -autodefs c -index t.nw > t.tex
+ latex t
+ latex t
+
+on the file
+
+<<Section A>>=
+int num;
+<<Section B>>=
+/* num is the number ... */
+<<Section C>>=
+printf("num is the number of things\n");
+@
+\nowebindex
+
+noweave (finduses) will generate a reference to num in each of sections B and C.
+
+Now try
+
+ noweave -autodefs c -filter C.filter -index t.nw > t.tex
+ latex t
+ latex t
+
+(NOTE: -filter first, -index next!)
+You get a pretty-printed version without these references. All pretty-printer
+filters suppress these spurious references.
+
+
+2) A bug in pretty-printing operators has been fixed. For example, if ``=='' is
+meant to be typeset as ``\equiv'', say, but ``==='' is supposed to be left alone, the
+old version would typeset ``==='' as ``\equiv=''.
+
+
+3) For those who know about OOT: the autodefs.oot now does not index identifiers
+declared in subprograms. This reduces clutter. However, it has the capability to
+index such identifiers selectively if the user supplies an argument to the filter,
+the name of a file listing subprogram names one per line. (See ootdefs.nw for
+details.)
diff --git a/web/noweb/contrib/kostas/defns.nw b/web/noweb/contrib/kostas/defns.nw
new file mode 100644
index 0000000000..0d3326c446
--- /dev/null
+++ b/web/noweb/contrib/kostas/defns.nw
@@ -0,0 +1,33 @@
+<<*>>=
+procedure go()
+ local line
+ while line := read() do {
+ apply(prepass, line)
+ write(line)
+ apply(postpass, line)
+ }
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+@
+[[indextext]] is a hack to introduce suitable ``[[@index nl]],'' but it
+messes up the line counts!
+<<*>>=
+procedure writedefn(defn)
+ static indextext
+ initial indextext := ""
+ if /defn then
+ *indextext > 0 & <<flush index>>
+ else {
+ if *indextext + *defn > 65 then <<flush index>>
+ write("@index defn ", defn)
+ indextext ||:= " " || defn
+ }
+ return
+end
+<<flush index>>=
+{ # write("@index nl") # don't!
+ indextext := ""
+}
diff --git a/web/noweb/contrib/kostas/email b/web/noweb/contrib/kostas/email
new file mode 100644
index 0000000000..fec98b1e32
--- /dev/null
+++ b/web/noweb/contrib/kostas/email
@@ -0,0 +1 @@
+ko@surya.ho.att.com
diff --git a/web/noweb/contrib/kostas/icon_translation_table b/web/noweb/contrib/kostas/icon_translation_table
new file mode 100644
index 0000000000..d3b8099666
--- /dev/null
+++ b/web/noweb/contrib/kostas/icon_translation_table
@@ -0,0 +1,140 @@
+# This file defines translations into \TeX\ code for reserved words, and keywords of Icon.
+# It also defines translations for special tokens, such as <=.
+
+
+# Initialize the translation table to contain nulls.
+translation := table()
+
+
+# Reserved words.
+translation["by"] := "{\\ttb{}by}"
+translation["break"] := "{\\ttb{}break}"
+translation["case"] := "{\\ttb{}case}"
+translation["create"] := "{\\ttb{}create}"
+translation["default"] := "{\\ttb{}default}"
+translation["do"] := "{\\ttb{}do}"
+translation["else"] := "{\\ttb{}else}"
+translation["end"] := "{\\ttb{}end}"
+translation["every"] := "{\\ttb{}every}"
+translation["global"] := "{\\ttb{}global}"
+translation["fail"] := "{\\ttb{}fail}"
+translation["if"] := "{\\ttb{}if}"
+translation["initial"] := "{\\ttb{}initial}"
+translation["link"] := "{\\ttb{}link}"
+translation["local"] := "{\\ttb{}local}"
+translation["next"] := "{\\ttb{}next}"
+translation["not"] := "{\\ttb{}not}"
+translation["of"] := "{\\ttb{}of}"
+translation["procedure"] := "{\\ttb{}procedure}"
+translation["record"] := "{\\ttb{}record}"
+translation["repeat"] := "{\\ttb{}repeat}"
+translation["return"] := "{\\ttb{}return}"
+translation["static"] := "{\\ttb{}static}"
+translation["suspend"] := "{\\ttb{}suspend}"
+translation["to"] := "{\\ttb{}to}"
+translation["then"] := "{\\ttb{}then}"
+translation["while"] := "{\\ttb{}while}"
+translation["until"] := "{\\ttb{}until}"
+
+# Icon keywords.
+translation["&ascii"] := "{\\ttb{}&ascii}"
+translation["&clock"] := "{\\ttb{}\&clock}"
+translation["&collections"] := "{\\ttb{}\&collections}"
+translation["&cset"] := "{\\ttb{}\&cset}"
+translation["&current"] := "{\\ttb{}\&current}"
+translation["&date"] := "{\\ttb{}\&date}"
+translation["&dateline"] := "{\\ttb{}\&dateline}"
+translation["&digits"] := "{\\ttb{}\&digits}"
+translation["&error"] := "{\\ttb{}\&error}"
+translation["&errornumber"] := "{\\ttb{}\&errornumber}"
+translation["&errortext"] := "{\\ttb{}\&errortext}"
+translation["&errorvalue"] := "{\\ttb{}\&errorvalue}"
+translation["&errout"] := "{\\ttb{}\&errout}"
+translation["&fail"] := "{\\ttb{}\&fail}"
+translation["&features"] := "{\\ttb{}\&features}"
+translation["&file"] := "{\\ttb{}\&file}"
+translation["&host"] := "{\\ttb{}\&host}"
+translation["&input"] := "{\\ttb{}\&input}"
+translation["&lcase"] := "{\\ttb{}\&lcase}"
+translation["&letters"] := "{\\ttb{}\&letters}"
+translation["&level"] := "{\\ttb{}\&level}"
+translation["&line"] := "{\\ttb{}\&line}"
+translation["&main"] := "{\\ttb{}\&main}"
+translation["&null"] := "{\\ttb{}\&null}"
+translation["&output"] := "{\\ttb{}\&output}"
+translation["&pos"] := "{\\ttb{}\&pos}"
+translation["&random"] := "{\\ttb{}\&random}"
+translation["&regions"] := "{\\ttb{}\&regions}"
+translation["&source"] := "{\\ttb{}\&source}"
+translation["&storage"] := "{\\ttb{}\&storage}"
+translation["&subject"] := "{\\ttb{}\&subject}"
+translation["&time"] := "{\\ttb{}\&time}"
+translation["&trace"] := "{\\ttb{}\&trace}"
+translation["&ucase"] := "{\\ttb{}\&ucase}"
+translation["&version"] := "{\\ttb{}\&version}"
+
+# Added in Version 8.10.
+translation["&allocated"] := "{\\ttb{}\&allocated}"
+translation["&e"] := "{\\ttb{}\&e}"
+translation["&phi"] := "{\\ttb{}\&phi}"
+translation["&pi"] := "{\\ttb{}\&pi}"
+translation["&progname"] := "{\\ttb{}\&progname}"
+
+# Added by the X interface.
+#translation["&col"] := "{\\ttb{}\&col}"
+#translation["&control"] := "{\\ttb{}\&control}"
+#translation["&interval"] := "{\\ttb{}\&interval}"
+#translation["&ldrag"] := "{\\ttb{}\&ldrag}"
+#translation["&lpress"] := "{\\ttb{}\&lpress}"
+#translation["&lrelease"] := "{\\ttb{}\&lrelease}"
+#translation["&mdrag"] := "{\\ttb{}\&mdrag}"
+#translation["&meta"] := "{\\ttb{}\&meta}"
+#translation["&mpress"] := "{\\ttb{}\&mpress}"
+#translation["&mrelease"] := "{\\ttb{}\&mrelease}"
+#translation["&resize"] := "{\\ttb{}\&resize}"
+#translation["&rdrag"] := "{\\ttb{}\&rdrag}"
+#translation["&row"] := "{\\ttb{}\&row}"
+#translation["&rpress"] := "{\\ttb{}\&rpress}"
+#translation["&rrelease"] := "{\\ttb{}\&rrelease}"
+#translation["&shift"] := "{\\ttb{}\&shift}"
+#translation["&window"] := "{\\ttb{}\&window}"
+#translation["&x"] := "{\\ttb{}\&x}"
+#translation["&y"] := "{\\ttb{}\&y}"
+
+
+# Translator directives (V8.10).
+translation["$include"] := "{\\ttb{}\\$include}"
+translation["$line"] := "{\\ttb\\$line}"
+translation["$define"] := "{\\ttb\\$define}"
+translation["$undef"] := "{\\ttb\\$undef}"
+translation["$ifdef"] := "{\\ttb\\$ifdef}"
+translation["$ifndef"] := "{\\ttb\\$ifndef}"
+translation["$else"] := "{\\ttb\\$else}"
+translation["$endif"] := "{\\ttb\\$endif}"
+
+
+# Translations for operators, and other good stuff.
+translation["{"] := "\\{"
+translation["}"] := "\\}"
+translation["\\"] := "\\verb|\\|"
+translation["<"] := "\\(<\\)"
+translation[">"] := "\\(>\\)"
+translation["<="] := "\\(\\le\\)"
+translation[">="] := "\\(\\ge\\)"
+translation["~="] := "\\(\\neq\\)"
+translation["++"] := "\\(\\cup\\)"
+translation["**"] := "\\(\\cap\\)"
+translation["--"] := "\\(\\setminus\\)"
+translation["&"] := "\\(\\land\\)" # Conjunction
+translation["|"] := "\\(\\lor\\)" # Alternation
+translation[">>"] := "\\(\\succ\\)"
+translation["<<"] := "\\(\\prec\\)"
+translation["||"] := "\\(\\Vert\\)"
+translation[">>="] := "\\(\\succeq\\)"
+translation["<<="] := "\\(\\preceq\\)"
+#translation["=="] := ?
+#translation["~=="] := ?
+translation["==="] := "\\(\\equiv\\)"
+translation["~==="] := "\\(\\not\\equiv\\)"
+translation[":=:"] := "\\(\\leftrightarrow\\)"
+translation["<->"] := "\\(\\leftrightarrow\\)"
diff --git a/web/noweb/contrib/kostas/math_translation_table b/web/noweb/contrib/kostas/math_translation_table
new file mode 100644
index 0000000000..cc57c4e995
--- /dev/null
+++ b/web/noweb/contrib/kostas/math_translation_table
@@ -0,0 +1,68 @@
+# This file defines translations into \TeX\ code for some of the most common Mathematica
+# keywords. Not all of them, because there are too many.
+# It also defines translations for special tokens, such as <=.
+
+
+# Initialize the translation table to contain nulls.
+translation := table()
+
+# Keywords.
+translation["Abort"] := "{\\ttb{}Abort}"
+translation["And"] := "{\\ttb{}And}"
+translation["Append"] := "{\\ttb{}Append}"
+translation["AppendTo"] := "{\\ttb{}AppendTo}"
+translation["Apply"] := "{\\ttb{}Apply}"
+translation["Array"] := "{\\ttb{}Array}"
+translation["Assert"] := "{\\ttb{}Assert}" # This is mine.
+translation["Begin"] := "{\\ttb{}Begin}"
+translation["BeginPackage"] := "{\\ttb{}BeginPackage}"
+translation["Block"] := "{\\ttb{}Block}"
+translation["Break"] := "{\\ttb{}Break}"
+translation["Chop"] := "{\\ttb{}Chop}"
+translation["Continue"] := "{\\ttb{}Continue}"
+translation["Do"] := "{\\ttb{}Do}"
+translation["End"] := "{\\ttb{}End}"
+translation["EndPackage"] := "{\\ttb{}EndPackage}"
+# My addition:
+translation["ExitWhen"] := "{\\ttb{}ExitWhen}"
+translation["False"] := "{\\ttb{}False}"
+translation["For"] := "{\\ttb{}For}"
+translation["Function"] := "{\\ttb{}Function}"
+translation["If"] := "{\\ttb{}If}"
+translation["Join"] := "{\\ttb{}Join}"
+translation["Length"] := "{\\ttb{}Length}"
+# My addition:
+translation["Loop"] := "{\\ttb{}Loop}"
+translation["Map"] := "{\\ttb{}Map}"
+translation["Module"] := "{\\ttb{}Module}"
+translation["Needs"] := "{\\ttb{}Needs}"
+translation["Not"] := "{\\ttb{}Not}"
+translation["Part"] := "{\\ttb{}Part}"
+translation["Prepend"] := "{\\ttb{}Prepend}"
+translation["Print"] := "{\\ttb{}Print}"
+translation["Return"] := "{\\ttb{}Return}"
+translation["Scan"] := "{\\ttb{}Scan}"
+translation["Switch"] := "{\\ttb{}Switch}"
+translation["Table"] := "{\\ttb{}Table}"
+translation["Take"] := "{\\ttb{}Take}"
+translation["True"] := "{\\ttb{}True}"
+translation["Union"] := "{\\ttb{}Union}"
+translation["Which"] := "{\\ttb{}Which}"
+translation["While"] := "{\\ttb{}While}"
+
+
+# Translations for operators, etc.
+translation["{"] := "\\{"
+translation["}"] := "\\}"
+translation["<"] := "\\(<\\)"
+translation[">"] := "\\(>\\)"
+translation["!="] := "\\(\\neq\\)"
+translation["=="] := "\\(\\equiv\\)"
+translation["<="] := "\\(\\le\\)"
+translation[">="] := "\\(\\ge\\)"
+translation["->"] := "\\(\\rightarrow\\)"
+translation["&&"] := "\\(\\land\\)"
+translation["||"] := "\\(\\lor\\)"
+translation["**"] := "\\(\\otimes\\)"
+translation["<>"] := "\\(\\bowtie\\)"
+
diff --git a/web/noweb/contrib/kostas/mathdefs.nw b/web/noweb/contrib/kostas/mathdefs.nw
new file mode 100644
index 0000000000..e77f7d3845
--- /dev/null
+++ b/web/noweb/contrib/kostas/mathdefs.nw
@@ -0,0 +1,24 @@
+\section{Finding \textsl{Mathematica} definitions}
+
+This will simply recognize definitions made with ``:=''.
+<<*>>=
+procedure main(args)
+ go()
+end
+<<*>>=
+procedure postpass(name, arg)
+ static kind, id
+ initial {kind := "bogus"; id := &letters ++ &digits}
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then
+ arg ? if s := tab(find(":=")) then
+ {s ? {tab(many(' ')); writedefn(tab(many(id)))}
+ }
+ }
+ return
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
diff --git a/web/noweb/contrib/kostas/oot_translation_table b/web/noweb/contrib/kostas/oot_translation_table
new file mode 100644
index 0000000000..0ca9078412
--- /dev/null
+++ b/web/noweb/contrib/kostas/oot_translation_table
@@ -0,0 +1,137 @@
+# This file defines translations into \TeX\ code for keywords of OOT (Object-Oriented
+# Turing). It also defines translations for special tokens, such as <=.
+
+# Initialize the translation table to contain nulls.
+translation := table()
+
+# Reserved words.
+translation["addressint"] := "{\\ttb{}addressint}"
+translation["all"] := "{\\ttb{}all}"
+translation["and"] := "\\(\\land\\)"
+translation["anyclass"] := "{\\ttb{}anyclass}"
+translation["array"] := "{\\ttb{}array}"
+translation["assert"] := "{\\ttb{}assert}"
+translation["begin"] := "{\\ttb{}begin}"
+translation["bind"] := "{\\ttb{}bind}"
+translation["body"] := "{\\ttb{}body}"
+translation["boolean"] := "{\\ttb{}boolean}"
+translation["by"] := "{\\ttb{}by}"
+translation["case"] := "{\\ttb{}case}"
+translation["char"] := "{\\ttb{}char}"
+translation["cheat"] := "{\\ttb{}cheat}"
+translation["checked"] := "{\\ttb{}checked}"
+translation["class"] := "{\\ttb{}class}"
+translation["close"] := "{\\ttb{}close}"
+translation["collection"] := "{\\ttb{}collection}"
+translation["const"] := "{\\ttb{}const}"
+translation["decreasing"] := "{\\ttb{}decreasing}"
+translation["deferred"] := "{\\ttb{}deferred}"
+translation["div"] := "{\\ttb{}div}"
+translation["else"] := "{\\ttb{}else}"
+translation["elsif"] := "{\\ttb{}elsif}"
+translation["end"] := "{\\ttb{}end}"
+translation["enum"] := "{\\ttb{}enum}"
+translation["exit"] := "{\\ttb{}exit}"
+translation["export"] := "{\\ttb{}export}"
+translation["external"] := "{\\ttb{}external}"
+translation["false"] := "{\\ttb{}false}"
+translation["flexible"] := "{\\ttb{}flexible}"
+translation["for"] := "{\\ttb{}for}"
+translation["fork"] := "{\\ttb{}fork}"
+translation["forward"] := "{\\ttb{}forward}"
+translation["free"] := "{\\ttb{}free}"
+translation["function"] := "{\\ttb{}function}"
+translation["get"] := "{\\ttb{}get}"
+translation["if"] := "{\\ttb{}if}"
+translation["implement"] := "{\\ttb{}implement}"
+translation["import"] := "{\\ttb{}import}"
+translation["in"] := "\\(\\in\\)"
+translation["include"] := "{\\ttb{}include}"
+translation["inherit"] := "{\\ttb{}inherit}"
+translation["init"] := "{\\ttb{}init}"
+translation["int"] := "{\\ttb{}int}"
+translation["int1"] := "{\\ttb{}int1}"
+translation["int2"] := "{\\ttb{}int2}"
+translation["int4"] := "{\\ttb{}int4}"
+translation["invariant"] := "{\\ttb{}invariant}"
+translation["label"] := "{\\ttb{}label}"
+translation["loop"] := "{\\ttb{}loop}"
+translation["mod"] := "{\\ttb{}mod}"
+translation["module"] := "{\\ttb{}module}"
+translation["monitor"] := "{\\ttb{}monitor}"
+translation["nat"] := "{\\ttb{}nat}"
+translation["nat1"] := "{\\ttb{}nat1}"
+translation["nat2"] := "{\\ttb{}nat2}"
+translation["nat4"] := "{\\ttb{}nat4}"
+translation["new"] := "{\\ttb{}new}"
+translation["nil"] := "{\\ttb{}nil}"
+translation["not"] := "\\(\\neg\\)\\kern-0.3em"
+translation["of"] := "{\\ttb{}of}"
+translation["opaque"] := "{\\ttb{}opaque}"
+translation["open"] := "{\\ttb{}open}"
+translation["or"] := "\\(\\lor\\)"
+translation["pause"] := "{\\ttb{}pause}"
+translation["pervasive"] := "{\\ttb{}pervasive}"
+translation["pointer"] := "{\\ttb{}pointer}"
+translation["post"] := "{\\ttb{}post}"
+translation["pre"] := "{\\ttb{}pre}"
+translation["procedure"] := "{\\ttb{}procedure}"
+translation["process"] := "{\\ttb{}process}"
+translation["put"] := "{\\ttb{}put}"
+translation["quit"] := "{\\ttb{}quit}"
+translation["read"] := "{\\ttb{}read}"
+translation["real"] := "{\\ttb{}real}"
+translation["real4"] := "{\\ttb{}real4}"
+translation["real8"] := "{\\ttb{}real8}"
+translation["record"] := "{\\ttb{}record}"
+translation["register"] := "{\\ttb{}register}"
+translation["result"] := "{\\ttb{}result}"
+translation["return"] := "{\\ttb{}return}"
+translation["seek"] := "{\\ttb{}seek}"
+translation["set"] := "{\\ttb{}set}"
+#translation["shl"] := "\\(\\triangleleft\\)"
+translation["shl"] := "{\\ttb{}shl}"
+#translation["shr"] := "\\(\\triangleright\\)"
+translation["shr"] := "{\\ttb{}shr}"
+translation["signal"] := "{\\ttb{}signal}"
+translation["skip"] := "{\\ttb{}skip}"
+translation["string"] := "{\\ttb{}string}"
+translation["tag"] := "{\\ttb{}tag}"
+translation["tell"] := "{\\ttb{}tell}"
+translation["then"] := "{\\ttb{}then}"
+translation["to"] := "{\\ttb{}to}"
+translation["true"] := "{\\ttb{}true}"
+translation["type"] := "{\\ttb{}type}"
+translation["unchecked"] := "{\\ttb{}unchecked}"
+translation["union"] := "{\\ttb{}union}"
+translation["unit"] := "{\\ttb{}unit}"
+translation["unqualified"] := "{\\ttb{}unqualified}"
+translation["var"] := "{\\ttb{}var}"
+translation["wait"] := "{\\ttb{}wait}"
+translation["when"] := "{\\ttb{}when}"
+translation["write"] := "{\\ttb{}write}"
+translation["xor"] := "\\(\\oplus\\)"
+
+# Translations for operators.
+translation["<"] := "\\(<\\)"
+translation[">"] := "\\(>\\)"
+translation["<="] := "\\(\\le\\)"
+translation[">="] := "\\(\\ge\\)"
+translation["=>"] := "\\(\\Rightarrow\\)"
+translation["**"] := "\\^{}"
+translation["~="] := "\\(\\neq\\)"
+translation["->"] := "\\(\\triangleright\\)"
+
+
+# Pre-processor directives
+translation["#else"] := "{#\\ttb{}else}"
+translation["#elsif"] := "{#\\ttb{}elsif}"
+translation["#end"] := "{#\\ttb{}end}"
+translation["#if"] := "{#\\ttb{}if}"
+translation["#macro"] := "{#\\ttb{}macro}"
+
+
+# Turing Plus
+#translation["child"] := "{\\ttb{}child}"
+#translation["stub"] := "{\\ttb{}stub}"
+
diff --git a/web/noweb/contrib/kostas/ootdefs.nw b/web/noweb/contrib/kostas/ootdefs.nw
new file mode 100644
index 0000000000..dcbf8aedea
--- /dev/null
+++ b/web/noweb/contrib/kostas/ootdefs.nw
@@ -0,0 +1,198 @@
+% -*-lang : icon-*-
+
+\documentclass [11pt] {article}
+\usepackage {noweb}
+\usepackage {fullpage}
+\pagestyle {noweb}
+
+\title {Automatic \texttt{noweb} Indexing for OOT Identifiers}
+\author{Kostas N. Oikonomou \\ \textsf{ko@surya.ho.att.com}}
+
+\begin {document}
+\maketitle
+
+@ This code builds a [[noweb]] filter which produces automatic index entries for OOT
+identifiers. It is used with the generic file [[icon/defns.nw]]. (The Makefile takes
+care of this.)\\
+\textsc{Note}: There are some good examples here of how someone used to programming
+in Turing can screw up in Icon. They have to do with assignment (Icon may succeed or
+fail), and with booleans.
+<<*>>=
+<<Finding OOT definitions>>
+<<Other routines needed by [[defns.nw]]>>
+@
+
+
+@
+\section {Finding OOT definitions}
+
+[[begin_decl]] is a set of reserved words that signal the beginning of a declaration.
+Ideally, after encountering a token in [[begin_decl]], we would find the identifier
+and write an index entry. However, some declarations are tricky:
+\begin {enumerate}
+ \item {\ttb{}deferred procedure} P
+ \item {\ttb{}const pervasive} k := 3
+ \item {\ttb{}external} \texttt{"}f\texttt{"} {\ttb{}function} F
+ \item {\ttb{}var} x, y, z : {\ttb{}real}
+ \item {\ttb{}import} a, b, {\ttb{}var} u \% No declarations here!
+ \item We normally don't index identifiers declared inside procedures or functions.
+ This can be changed, if desired, by making [[ie_list]] empty. However, it is
+ also possible to invoke the filter with an argument \texttt{\itshape filename},
+ where \texttt{\itshape filename\/} contains subprogram names one per line. Then
+ the local declarations in these subprograms {\em will\/} be indexed\footnote {For
+ this to work, invoke [[noweave]] as \texttt{noweave -autodefs "oot {\itshape
+ filename\/}" -filter oot.filter -index}}.
+\end {enumerate}
+Handling these cases makes life a bit more difficult. We do it by setting up various
+categories of tokens (Icon lists).
+@
+
+
+<<Set up token categories>>=
+id_chars := &letters ++ &digits ++ '_'
+begin_decl := ["class", "const", "function", "module", "monitor", "procedure",
+ "process", "type", "var"]
+qualifier1 := ["deferred", "external", "forward"] # Cases 1, 3
+qualifier2 := ["pervasive"] # Case 2
+ie_list := ["import", "export"]
+begin_subprogram := ["procedure", "function"]
+@
+
+@
+
+
+@
+<<Finding OOT definitions>>=
+procedure postpass(name, arg)
+ static kind, id_chars, begin_decl, qualifier1, qualifier2, ie_list,
+ begin_subprogram, in_ie_list, in_subprogram, sub_name
+ local token
+ initial {
+ <<Set up token categories>>
+ <<Initialize static variables>>
+ }
+ if name == "begin" then
+ arg ? kind := tab(upto(' ')|0)
+ else
+ if name == "text" & kind == "code" then
+ arg ? {<<Go for the identifiers>>}
+ return
+end
+@
+
+@
+<<Initialize static variables>>=
+kind := "bogus"
+in_ie_list := &null
+in_subprogram := &null
+@
+
+@
+<<Go for the identifiers>>=
+tab(many(' '))
+token := tab(many(id_chars)) # May be null.
+if /in_ie_list & /in_subprogram then # ``/'' is Turings' \textbf{not}.
+ case token of {
+ !ie_list : in_ie_list := "true"
+ !qualifier1 : {
+ <<If \textbf{external}, skip the quoted string>>
+ <<Find the identifiers and write index entries>>}
+ !begin_subprogram : <<Index [[sub_name]] and remember it>>
+ !begin_decl : {
+ tab(match(!qualifier2)); tab(many(' ')) # Case 2
+ <<Find the identifiers and write index entries>>}
+ }
+else {
+ <<Check for end of \textbf{import/export} list>>
+ <<Check for end of subprogram>>}
+@
+
+
+@ This is case 3. A quoted string may or may not be there!
+<<If \textbf{external}, skip the quoted string>>=
+if token == "external" then {
+ tab(many(' '))
+ # Icon note: the next expression fails if one of the sub-expressions fails.
+ tab(match('"')) & tab(many(id_chars)) & tab(match('"'))
+ tab(many(' '))
+}
+@
+
+@ This is case 6. [[sub_name]] is the subprogram's identifier.
+<<Index [[sub_name]] and remember it>>=
+{tab(many(' '))
+ sub_name := tab(many(id_chars))
+ writedefn(sub_name) # Defined in \texttt{defns.nw}
+ # \texttt{sub\_name ~== !subs\_to\_index} doesn't work. Why does it work in \texttt{case}?
+ if not member(set(subs_to_index), sub_name) then in_subprogram:= "true"}
+@
+
+@ This is case 4.
+Multiple identifiers can occur only in \textbf{var} or \textbf{const} declarations.
+<<Find the identifiers and write index entries>>=
+repeat {
+ writedefn(tab(many(id_chars))) # Defined in \texttt{defns.nw}
+ tab(many(' '))
+ if not tab(match(",")) then break
+ tab(many(' '))
+}
+@
+
+
+@ We assume that every line of a multi-line \textbf{import/export} lists ends with a
+comma, unless it is the last line. So if [[in_ie_list]] is set, we check the last
+non-blank character of the line. If it is not a ``,'' we set [[in_ie_list]] to null.
+Clearly, the Turing compiler will accept multi-line lists even though their lines do
+not end with a comma, so this method of detecting the end of the list is not
+foolproof. It is, however, simple.
+<<Check for end of \textbf{import/export} list>>=
+# This is not Turing! \texttt{in\_list := trim(arg)[-1] == ","} is wrong!
+if \in_ie_list then
+ if arg == "" | trim(arg)[-1] ~== "," then in_ie_list := &null
+@
+
+@
+<<Check for end of subprogram>>=
+if \in_subprogram then
+ if \token == "end" then
+ {tab(many(' ')); if tab(match(sub_name)) then in_subprogram := &null}
+@
+
+
+
+@
+\section {Procedures [[main]] and [[prepass]]}
+
+This is copied (modified) from [[icon/icondefs.nw]].
+<<Other routines needed by [[defns.nw]]>>=
+global subs_to_index
+procedure main(args)
+ local name, f
+ <<Initialize [[subs_to_index]]>>
+ go()
+end
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # Force newline.
+end
+@
+
+@
+<<Initialize [[subs_to_index]]>>=
+subs_to_index := []
+f := open(args[1], "r")
+if \f then {
+ every put(subs_to_index, !f) # Neat! See p. 132 of the Icon book.
+ writes(&errout, "(Indexing subprograms")
+ every writes(&errout, " ", !subs_to_index)
+ write(&errout, ")")
+ close(f)
+}
+@
+
+
+
+%@
+%\section {Index}
+%\nowebindex
+
+\end {document} \ No newline at end of file
diff --git a/web/noweb/contrib/kostas/pp.nw b/web/noweb/contrib/kostas/pp.nw
new file mode 100644
index 0000000000..05e6c18254
--- /dev/null
+++ b/web/noweb/contrib/kostas/pp.nw
@@ -0,0 +1,541 @@
+% -*-lang : icon-*-
+
+\documentclass [11pt] {article}
+\usepackage {noweb}
+\usepackage {fullpage}
+\pagestyle {noweb}
+
+\title {Extending Noweb With Some Typesetting}
+\author{Kostas N. Oikonomou \\ \textsf{ko@surya.ho.att.com}}
+
+\begin {document}
+\maketitle
+\tableofcontents
+
+@
+\section {Introduction}
+
+This is a pretty-printer, written in Icon, for the [[noweb]] system. The capabilities
+of the prettyprinter are to typeset reserved words, comments, quoted strings, and
+special (e.g.\ mathematical) symbols of the target language in an almost arbitrary
+way\footnote{It is also possible to typeset identifiers arbitrarily.}. This
+generality is achieved by the brute-force method of looking up the translation of
+(\TeX\ code for) a token in a table. See \S\ref{sec:lang} for the languages that can
+be handled. Adding a new language entails making additions \emph{only} to
+\S\ref{sec:lang}. All the material in \S\ref{sec:ind} is language-independent, and
+should not be touched.
+
+The pretty-printer's design is based on the following two premises:
+\begin {itemize}
+ \item It should be as independent of the target language as possible, and
+ \item We don't want to write a full-blown scanner for the target language.
+\end {itemize}
+Strings of characters of the target language which we want to typeset specially are
+called ``interesting tokens''. Having had some experience with Web and SpiderWeb, we
+define three categories of interesting tokens:
+\begin {enumerate}
+ \item Reserved words of the target language: we want to typeset them in bold, say.
+ \item Other strings that we want to typeset specially: e.g. $\le$ for [[<=]].
+ \item Comment and quoting tokens (characters): we want what follows them or what is
+ enclosed by them to be typeset literally.
+\end {enumerate}
+In addition, comments are typeset in roman font, and math mode is active in comments.
+
+A table [[translation]] defines a translation into \TeX\ code for every interesting
+token in the target language. Here is an excerpt from the translation table for
+Object-Oriented Turing:
+\begin {center}
+ \begin {tabular}{l}
+ [[translation["addressint"] := "{\\ttb{}addressint}"]] \\
+ [[translation["all"] := "{\\ttb{}all}"]] \\
+ [[translation["and"] := "\\(\\land\\)"]] \\
+ [[translation["anyclass"] := "{\\ttb{}anyclass}"]] \\
+ [[translation["array"] := "{\\ttb{}array}"]] \\
+ [[translation["~="] := "\\(\\neq\\)"]]
+ \end {tabular}
+\end {center}
+(Here the control sequence \verb+\ttb+ selects the bold typewriter font
+cmttb10\footnote{The empty group \{\} serves to separate the control sequence from
+its argument without introducing an extra space.}.) We use four sets of strings to
+define the tokens in categories 2 and 3:
+\begin {center}
+ [[special]], [[comment1]], [[comment2]], [[quote2]].
+\end {center}
+[[comment1]] is for unbalanced comment strings (e.g.\ the character [[%]] in Turing
+and [[#]] in Icon), [[comment2]] is for balanced comment strings (e.g.\ [[/*]] and
+[[*/]]), and [[quote2]] is for literal quotes, such as [["]], which we assume to be
+balanced.
+
+Our approach to recognizing the interesting tokens while scanning a line, is to have
+a set of characters [[interesting]] (an Icon cset), containing all the characters by
+which an interesting token may begin. [[interesting]] is the union of
+\begin {itemize}
+ \item the cset defining the characters which may begin a reserved word, and
+ \item the cset containing the initial characters of all strings in the special,
+ comment, and quote sets.
+\end {itemize}
+The basic idea is this: given a line of text, we scan up to a character in
+[[interesting]], and, depending on what this character is, we may try to complete the
+token by further scanning. If we succeed, we look up the token in the
+[[translation]] table, and if the token is found, we output its translation,
+otherwise we output the token itself unchanged. When comment or quote tokens are
+recognized, further processing of the line may stop altogether, or temporarily, until
+a matching token is found.
+
+
+\section {Languages}
+\label{sec:lang}
+The languages handled at the moment are C, C++, Icon, Object-Oriented Turing (OOT),
+and Mathematica. Looking at the structure that follows should make it clear that
+adding another language should be easy. Only this section has to be touched.
+<<C>>=
+<<[[main]] for C>>
+<<Language-independent procedures>>
+@
+<<C++>>=
+<<[[main]] for C++>>
+<<Language-independent procedures>>
+@
+<<OOT>>=
+<<[[main]] for OOT>>
+<<Language-independent procedures>>
+@
+<<Icon>>=
+<<[[main]] for Icon>>
+<<Language-independent procedures>>
+@
+<<Mathematica>>=
+<<[[main]] for Mathematica>>
+<<Language-independent procedures>>
+@
+
+
+@
+\subsection {Main Procedures}
+
+<<[[main]] for C>>=
+procedure main(args)
+ <<Local variables>>
+ $include "C_translation_table"
+ <<C interesting tokens>>
+ <<Emit special {\TeX} definitions>>
+ while line := read() do filter(line)
+end
+@
+@
+<<[[main]] for C++>>=
+procedure main(args)
+ <<Local variables>>
+ $include "C++_translation_table"
+ <<C interesting tokens>>
+ <<Emit special {\TeX} definitions>>
+ while line := read() do filter(line)
+end
+@
+@
+<<[[main]] for OOT>>=
+procedure main(args)
+ <<Local variables>>
+ $include "oot_translation_table"
+ <<OOT interesting tokens>>
+ <<Emit special {\TeX} definitions>>
+ while line := read() do filter(line)
+end
+@
+@
+<<[[main]] for Icon>>=
+procedure main(args)
+ <<Local variables>>
+ $include "icon_translation_table"
+ <<Icon interesting tokens>>
+ <<Emit special {\TeX} definitions>>
+ while line := read() do filter(line)
+end
+@
+@
+<<[[main]] for Mathematica>>=
+procedure main(args)
+ <<Local variables>>
+ $include "math_translation_table"
+ <<Mathematica interesting tokens>>
+ <<Emit special {\TeX} definitions>>
+ while line := read() do filter(line)
+end
+@
+
+
+@
+\subsection {Definition of the Interesting Tokens}
+\label{sec:int}
+
+\textsc{Note}: all of the lists [[special]] must be arranged so that longest tokens
+come first!
+<<OOT interesting tokens>>=
+res_word_chars := &letters ++ '#'
+id_chars := res_word_chars ++ &digits ++ '_'
+comment1 := ["%"] # Unbalanced comment
+comment2 := [["/*", "*/"]] # Balanced comment. This is a set of \emph{pairs}.
+quote2 := [["\"","\""]] # Balanced quote
+# The special tokens must be sorted so that longest strings come first!
+special := ["~=", "**", ">=", "<=", "=>", "->", ">", "<"]
+<<Detecting the beginning of a token>>
+@
+@ Icon presents an interesting problem, unresolved at this time. See \S\ref{sec:todo}.
+<<Icon interesting tokens>>=
+res_word_chars := &letters ++ '&$'
+id_chars := res_word_chars ++ &digits ++ '_'
+comment1 := ["#"]
+comment2 := [[]]
+quote2 := [["\"","\""], ["\'","\'"]]
+special := ["\\", "||", ">=", "<=", "=>", "~=", "++", "**", "--", "{", "}", "<", ">"]
+<<Detecting the beginning of a token>>
+@
+<<Mathematica interesting tokens>>=
+res_word_chars := &letters ++ '&$'
+id_chars := res_word_chars ++ &digits
+comment1 := []
+comment2 := [["(*", "*)"]]
+quote2 := [["\"", "\""]]
+special := ["!=", "==", ">=", "<=", "->", "||", "&&", "<>", "**", "{", "}", "<", ">"]
+<<Detecting the beginning of a token>>
+@
+<<C interesting tokens>>=
+res_word_chars := &letters ++ '#'
+id_chars := res_word_chars ++ &digits ++ '_'
+comment1 := []
+comment2 := [["/*", "*/"]]
+quote2 := [["\"","\""],["\'","\'"]]
+special := ["!=", ">=", "<=", "@<<", "@>>", "||", "&&", "->", "{", "}", "<", ">"]
+<<Detecting the beginning of a token>>
+@
+
+
+
+@
+\section {Language-Independent Pretty-Printing}
+\label{sec:ind}
+<<Language-independent procedures>>=
+<<Global variables>>
+<<Procedure [[filter]]>>
+<<Procedure [[TeXify]]>>
+@
+
+@
+\subsection {Detecting the Beginning of a Token}
+
+For each interesting category define a cset containing the characters by which a
+token in that category may begin.
+<<Detecting the beginning of a token>>=
+begin_comment1 := begin_comment2 := begin_quote2 := begin_special := ''
+every e := !comment1 do begin_comment1 ++:= cset(e[1])
+every e := !comment2 do begin_comment2 ++:= cset(e[1][1])
+every e := !quote2 do begin_quote2 ++:= cset(e[1])
+every e := !special do begin_special ++:= cset(e[1])
+<<Check that these sets are disjoint>>
+interesting := res_word_chars ++ begin_comment1 ++ begin_comment2 ++
+ begin_quote2 ++ begin_special
+@
+@ The token recognition method used in procedure [[TeXify]] is based on the
+assumption that the above sets are mutually disjoint, and that they also do not
+intersect the set [[id_chars]]. If this assumption does not hold, the results are
+unpredictable.
+<<Check that these sets are disjoint>>=
+I := begin_comment1 ** begin_comment2 ** begin_quote2 ** begin_special ** id_chars
+if *I ~= 0 then stop ("** Pretty-printer problem: the characters in the set ",
+ image(I), "\n may begin tokens in more than one category!")
+@
+
+@ Local and global variables for the [[main]]'s.
+\enlargethispage*{1cm}
+<<Local variables>>=
+local line, special_set
+<<Global variables>>=
+global translation, res_word_chars, id_chars, special, comment1, comment2, quote2
+global interesting, begin_special, begin_comment1, begin_comment2, begin_quote2
+@
+
+
+@
+\subsection {The procedure TeXify}
+
+This procedure formats [[@text]] lines in the [[noweb]] file. It is called by
+procedure [[filter]]. Note that every \TeX{}ified line is a ``literal'' in
+[[noweb]]'s sense.
+<<Procedure [[TeXify]]>>=
+procedure TeXify(line, p0)
+ <<Local variables for [[TeXify]]>>
+ writes("@literal ")
+ line ?
+ {if \in_comment1 then
+ <<Write unbalanced comment text>>
+ else if \in_comment2 then
+ <<Write balanced comment text>>
+ else if \in_quote then
+ <<Write quoted text>>
+ else
+ <<Not inside a comment or quote>>
+ # Write the remainder of the line, if any.
+ writes(tab(0))
+ }
+ write()
+end
+@
+@
+<<Not inside a comment or quote>>=
+while writes(tab(upto(interesting))) do
+ case &pos+1 of {
+ # To understand the \texttt{&pos+1}, look at Icon's semantics of \texttt{case} and of \texttt{any}.
+ any(id_chars) : <<Identifier or reserved word>>
+ any(begin_special) : <<Possible ``special'' token>>
+ any(begin_comment1) : <<Possible unbalanced comment>>
+ any(begin_comment2) : <<Possible balanced comment>>
+ any(begin_quote2) : <<Possible quote>>
+ default : <<Internal error!>>
+ }
+@
+@ Well, if we got here there's something wrong in the scanning algorithm. [[p0]] is
+the position in the line of the source file where the argument [[line]] of [[TeXify]]
+begins.
+<<Internal error!>>=
+stop("\n** Error in pretty-printer procedure TeXify:\n input line ", line_num,
+ ", column ", p0+&pos-2)
+# Note: this is the column in the Emacs sense, i.e.\ the first character is in column 0.
+@
+
+
+@
+\subsubsection {Handling the interesting tokens}
+
+All identifiers will be matched (and some non-identifiers, such as explicit numeric
+constants), but the [[translation]] table defines \TeX\ code for reserved words
+only. Matching this larger set allows one to include translations for some
+identifiers too.
+
+As an exercise in understanding Icon's semantics, spend some time figuring out why
+saying {\ttfamily writes(if t := translation[token] then t else token)} will
+\emph{not} work here\footnote{Hint: consider the case in which no translation is
+defined for the token.}.
+<<Identifier or reserved word>>=
+{token := tab(many(id_chars))
+ t := translation[token]
+ writes(if \t then t else token)}
+@
+
+@ There are two issues here. Suppose our set [[special]] contains both [[=]] and
+[[==]], and it does not contain [[=-]]. What happens when we encounter [[=]]?
+First, we have to be sure that this is not the string [[==]]. So (a) we must match
+the {\em longest\/} token in [[special]], in case a special token is a prefix of
+another special token. Second, we must check that we do not have the string [[=-]],
+since this is not a special token. So (b) we must check that a token in [[special]]
+is followed by a proper terminating character.
+
+To ensure (a), [[match(!special)]] will match the longest token if the list
+[[special]] is arranged so that longest tokens come first, as noted in
+\S\ref{sec:int}. To ensure (b) define the cset [[not_special]]:
+<<Global variables>>=
+global not_special
+<<Detecting the beginning of a token>>=
+special_set := ''
+every e := !special do special_set ++:= cset(e)
+not_special := ~special_set
+@
+
+@ We will {\em assume\/} that if a token in [[special]] is followed by a character in
+[[not_special]] (or the end of the line), then it is a legitimate special token. So
+<<Possible ``special'' token>>=
+if (token := tab(match(!special)) & (any(not_special) | pos(0))) then
+ writes(translation[token])
+else
+ writes(move(1))
+@
+
+
+@
+\subsubsection {Comments and quotes}
+
+Procedures [[filter]] and [[TeXify]] interact via the variables [[in_comment]] and
+[[in_quote]] in handling comments and quotes. This is because the [[finduses]] and
+[[noidx]] filters are language-independent, and so can insert spurious [[@index]] and
+[[@xref]] lines in the middle of commented or quoted text of the target language.
+While this is merely an annoyance with balanced quotes and comments, it causes a real
+problem with unbalanced comments, in that [[TeXify]] cannot detect the end of an
+\emph{unbalanced} comment. This must be done by [[filter]], when it encounters a
+[[@nl]] line. See \S\ref{sec:filter} for some more details.
+<<Global variables>>=
+global in_comment1, in_comment2, in_quote
+@
+
+
+@ If we match a token in [[comment1]], we output it and the rest of the line as is,
+but in [[\rm]] font. Within a comment, characters special to \TeX\ are active,
+e.g. \verb+$x^2$+ will produce $x^2$. A problem with this is that if you comment out
+the (C) line \verb+printf("Hi there!\n")+, \TeX\ will complain that [[\n]] is an
+undefined control sequence.
+<<Possible unbalanced comment>>=
+if writes(tab(match(!comment1))) then
+ {in_comment1 := "yes"
+ writes("\\begcom{}" || tab(0))
+ break} # We let \texttt{filter} detect the end of the comment.
+else
+ writes(move(1)) # The character wasn't the beginning of a comment token.
+@
+
+
+@ If we are at this point, it is not necessarily true that we have found a comment.
+For example, in \textsl{Mathematica} comments begin with a [[(]], which may also
+appear in [[x+(y+z)]]. The additional complexity comes from the fact the we have to
+handle comments extending over many lines.
+<<Possible balanced comment>>=
+{every c := !comment2 do
+ # The conjunction is needed here!
+ {writes(c_open := tab(match(c[1]))) & c_close := c[2] & break}
+ if \c_open then
+ {in_comment2 := "yes"
+ writes("\\begcom{}")
+ <<Write balanced comment text>>}
+ else
+ writes(move(1)) # The character wasn't the beginning of a comment after all.
+}
+@
+@ Quoted strings may extend over multiple lines. Except for the formatting, we handle
+them like balanced comments.
+<<Possible quote>>=
+{every q := !quote2 do
+ {writes(q_open := tab(match(q[1]))) & q_close := q[2] & break}
+ if \q_open then
+ {in_quote := "yes"
+ <<Write quoted text>>}
+ else
+ writes(move(1)) # The character wasn't the beginning of a quoting token.
+}
+@
+@
+<<Write unbalanced comment text>>=
+writes(tab(0))
+@
+@
+<<Write balanced comment text>>=
+{if writes(tab(find(c_close))) then # Comment ends here
+ {writes("\\endcom{}" || move(*c_close))
+ in_comment2 := &null}
+ else # Comment doesn't close on this line
+ writes(tab(0))
+}
+@
+@ After encountering a quote we write literally, except that we precede every
+character special to \TeX\ by a backslash and follow it by an empty group. (This is
+necessary for the characters ``\~{}'' and ``\^{}''.)
+<<Write quoted text>>=
+{q := tab(find(q_close)|0) # $q$ doesn't include the closing quote.
+ q ? {while writes(tab(upto(TeXspecial))) do writes("\\" || move(1) || "{}")
+ writes(tab(0))}
+ if writes(tab(match(q_close))) then # Quote ends on this line
+ in_quote := &null
+}
+@
+@
+<<Local variables for [[TeXify]]>>=
+local token, c, t, q, c_open
+static c_close, q_close, TeXspecial
+initial {TeXspecial := '\\${}&#^_%~'} # The cset of characters treated specially by \TeX.
+@
+
+
+
+@
+\subsection {Filtering the Input}
+\label{sec:filter}
+
+First we set up the typewriter bold font [[\ttb]], corresponding to cmttb10. Then we
+define the macros [[\begcom]] (begin comment) and [[\endcom]]. [[\begcom]]
+\begin {itemize}
+ \item switches to [[\rmfamily]],
+ \item activates [[$]] by changing its catcode to 3,
+ \item makes the characters ``\texttt{\^{}}'' and ``[[_]]'' active for superscripts
+ and subscripts,
+ \item changes the catcode of the space character to 10. This way comments will be
+ typeset normally, and not as if [[\obeyspaces]] were active.
+\end {itemize}
+<<Emit special {\TeX} definitions>>=
+write("@literal \\DeclareFontShape{OT1}{cmtt}{bx}{n}{ <-> cmttb10 }{}")
+write("@nl")
+write("@literal \\def\\ttb{\\bfseries}")
+write("@nl")
+write("@literal \\def\\begcom{\\begingroup\\rmfamily \\catcode`\\$=3_
+ \\catcode`\\^=7 \\catcode`\\_=8 \\catcode`\\ =10}")
+write("@nl")
+write("@literal \\def\\endcom{\\endgroup}")
+write("@nl")
+@
+
+
+@ Procedure [[filter]] is straightforward, except that it interacts with [[TeXify]]
+when it comes to comments and quotes. [[line_num]] is used by both.
+<<Global variables>>=
+global line_num
+<<Emit special {\TeX} definitions>>=
+line_num := 0
+<<Procedure [[filter]]>>=
+procedure filter(line)
+ static kind # Local and static.
+ local keyword, rest, p0
+ line_num := line_num + 1 # line no. in the input file; used by \texttt{TeXify}.
+ line ? (keyword := tab(upto(' ')|0) &
+ rest := if tab(match(" ")) then {p0 := &pos; tab(0)} else &null)
+ case keyword of {
+ "@begin" : {rest ? kind := tab(many(&letters))
+ write(line)}
+ "@text" : if \kind == "code" then TeXify(rest,p0) else write(line)
+ "@nl" : {if \in_comment1 then # This must be an unbalanced comment.
+ {write("@literal \\endcom{}"); in_comment1 := &null}
+ write(line)}
+ "@index" | "@xref" : <<Not if in comment or quote!>>
+ default : write(line)
+ }
+ return
+end
+@
+
+@ Don't output spurious [[@index]] or [[@xref]] lines when in a comment or quote.
+([[@index]] is produced by [[finduses]] and [[@xref]] by [[noidx]].)
+This works only if the language filter is run {\em before\/} [[noidx]].
+<<Not if in comment or quote!>>=
+if /in_comment1 & /in_comment2 & /in_quote then write(line)
+@
+
+
+
+@
+\section {To do}
+\label{sec:todo}
+
+We have the following unresolved issue, exemplified by Icon. The current filter
+translates the symbol ``\&''as ``$\land$'', even though ``\&'' is {\em not\/} in
+Icon's [[special]]. This happens because ``\&'' is in Icon's [[res_word_chars]], and
+a translation for it is defined in [[icon_translation_table]]. So when [[TeXify]]
+encounters it, it recognizes it as an Icon reserved word, and uses the translation
+defined for it. Now if this translation is not wanted, remove ``\&'' from
+[[icon_translation_table]] and don't bother me any more. However, if this
+translation is ok, we have an inconsistency, in that ``\&'' is not in [[special]].
+
+While this is not a real problem, achieving consistency (which may be needed in a
+more general case) is not so easy. If we add ``\&'' to [[special]], the check in
+$\langle$\textit{Check that these sets are disjoint\/}$\rangle$ will fail. To fix
+this, we could
+\begin {enumerate}
+ \item Add a constraint to the recognition of a reserved word: it has to be
+ a token of length $>1$.
+ \item Revise the [[case]] structure in $\langle$\textit{Not inside a comment or
+ quote\/}$\rangle$, as it will no longer work.
+\end {enumerate}
+We could also consider having a separate translation table for special tokens.
+@
+
+
+@
+\appendix
+\section {Index}
+\nowebindex
+
+
+\end {document} \ No newline at end of file
diff --git a/web/noweb/contrib/leew/Makefile b/web/noweb/contrib/leew/Makefile
new file mode 100644
index 0000000000..975bf88864
--- /dev/null
+++ b/web/noweb/contrib/leew/Makefile
@@ -0,0 +1,6 @@
+SHELL=/bin/sh
+all:
+install:
+source:
+clean:
+ /bin/rm -f nocond *.dvi *.log *.aux *.toc *.tex *.tex nocond.1
diff --git a/web/noweb/contrib/leew/README b/web/noweb/contrib/leew/README
new file mode 100644
index 0000000000..337fb068c9
--- /dev/null
+++ b/web/noweb/contrib/leew/README
@@ -0,0 +1,12 @@
+Lee Wittenberg has kindly provided his port of noweb to DOS, which
+includes executable binaries. It once appeared in the DOS
+subdirectory of the standard noweb distribution, but it got superseded
+by somebody else's port later on.
+
+nocond is a slick noweb filter that supports conditional code in a
+nicer way than ugly old #ifdef's.
+
+nobrace looks for unbalanced braces in code chunks.
+
+pretty-comment uses LaTeX to typeset inline comments...
+and it's written in SNOBOL!
diff --git a/web/noweb/contrib/leew/custom-code/README.custom-code b/web/noweb/contrib/leew/custom-code/README.custom-code
new file mode 100644
index 0000000000..06367f1ceb
--- /dev/null
+++ b/web/noweb/contrib/leew/custom-code/README.custom-code
@@ -0,0 +1,17 @@
+The "custom-code" script is a simple noweb filter that allows for some
+very simple typesetting of code chunks. It simply inserts a
+
+ \bgroup\nwcustomcode ... \egroup
+
+wrapper around everything in code chunks and quoted code. The user
+simply defines the \nwcustomcode macro to typeset the code
+appropriately. This is primarily useful for programming languages like
+Neliac (and, perhaps, APL), which use specialized character sets (and
+don't look quite right when rendered in ``standard'' ASCII characters.
+
+The "example.nw" file demonstrates "custom-code" in action. Simply
+
+ noweave -t4 -delay -index example.nw -filter custom-code >example.tex
+
+and run the result through LaTeX for a sample of the same code both
+with and without the custom typesetting.
diff --git a/web/noweb/contrib/leew/custom-code/custom-code b/web/noweb/contrib/leew/custom-code/custom-code
new file mode 100755
index 0000000000..4d9ce45104
--- /dev/null
+++ b/web/noweb/contrib/leew/custom-code/custom-code
@@ -0,0 +1,12 @@
+#!/bin/awk -f
+BEGIN { needcontrol = 0; }
+/^@begin code / { needcontrol = 1 }
+/^@quote$/ { needcontrol = 1 }
+/^@text / { if (needcontrol) {
+ print "@literal \\bgroup\\nwcustomcode{}"
+ }
+ needcontrol = 0
+ }
+/^@end code / { print "@literal \\egroup{}" }
+/^@endquote$/ { print "@literal \\egroup{}" }
+ { print }
diff --git a/web/noweb/contrib/leew/custom-code/example.nw b/web/noweb/contrib/leew/custom-code/example.nw
new file mode 100644
index 0000000000..c6a0b252f5
--- /dev/null
+++ b/web/noweb/contrib/leew/custom-code/example.nw
@@ -0,0 +1,101 @@
+% to weave:
+% noweave -t4 -delay -index example.nw -filter custom-code >example.tex
+%
+\documentclass{article}
+\usepackage{noweb}
+\noweboptions{smallcode}
+\topmargin=0pt
+\textheight=9in
+\def\sub#1{$_{#1}$}
+\def\minus{-}
+\def\plus{+}
+\def\equals{=}
+\def\lt{<}
+\def\gt{>}
+\def\neliac{%
+ \catcode`_=\active%
+ \catcode`|=\active%
+ \catcode`&=\active%
+ \catcode`*=\active%
+ \catcode`'=\active%
+ \catcode`^=\active%
+ \catcode`-=\active%
+ \catcode`+=\active%
+ \catcode`==\active%
+ \catcode`<=\active%
+ \catcode`>=\active%
+ \catcode`/=\active%
+}
+\bgroup\neliac
+\global\def\nwcustomcode{\neliac%
+ \global\def_##1{\sub{##1}}%
+ \global\def|{$\cup$}%
+ \global\def&{$\cap$}%
+ \global\def*{$\times$}%
+ \global\def'{$\vert$}%
+ \global\def^{$\uparrow$}%
+ \global\def+{$\plus$}%
+ \global\def={$\equals$}%
+ \global\def/##1{\(\ifx##1=\ne\else\slash##1\fi\)}%
+ \global\def<##1{\(\ifx##1=\le\else\lt##1\fi\)}%
+ \global\def>##1{\(\ifx##1=\ge\else\gt##1\fi\)}%
+ \global\def-##1{\(\ifx##1>\to\else\minus##1\fi\)}%
+}
+\egroup
+
+\begin{document}
+Here is some actual code from the original Neliac compiler for the
+Univac M-460 ``Countess'' computer (written in Neliac, of course):
+<<*>>=
+DEBUG SCAN:
+i = 0: standard compiling location -> i; ;
+j = 0: obj prog std last address -> j; ;
+i = i(1)j{ [i] = straight jump function | [i] = return jump function:
+ fault 9. ; [i](15 -> 29) = 61000_8 & [i](0 -> 14) - bias -> k /= 0:
+ { [k] = 0 | [k] = straight jump function: fault 10. ; }; ;
+l'oop exit: }. check key sets, turn off flex, clear indices,
+key[2] /= 0: dump name lists and stop. exit.
+F'AULT 9:
+start flex, carriage return upper case, 69 -> lower loop limit,
+72 -> upper loop limit, dump a title,
+n = 177_8(1)0{ undefined name location[n] = i:
+ write undefined name, continue. ; },
+C'ONTINUE: write address, loop exit.
+F'AULT 10:
+start flex, carriage return upper case,
+77 -> lower loop limit, 82 -> upper loop limit, dump a title,
+n = 777_8(1)0{ name address[n] - bias = k: write name, go on. ; },
+k -> upper dump buffer[1], dump five number,
+G'O ON: write address, loop exit.
+W'RITE ADDRESS:
+{ 73 -> lower loop limit, 76 -> upper loop limit, dump a title,
+i -> upper dump buffer[1], dump five numbers, }. e'xit: . .
+@
+And here is the very same code without the \verb"custom-code"
+typesetting:\let\nwcustomcode=\relax
+<<*>>=
+DEBUG SCAN:
+i = 0: standard compiling location -> i; ;
+j = 0: obj prog std last address -> j; ;
+i = i(1)j{ [i] = straight jump function | [i] = return jump function:
+ fault 9. ; [i](15 -> 29) = 61000_8 & [i](0 -> 14) - bias -> k /= 0:
+ { [k] = 0 | [k] = straight jump function: fault 10. ; }; ;
+l'oop exit: }. check key sets, turn off flex, clear indices,
+key[2] /= 0: dump name lists and stop. exit.
+F'AULT 9:
+start flex, carriage return upper case, 69 -> lower loop limit,
+72 -> upper loop limit, dump a title,
+n = 177_8(1)0{ undefined name location[n] = i:
+ write undefined name, continue. ; },
+C'ONTINUE: write address, loop exit.
+F'AULT 10:
+start flex, carriage return upper case,
+77 -> lower loop limit, 82 -> upper loop limit, dump a title,
+n = 777_8(1)0{ name address[n] - bias = k: write name, go on. ; },
+k -> upper dump buffer[1], dump five number,
+G'O ON: write address, loop exit.
+W'RITE ADDRESS:
+{ 73 -> lower loop limit, 76 -> upper loop limit, dump a title,
+i -> upper dump buffer[1], dump five numbers, }. e'xit: . .
+@ \relax
+\end{document}
diff --git a/web/noweb/contrib/leew/custom-code/example.pdf b/web/noweb/contrib/leew/custom-code/example.pdf
new file mode 100644
index 0000000000..51145950df
--- /dev/null
+++ b/web/noweb/contrib/leew/custom-code/example.pdf
Binary files differ
diff --git a/web/noweb/contrib/leew/custom-code/example.tex b/web/noweb/contrib/leew/custom-code/example.tex
new file mode 100644
index 0000000000..b039a96f3f
--- /dev/null
+++ b/web/noweb/contrib/leew/custom-code/example.tex
@@ -0,0 +1,105 @@
+% to weave:% ===> this file was generated automatically by noweave --- better not edit it
+% noweave -t4 -delay -index example.nw -filter custom-code >example.tex
+%
+\documentclass{article}
+\usepackage{noweb}
+\noweboptions{smallcode}
+\topmargin=0pt
+\textheight=9in
+\def\sub#1{$_{#1}$}
+\def\minus{-}
+\def\plus{+}
+\def\equals{=}
+\def\lt{<}
+\def\gt{>}
+\def\neliac{%
+ \catcode`_=\active%
+ \catcode`|=\active%
+ \catcode`&=\active%
+ \catcode`*=\active%
+ \catcode`'=\active%
+ \catcode`^=\active%
+ \catcode`-=\active%
+ \catcode`+=\active%
+ \catcode`==\active%
+ \catcode`<=\active%
+ \catcode`>=\active%
+ \catcode`/=\active%
+}
+\bgroup\neliac
+\global\def\nwcustomcode{\neliac%
+ \global\def_##1{\sub{##1}}%
+ \global\def|{$\cup$}%
+ \global\def&{$\cap$}%
+ \global\def*{$\times$}%
+ \global\def'{$\vert$}%
+ \global\def^{$\uparrow$}%
+ \global\def+{$\plus$}%
+ \global\def={$\equals$}%
+ \global\def/##1{\(\ifx##1=\ne\else\slash##1\fi\)}%
+ \global\def<##1{\(\ifx##1=\le\else\lt##1\fi\)}%
+ \global\def>##1{\(\ifx##1=\ge\else\gt##1\fi\)}%
+ \global\def-##1{\(\ifx##1>\to\else\minus##1\fi\)}%
+}
+\egroup
+
+\begin{document}
+Here is some actual code from the original Neliac compiler for the
+Univac M-460 ``Countess'' computer (written in Neliac, of course):
+\nwfilename{example.nw}\nwbegincode{1}\sublabel{NW36h5rr-1p0Y9w-1}\nwmargintag{{\nwtagstyle{}\subpageref{NW36h5rr-1p0Y9w-1}}}\moddef{*~{\nwtagstyle{}\subpageref{NW36h5rr-1p0Y9w-1}}}\endmoddef\nwstartdeflinemarkup\nwprevnextdefs{\relax}{NW36h5rr-1p0Y9w-2}\nwenddeflinemarkup
+\bgroup\nwcustomcode{}DEBUG SCAN:
+i = 0: standard compiling location -> i; ;
+j = 0: obj prog std last address -> j; ;
+i = i(1)j\{ [i] = straight jump function | [i] = return jump function:
+ fault 9. ; [i](15 -> 29) = 61000_8 & [i](0 -> 14) - bias -> k /= 0:
+ \{ [k] = 0 | [k] = straight jump function: fault 10. ; \}; ;
+l'oop exit: \}. check key sets, turn off flex, clear indices,
+key[2] /= 0: dump name lists and stop. exit.
+F'AULT 9:
+start flex, carriage return upper case, 69 -> lower loop limit,
+72 -> upper loop limit, dump a title,
+n = 177_8(1)0\{ undefined name location[n] = i:
+ write undefined name, continue. ; \},
+C'ONTINUE: write address, loop exit.
+F'AULT 10:
+start flex, carriage return upper case,
+77 -> lower loop limit, 82 -> upper loop limit, dump a title,
+n = 777_8(1)0\{ name address[n] - bias = k: write name, go on. ; \},
+k -> upper dump buffer[1], dump five number,
+G'O ON: write address, loop exit.
+W'RITE ADDRESS:
+\{ 73 -> lower loop limit, 76 -> upper loop limit, dump a title,
+i -> upper dump buffer[1], dump five numbers, \}. e'xit: . .
+\egroup{}\nwalsodefined{\\{NW36h5rr-1p0Y9w-2}}\nwnotused{*}\nwendcode{}\nwbegindocs{2}\nwdocspar
+And here is the very same code without the \verb"custom-code"
+typesetting:\let\nwcustomcode=\relax
+\nwenddocs{}\nwbegincode{3}\sublabel{NW36h5rr-1p0Y9w-2}\nwmargintag{{\nwtagstyle{}\subpageref{NW36h5rr-1p0Y9w-2}}}\moddef{*~{\nwtagstyle{}\subpageref{NW36h5rr-1p0Y9w-1}}}\plusendmoddef\nwstartdeflinemarkup\nwprevnextdefs{NW36h5rr-1p0Y9w-1}{\relax}\nwenddeflinemarkup
+\bgroup\nwcustomcode{}DEBUG SCAN:
+i = 0: standard compiling location -> i; ;
+j = 0: obj prog std last address -> j; ;
+i = i(1)j\{ [i] = straight jump function | [i] = return jump function:
+ fault 9. ; [i](15 -> 29) = 61000_8 & [i](0 -> 14) - bias -> k /= 0:
+ \{ [k] = 0 | [k] = straight jump function: fault 10. ; \}; ;
+l'oop exit: \}. check key sets, turn off flex, clear indices,
+key[2] /= 0: dump name lists and stop. exit.
+F'AULT 9:
+start flex, carriage return upper case, 69 -> lower loop limit,
+72 -> upper loop limit, dump a title,
+n = 177_8(1)0\{ undefined name location[n] = i:
+ write undefined name, continue. ; \},
+C'ONTINUE: write address, loop exit.
+F'AULT 10:
+start flex, carriage return upper case,
+77 -> lower loop limit, 82 -> upper loop limit, dump a title,
+n = 777_8(1)0\{ name address[n] - bias = k: write name, go on. ; \},
+k -> upper dump buffer[1], dump five number,
+G'O ON: write address, loop exit.
+W'RITE ADDRESS:
+\{ 73 -> lower loop limit, 76 -> upper loop limit, dump a title,
+i -> upper dump buffer[1], dump five numbers, \}. e'xit: . .
+\egroup{}\nwendcode{}
+
+\nwixlogsorted{c}{{*}{NW36h5rr-1p0Y9w-1}{\nwixd{NW36h5rr-1p0Y9w-1}\nwixd{NW36h5rr-1p0Y9w-2}}}%
+\nwbegindocs{4}\relax
+\end{document}
+\nwenddocs{}
diff --git a/web/noweb/contrib/leew/custom-code/n b/web/noweb/contrib/leew/custom-code/n
new file mode 100644
index 0000000000..b2016f1622
--- /dev/null
+++ b/web/noweb/contrib/leew/custom-code/n
@@ -0,0 +1,20 @@
+Date: Wed, 13 May 2009 19:32:13 -0400
+From: Alec <alec@deviant-logic.net>
+To: Norman Ramsey <nr@cs.tufts.edu>
+Subject: Re: A couple links
+
+Actually, the pain and suffering from the python article
+turns out to be found at his followup post on tail calls on
+his regular blog:
+http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html
+
+It's truly thrilling.
+
+-A
+
+On Wed, May 6, 2009 at 9:44 PM, Norman Ramsey
+<nr@cs.tufts.edu> wrote:
+> Thanks!
+>
+> N
+>
diff --git a/web/noweb/contrib/leew/email b/web/noweb/contrib/leew/email
new file mode 100644
index 0000000000..e6186cf003
--- /dev/null
+++ b/web/noweb/contrib/leew/email
@@ -0,0 +1,2 @@
+Lee Wittenberg <leew@alumni.stanford.edu>
+
diff --git a/web/noweb/contrib/leew/nobrace.nw b/web/noweb/contrib/leew/nobrace.nw
new file mode 100644
index 0000000000..1190f8a291
--- /dev/null
+++ b/web/noweb/contrib/leew/nobrace.nw
@@ -0,0 +1,321 @@
+%
+% to tangle:
+% notangle -t4 -L nobrace.nw > nobrace.icn
+% to weave:
+% noweave -t4 -delay -autodefs icon -index nobrace.nw > nobrace.tex
+% to create the manpage:
+% notangle -Rnobrace.1 nobrace.nw > nobrace.1
+%
+\documentclass{article}
+
+\usepackage{noweb,multicol}
+\noweboptions{longchunks} % noweave -option longchunks would be
+ % better, but won't work with -delay, and
+ % we need stuff before \begin{document}
+
+% show spaces in string constants
+\global\let\xsetup=\setupcode
+\bgroup
+ \catcode`\"=\active\gdef\setupcode{\xsetup
+ \catcode`\"=\active\def"##1"{\char`\"\xxx{##1}\char`\"}}%
+\egroup
+\bgroup
+ \catcode`\ =\active\gdef\xxx#1{{\catcode`\ =\active\chardef ='40#1}}%
+\egroup
+
+\def\noweb/{\texttt{noweb}}
+\def\nobrace/{\texttt{nobrace}}
+\def\notangle/{\texttt{notangle}}
+\def\noweave/{\texttt{noweave}}
+
+\title {A Filter For Matching Braces in \noweb/ Programs%
+ \thanks{Copyright \copyright~1996 by Lee Wittenberg.
+ Although this software is freely distributable, it is not in
+ the public domain. It is provided ``as is'' and without any
+ express or implied warranties, including, without limitation,
+ the implied warranties of merchantability and fitness for a
+ particular purpose.}}
+\author {Lee Wittenberg\\\tt leew@pilot.njin.net}
+
+\pagestyle{noweb}
+\begin{document}
+\maketitle
+@ \iffalse
+%
+% We don't want a troff man page woven by TeX, do we?
+%
+<<nobrace.1>>=
+.TH NOBRACE 1 "local 4/9/96"
+.SH NAME
+nobrace \- check noweb chunks for brace mismatches
+.SH SYNOPSIS
+.B nobrace
+[ brace-pair ... ]
+.SH DESCRIPTION
+.I nobrace
+is a filter designed to work with
+.I notangle(1)
+or
+.I noweave(1)
+to ensure that the braces in each code chunk are balanced.
+.I nobrace
+generates warning messages on the standard error stream for each
+chunk with unbalanced braces.
+
+If no brace pairs are specified on the command line,
+.I nobrace
+will check parentheses, square brackets, and curly braces.
+.SH BUGS
+.I nobrace
+is naive about braces in string constants, comments, etc.
+.PP
+No provision is made for multiple character braces, so C-style
+comments cannot be checked (nor can Algol-like \fBbegin\fP's and
+\fBend\fP's).
+.PP
+This manual page would be better if its author knew more about troff
+and the -man macros.
+.SH SEE ALSO
+.I notangle(1), noweave(1)
+.SH AUTHOR
+Lee Wittenberg. Internet address: \fBleew@pilot.njin.net\fP
+@ \fi
+@
+\section{Introduction}
+Many literate programming authorities
+consider it good practice for each code chunk definition to be syntactically
+and semantically complete in itself, with each chunk use representing
+a complete entity (statement, expression, etc.). To be complete, the
+braces in a chunk must be balanced. This web provides a
+\noweb/ filter that warns the user about mismatched braces in chunks.
+@
+\section{The Program}
+The main program reads and echoes each
+line of the standard input (so it will be invisible in the pipeline),
+processing only relevant markup lines.
+<<*>>=
+procedure main(args)
+ <<Initialization>>
+ while inputline := read() do {
+ write(inputline)
+ inputline ? {
+ <<Process relevant markup lines>>
+ {} # for final else
+ }
+ }
+end
+@
+Each command-line
+argument is taken to be a pair of braces, the open brace first. We
+construct two tables, [[pair]], and [[delta]], which are used to keep
+the brace balancing straight and separate (we don't want `[[{]]'
+matching `[[)]]'). We use the [[braces]] cset for scanning the text
+lines in code chunks.
+
+If no command line arguments are specified, we assume `\verb"() [] {}"'.
+<<Initialization>>=
+pair := table("")
+delta := table(0)
+braces := ''
+if *args = 0 then
+ args := ["()", "[]", "{}"]
+every p := !args do {
+ braces ++:= p
+ every pair[!p] := p
+ delta[p[1]] := +1
+ delta[p[2]] := -1
+}
+@ %def pair delta braces
+@
+\section{Relevant Markup}
+Our \emph{raison d'\^etre} is to match braces in code chunks.
+Each [[@text]] line in a code chunk is scanned for braces, which we
+attempt to balance.
+<<Process relevant markup lines>>=
+if ="@text " then {
+ if \code then {
+ line := tab(0)
+ every p := upto(braces, line) do {
+ b := line[p]
+ <<Balance brace [[b]] at [[p]]>>
+ }
+ }
+} else
+@
+Whenever we enter a code chunk, we need to set our [[code]] flag,
+<<Process relevant markup lines>>=
+if ="@begin code " then {
+ code := 1
+} else
+@ \noindent
+and reset it whenever we leave. Whenever a code chunk ends (thus
+ending a definition), we also need to check for any remaining umatched
+braces in that chunk.
+<<Process relevant markup lines>>=
+if ="@end code " then {
+ code := &null
+ <<Check for unmatched braces>>
+} else
+@
+All webs start with a text chunk, not code.
+<<Initialization>>=
+code := &null
+@ %def code
+@
+The variables [[curr_chunkname]], [[curr_filename]], and [[curr_line]]
+help keep track of where mismatches are found.
+@ \noindent
+We initialize them to ``safe'' values, just in case.
+<<Initialization>>=
+curr_line := 1
+curr_filename := "Standard Input"
+curr_chunkname := "***Unknown Chunk***"
+@ %def curr_filename curr_line curr_chunkname
+@
+Newlines simply increase the [[curr_line]] count.
+<<Process relevant markup lines>>=
+if ="@nl" & pos(0) then {
+ curr_line +:= 1
+} else
+@
+Whenever we get a new file name, we make note of it.
+<<Process relevant markup lines>>=
+if ="@file " then {
+ curr_filename := tab(0)
+ curr_line := 1
+} else
+@
+The [[@line]] directive can be used to adjust the current line
+number in a source file. We hear and obey.
+<<Process relevant markup lines>>=
+if ="@line " then {
+ curr_line := integer(tab(0))
+} else
+@
+New chunk definitions give us a new [[curr_chunkname]].
+``[[<<Check for unmatched braces>>]]''
+is here because it is not illegal for a single code chunk to have more
+than one definition. None of the standard tools produce anything like
+that, but we allow for this (remote) possibility in the interests of
+defensive programming.
+<<Process relevant markup lines>>=
+if ="@defn " then {
+ <<Check for unmatched braces>>
+ curr_chunkname := tab(0)
+} else
+@
+\section{Dealing With Braces}
+Whenever we see an opening brace, we push its location
+on the appropriate stack,
+and when we see a closing brace, we pop the
+corresponding opening brace's location
+(we use [[pull]] instead of [[pop]] to keep the list sorted; we use
+list concatenation instead of [[put]] because of Icon's table
+initialization semantics).
+
+If there is no opening brace to pop,
+we've found a mismatched closing brace.
+We add each line containing a brace to the [[error_line]] table
+because it may be needed for a warning message.
+<<Balance brace [[b]] at [[p]]>>=
+if delta[b] > 0 then {
+# put(bstack[pair[b]], loc(curr_line, p))
+ bstack[pair[b]] |||:= [loc(curr_line, p)]
+} else {
+ pull(bstack[pair[b]]) |
+ {<<Note brace error at [[curr_line]], [[p]]>>}
+}
+error_line[curr_line] := line
+@
+A brace's location is a line number and a column position in that
+line.
+<<*>>=
+record loc(line,col)
+@
+We keep all brace errors in a sorted list, [[error_list]].
+<<Note brace error at [[curr_line]], [[p]]>>=
+put(error_list, loc(curr_line, p))
+@
+The brace stacks are initially empty, as is the error list.
+<<Initialization>>=
+bstack := table([])
+error_list := []
+error_line := table("")
+@ %def bstack error_list error_line
+@
+If either the error list or any of the brace stacks are not empty, we
+have mismatched braces
+<<Check for unmatched braces>>=
+if (*error_list | *!bstack) ~= 0 then {
+ <<Generate warning messages>>
+}
+@
+We merge [[error_list]] with all the brace stacks to create a single
+(sorted) list of mismatched brace locations. We write a single
+warning message for the chunk, followed by all the lines with
+mismatched braces. When we're finished, we clear the error list and
+the brace stacks for the next chunk definition.
+<<Generate warning messages>>=
+every error_list := merge(!bstack, error_list)
+write(&errout, "Warning: Mismatched braces in @<<",
+ curr_chunkname, ">>",
+ if curr_filename ~== ""
+ then " (" || curr_filename || ")"
+ else "",
+ ":")
+<<Display all relevant lines with mismatched braces marked>>
+error_list := []
+bstack := table([])
+@
+For each line represented in the error list, we print the line with a
+marker line under it. We use the `\verb"^"' character to mark the
+position of each mismatched brace. Each line is prefixed with its
+line number.
+<<Display all relevant lines with mismatched braces marked>>=
+lineno := 0;
+every e := !error_list do {
+ if e.line ~= lineno then {
+ if lineno ~=0 then
+ write(&errout, marker)
+ lineno := e.line
+ write(&errout, right(e.line || ": ", 10),
+ error_line[e.line])
+ marker := repl(" ", 10)
+ }
+ marker := left(marker, e.col+10-1) || "^"
+}
+write(&errout, marker)
+@
+The [[merge]] procedure merges two sorted lists of [[loc]]'s. We plow
+through both lists more or less in parallel, adding the earliest
+brace location to the result list. When [[a]] is exhausted,
+the remaining elements of [[b]] are concatenated to the result. Thus,
+the longer list should always be passed as the second parameter if
+possible.
+<<*>>=
+procedure merge(a, b)
+ local i, j, result
+ result := []
+ i := j := 1
+ while a[i] do {
+ if a[i].line > b[j].line |
+ (a[i].line = b[j].line & a[i].col > b[j].col) then {
+ put(result, b[j])
+ j +:= 1
+ } else {
+ put(result, a[i])
+ i +:= 1
+ }
+ }
+ return result ||| b[j:0]
+end
+@
+\appendix
+\section{Chunk Index}
+\nowebchunks
+\section{Identifier Index}
+\begin{multicols}{2}
+\nowebindex
+\end{multicols}
+@
+\end{document}
diff --git a/web/noweb/contrib/leew/nocond.nw b/web/noweb/contrib/leew/nocond.nw
new file mode 100644
index 0000000000..50eb35bc64
--- /dev/null
+++ b/web/noweb/contrib/leew/nocond.nw
@@ -0,0 +1,375 @@
+%
+% $Header: d:/noweb/work/RCS/nocond.nw%v 1.4 1995/07/29 17:14:49 LEEW Exp LEEW $
+% $Workfile$
+%
+% to tangle the sed script
+% notangle -t4 -R"sed script" nocond.nw > nocond
+% to tangle the shell script:
+% notangle -t4 -R"shell script" nocond.nw > nocond
+% to tangle the awk program
+% notangle -t4 -Rnocond.awk nocond.nw > nocond.awk
+% (use -filter "nocond MKS AWKC" if necessary)
+% to weave:
+% noweave -t4 -delay -x nocond.nw > nocond.tex
+%
+\documentstyle[noweb,twoside]{article}
+\noweboptions{longchunks}
+\let\nwnotused=\nwoutput
+\oddsidemargin=63pt % standard LaTeX margins don't work well for 2-sided webs
+\evensidemargin=63pt
+
+\ifx\LaTeXe\undefined\def\LaTeXe{\LaTeX2e}\fi % for old installations
+\def\noweb/{{\tt noweb}}
+\def\nocond/{{\tt nocond}}
+\def\notangle/{{\tt notangle}}
+\def\noweave/{{\tt noweave}}
+
+\title {A Filter For Conditional Tangling in \noweb/%
+ \thanks{Copyright \copyright~1994, 1995 by Lee Wittenberg.
+ Although this software is freely distributable, it is not in
+ the public domain. It is provided ``as is'' and without any
+ express or implied warranties, including, without limitation,
+ the implied warranties of merchantability and fitness for a
+ particular purpose.}}
+\author {Lee Wittenberg\\\tt leew@pilot.njin.net}
+
+%\input{nocondmac.tex}
+\bgroup
+\catcode`\@=11
+\global\let\nc@LA=\LA
+\gdef\nocondmark#1)){\/{\bf[\negthinspace[#1]\negthinspace]}}%
+\global\let\nc@notused=\nwnotused
+\global\let\nc@output=\nwoutput
+\gdef\nc@rootchunk#1{\nwcodecomment{\nocondrootnote}%
+ \global\let\nwnotused=\nc@notused
+ \global\let\nwoutput=\nc@output
+}%
+\gdef\nocondrootnote{Conditional definition.}%
+% for noweb 2.6 (bug, since fixed?)
+\global\@namedef{r@???}{{0}{\nocondxref}}
+% for noweb 2.5:
+\global\@namedef{r@nw@notdef}{{0}{\nocondxref}}
+\gdef\nocondxref{(conditional)}
+\global\let\nc@nwixlog=\nwixlogsorted
+\gdef\nwixlogsorted#1#2{
+\ifx#1c%
+ \immediate\write\@auxout{\string\bgroup\string\catcode`\string\(=\string\active}
+\fi
+ \nc@nwixlog{#1}{#2}
+\ifx#1c%
+ \immediate\write\@auxout{\string\egroup}
+\fi}%
+\catcode`\(=\active
+\gdef\LA{\nc@LA
+ \catcode`\(=\active
+ \def(##1{\ifx##1(\global\let\nwnotused=\nc@rootchunk
+ \global\let\nwoutput=\nc@rootchunk
+ \nocondmark
+ \else\char`\(##1\fi}%
+}%
+\egroup
+\pagestyle{noweb}
+\begin{document}
+\maketitle
+@ \iffalse
+%
+% We don't want a troff man page woven by TeX, do we?
+%
+<<nocond.1>>=
+.TH NOCOND 1 "local 8/1/94"
+.SH NAME
+nocond \- provide noweb with conditional tangling
+.SH SYNOPSIS
+.B nocond
+version
+.br
+\fBawk -f nocond.awk\fP version
+.SH DESCRIPTION
+.I nocond
+is a filter designed to work with
+.I notangle(1)
+to provide it with a simple
+conditional capability. Chunk definitions may be
+marked as conditional by including a version name
+wrapped in double parentheses as part of the chunk name.
+.PP
+.I nocond
+concatenates its command line arguments
+(with a single space between each argument) to form
+a version name, and removes matching conditional marks
+from chunk definition names so
+.I notangle(1)
+will include the chunks as part of the appropriate
+definition.
+.PP
+.I nocond
+also provides a file of TeX macros, \fInocondmac.tex\fP, which
+will nicely typeset conditional chunk names.
+.SH EXAMPLE
+Suppose that a Pascal web (\fIpgm.nw\fP) uses the chunk
+.IP
+\fB@<<\fPOpen the output file\fB@>>\fP
+.PP
+The author can provide multiple definitions of this chunk:
+.IP
+\fB@<<\fPOpen the output file ((UCSD Pascal))\fB@>>=\fP
+.nf
+REWRITE(outfile, 'XYZ.DAT');
+\fB@<<\fPOpen the output file ((Turbo Pascal))\fB@>>=\fP
+ASSIGN(outfile, 'XYZ.DAT');
+REWRITE(outfile);
+.fi
+.PP
+To tangle the UCSD Pascal version, the command line
+.IP
+notangle -filter "nocond UCSD Pascal" pgm.nw > pgm.pas
+.PP
+will suffice. The Turbo Pascal version can be tangled
+similarly.
+.SH SEE ALSO
+.I notangle(1)
+.SH AUTHOR
+Lee Wittenberg. Internet address: \fBleew@pilot.njin.net\fP
+@ \fi
+@
+\section{Introduction}
+This program is a very simple filter that provides \notangle/
+with a simple conditional capability. It should be
+written in {\tt sed}, but non-Unix versions
+of that venerable utility are not as readily available as they
+should be, so we are using Awk instead (however, see
+section~\ref{sed script}).
+
+\section{The Awk Program}
+The Awk program simply passes all its input lines to the
+standard output. However, when it encounters a chunk
+definition name, it first removes any conditional marks that
+match the version specified on the command line.
+<<nocond.awk>>=
+<<Version control info>>
+BEGIN{
+ <<System-dependent initialization>>
+ <<Initialization>>
+}
+<<Remove desired conditional marks from any chunk definition names>>
+{print}
+<<Version control info>>
+@
+Chunk definition names are prefixed with the markup code
+`\verb*"@defn "', and [[gsub]] is just made for this kind of
+work.
+<<Remove desired conditional marks from any chunk definition names>>=
+/^@defn / { gsub(pattern, "", $0) }
+@
+We want to remove marks surrounded by `\verb"(("' and
+`\verb"))"'. We need the backslashes in the pattern so
+Awk doesn't treat the parentheses as grouping symbols.
+<<Initialization>>=
+<<Use [[ARGV]] to determine the [[version]] desired>>
+pattern = " *\(\(" version "\)\)"
+@
+Some command processors are not very friendly about dealing
+with command line arguments containing spaces, so rather than
+require the version name to be supplied as a single argument,
+we treat all the arguments as a single, multi\-word one (with
+single spaces between the words). We then set [[ARGC]] to~1 to
+prevent Awk from trying to re-use the arguments as filenames.
+<<Use [[ARGV]] to determine the [[version]] desired>>=
+version = ARGV[1]
+for (i = 2; i < ARGC; i++) {
+ version = version " " ARGV[i]
+}
+ARGC = 1
+@
+\subsection{System Dependencies}
+The MKS Awk compiler tends to get confused about command line
+arguments, even though the interpreter has no problems. The
+following kludge seems to take care of it (don't ask):
+<<System-dependent initialization ((MKS AWKC))>>=
+ARGV[1]
+@
+It's likely that other system-dependencies will arise as
+\nocond/ is tried with other versions of Awk. A bit
+depressing, but that's what the tool was designed for, and it's
+kind of nice to use it to implement itself. Since every Awk
+won't require special initialization, we provide a null chunk
+to avoid ``undefined chunk'' complaints from \notangle/.
+<<System-dependent initialization>>=
+@
+\section{The Shell Script}
+Unix users can use the following shell script as a \notangle/
+filter:
+<<shell script>>=
+nawk '<<nocond.awk>>'
+@
+\section{A {\tt sed} Script}
+\label{sed script}.
+{\sc Gnu} Awk, running under Linux, doesn't seem amenable to any
+patches that will make the above Awk program work correctly (the
+[[gsub]] function seems to be a sore spot in many Awk implementations).
+A {\tt sed} script, therefore, seems to be a necessity. The following
+does the trick.
+<<sed script>>=
+<<Version control info>>
+sed "/^@defn/s/ *(($*))//"
+@
+\section{Weaving a Conditional Web}
+Some people think the double parentheses don't look very
+good in woven output, and that the version name should stand
+out a bit from the chunk name. We provide the macro file
+\verb"nocondmac.tex" for those with such beliefs. These macros
+should be usable both in plain \TeX\ and \LaTeX, but have only
+been tested with the latter. They seem to work okay in \LaTeXe{}
+(in both native and compatibility modes), as well.
+
+We simply redefine the meaning of \noweb/'s [[\LA]] macro to
+make `\verb"("' an active character that typesets stuff in
+{\tt ((~$\ldots$~))} nicely and leaves other parentheses alone.
+As long as [[\LA]] exists and contains a \verb"\bgroup" this
+ought to work.
+<<nocondmac.tex>>=
+\bgroup
+\catcode`\@=11
+\global\let\nc@LA=\LA
+<<Useful macros>>
+<<Make `[[(]]' active>>
+\gdef\LA{\nc@LA
+ <<Make `[[(]]' active>>
+ \def(##1{\ifx##1(<<Adjust root chunk footnote>>\nocondmark
+ \else\char`\(##1\fi}%
+}%
+\egroup
+<<Make `[[(]]' active>>=
+\catcode`\(=\active
+@
+The real work will be done by [[\nocondmark]]. This is the
+only macro that should be changed if you want to adjust the way
+conditionals are typeset.
+<<Useful macros>>=
+\gdef\nocondmark#1)){\/{\bf[\negthinspace[#1]\negthinspace]}}%
+@
+In \LaTeX\ webs,
+the cross-reference footnotes for root chunks are generated by
+[[\nwnotused]] or [[\nwoutput]], depending on whether the woven
+output was generated with the \notangle/ or \noweb/ command.
+We note the original definitions, but change them to
+print `Conditional definition.' when a chunk name includes
+{\tt ((~$\ldots$~))}.
+<<Useful macros>>=
+\ifx\nwnotused\undefined\else
+ \global\let\nc@notused=\nwnotused
+\fi
+\ifx\nwoutput\undefined\else
+ \global\let\nc@output=\nwoutput
+\fi
+<<Adjust root chunk footnote>>=
+\ifx\nc@rootchunk\undefined\else
+\global\let\nwnotused=\nc@rootchunk
+\global\let\nwoutput=\nc@rootchunk
+\fi
+@
+The macro [[\nc@rootchunk]] is defined so that it resets
+[[\nwnotused]] and [[\nwoutput]] when it's finished, so that
+real root chunks will have the proper footnote. We use
+[[\nocondrootnote]] so that the conditional footnote can
+easily be customized.
+<<Useful macros>>=
+\ifx\nwnotused\undefined\else
+ \ifx\nwoutput\undefined\else
+ \gdef\nc@rootchunk#1{\nwcodecomment{\nocondrootnote}%
+ \global\let\nwnotused=\nc@notused
+ \global\let\nwoutput=\nc@output
+ }%
+ \gdef\nocondrootnote{Conditional definition.}%
+\fi\fi
+@
+In a web with conditional definitions, chunks that appear to be
+undefined are actually conditionally defined, so we change the
+`never defined' message to a more meaningful `conditional'.
+<<Useful macros>>=
+\ifx\documentstyle\undefined\else % LaTeX only
+% noweb 2.5:
+\global\@namedef{r@nw@notdef}{{0}{\nocondxref}}
+% noweb 2.6: (bug, since fixed?)
+\global\@namedef{r@???}{{0}{\nocondxref}}
+\gdef\nocondxref{(conditional)}
+\fi
+@
+The chunk index is a bit of a problem because \TeX\ assigns
+catcodes when a token is first read, but the chunk index is
+read in as part of the \verb".aux" file, when `\verb"("' is not
+an active character. We fix [[\nwixlogsorted]] so it will
+change the catcode of `\verb"("' temporarily for chunk index
+info in the \verb".aux" file.
+<<Useful macros>>=
+\ifx\nwixlogsorted\undefined\else
+ \global\let\nc@nwixlog=\nwixlogsorted
+ \gdef\nwixlogsorted#1#2{
+ \ifx#1c
+ \immediate\write\@auxout{\string\bgroup
+ \string\catcode`\string\(=\string\active}%
+ \fi
+ \nc@nwixlog{#1}{#2}
+ \ifx#1c
+ \immediate\write\@auxout{\string\egroup}%
+ \fi
+ }%
+\fi
+@
+On the other hand, all we need do for
+[[\nowebchunks@external]] is to set the catcode. Note
+that the \verb"externalindex" option must be set {\em after\/}
+executing \verb"\input nocondmac.tex" for things to work
+properly.
+<<Useful macros>>=
+\ifx\nowebchunks@external\undefined\else
+ \global\let\nc@chunks@external=\nowebchunks@external
+ \gdef\nowebchunks@external{%
+ \bgroup
+ <<Make `[[(]]' active>>
+ \nc@chunks@external
+ \egroup
+ }%
+\fi
+@
+\appendix
+\section {Language and Version Control Tools}
+This puts revision information in the program so we can make
+sure things don't get ``out of sync.''
+<<Version control info>>=
+# $Header: d:/noweb/work/RCS/nocond.nw%v 1.4 1995/07/29 17:14:49 LEEW Exp LEEW $
+@
+\section {Chunk Index}
+\nowebchunks
+%\twocolumn[\section{Identifier Index}] % no point, really, for this web
+%\nowebindex
+@
+\end{document}
+% $Log: nocond.nw%v $
+% Revision 1.4 1995/07/29 17:14:49 LEEW
+% Added sed script; minor cosmetic changes
+%
+% Revision 1.3 1994/09/11 18:06:26 LEEW
+% Fixed macros for noweb 2.6c
+%
+% Revision 1.2 1994/08/05 20:46:48 LEEW
+% Added macros to typeset chunk index correctly.
+%
+% Revision 1.1 1994/08/01 14:05:33 LEEW
+% Changed manpage to troff format.
+% Spiffed up nocondmac macros.
+% Removed non-standard macro packages.
+%
+% Revision 1.0 1994/06/20 17:47:55 LEEW
+% First public version.
+%
+% Revision 0.3 1994/06/20 17:31:49 LEEW
+% Added TeX macros
+%
+% Revision 0.2 1994/06/20 16:36:59 LEEW
+% Awk script complete
+%
+% Revision 0.1 1994/06/20 14:54:49 LEEW
+% Manpage only.
+%
+% $Header: d:/noweb/work/RCS/nocond.nw%v 1.4 1995/07/29 17:14:49 LEEW Exp LEEW $
diff --git a/web/noweb/contrib/leew/strhack.nw b/web/noweb/contrib/leew/strhack.nw
new file mode 100644
index 0000000000..4b0e3fff9d
--- /dev/null
+++ b/web/noweb/contrib/leew/strhack.nw
@@ -0,0 +1,32 @@
+\documentstyle[11pt,noweb]{article}
+\noweboptions{longchunks,noidentxref,smallcode}
+\pagestyle{noweb}
+
+\def\noweb/{{\tt noweb}}
+
+\title{A Hack for Typesetting Strings in \noweb/\thanks{This
+code is hereby placed in the public domain.}}
+\author{Lee Wittenberg\\Kean College of New Jersey\\Union, NJ
+07083\\\tt leew@pilot.njin.net}
+
+\begin{document}
+\maketitle
+
+The following macros adjust things so that \noweb/ will use
+``visible spaces'' in double-quoted strings within code chunks.
+The same effect can be
+achieved for single-quoted strings by replacing each occurrence
+of `[["]]', below, with `[[']]'.
+It doesn't work within \verb"[["~\ldots~\verb"]]" (although I
+can't figure out why).
+<<*>>=
+\global\let\xsetup=\setupcode
+\bgroup
+ \catcode`\"=\active\gdef\setupcode{\xsetup
+ \catcode`\"=\active\def"##1"{\char`\"\xxx{##1}\char`\"}}%
+\egroup
+\bgroup
+ \catcode`\ =\active\gdef\xxx#1{{\catcode`\ =\active\chardef ='40#1}}%
+\egroup
+@
+\end{document}
diff --git a/web/noweb/contrib/leyn/README b/web/noweb/contrib/leyn/README
new file mode 100644
index 0000000000..79d24b3a3b
--- /dev/null
+++ b/web/noweb/contrib/leyn/README
@@ -0,0 +1,23 @@
+ttroots
+=======
+
+-Allows underscores in root chunks that are written to disk.
+-All root chunks are printed out in the LaTeX document as
+ upright verbatim names.
+
+
+notangleall
+===========
+
+-creates all required directories for the code chunks
+-tangles all root chunks (as noweb -t)
+-makes all scripts mared executable. The marking is done
+ as follows:
+ %unx chmod +x chunk_name
+ <<chunk_name>>=
+ ...
+ @
+
+ Can also be used for other UNIX commands that should be
+ executed after the tangling.
+
diff --git a/web/noweb/contrib/leyn/email b/web/noweb/contrib/leyn/email
new file mode 100644
index 0000000000..f330ba5499
--- /dev/null
+++ b/web/noweb/contrib/leyn/email
@@ -0,0 +1 @@
+Francky.Leyn@esat.kuleuven.ac.be
diff --git a/web/noweb/contrib/leyn/notangleall b/web/noweb/contrib/leyn/notangleall
new file mode 100755
index 0000000000..9ab9f75e8d
--- /dev/null
+++ b/web/noweb/contrib/leyn/notangleall
@@ -0,0 +1,27 @@
+#! /bin/sh
+#
+# notangleall
+#
+# -creates all required directories for the code chunks
+# -tangles all root chunks (as noweb -t)
+# -makes all scripts mared executable. The marking is done
+# as follows:
+# %unx chmod +x chunk_name
+# <<chunk_name>>=
+# ...
+# @
+#
+# Can also be used for other UNIX commands that should be
+# executed after the tangling.
+
+
+echo 'making required subdirs'
+noroots $1 | \
+ sed '/<<[^/]*>>/d ; s/<<\(.*\)\/[^\/]*>>/\1/' | \
+ sort | uniq | sed 's/\(.*\)/mkdir -p \1 ;/' | sh
+
+echo 'extracting code chunks'
+noweb -t $1
+
+echo 'making scripts executable'
+egrep '^%unix' $1 | sed 's/%unix //; s/.*/& ;/' | sh
diff --git a/web/noweb/contrib/leyn/ttroots b/web/noweb/contrib/leyn/ttroots
new file mode 100755
index 0000000000..b03bc91922
--- /dev/null
+++ b/web/noweb/contrib/leyn/ttroots
@@ -0,0 +1,41 @@
+#! /bin/sh
+#
+# ttroots
+#
+# -Allows underscores in root chunks that are written to disk.
+# -All root chunks are printed out in the LaTeX document as
+# upright verbatim names.
+
+gawk '
+ { line[NR] = $0 ; }
+# a root chunk name can not contain spaces
+$1 == "@use" && NF == 2 { used[$2] = 1 ; next ; }
+$1 == "@defn" && NF == 2 { defined[$2] = 1 ; }
+
+END {
+ # determine root chunks
+ for (i in defined)
+ if (!(i in used))
+ root_chunks[i] = 1 ;
+
+ # root chunk substitutions
+ # Root chunk names can be used in 3 contexts:
+ # @defn name
+ # @xref notused name
+ # @xref chunkbegin label name
+ for (i=1; i<=NR; i++) {
+ if (line[i] ~ /^(@xref notused|@xref chunkbegin|@defn)/) {
+ nr = split(line[i], array, " ") ;
+ stat = array[1] ;
+ name = array[nr] ;
+ if ((stat == "@xref" || (stat == "@defn" && nr == 2)) && (name in root_ch
+unks)) {
+ replace = " \\textup{\\texttt{"name"}}" ;
+ gsub("_", "\\_", replace) ;
+ gsub(" "name, replace, line[i]) ;
+ } ;
+ } ;
+ print line[i] ;
+ }
+}
+'
diff --git a/web/noweb/contrib/norman/Makefile b/web/noweb/contrib/norman/Makefile
new file mode 100644
index 0000000000..471f71e82b
--- /dev/null
+++ b/web/noweb/contrib/norman/Makefile
@@ -0,0 +1,10 @@
+LIB=/dev/null # to be overridden
+DIRS=numarkup
+
+all: ; for i in $(DIRS); do (cd $$i; make ICONC=$(ICONC) ICONT=$(ICONT) all); done
+install: ; for i in $(DIRS); do (cd $$i; make LIB=$(LIB) BIN=$(BIN) install); done
+source: ; for i in $(DIRS); do (cd $$i; make source); done
+clean: ; for i in $(DIRS); do (cd $$i; make clean); done
+iconlib: # cheap hack for slackmake
+ true
+
diff --git a/web/noweb/contrib/norman/README b/web/noweb/contrib/norman/README
new file mode 100644
index 0000000000..722d895409
--- /dev/null
+++ b/web/noweb/contrib/norman/README
@@ -0,0 +1,6 @@
+cleanchunks.nw escape special characters in chunk names
+moddate.nw use file modification time as date (POSIX)
+numarkup contains a substitute for markup that works with nuweb files
+pp contains a very simple prettyprinter
+scopehack.icn A hack for scoping files; see the FAQ
+generate-to A hack for renumbering lines in tools like yacc
diff --git a/web/noweb/contrib/norman/cleanchunks.nw b/web/noweb/contrib/norman/cleanchunks.nw
new file mode 100644
index 0000000000..9334c11225
--- /dev/null
+++ b/web/noweb/contrib/norman/cleanchunks.nw
@@ -0,0 +1,42 @@
+\section{Code to clean up special characters in chunk names}
+
+Some people want to use {\tt noweb} to browse big pieces of legacy
+code without having to touch any of it by hand. Since legacy code
+sometimes uses underscores and other special characters in chunk
+names, it makes sense to have a filter to escape special characters in
+chunk names.
+<<*>>=
+procedure main()
+ local tag, line
+ while line := read() do
+ line ?
+ if tag := =("@defn " | "@use ") then
+ write(tag, TeXliteral(tab(0)))
+ else
+ write(line)
+end
+@
+<<'\\{}$&#^_ ~%'>>=
+<<*>>=
+procedure TeXliteral(arg)
+ static nospace, code, TeXspecials
+ initial { codes := ["\\", 92, "{", 123, "}", 125, "$", 36, "&", 38, "#", 35, "^", 94,
+ "_", 95, "%", 37, "~", 126]
+ code := table()
+ TeXspecials := '\\{}$&#^_~%'
+ while (c := get(codes), n := get(codes)) do code[c] := string(n)
+ if c := !TeXspecials & c ~== " " & not member(code, c) then
+ stop("internal error, character-code mismatch, report a bug!")
+ }
+ s := ""
+ arg ? {
+ while s ||:= tab(upto(TeXspecials)) do {
+ c := move(1)
+ if member(code, c) then
+ s ||:= "{\\tt\\char" || code[c] || "}"
+ else
+ s ||:= "\\" || c
+ }
+ return s || tab(0)
+ }
+end
diff --git a/web/noweb/contrib/norman/email b/web/noweb/contrib/norman/email
new file mode 100644
index 0000000000..d87018308d
--- /dev/null
+++ b/web/noweb/contrib/norman/email
@@ -0,0 +1 @@
+nr@eecs.harvard.edu
diff --git a/web/noweb/contrib/norman/generate-to b/web/noweb/contrib/norman/generate-to
new file mode 100755
index 0000000000..9bc8f65e6e
--- /dev/null
+++ b/web/noweb/contrib/norman/generate-to
@@ -0,0 +1,24 @@
+#!/usr/bin/env lua5.1
+
+-- Usage: $0 filename
+-- Reads from stdin and writes to filename, renumbering directives
+-- that say "generated code"
+
+assert(#arg == 1, 'Usage: $0 outfilename')
+local filename = assert(arg[1])
+
+local f = assert(io.open(filename, 'w'))
+
+local n = 0 -- how many lines have already been written to f
+local function rewrite()
+ return string.format('#line %d "%s"', n, filename)
+end
+for l in io.lines() do
+ n = n + 1
+ l = l:gsub('%#line%s+%d+%s*"generated code"', rewrite, 1)
+ f:write(l, '\n')
+end
+
+f:close()
+
+ \ No newline at end of file
diff --git a/web/noweb/contrib/norman/htmlgif/htmlgif.icn b/web/noweb/contrib/norman/htmlgif/htmlgif.icn
new file mode 100644
index 0000000000..1a681be801
--- /dev/null
+++ b/web/noweb/contrib/norman/htmlgif/htmlgif.icn
@@ -0,0 +1,54 @@
+# htmlgif -- convert eps references to gifs
+
+procedure newer(target, prereq)
+ return system("newer " || target || " " || prereq) == 0
+end
+
+procedure main(args)
+ if *args > 0 then every cvt(open(!args))
+ else cvt(&input)
+ return
+end
+
+procedure cvt(file)
+ while line := read(file) do
+ line ?
+ if (pre := tab(find("<a ")), optwhite(), ="<a href=", optwhite(),
+ ps := tab(upto(' \t>')), optwhite(), =">",
+ tab(lookfor(s := "PostScript figure " || (ps|strip_quotes(ps)))),
+ =s, any(' ]<>"'), tab(find("</a>")), post := tab(0)) then
+ {
+ ps := strip_quotes(ps)
+ gif := suffex(ps) || ".gif"
+ write(pre, "<img inline src=", quote(gif),
+ " alt=", quote("[GIF derived from PostScript figure " || ps || "]"), ">",
+ post)
+ if not newer(gif, ps) then
+ system("pstopbm " || ps || " | ppmtogif | giftool -rgb white > " || gif)
+ } else {
+ write(line)
+ }
+ return
+end
+
+procedure lookfor(s)
+ suspend find(s)
+end
+
+procedure strip_quotes(s)
+ return if s[1] == s[-1] == "\"" then s[2:-1] else s
+end
+
+procedure suffex(s)
+ static nodot
+ initial nodot := ~ '.'
+ s ? return if (b := tab(upto('.')), =".", tab(many(nodot)), pos(0)) then b else s
+end
+
+procedure quote(s)
+ return "\"" || s || "\""
+end
+
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
diff --git a/web/noweb/contrib/norman/htmlgif/newer.c b/web/noweb/contrib/norman/htmlgif/newer.c
new file mode 100644
index 0000000000..9b741bd6f9
--- /dev/null
+++ b/web/noweb/contrib/norman/htmlgif/newer.c
@@ -0,0 +1,19 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <errno.h>
+
+main(int argc, char *argv[]) {
+ struct stat b1, b2;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s file1 file2\n", argv[0]);
+ exit (-1);
+ } else if (stat(argv[1],&b1) < 0) {
+ perror(argv[1]);
+ exit(-2);
+ } else if (stat(argv[2],&b2) < 0) {
+ perror(argv[2]);
+ exit(-2);
+ } else exit(b1.st_mtime > b2.st_mtime ? 0 : 1);
+}
diff --git a/web/noweb/contrib/norman/htmlgif/pstopbm b/web/noweb/contrib/norman/htmlgif/pstopbm
new file mode 100755
index 0000000000..eeb65ff385
--- /dev/null
+++ b/web/noweb/contrib/norman/htmlgif/pstopbm
@@ -0,0 +1,86 @@
+#!/bin/sh
+# exec gs -sDEVICE=djet500 -sOutputFile=- -q -dNOPAUSE "$@"
+
+device=pbm
+case $0 in
+ *pbm) device=pbm ;;
+ *ppm) device=ppm ;;
+esac
+
+border=10
+leftborder=$border
+rightborder=$border
+upperborder=$border
+lowerborder=$border
+translate=yes
+showpage=showpage
+
+while [ $# -gt 0 ]; do
+ case $1 in
+ -border) border="$2"
+ leftborder=$border
+ rightborder=$border
+ upperborder=$border
+ lowerborder=$border
+ shift ;;
+ -upper) upperborder="$2" ; shift ;;
+ -lower) lowerborder="$2" ; shift ;;
+ -left) leftborder="$2" ; shift ;;
+ -right) rightborder="$2" ; shift ;;
+ -notrans) translate= ;;
+ -showpage) showpage=showpage ;;
+ -noshowpage) showpage= ;;
+ -*) echo "Unknown option $1" 1>&2 ; exit 1;;
+ *) break ;;
+ esac
+ shift
+done
+
+tmp=$(mktemp)
+tmpa=$(mktemp --suffix=.a)
+if [ $# -eq 0 ]; then cat > $tmp; else cat "$@" > $tmp; fi
+
+if echo "$@" | fgrep .eps > /dev/null; then
+ echo showpage >> $tmp
+fi
+
+set foo `psbb $tmp`
+shift
+
+if [ -n "$translate" -a $# -eq 4 ]; then
+
+ llx="$1" lly="$2" urx="$3" ury="$4"
+ llx=`expr $llx - $leftborder`
+ lly=`expr $lly - $lowerborder`
+ urx=`expr $urx + $rightborder`
+ ury=`expr $ury + $upperborder`
+ width=`expr $urx - $llx`
+ height=`expr $ury - $lly`
+
+ awk '{print}
+ /^%%EndComments/ { printf "%d neg %d neg translate\n", '"$llx, $lly"' }
+ ' $tmp > $tmpa
+ echo "$showpage" |
+ gs -q -g"${width}x$height" -sDEVICE=$device -sOutputFile=- -dNOPAUSE $tmpa -
+else
+ echo "$showpage" |
+ gs -q -sDEVICE=$device -sOutputFile=- -dNOPAUSE $tmp -
+fi
+
+# rm -f $tmp $tmpa
+
+exit 0
+
+#### old version
+
+
+
+if [ $# -eq 0 ]; then
+ tmp=$(mktemp)
+ cat > $tmp
+ gs -q -sDEVICE=$device -sOutputFile=- -dNOPAUSE -dMAGSTEP=1.0 $tmp
+else
+ gs -q -sDEVICE=$device -sOutputFile=- -dNOPAUSE -dMAGSTEP=1.0 "$@"
+fi
+rm -rf $tmp
+
diff --git a/web/noweb/contrib/norman/moddate.nw b/web/noweb/contrib/norman/moddate.nw
new file mode 100644
index 0000000000..bf43e8fe4f
--- /dev/null
+++ b/web/noweb/contrib/norman/moddate.nw
@@ -0,0 +1,79 @@
+% -*- mode: Noweb; noweb-code-mode: c-mode -*-
+\section{Using file modification dates}
+
+\date{October 31, 1996}
+
+This \texttt{noweb} filter
+sets the date to the modification date of the file being woven.
+It relies on the convention that
+\begin{quote}
+\verb+\date{+\emph{mumble}\verb+}+
+\end{quote}
+appears on a line by itself. \emph{Mumble} stands for any string.
+The filter replaces \emph{Mumble} with the modifcation date and time
+of the file as announced by \verb+@file+.
+
+The filter uses POSIX functions, and it uses the \texttt{noweb} input
+stuff, so it has to be linked with
+\texttt{getline.o} \texttt{columns.o}, and \texttt{errors.o} from the
+\texttt{noweb} distribution.
+<<moddate.c*>>=
+<<includes>>
+<<local procs>>
+main() {
+ char *s;
+ char *file = NULL;
+ while (s = getline(stdin))
+ if (match("@file ", s)) {
+ printf("%s", s);
+ file = get_file_name(s);
+ } else if (matches_date(s) && file != NULL)
+ print_modification_time(file);
+ else
+ printf("%s", s);
+}
+@
+Matching ideas are stolen from Icon.
+<<local procs>>=
+match(char *pattern, char *s) {
+ return !strncmp(pattern, s, strlen(pattern));
+}
+<<local procs>>=
+matches_date(char *s) {
+ return match("@text \\date{", s) && s[strlen(s)-2] == '}';
+}
+@
+Allocate space for a file name and strip the trailing newline.
+<<local procs>>=
+char *get_file_name(char *s) {
+ char *p = (char *)malloc(strlen(s)); /* wastes some characters */
+ assert(p);
+ strcpy(p, s + strlen("@file "));
+ p[strlen(p)-1] = 0; /* trim newline */
+ return p;
+}
+@
+To get a nicer format for the time, I would replace the call to
+[[asctime]] with something else.
+<<local procs>>=
+void print_modification_time(char *file) {
+ struct stat buf;
+ int n = stat(file, &buf);
+ char *time;
+ if (n) {fprintf(stderr, "could not stat %s\n", file); exit(1); }
+ time = asctime(localtime(&buf.st_mtime));
+ if (time[strlen(time)-1] == '\n')
+ time[strlen(time)-1] = 0;
+ printf("@text \\date{%s}\\def\\today{%s}\n", time, time);
+}
+@
+<<includes>>=
+#include <time.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdio.h>
+#include "getline.h"
+
diff --git a/web/noweb/contrib/norman/numarkup/Makefile b/web/noweb/contrib/norman/numarkup/Makefile
new file mode 100644
index 0000000000..9165670393
--- /dev/null
+++ b/web/noweb/contrib/norman/numarkup/Makefile
@@ -0,0 +1,37 @@
+LIB=/dev/null # to be overridden
+CC = cc
+CFLAGS = -O
+
+TARGET = numarkup
+OBJS = main.o pass1.o latex.o input.o scraps.o names.o arena.o global.o
+
+.SUFFIXES: .nw
+.nw.c: ; notangle -R"$@"'*' -L $< | cpif $@
+.nw.h: ; notangle -R"$@" $< | cpif $@
+
+all:
+ noweb -t numarkup.nw
+ make $(TARGET)
+
+install:
+ noweb -t numarkup.nw
+ make $(TARGET)
+ strip $(TARGET)
+ cp $(TARGET) $(LIB)
+
+source: main.c pass1.c latex.c input.c scraps.c names.c arena.c global.c
+
+clean:
+ rm -f *.o *.c *.h *.tex *.log *.dvi *~ *.blg $(TARGET) *.html *~
+
+$(OBJS): global.h
+
+$(TARGET): $(OBJS)
+ $(CC) -o $(TARGET) $(OBJS)
+
+numarkup.html: numarkup.nw
+ noweave -filter l2h -html -index numarkup.nw > numarkup.html
+
+numarkup.tex: numarkup.nw
+ noweb -o numarkup.nw
+
diff --git a/web/noweb/contrib/norman/numarkup/numarkup.bbl b/web/noweb/contrib/norman/numarkup/numarkup.bbl
new file mode 100644
index 0000000000..224d2050b3
--- /dev/null
+++ b/web/noweb/contrib/norman/numarkup/numarkup.bbl
@@ -0,0 +1,58 @@
+\begin{thebibliography}{10}
+
+\bibitem{aho:75}
+Alfred~V. Aho and Margaret~J. Corasick.
+\newblock Efficient string matching: An aid to bibliographic search.
+\newblock {\em Communications of the ACM}, 18(6):333--340, June 1975.
+
+\bibitem{hanson:90}
+David~R. Hanson.
+\newblock Fast allocation and deallocation of memory based on object lifetimes.
+\newblock {\em Software -- Practice and Experience}, 20(1):5--12, January 1990.
+
+\bibitem{knuth:84}
+Donald~E. Knuth.
+\newblock Literate programming.
+\newblock {\em The Computer Journal}, 27(2):97--111, May 1984.
+
+\bibitem{metafont:program}
+Donald~E. Knuth.
+\newblock {\em {{\small\sf METAFONT:}} The Program}.
+\newblock Computers \& Typesetting. Addison-Wesley, 1986.
+
+\bibitem{tex:program}
+Donald~E. Knuth.
+\newblock {\em {{\TeX}}: The Program}.
+\newblock Computers \& Typesetting. Addison-Wesley, 1986.
+
+\bibitem{texbook}
+Donald~E. Knuth.
+\newblock {\em The {{\TeX}}book}.
+\newblock Computers \& Typesetting. Addison-Wesley, 1986.
+
+\bibitem{latex}
+Leslie Lamport.
+\newblock {\em {{\LaTeX:}} A Document Preparation System}.
+\newblock Addison-Wesley, 1986.
+
+\bibitem{levy:90}
+Silvio Levy and Donald~E. Knuth.
+\newblock {{\tt CWEB}} user manual: The {{\small CWEB}} system of structured
+ documentation.
+\newblock Technical Report {\small STAN}-{\small CS}-83-977, Stanford
+ University, October 1990.
+\newblock Available for anonymous ftp from {\tt labrea.stanford.edu} in
+ directory {\tt pub/cweb}.
+
+\bibitem{noweb}
+Norman Ramsey.
+\newblock Literate-programming tools need not be complex.
+\newblock Submitted to IEEE Software, August 1992.
+
+\bibitem{funnelweb}
+Ross~N. Williams.
+\newblock {FunnelWeb} user's manual, May 1992.
+\newblock Available for anonymous ftp from {\tt sirius.itd.adelaide.edu.au} in
+ directory {\tt pub/funnelweb}.
+
+\end{thebibliography}
diff --git a/web/noweb/contrib/norman/numarkup/numarkup.nw b/web/noweb/contrib/norman/numarkup/numarkup.nw
new file mode 100644
index 0000000000..e47c5a356c
--- /dev/null
+++ b/web/noweb/contrib/norman/numarkup/numarkup.nw
@@ -0,0 +1,1264 @@
+\documentstyle[noweb]{report}
+
+\title{Nuweb front end for noweb}
+\author{Norman Ramsey\\(from code by Preston Briggs)}
+
+\begin{document}
+\pagenumbering{roman}
+\maketitle
+\tableofcontents
+
+\chapter{Introduction}
+\pagenumbering{arabic}
+
+This code reads one or more nuweb files and produces noweb intermediate code
+ (as described in the {\em Noweb Hackers' Guide}) on
+standard output.
+It was created by modifying version 0.87 of nuweb.
+
+
+
+\chapter{The Overall Structure}
+
+Processing a web requires two major steps:
+\begin{enumerate}
+\item Read the source, accumulating file names, macro names, scraps,
+and lists of cross-references.
+This pass is needed so we can disambiguated scrap names.
+\item Reread the source, transforming it to noweb form on standard output.
+\end{enumerate}
+
+
+\section{Files}
+
+I have divided the program into several files for quicker
+recompilation during development.
+<<global.h>>=
+<<Include files>>
+<<Type declarations>>
+<<Global variable declarations>>
+<<Function prototypes>>
+@
+We'll need at least three of the standard system include files.
+<<Include files>>=
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+@ %def FILE stderr exit fprintf fputs fopen fclose getc putc strlen toupper isupper islower isgraph isspace tempnam remove malloc size_t
+@
+\newpage
+\noindent
+I also like to use [[TRUE]] and [[FALSE]] in my code.
+I'd use an [[enum]] here, except that some systems seem to provide
+definitions of [[TRUE]] and [[FALSE]] be default. The following
+code seems to work on all the local systems.
+<<Type declarations>>=
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE (!0)
+#endif
+@
+\subsection{The Main Files}
+
+The code is divided into four main files (introduced here) and five
+support files (introduced in the next section).
+The file [[main.c]] will contain the driver for the whole program
+(see Section~\ref{main-routine}).
+<<main.c*>>=
+#include "global.h"
+@
+The first pass over the source file is contained in [[pass1.c]].
+It handles collection of all the file names, macros names, and scraps
+(see Section~\ref{pass-one}).
+<<pass1.c*>>=
+#include "global.h"
+@
+The [[.tex]] file is created during a second pass over the source
+file. The file [[latex.c]] contains the code controlling the
+construction of the [[.tex]] file
+(see Section~\ref{latex-file}).
+<<latex.c*>>=
+#include "global.h"
+@
+\subsection{Support Files}
+
+The support files contain a variety of support routines used to define
+and manipulate the major data abstractions.
+The file [[input.c]] holds all the routines used for referring to
+source files (see Section~\ref{source-files}).
+<<input.c*>>=
+#include "global.h"
+@
+Creation and lookup of scraps is handled by routines in [[scraps.c]]
+(see Section~\ref{scraps}).
+<<scraps.c*>>=
+#include "global.h"
+@
+The handling of file names and macro names is detailed in [[names.c]]
+(see Section~\ref{names}).
+<<names.c*>>=
+#include "global.h"
+@
+Memory allocation and deallocation is handled by routines in [[arena.c]]
+(see Section~\ref{memory-management}).
+<<arena.c*>>=
+#include "global.h"
+@
+Finally, for best portability, I seem to need a file containing
+(useless!) definitions of all the global variables.
+<<global.c*>>=
+#include "global.h"
+<<Global variable definitions>>
+@
+\section{The Main Routine} \label{main-routine}
+
+The main routine is quite simple in structure.
+It wades through the optional command-line arguments,
+then handles any files listed on the command line.
+<<main.c*>>=
+void main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int arg = 1;
+ <<Interpret command-line arguments>>
+ <<Process the remaining arguments (file names)>>
+ exit(0);
+}
+@
+\subsection{Command-Line Arguments}
+
+There is one possible command-line argument:
+\begin{description}
+\item[\tt -v] The verbose flag. Forces output of progress reports.
+\end{description}
+
+Global flags are declared for each of the arguments.
+<<Global variable declarations>>=
+extern int verbose_flag; /* if TRUE, write progress information */
+@
+The flags are all initialized for correct default behavior.
+
+<<Global variable definitions>>=
+int verbose_flag = FALSE;
+@
+We save the invocation name of the command in a global variable
+[[command_name]] for use in error messages.
+<<Global variable declarations>>=
+extern char *command_name;
+<<Global variable definitions>>=
+char *command_name = NULL;
+@
+The invocation name is conventionally passed in [[argv[0]]].
+<<Interpret command-line arguments>>=
+command_name = argv[0];
+@
+We need to examine the remaining entries in [[argv]], looking for
+command-line arguments.
+<<Interpret command-line arguments>>=
+while (arg < argc) {
+ char *s = argv[arg];
+ if (*s++ == '-') {
+ <<Interpret the argument string [[s]]>>
+ arg++;
+ }
+ else break;
+}
+@
+Several flags can be stacked behind a single minus sign; therefore,
+we've got to loop through the string, handling them all.
+<<Interpret the argument string [[s]]>>=
+{
+ char c = *s++;
+ while (c) {
+ switch (c) {
+ case 'v': verbose_flag = TRUE;
+ break;
+ default: fprintf(stderr, "%s: unexpected argument ignored. ",
+ command_name);
+ fprintf(stderr, "Usage is: %s [-v] file...\n",
+ command_name);
+ break;
+ }
+ c = *s++;
+ }
+}
+@
+\subsection{File Names}
+
+We expect at least one file name. While a missing file name might be
+ignored without causing any problems, we take the opportunity to report
+the usage convention.
+<<Process the remaining arguments (file names)>>=
+{
+ if (arg >= argc) {
+ fprintf(stderr, "%s: expected a file name. ", command_name);
+ fprintf(stderr, "Usage is: %s [-v] file-name...\n", command_name);
+ exit(-1);
+ }
+ do {
+ <<Handle the file name in [[argv[arg]]]>>
+ arg++;
+ } while (arg < argc);
+}
+@
+The code to handle a particular file name is rather more tedious than
+the actual processing of the file. A file name may be an arbitrarily
+complicated path name, with an optional extension. If no extension is
+present, we add [[.w]] as a default. The extended path name will be
+kept in a local variable [[source_name]].
+<<Handle the file name in [[argv[arg]]]>>=
+{
+ char source_name[100];
+ <<Build [[source_name]]>>
+ <<Process a file>>
+}
+@
+I bump the pointer [[p]] through all the characters in [[argv[arg]]],
+copying all the characters into [[source_name]] (via the pointer
+[[q]]).
+
+At each slash, I update [[trim]] to point just past the
+slash in [[source_name]]. The effect is that [[trim]] will point
+at the file name without any leading directory specifications.
+
+The pointer [[dot]] is made to point at the file name extension, if
+present. If there is no extension, we add [[.w]] to the source name.
+In any case, we create the [[tex_name]] from [[trim]], taking
+care to get the correct extension.
+<<Build [[source_name]]>>=
+{
+ char *p = argv[arg];
+ char *q = source_name;
+ char *dot = NULL;
+ char c = *p++;
+ while (c) {
+ *q++ = c;
+ if (c == '/') {
+ dot = NULL;
+ }
+ else if (c == '.')
+ dot = q - 1;
+ c = *p++;
+ }
+ *q = '\0';
+ if (!dot) {
+ *q++ = '.';
+ *q++ = 'w';
+ *q = '\0';
+ }
+}
+@
+Now that we're finally ready to process a file, it's not really too
+complex. We bundle most of the work into routines [[pass1]]
+(see Section~\ref{pass-one}) and [[write_tex]] (see
+Section~\ref{latex-file}). After we're finished with a
+particular file, we must remember to release its storage (see
+Section~\ref{memory-management}).
+<<Process a file>>=
+{
+ pass1(source_name);
+ write_tex(source_name, "bogus");
+ arena_free();
+}
+@
+\section{Pass One} \label{pass-one}
+
+During the first pass, we scan the file, saving names so we'll be able to
+disambiguated them later.
+<<Function prototypes>>=
+extern void pass1();
+@
+The routine [[pass1]] takes a single argument, the name of the
+source file. It opens the file, then initializes the scrap structures
+(see Section~\ref{scraps}) and the roots of the file-name tree, the
+macro-name tree, and the tree of user-specified index entries (see
+Section~\ref{names}). After completing all the
+necessary preparation, we make a pass over the file, filling in all
+our data structures. Next, we seach all the scraps for references to
+the user-specified index entries. Finally, we must reverse all the
+cross-reference lists accumulated while scanning the scraps.
+<<pass1.c*>>=
+void pass1(file_name)
+ char *file_name;
+{
+ if (verbose_flag)
+ fprintf(stderr, "reading %s\n", file_name);
+ source_open(file_name);
+ macro_names = NULL;
+ file_names = NULL;
+ <<Scan the source file, looking for at-sequences>>
+}
+@
+The only thing we look for in the first pass are the command
+sequences. All ordinary text is skipped entirely.
+<<Scan the source file, looking for at-sequences>>=
+{
+ int c = source_get();
+ while (c != EOF) {
+ if (c == '@')
+ <<Scan at-sequence>>
+ c = source_get();
+ }
+}
+@
+Only four of the at-sequences are interesting during the first pass.
+We skip past others immediately; warning if unexpected sequences are
+discovered.
+<<Scan at-sequence>>=
+{
+ c = source_get();
+ switch (c) {
+ case 'O':
+ case 'o': <<Build output file definition>>
+ break;
+ case 'D':
+ case 'd': <<Build macro definition>>
+ break;
+ case '@':
+ case 'u':
+ case 'm':
+ case 'f': /* ignore during this pass */
+ break;
+ default: fprintf(stderr,
+ "%s: unexpected @ sequence ignored (%s, line %d)\n",
+ command_name, source_name, source_line);
+ break;
+ }
+}
+@
+\subsection{Accumulating Definitions}
+
+There are two steps required to handle a definition:
+\begin{enumerate}
+\item Build an entry for the name so we can look it up later.
+\item Skip past the scrap.
+\end{enumerate}
+We go through the same steps for both file names and macro names.
+<<Build output file definition>>=
+{
+ collect_file_name();
+ collect_scrap();
+}
+<<Build macro definition>>=
+{
+ collect_macro_name();
+ collect_scrap();
+}
+@
+\section{Writing the Latex File} \label{latex-file}
+
+The second pass (invoked via a call to [[write_tex]]) copies most of
+the text from the source file straight into a [[.tex]] file.
+Definitions are formatted slightly and cross-reference information is
+printed out.
+
+Note that all the formatting is handled in this section.
+If you don't like the format of definitions or indices or whatever,
+it'll be in this section somewhere. Similarly, if someone wanted to
+modify nuweb to work with a different typesetting system, this would
+be the place to look.
+
+<<Function prototypes>>=
+extern void write_tex();
+@
+We need a few local function declarations before we get into the body
+of [[write_tex]].
+<<latex.c*>>=
+static void copy_scrap(); /* formats the body of a scrap */
+@
+The routine [[write_tex]] takes two file names as parameters: the
+name of the web source file and the name of the [[.tex]] output file.
+<<latex.c*>>=
+void write_tex(file_name, tex_name)
+ char *file_name;
+ char *tex_name;
+{
+ if (verbose_flag)
+ fprintf(stderr, "writing %s\n", "standard output");
+ source_open(file_name);
+ printf("@file %s\n", file_name);
+ <<Copy [[source_file]] into standard output, transforming to noweb>>
+}
+@
+We make our second (and final) pass through the source web, this time
+copying characters straight into the [[.tex]] file. However, we keep
+an eye peeled for [[@]]~characters, which signal a command sequence.
+
+We keep track of state.
+
+<<Copy [[source_file]] into standard output, transforming to noweb>>=
+{
+ int scraps = 1;
+ int c = source_get();
+ int docs_begun = 0;
+ while (c != EOF) {
+ if (c == '@') {
+ <<Interpret at-sequence>>
+ } else {
+ <<begin documentation chunk>>
+ if (c == '\n')
+ printf("\n@nl\n@text ");
+ else
+ putchar(c);
+ c = source_get();
+ }
+ }
+}
+<<begin documentation chunk>>=
+if (!docs_begun) {
+ docs_begun = 1;
+ printf("@begin docs %d\n", ++chunk_count);
+ printf("@text ");
+}
+@
+
+Counting chunks needs a global variable.
+<<Global variable declarations>>=
+
+extern int chunk_count;
+<<Global variable definitions>>=
+
+int chunk_count = 0;
+<<end documentation chunk>>=
+
+if (docs_begun) {
+ printf("\n@end docs %d\n", chunk_count);
+ docs_begun = 0;
+}
+<<Interpret at-sequence>>=
+{
+ int big_definition = FALSE;
+ c = source_get();
+ switch (c) {
+ case 'O': big_definition = TRUE;
+ case 'o': <<end documentation chunk>>
+ <<Write output file definition>>
+ break;
+ case 'D': big_definition = TRUE;
+ case 'd': <<end documentation chunk>>
+ <<Write macro definition>>
+ break;
+ case 'f': <<Write index of file names>>
+ break;
+ case 'm': <<Write index of macro names>>
+ break;
+ case 'u': <<Write index of user-specified names>>
+ break;
+ case '@': <<begin documentation chunk>> putchar(c); /* fall through */
+ default: c = source_get();
+ break;
+ }
+}
+@
+Macro and file definitions are formatted nearly identically.
+<<Write output file definition>>=
+{
+ Name *name = collect_file_name();
+ printf("@begin code %d\n", ++chunk_count);
+ printf("@defn %s%s\n@nl\n", name->spelling, name->debug_flag ? "*" : "");
+ copy_scrap();
+ <<Finish the scrap environment>>
+}
+<<Write macro definition>>=
+{
+ Name *name = collect_macro_name();
+ printf("@begin code %d\n", ++chunk_count);
+ printf("@defn %s\n@nl\n", name->spelling);
+ copy_scrap();
+ <<Finish the scrap environment>>
+}
+<<Finish the scrap environment>>=
+{
+ printf("\n@end code %d\n", chunk_count);
+ do
+ c = source_get();
+ while (isspace(c)); /* may not be appropriate for noweb */
+}
+@
+\subsubsection{Formatting a Scrap}
+<<latex.c*>>=
+static void copy_scrap()
+{
+ int c = source_get();
+ int indent = 0;
+ printf("@text ");
+ while (1) {
+ switch (c) {
+ case '@': <<Check at-sequence for end-of-scrap>>
+ break;
+ case '\n': printf("\n@nl\n@text ");
+ indent = 0;
+ break;
+ case '\t': <<Expand tab into spaces>>
+ break;
+ default: putchar(c);
+ indent++;
+ break;
+ }
+ c = source_get();
+ }
+}
+<<Expand tab into spaces>>=
+{
+ int delta = 8 - (indent % 8);
+ indent += delta;
+ while (delta > 0) {
+ putchar(' ');
+ delta--;
+ }
+}
+<<Check at-sequence for end-of-scrap>>=
+{
+ c = source_get();
+ switch (c) {
+ case '@': putchar('@');
+ break;
+ case '|': printf("\n");
+ <<print out index entries>> /* fall through */
+ case '}': return;
+ case '<': <<Format macro name>>
+ break;
+ default : fprintf(stderr, "%s: unexpected @%c in scrap (%s, %d)\n",
+ command_name, c, source_name, source_line);
+ exit(-1);
+ }
+}
+<<print out index entries>>=
+{
+ do {
+ char new_name[100];
+ char *p = new_name;
+ do
+ c = source_get();
+ while (isspace(c));
+ if (c != '@') {
+ Name *name;
+ do {
+ *p++ = c;
+ c = source_get();
+ } while (c != '@' && !isspace(c));
+ *p = '\0';
+ printf("@index defn %s\n", new_name);
+ }
+ } while (c != '@');
+ printf("@text "); /* maintain invariant, even though no more text is coming */
+ c = source_get();
+ if (c != '}') {
+ fprintf(stderr, "%s: unexpected @%c in scrap (%s, %d)\n",
+ command_name, c, source_name, source_line);
+ exit(-1);
+ }
+}
+<<Format macro name>>=
+{
+ Name *name = collect_scrap_name();
+ printf("\n@use %s\n@text ", name->spelling);
+}
+@
+\subsection{Generating the Indices}
+
+<<Write index of file names>>=
+{
+ /* noweb doesn't do files; they're all macros */
+ c = source_get();
+}
+<<Write index of macro names>>=
+{
+ <<begin documentation chunk>>
+ printf("\\nowebchunks ");
+ c = source_get();
+}
+<<Write index of user-specified names>>=
+{
+ <<begin documentation chunk>>
+ printf("\\nowebindex ");
+ c = source_get();
+}
+@
+\chapter{The Support Routines}
+
+\section{Source Files} \label{source-files}
+
+\subsection{Global Declarations}
+
+We need two routines to handle reading the source files.
+<<Function prototypes>>=
+extern void source_open(); /* pass in the name of the source file */
+extern int source_get(); /* no args; returns the next char or EOF */
+@
+There are also two global variables maintained for use in error
+messages and such.
+<<Global variable declarations>>=
+extern char *source_name; /* name of the current file */
+extern int source_line; /* current line in the source file */
+<<Global variable definitions>>=
+char *source_name = NULL;
+int source_line = 0;
+@
+\subsection{Local Declarations}
+
+
+<<input.c*>>=
+static FILE *source_file; /* the current input file */
+static int source_peek;
+static int double_at;
+static int include_depth;
+<<input.c*>>=
+struct {
+ FILE *file;
+ char *name;
+ int line;
+} stack[10];
+@
+\subsection{Reading a File}
+
+The routine [[source_get]] returns the next character from the
+current source file. It notices newlines and keeps the line counter
+[[source_line]] up to date. It also catches [[EOF]] and watches
+for [[@]]~characters. All other characters are immediately returned.
+<<input.c*>>=
+int source_get()
+{
+ int c = source_peek;
+ switch (c) {
+ case EOF: <<Handle [[EOF]]>>
+ return c;
+ case '@': <<Handle an ``at'' character>>
+ return c;
+ case '\n': source_line++;
+ default: source_peek = getc(source_file);
+ return c;
+ }
+}
+@
+This whole [[@]]~character handling mess is pretty annoying.
+I want to recognize [[@i]] so I can handle include files correctly.
+At the same time, it makes sense to recognize illegal [[@]]~sequences
+and complain; this avoids ever having to check anywhere else.
+Unfortunately, I need to avoid tripping over the [[@@]]~sequence;
+hence this whole unsatisfactory [[double_at]] business.
+<<Handle an ``at'' character>>=
+{
+ c = getc(source_file);
+ if (double_at) {
+ source_peek = c;
+ double_at = FALSE;
+ c = '@';
+ }
+ else
+ switch (c) {
+ case 'i': <<Open an include file>>
+ break;
+ case 'f': case 'm': case 'u':
+ case 'd': case 'o': case 'D': case 'O':
+ case '{': case '}': case '<': case '>': case '|':
+ source_peek = c;
+ c = '@';
+ break;
+ case '@': source_peek = c;
+ double_at = TRUE;
+ break;
+ default: fprintf(stderr, "%s: bad @ sequence (%s, line %d)\n",
+ command_name, source_name, source_line);
+ exit(-1);
+ }
+}
+<<Open an include file>>=
+{
+ char name[100];
+ if (include_depth >= 10) {
+ fprintf(stderr, "%s: include nesting too deep (%s, %d)\n",
+ command_name, source_name, source_line);
+ exit(-1);
+ }
+ <<Collect include-file name>>
+ stack[include_depth].name = source_name;
+ stack[include_depth].file = source_file;
+ stack[include_depth].line = source_line + 1;
+ include_depth++;
+ source_line = 1;
+ source_name = save_string(name);
+ source_file = fopen(source_name, "r");
+ if (!source_file) {
+ fprintf(stderr, "%s: can't open include file %s\n",
+ command_name, source_name);
+ exit(-1);
+ }
+ source_peek = getc(source_file);
+ c = source_get();
+}
+<<Collect include-file name>>=
+{
+ char *p = name;
+ do
+ c = getc(source_file);
+ while (c == ' ' || c == '\t');
+ while (isgraph(c)) {
+ *p++ = c;
+ c = getc(source_file);
+ }
+ *p = '\0';
+ if (c != '\n') {
+ fprintf(stderr, "%s: unexpected characters after file name (%s, %d)\n",
+ command_name, source_name, source_line);
+ exit(-1);
+ }
+}
+@
+If an [[EOF]] is discovered, the current file must be closed and
+input from the next stacked file must be resumed. If no more files are
+on the stack, the [[EOF]] is returned.
+<<Handle [[EOF]]>>=
+{
+ fclose(source_file);
+ if (include_depth) {
+ include_depth--;
+ source_file = stack[include_depth].file;
+ source_line = stack[include_depth].line;
+ source_name = stack[include_depth].name;
+ source_peek = getc(source_file);
+ c = source_get();
+ }
+}
+@
+\subsection{Opening a File}
+
+The routine [[source_open]] takes a file name and tries to open the
+file. If unsuccessful, it complains and halts. Otherwise, it sets
+[[source_name]], [[source_line]], and [[double_at]].
+<<input.c*>>=
+void source_open(name)
+ char *name;
+{
+ source_file = fopen(name, "r");
+ if (!source_file) {
+ fprintf(stderr, "%s: couldn't open %s\n", command_name, name);
+ exit(-1);
+ }
+ source_name = name;
+ source_line = 1;
+ source_peek = getc(source_file);
+ double_at = FALSE;
+ include_depth = 0;
+}
+@
+\section{Scraps} \label{scraps}
+<<scraps.c*>>=
+void collect_scrap()
+{
+ char *source = save_string(source_name);
+ int line = source_line;
+ <<Accumulate scrap and return>>
+}
+<<Accumulate scrap and return>>=
+{
+ int c = source_get();
+ while (1) {
+ switch (c) {
+ case EOF: fprintf(stderr, "%s: unexpected EOF in scrap (%s, %d)\n",
+ command_name, source, line);
+ exit(-1);
+ case '@': <<Handle at-sign during scrap accumulation>>
+ break;
+ default: c = source_get();
+ break;
+ }
+ }
+}
+<<Handle at-sign during scrap accumulation>>=
+{
+ c = source_get();
+ switch (c) {
+ case '@': c = source_get();
+ break;
+ case '|': <<skip user-specified index entries>>
+ case '}': return;
+ case '<': <<Handle macro invocation in scrap>>
+ break;
+ default : fprintf(stderr, "%s: unexpected @%c in scrap (%s, %d)\n",
+ command_name, c, source_name, source_line);
+ exit(-1);
+ }
+}
+<<skip user-specified index entries>>=
+{
+ do {
+ do
+ c = source_get();
+ while (c != '@');
+ c = source_get();
+ } while (c == '@');
+ if (c != '}') {
+ fprintf(stderr, "%s: unexpected @%c in scrap (%s, %d)\n",
+ command_name, c, source_name, source_line);
+ exit(-1);
+ }
+}
+<<Handle macro invocation in scrap>>=
+{
+ (void) collect_scrap_name();
+ c = source_get();
+}
+<<Function prototypes>>=
+extern void collect_scrap();
+@
+\section{Names} \label{names}
+<<Type declarations>>=
+typedef struct name {
+ char *spelling;
+ struct name *llink;
+ struct name *rlink;
+ int mark;
+ char tab_flag;
+ char indent_flag;
+ char debug_flag;
+} Name;
+<<Global variable declarations>>=
+extern Name *file_names;
+extern Name *macro_names;
+<<Global variable definitions>>=
+Name *file_names = NULL;
+Name *macro_names = NULL;
+<<Function prototypes>>=
+extern Name *collect_file_name();
+extern Name *collect_macro_name();
+extern Name *collect_scrap_name();
+extern Name *name_add();
+extern Name *prefix_add();
+extern char *save_string();
+<<names.c*>>=
+enum { LESS, GREATER, EQUAL, PREFIX, EXTENSION };
+
+static int compare(x, y)
+ char *x;
+ char *y;
+{
+ int len, result;
+ int xl = strlen(x);
+ int yl = strlen(y);
+ int xp = x[xl - 1] == ' ';
+ int yp = y[yl - 1] == ' ';
+ if (xp) xl--;
+ if (yp) yl--;
+ len = xl < yl ? xl : yl;
+ result = strncmp(x, y, len);
+ if (result < 0) return GREATER;
+ else if (result > 0) return LESS;
+ else if (xl < yl) {
+ if (xp) return EXTENSION;
+ else return LESS;
+ }
+ else if (xl > yl) {
+ if (yp) return PREFIX;
+ else return GREATER;
+ }
+ else return EQUAL;
+}
+@ %def compare LESS GREATER EQUAL PREFIX EXTENSION
+<<names.c*>>=
+char *save_string(s)
+ char *s;
+{
+ char *new = (char *) arena_getmem((strlen(s) + 1) * sizeof(char));
+ strcpy(new, s);
+ return new;
+}
+@ %def save_string
+<<names.c*>>=
+static int ambiguous_prefix();
+
+Name *prefix_add(root, spelling)
+ Name **root;
+ char *spelling;
+{
+ Name *node = *root;
+ while (node) {
+ switch (compare(node->spelling, spelling)) {
+ case GREATER: root = &node->rlink;
+ break;
+ case LESS: root = &node->llink;
+ break;
+ case EQUAL: return node;
+ case EXTENSION: node->spelling = save_string(spelling);
+ return node;
+ case PREFIX: <<Check for ambiguous prefix>>
+ return node;
+ }
+ node = *root;
+ }
+ <<Create new name entry>>
+}
+@ %def prefix_add
+@
+Since a very short prefix might match more than one macro name, I need
+to check for other matches to avoid mistakes. Basically, I simply
+continue the search down {\em both\/} branches of the tree.
+
+<<Check for ambiguous prefix>>=
+{
+ if (ambiguous_prefix(node->llink, spelling) ||
+ ambiguous_prefix(node->rlink, spelling))
+ fprintf(stderr,
+ "%s: ambiguous prefix @<%s...@> (%s, line %d)\n",
+ command_name, spelling, source_name, source_line);
+}
+<<names.c*>>=
+static int ambiguous_prefix(node, spelling)
+ Name *node;
+ char *spelling;
+{
+ while (node) {
+ switch (compare(node->spelling, spelling)) {
+ case GREATER: node = node->rlink;
+ break;
+ case LESS: node = node->llink;
+ break;
+ case EQUAL:
+ case EXTENSION:
+ case PREFIX: return TRUE;
+ }
+ }
+ return FALSE;
+}
+@ %def ambiguous_prefix
+<<names.c*>>=
+Name *name_add(root, spelling)
+ Name **root;
+ char *spelling;
+{
+ Name *node = *root;
+ while (node) {
+ int result = strcmp(node->spelling, spelling);
+ if (result > 0)
+ root = &node->llink;
+ else if (result < 0)
+ root = &node->rlink;
+ else
+ return node;
+ node = *root;
+ }
+ <<Create new name entry>>
+}
+@ %def name_add
+<<Create new name entry>>=
+{
+ node = (Name *) arena_getmem(sizeof(Name));
+ node->spelling = save_string(spelling);
+ node->mark = FALSE;
+ node->llink = NULL;
+ node->rlink = NULL;
+ node->tab_flag = TRUE;
+ node->indent_flag = TRUE;
+ node->debug_flag = FALSE;
+ *root = node;
+ return node;
+}
+@
+Name terminated by whitespace. Also check for ``per-file'' flags. Keep
+skipping white space until we reach scrap.
+<<names.c*>>=
+Name *collect_file_name()
+{
+ Name *new_name;
+ char name[100];
+ char *p = name;
+ int start_line = source_line;
+ int c = source_get();
+ while (isspace(c))
+ c = source_get();
+ while (isgraph(c)) {
+ *p++ = c;
+ c = source_get();
+ }
+ if (p == name) {
+ fprintf(stderr, "%s: expected file name (%s, %d)\n",
+ command_name, source_name, start_line);
+ exit(-1);
+ }
+ *p = '\0';
+ new_name = name_add(&file_names, name);
+ <<Handle optional per-file flags>>
+ if (c != '@' || source_get() != '{') {
+ fprintf(stderr, "%s: expected @{ after file name (%s, %d)\n",
+ command_name, source_name, start_line);
+ exit(-1);
+ }
+ return new_name;
+}
+@ %def collect_file_name
+<<Handle optional per-file flags>>=
+{
+ while (1) {
+ while (isspace(c))
+ c = source_get();
+ if (c == '-') {
+ c = source_get();
+ do {
+ switch (c) {
+ case 't': new_name->tab_flag = FALSE;
+ break;
+ case 'd': new_name->debug_flag = TRUE;
+ break;
+ case 'i': new_name->indent_flag = FALSE;
+ break;
+ default : fprintf(stderr, "%s: unexpected per-file flag (%s, %d)\n",
+ command_name, source_name, source_line);
+ break;
+ }
+ c = source_get();
+ } while (!isspace(c));
+ }
+ else break;
+ }
+}
+@
+Name terminated by \verb+\n+ or \verb+@{+; but keep skipping until \verb+@{+
+<<names.c*>>=
+Name *collect_macro_name()
+{
+ char name[100];
+ char *p = name;
+ int start_line = source_line;
+ int c = source_get();
+ while (isspace(c))
+ c = source_get();
+ while (c != EOF) {
+ switch (c) {
+ case '@': <<Check for terminating at-sequence and return name>>
+ break;
+ case '\t':
+ case ' ': *p++ = ' ';
+ do
+ c = source_get();
+ while (c == ' ' || c == '\t');
+ break;
+ case '\n': <<Skip until scrap begins, then return name>>
+ default: *p++ = c;
+ c = source_get();
+ break;
+ }
+ }
+ fprintf(stderr, "%s: expected macro name (%s, %d)\n",
+ command_name, source_name, start_line);
+ exit(-1);
+ return NULL; /* unreachable return to avoid warnings on some compilers */
+}
+@ %def collect_macro_name
+<<Check for terminating at-sequence and return name>>=
+{
+ c = source_get();
+ switch (c) {
+ case '@': *p++ = c;
+ break;
+ case '{': <<Cleanup and install name>>
+ default: fprintf(stderr,
+ "%s: unexpected @%c in macro name (%s, %d)\n",
+ command_name, c, source_name, start_line);
+ exit(-1);
+ }
+}
+<<Cleanup and install name>>=
+{
+ if (p > name && p[-1] == ' ')
+ p--;
+ if (p - name > 3 && p[-1] == '.' && p[-2] == '.' && p[-3] == '.') {
+ p[-3] = ' ';
+ p -= 2;
+ }
+ if (p == name || name[0] == ' ') {
+ fprintf(stderr, "%s: empty scrap name (%s, %d)\n",
+ command_name, source_name, source_line);
+ exit(-1);
+ }
+ *p = '\0';
+ return prefix_add(&macro_names, name);
+}
+<<Skip until scrap begins, then return name>>=
+{
+ do
+ c = source_get();
+ while (isspace(c));
+ if (c != '@' || source_get() != '{') {
+ fprintf(stderr, "%s: expected @{ after macro name (%s, %d)\n",
+ command_name, source_name, start_line);
+ exit(-1);
+ }
+ <<Cleanup and install name>>
+}
+@
+Terminated by \verb+@>+
+<<names.c*>>=
+Name *collect_scrap_name()
+{
+ char name[100];
+ char *p = name;
+ int c = source_get();
+ while (c == ' ' || c == '\t')
+ c = source_get();
+ while (c != EOF) {
+ switch (c) {
+ case '@': <<Look for end of scrap name and return>>
+ break;
+ case '\t':
+ case ' ': *p++ = ' ';
+ do
+ c = source_get();
+ while (c == ' ' || c == '\t');
+ break;
+ default: if (!isgraph(c)) {
+ fprintf(stderr,
+ "%s: unexpected character in macro name (%s, %d)\n",
+ command_name, source_name, source_line);
+ exit(-1);
+ }
+ *p++ = c;
+ c = source_get();
+ break;
+ }
+ }
+ fprintf(stderr, "%s: unexpected end of file (%s, %d)\n",
+ command_name, source_name, source_line);
+ exit(-1);
+ return NULL; /* unreachable return to avoid warnings on some compilers */
+}
+@ %def collect_scrap_name
+<<Look for end of scrap name and return>>=
+{
+ c = source_get();
+ switch (c) {
+ case '@': *p++ = c;
+ c = source_get();
+ break;
+ case '>': <<Cleanup and install name>>
+ default: fprintf(stderr,
+ "%s: unexpected @%c in macro name (%s, %d)\n",
+ command_name, c, source_name, source_line);
+ exit(-1);
+ }
+}
+@
+\section{Memory Management} \label{memory-management}
+
+I manage memory using a simple scheme inspired by Hanson's idea of
+{\em arenas\/}~\cite{hanson:90}.
+Basically, I allocate all the storage required when processing a
+source file (primarily for names and scraps) using calls to
+[[arena_getmem(n)]], where [[n]] specifies the number of bytes to
+be allocated. When the storage is no longer required, the entire arena
+is freed with a single call to [[arena_free()]]. Both operations
+are quite fast.
+<<Function prototypes>>=
+extern void *arena_getmem();
+extern void arena_free();
+<<arena.c*>>=
+typedef struct chunk {
+ struct chunk *next;
+ char *limit;
+ char *avail;
+} Chunk;
+@ %def Chunk
+@
+We define an empty chunk called [[first]]. The variable [[arena]] points
+at the current chunk of memory; it's initially pointed at [[first]].
+As soon as some storage is required, a ``real'' chunk of memory will
+be allocated and attached to [[first->next]]; storage will be
+allocated from the new chunk (and later chunks if necessary).
+<<arena.c*>>=
+static Chunk first = { NULL, NULL, NULL };
+static Chunk *arena = &first;
+@ %def first arena
+@
+\subsection{Allocating Memory}
+
+The routine [[arena_getmem(n)]] returns a pointer to (at least)
+[[n]] bytes of memory. Note that [[n]] is rounded up to ensure
+that returned pointers are always aligned. We align to the nearest
+8~byte segment, since that'll satisfy the more common 2-byte and
+4-byte alignment restrictions too.
+
+<<arena.c*>>=
+void *arena_getmem(n)
+ size_t n;
+{
+ char *q;
+ char *p = arena->avail;
+ n = (n + 7) & ~7; /* ensuring alignment to 8 bytes */
+ q = p + n;
+ if (q <= arena->limit) {
+ arena->avail = q;
+ return p;
+ }
+ <<Find a new chunk of memory>>
+}
+@ %def arena_getmem
+@
+If the current chunk doesn't have adequate space (at least [[n]]
+bytes) we examine the rest of the list of chunks (starting at
+[[arena->next]]) looking for a chunk with adequate space. If [[n]]
+is very large, we may not find it right away or we may not find a
+suitable chunk at all.
+<<Find a new chunk of memory>>=
+{
+ Chunk *ap = arena;
+ Chunk *np = ap->next;
+ while (np) {
+ char *v = sizeof(Chunk) + (char *) np;
+ if (v + n <= np->limit) {
+ np->avail = v + n;
+ arena = np;
+ return v;
+ }
+ ap = np;
+ np = ap->next;
+ }
+ <<Allocate a new chunk of memory>>
+}
+@
+If there isn't a suitable chunk of memory on the free list, then we
+need to allocate a new one.
+<<Allocate a new chunk of memory>>=
+{
+ size_t m = n + 10000;
+ np = (Chunk *) malloc(m);
+ np->limit = m + (char *) np;
+ np->avail = n + sizeof(Chunk) + (char *) np;
+ np->next = NULL;
+ ap->next = np;
+ arena = np;
+ return sizeof(Chunk) + (char *) np;
+}
+@
+\subsection{Freeing Memory}
+
+To free all the memory in the arena, we need only point [[arena]]
+back to the first empty chunk.
+<<arena.c*>>=
+void arena_free()
+{
+ arena = &first;
+}
+@ %def arena_free
+@
+\chapter{Indices} \label{indices}
+
+\section{Chunks}
+
+\nowebchunks
+
+\section{Identifiers}
+
+Knuth prints his index of indentifiers in a two-column format.
+I could force this automatically by emitting the [[\twocolumn]]
+command; but this has the side effect of forcing a new page.
+Therefore, it seems better to leave it this up to the user.
+
+\nowebindex
+
+\bibliographystyle{plain}
+\bibliography{literate}
+
+\end{document}
diff --git a/web/noweb/contrib/norman/pp/mkfile b/web/noweb/contrib/norman/pp/mkfile
new file mode 100644
index 0000000000..894316536f
--- /dev/null
+++ b/web/noweb/contrib/norman/pp/mkfile
@@ -0,0 +1,24 @@
+ICONT=icont
+
+%: %.icn
+ $ICONT $target
+
+%.icn: %.nw
+ notangle -L'#line %-1L "%F"%N' $prereq > $target
+
+all:V: pp pp.ps pp.html
+
+$BIN/nwpp: pp.icn
+ $ICONT -o $target $prereq
+
+pp.tex: pp.nw
+ noweave -delay -autodefs icon -index $prereq > $target
+
+pp.html: pp.nw
+ noweave -filter l2h -delay -autodefs icon -index -html $prereq > $target
+
+clean:V:
+ rm -f *~ *.tex *.dvi *.logf *.icn *.u1 *.u2 *.aux *.toc *.log
+
+clobber:V: clean
+ rm -f *.ps *.dvi *.html pp
diff --git a/web/noweb/contrib/norman/pp/pp.nw b/web/noweb/contrib/norman/pp/pp.nw
new file mode 100644
index 0000000000..b8260d226b
--- /dev/null
+++ b/web/noweb/contrib/norman/pp/pp.nw
@@ -0,0 +1,314 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+
+\documentclass {article}
+\usepackage {noweb}
+
+\title {Simple prettyprinting with Noweb}
+\author{Norman Ramsey\\ \texttt{nr@eecs.harvard.edu}}
+
+\begin {document}
+@
+\maketitle
+
+\section {Introduction}
+
+This is a pretty-printer, written as a filter for the noweb
+literate-programming tool.
+The prettyprinter does not touch indentation and line breaks; what it
+does is break each code line into tokens, then reformat the tokens.
+Some of the prettyprinter's capabilities are specified in a
+translation table.
+This table is written in a file, which must be named as the first argument.
+The prettyprinter will:
+\begin{itemize}
+\item format special tokens as specified in the parameter file
+\item keep track of which tokens need to be in math mode, and take
+care of it
+\item change underscores to subscripts in the names of identifiers
+\end{itemize}
+The prettyprinter doesn't do a great job with quoted strings, and it
+doesn't do anything intelligent with comments.
+Users are invited to improve these aspects.
+
+Using the prettyprinter requires changing the {\TeX} code that noweb
+runs at the start of a code chunk. This may do the job:
+\begin{verbatim}
+\usepackage{noweb}
+\let\originalprime='
+\def\setupcode{\catcode`\ =10 \catcode`\'=13 \regressprime}
+{\catcode`\'=\active
+ \makeatletter
+ \gdef\regressprime{\def'{^\bgroup\prim@s}}}
+\let\Tt\relax
+\end{verbatim}
+
+The prettyprinter uses the ``finduses'' model of symbols, alphanumerics, and
+delimiters.
+A token is
+\begin{itemize}
+\item whitespace,
+\item a maximal string of symbols,
+\item a maximal string of alphanumerics
+\item a single delimiter, or
+\item a string that begins with a delimiter and appears in the
+translation table.
+\end{itemize}
+<<*>>=
+global alphanum, symbols # anything else is a delimiter
+@ The defaults are as in ``finduses.''
+<<initialization>>=
+alphanum := &letters ++ &digits ++ '_\'@#'
+symbols := '!%^&*-+:=|~<>./?`'
+@
+All tokens become {\TeX} strings, and we track three kinds.
+<<*>>=
+record space(string) # white space
+record math(string) # string to appear in math mode
+record nonmath(string) # string to appear outside of math mode
+@ Space between two math tokens goes in math mode; space adjacent to a
+nonmath token goes in nonmath mode.
+@
+Sometimes we have to convert something to math mode.
+<<*>>=
+procedure mathcvt(s)
+ return case type(s) of {
+ "math" | "space" : s
+ "nonmath" : math("\\mbox{" || s.string || "}")
+ }
+ stop("bad math conversion of ", image(s))
+end
+procedure mathstring(s)
+ return mathcvt(s).string
+end
+@
+A table [[translation]] defines a translation into \TeX\ code for every interesting
+token in the target language.
+The table is a sequence of lines of the form
+\begin{quote}
+\begin{tabular}{ll}
+\verb+$+\emph{token} \emph{translation}&A math-mode token\\
+\verb+-+\emph{token} \emph{translation}&A non-math token\\
+\verb+A+\emph{chars}&List of all characters to be considered alphanumerics\\
+\verb+S+\emph{chars}&List of all characters to be considered symbols\\
+\end{tabular}
+\end{quote}
+Tokens, including identifiers and symbols, are considered to be
+math-mode tokens unless the translation table specifies otherwise.
+<<*>>=
+procedure read_translation(fname)
+ local f, line, k, v, t
+ f := open(fname) | stop("Cannot open file ", fname)
+ t := table()
+ while line := read(f) do
+ line ?
+ case move(1) of {
+ "$" : { tab(many(' \t')); k := tab(upto(' \t')); tab(many(' \t')); v := tab(0)
+ t[k] := math(v) }
+ "-" : { tab(many(' \t')); k := tab(upto(' \t')); tab(many(' \t')); v := tab(0)
+ t[k] := nonmath(v) }
+ "A" : alphanum := cset(tab(0))
+ "S" : symbols := cset(tab(0))
+ default : stop("Table entry must begin with $ or - or A or S")
+ }
+ close(f)
+ return t
+end
+@
+The rest is uninteresting Icon code, which surely could be better documented.
+<<*>>=
+global trans
+procedure main(args)
+ local curline, curmath
+ <<initialization>>
+ trans := read_translation(get(args)) | stop("Must specify translation table")
+ <<add \TeX\ specials to [[trans]]>>
+ dtrans := table()
+ every k := key(trans) & not any(symbols, k) & not any(alphanum, k) do
+ dtrans[k] := trans[k]
+ curline := []
+ code := &null
+ while line := read() do
+ line ? { <<consume input>> }
+end
+@
+Instead of escaping the {\TeX} specials, I just put them in the
+translation table if they aren't already.
+<<add \TeX\ specials to [[trans]]>>=
+every c := !"{}#$%^&_" do /trans[c] := math("\\" || c)
+/trans["\\"] := math("\\backslash ")
+@
+We accumulate tokens into [[curline]], then emit them when we reach
+the end of a line or the end of code.
+<<consume input>>=
+="@" | stop("Malformed line in noweb pipeline")
+keyword := tab(upto(' ')|0)
+value := if pos(0) then &null else (=" ", tab(0))
+case keyword of {
+ "begin" : {if match("code", value) then code := 1 else code := &null
+ write(line)}
+ "end" : { <<drain accumulation>>; code := &null; write(line) }
+ "quote" : {code := 1; write(line)}
+ "endquote" : {<<drain accumulation>>; code := &null; write(line)}
+ "text" : if \code then {<<accumulate [[value]]>>} else write(line)
+ "nl" | "use" : { <<drain accumulation>>; write(line) }
+ default : write(line)
+}
+@
+Converting text to tokens is the heart of the algorithm.
+This code looks at the first character and finds maximal sequences.
+Digit sequences are treated specially
+Strings with single or double quotes are hacked in.
+<<accumulate [[value]]>>=
+value ?
+ while not pos(0) do
+ if any(' \t') then put(curline, space(tab(many(' \t'))))
+ else if any(alphanum) then { # maximal alphanumeric string
+ id := tab(many(alphanum))
+ put(curline, xform_alphanum(id))
+ } else if any(symbols) then { # maximal symbol string
+ id := tab(many(symbols))
+ put(curline, xform_symbols(id))
+ } else if delim := =("\"" | "'") then {
+ put(curline, xform_literal(delim || tab(find(delim)) || =delim))
+ } else if =(id := key(dtrans)) then { # if delimiter starts table string, xlate
+ put(curline, dtrans[id])
+ } else { # single delimiter character
+ put(curline, math(move(1)))
+ }
+@
+Underscores become subscripts, initial hats become hats, and we wrap
+long strings in \verb+\mathit+ unless they are strings of digits.
+Leading underscores are botched.
+<<*>>=
+procedure xform_alphanum(id)
+ local base
+ if \trans[id] then return trans[id]
+ if id[1] == "^" then # scope is to end of symbol
+ return math("\\nwpphat{" || mathstring(xform_alphanum(id[2:0])) || "}")
+ id ?
+ if *(base := tab(upto('_'))) > 0 & move(1) & not pos(0) then
+ return math(mathstring(xform_alphanum(base)) || "_" ||
+ mathstring(xform_alphanum(tab(0))))
+ else
+ return math(mathwrap(tab(0)))
+end
+procedure mathwrap(s)
+ if *s = 1 then return s
+ else if s ? (tab(upto('\'') == 2), tab(many('\'')), pos(0)) then
+ return "{" || s || "}"
+ else if upto(~&digits, s) then return "{\\mathit{" || s || "}}"
+ else return s # numbers don't get italic
+end
+@
+Symbols don't get any of this massaging.
+<<*>>=
+procedure xform_symbols(id)
+ if \trans[id] then return trans[id]
+ return math(id)
+end
+@
+I haven't tested any of this literal jazz.
+<<*>>=
+procedure xform_literal(id)
+ static chars
+ initial chars := "=|+-@!$#" || &letters || &digits
+ if c := !chars & not(find(c, id)) then
+ return nonmath("\\verb" || c || id || c)
+ else
+ return nonmath("\\texttt{" || id || "}")
+end
+@
+To emit tokens, I track mathness, and I turn it on and off
+appropriately.
+I also make sure to get space outside of math mode wherever
+appropriate, so it will show up.
+<<drain accumulation>>=
+if *curline > 0 then {
+ writes("@literal ")
+ curmath := &null
+ while t := get(curline) do
+ case type(t) of {
+ "math" : { <<ensure math>>; writes(t.string) }
+ "nonmath" : { <<ensure non-math>>; writes(t.string) }
+ "space" : { if /curmath then writes(repl("{\\ }", *t.string))
+ else if type(curline[1]) == "math" then writes(t.string)
+ else { <<ensure non-math>>; writes(repl("{\\ }", *t.string)) }
+ }
+ default : stop("This can't happen --- bad token ", image(t))
+ }
+ <<ensure non-math>>
+ write()
+}
+<<ensure math>>=
+/curmath := 1 & writes("\\(")
+<<ensure non-math>>=
+\curmath := &null & writes("\\)")
+@
+\section{Example}
+Here's a fragment of source code I used in a paper:
+\begin{verbatim}
+fun simple () =
+ let (b_I --> PC := target_I | I_c) = tgt[PC]
+ in if [[b_I]] then
+ PC := [[target_I]] | [[I_c]]
+ else
+ PC := succ(PC) | [[I_c]]
+ fi
+ ; simple()
+ end
+\end{verbatim}
+Here's the corresponding output\ifhtml
+, which looks pretty stupid in HTML because it's intended for {\TeX}\fi:
+\begin{trivlist}
+\item \obeylines
+\textbf{fun}\ \({\mathit{simple}} () \equiv \)
+\ \ \textbf{let}\ \((b_I \mathbin{\rightarrow} {\mathit{PC}} \mathrel{:=} {\mathit{target}}_I \mathrel{|} I_c) \equiv {\mathit{tgt}}[{\mathit{PC}}]\)
+\ \ \textbf{in}\ \ \textbf{if}\ \([\![b_I]\!]\)\ \textbf{then}
+\ \ \ \ \ \ \ \ \({\mathit{PC}} \mathrel{:=} [\![{\mathit{target}}_I]\!] \mathrel{|} [\![I_c]\!]\)
+\ \ \ \ \ \ \textbf{else}
+\ \ \ \ \ \ \ \ \({\mathit{PC}} \mathrel{:=} {\mathit{succ}}({\mathit{PC}}) \mathrel{|} [\![I_c]\!]\)
+\ \ \ \ \ \ \textbf{fi}
+\ \ \ \ \ \ \(; {\mathit{simple}}()\)
+\ \ \textbf{end}
+\end{trivlist}
+@
+And finally,
+here's the translation table I used:
+{\small
+\begin{verbatim}
+A^_'@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#
+S!%&*-+:=|~<>./?`
+$true \textbf{true}
+$false \textbf{false}
+-if \textbf{if}
+-then \textbf{then}
+-else \textbf{else}
+-fi \textbf{fi}
+-fun \textbf{fun}
+-let \textbf{let}
+-in \textbf{in}
+-end \textbf{end}
+$@[[ [\![
+$@]] ]\!]
+$:= \mathrel{:=}
+$andalso \land
+$--> \mathbin{\rightarrow}
+$= \equiv
+$== =
+$| \mathrel{|}
+$~ \mathord{-}
+$not \lnot
+$!= \ne
+$<= \le
+$>= \ge
+$... \bullet
+\end{verbatim}
+\par}
+
+
+\appendix
+\section {Index}
+\nowebindex
+\nowebchunks
+@
+\end {document}
diff --git a/web/noweb/contrib/norman/scopehack.icn b/web/noweb/contrib/norman/scopehack.icn
new file mode 100644
index 0000000000..d837a2ff61
--- /dev/null
+++ b/web/noweb/contrib/norman/scopehack.icn
@@ -0,0 +1,44 @@
+# scopehack; a replacement for totex but splitting output into multiple files
+
+global totex
+
+procedure main(args)
+ totex := "PATH=/usr/local/noweb/lib:/usr/lib/noweb:$PATH totex"
+ every totex ||:= " '" || !args || "'"
+
+ lines := []
+ file
+
+ while line := read() do {
+ line ?
+ if ="@fatal" then exit(1)
+ else if ="@file " then
+ if =\file & pos(0) then # no change
+ &null
+ else {
+ flush(file, lines)
+ file := tab(0)
+ }
+ put(lines, line)
+ }
+ flush(file, lines)
+end
+
+procedure flush(file, lines)
+ if /file & *lines > 0 then
+ stop("First line is not @file")
+ else if *lines = 0 then
+ return
+ else {
+ outfile := suffex(file) || ".tex"
+ p := open(totex || " > " || outfile, "wp") | stop ("cannot run ", totex)
+ while write(p, get(lines))
+ close(p)
+ return
+ }
+end
+
+procedure suffex(s)
+ return reverse (reverse(s) ? {tab(upto('.')) & ="."; tab(0)})
+end
+
diff --git a/web/noweb/contrib/partingr/README b/web/noweb/contrib/partingr/README
new file mode 100644
index 0000000000..a0f06fecb0
--- /dev/null
+++ b/web/noweb/contrib/partingr/README
@@ -0,0 +1,148 @@
+This is plain TeX indexing and cross-reference support for noweb.
+
+total 38
+-rwxr-x--- 1 partingr 959 Aug 2 14:10 TeXthings
+-rwxr-x--- 1 partingr 5544 Aug 2 14:19 addscore.nw
+-rwxr-xr-x 1 partingr 4672 Aug 2 13:35 mm2mx63
+-rwxr-xr-x 1 partingr 5033 Aug 2 13:35 mm2mx64
+-rwxr-xr-x 1 partingr 5180 Aug 2 13:35 mm2mx65
+-rwxr-xr-x 1 partingr 1445 Aug 2 13:37 mm2tex
+-rwxr-xr-x 1 partingr 4109 Aug 2 13:35 mx2tex31
+-rwxr-xr-x 1 partingr 4055 Aug 2 13:35 nwindex.tex
+-rwxr-x--- 1 partingr 67 Aug 2 14:14 nwnweave
+-rwxr-xr-x 1 partingr 35 Aug 2 13:35 nwtangle
+-rwxr-xr-x 1 partingr 64 Aug 2 13:35 nwweave
+-rwxr-xr-x 1 partingr 524 Aug 2 13:58 xpand
+
+This is what each file does/is:
+
+TeXthings perl 'header' file. needs to be somewhere
+ perl will find it when it executes mm2mx63
+ or mx2tex31 or mm2tex.
+
+mm2mx63 version 6.3 of mm2mx. converts mm files
+ (those created by markup) into mx files
+ (which is my modified markup file).
+ sectionref macros are aaa,aab,aac,aad
+ reads from STDIN and outputs to STDOUT
+ see below for cli options.
+
+mm2mx64 version 6.4 of mm2mx. virtually the same
+ as mm2mx63, but the sectionref macros that
+ get created have different names. default
+ is za,zc,zd etc. (I have lots of 2 character
+ macros for TeX so I don't use this so much,
+ but it might be useful...)
+
+mm2mx65 same as mm2mx63, but converts @<name@> in
+ documentation chunks into a @use reference
+ so you get the reference style in the
+ documentation, if you see what I mean.
+ EG. "see @<main@>" will become
+ "see <main 1a>" if main is defined in 1a
+ (with the proper typesetting for the module
+ name of course).
+
+mx2tex31 converts mx files into TeX. see below for
+ cli options.
+
+mm2tex weaver for normal markup files. tends to be
+ faster than awk because perl semi-compiles
+ it's programs before execution.
+
+nwindex.tex TeX macros for indexing.
+
+nwnweave shell script to weave a file with certain
+ cli options.
+
+nwweave shell script to weave a file with certain
+ cli options.
+
+xpand expands ...>> references in markup files.
+ !only *after* a full name has been seen!
+
+CLI OPTIONS:
+
+mm2mx63 -i create an identifier index from @ %def lines
+ -m create a module index
+ -n case insensitive module name matching
+ (nb all module names come out in lower case)
+
+mx2tex31 -i create the indexes (from the mx file)
+ -n name set the name of the output files. input is
+ from STDIN, output is to name.tex and
+ name.texnique.
+ -s hack for 'only first definition gets the full
+ list of defining chunks'.
+ (look at output to see the difference)
+ -f name takes the markup file from name.markup and
+ outputs to name.tex and name.texnique
+ -h help message
+ -q no output to terminal at all
+
+NWINDEX.MAC
+
+When mx2tex31 creates a TeX file, it inserts 'hooks' into the code
+so that the chunk references can be printed out according to the
+user's preferences.
+
+For all the hooks, \list contains a list of the defining chunks
+of the named chunk and \ulist contains a list of the chunks the
+named chunk is used in.
+(These lists are from Appendix D of The TeXBook. Items are
+seperated by \\ and contained in braces, so a list containing 1,2,3
+would be defined as \def\list{\\{1}\\{2}\\{3}}
+
+For a chunk defined in 1a and 1b, and used in 1c
+\list={\\{1a}\\{1b}}
+\ulist={\\{1c}}
+
+3 hooks are provided...
+
+\inmodname is called just before the right-angle of the chunk name
+\beforecode is called just after the chunk name (and angles) have
+ been set
+\aftercode is called just before \nwendcode{}
+
+The default definitions:
+\inmodname = put the *first* defining chunk xref in chunk names
+\beforecode = empty
+\aftercode = 'This definition is continued in section...' if the name
+ is defined in more than one chunk and
+ 'This code is used in section...'
+
+[look at the output to see what happens]
+This gives output like the LaTeX cross-referencing (and like CWEB).
+
+There are macros in nwindex.tex for printing out lists neatly
+(ie with commas and 'and' at the end) and for putting
+'section' or 'sections' at the front of the list.
+
+[if you need more info, either email me or wait for the documentation
+ which should be finished this week]
+
+INDEXES
+
+if asked to, mx2tex31 creates two files: name.ids and name.mods
+ids - identifier index
+mods - module index
+
+It *doesn't* include these by default in the TeX file. you have
+to ask for them by putting \printindex{ids} or \printindex{mods}
+
+you have to ask for them because (IMHO) indexes aren't vitally
+important while a program is being developed or for small
+programs.
+
+the indexes are created in seperate files to allow other tools
+to create them independently of mx2tex31. for example, a
+c program could create name.ids by parsing the code chunks
+for identifiers etc. (like CWEB/WEB do) which would be a
+better way of indexing than @ %def lines...
+
+
+BTW I apologise for this documentation. I haven't had a
+chance to get a proper version written yet.
+
+Do people want a TeXinfo version of the documentation or
+just plain TeX file?
diff --git a/web/noweb/contrib/partingr/TeXthings b/web/noweb/contrib/partingr/TeXthings
new file mode 100755
index 0000000000..35f537a93f
--- /dev/null
+++ b/web/noweb/contrib/partingr/TeXthings
@@ -0,0 +1,52 @@
+sub convquotes
+{
+ local($line)=@_;
+ local($pre,$mid,$end,$obrace,$cbrace);
+
+ $obrace=index($line,'[[',0);
+ while($obrace!=-1)
+ {
+ $pre=substr($line,0,$obrace);
+ $cbrace=index($line,']]',$obrace);
+ while(substr($line,$cbrace+2,1) eq ']')
+ { $cbrace++;
+ }
+ $mid=substr($line,$obrace+2,$cbrace-$obrace-2);
+ $end=substr($line,$cbrace+2);
+ $line=$pre . "\\code{}" . &TeXliteral($mid) . "\\edoc{}" . $end;
+ $obrace=index($line,'[[',0);
+ }
+ return $line;
+}
+
+sub escapebslash
+{
+ local($line)=@_;
+
+ $line=~s/([\\\{\}])/\n\1/g;
+ $line=~s/\n/\\/g;
+ return $line;
+}
+
+sub TeXliteral
+{
+ local($_)=@_;
+
+ s/\\/<\\char92>/g;
+ s/\}/<\\char125}/g;
+ s/\{/{\\char123}/g;
+ s/<\\char/{\\char/g;
+ s/\{\\char92>/{\\char92}/g;
+ s/\$/{\\char36}/g;
+ s/&/{\\char38}/g;
+ s/#/{\\char35}/g;
+ s/\^/{\\char94}/g;
+ s/_/{\\char95}/g;
+ s/%/{\\char37}/g;
+ s/~/{\\char126}/g;
+ s/ /\\ /g;
+ return $_;
+}
+
+1;
+
diff --git a/web/noweb/contrib/partingr/addscore.nw b/web/noweb/contrib/partingr/addscore.nw
new file mode 100644
index 0000000000..e0e5d9eb79
--- /dev/null
+++ b/web/noweb/contrib/partingr/addscore.nw
@@ -0,0 +1,183 @@
+\def\musecs{$\mu$secs}
+\itemwidth=.25in
+@
+\section{Archery Database: {\tt AddScore}}
+This perl script adds a score (or scores) to the archery database.
+It provides only a basic user interface.
+
+<<addscore>>=
+<<setup>>
+<<main program loop>>
+<<subroutines>>
+@
+
+\section{Setting up the database and script}
+Because much of the code is shared between this family of scripts,
+some of the code is in subroutine files. We [[require]] these.
+
+<<setup>>=
+require "custom" || die "can't open custom routines library";
+require "archsubs" || die "can't open subroutines library";
+@ %def &readrounds &init
+
+Early versions of this script allowed you to abort an entry by not
+typing anything at a prompt. However this became cumbersome when only
+the third prompt would let you do this. So we now trap [[SIGINT]]
+and point it to the same abort routine.
+
+<<setup>>=
+$SIG{'INT'}='abort';
+@ %def $SIG
+
+We need know what date it is today (for the default database and
+date) so we get this from the operating system via the [[gmtime()]]
+call.
+
+<<setup>>=
+$start=time;
+($ts,$tmi,$th,$tmd,$tmo,$ty,@junk)=gmtime($start);
+@ %def $start $ts $tmi $th $tmd $tmo $ty @junk | $start gmtime()
+
+Now we read in the rounds database, and open the relevant dbm file for
+the archery database. [[&init]] handles the command line options that
+relate to the person and year that are asked for.
+
+<<setup>>=
+&readrounds;
+do &init;
+@ %def | &readrounds &init
+\section{The main body of the program}
+The main part of the program justs loops asking the user for
+a score to be entered and then prompting for another loop.
+
+Unfortunately, we still treat dates as strings (due to problems in the
+conversion of dates to \musecs\ and back) so all this data cannot
+be accessed by date order.
+
+\subsection{Outline of main loop}
+<<main...>>=
+while(1)
+{
+ <<date entry and validation>>
+ <<round entry and validation>>
+ <<score entry and validation>>
+ <<create and store dbm entry>>
+ <<prompt user for another go>>
+}
+@
+
+We close the dbm database explicitly here, just to be on the safe side.
+<<main...>>=
+dbmclose(scores);
+@
+\subsection{Entering the date}
+<<date...>>=
+ dateloop:
+ while(1)
+ {
+ print "Enter date ($tmd-$tmo-$year) - ";
+ $date=scalar(<STDIN>);
+ chop $date;
+ $date=join('-',$tmd,$tmo) unless $date;
+ if($date=~/(\d{1,2})-(\d{1,2})/)
+ {
+ $dt_ntrd=1;
+ $dindex=sprintf("%02d:%02d:%04d",$1,$2,$year);
+ $usecs=&retime($1,$2,$year);
+
+ ($xts,$xtmi,$xth,$xtmd,$xtmo,$xty,@junk)=gmtime($usecs);
+ printf "%02d-%02d-%04d\n",$xtmd,$xtmo,$xty;
+
+ last dateloop;
+ }
+ else { print "invalid date\n"; }
+ }
+@ %def dateloop: $date $dt_ntrd $dindex $usecs $xts $xtmi $xth $xtmd $xtmo $xty @junk | STDIN &retime() gmtime()
+\subsection{Entering the round}
+<<round...>>=
+ $round=&getround;
+ ($rtype,@rdists)=split(/,/,@rounds{$round});
+ $mult=($rtype='y'?9:10);
+@ %def $round @rdists $mult | $rtype @rounds{} &getround
+\subsection{Entering the score}
+<<score...>>=
+ until(defined($sc_ntrd))
+ {
+ print 'Enter scores (100,100,100) - ';
+ $sclist=scalar(<STDIN>);
+ chop $sclist;
+ &abort unless $sclist;
+ @rscores=split(/,/,$sclist);
+ if(2*$#rscores==$#rdists-1) {$sc_ntrd=1;}
+ else { print "wrong number of scores\n"; }
+ for($i=0;$i<=$#rscores;$i++)
+ {
+ $ms=@rdists[2*$i]*$mult;
+ if(@rscores[$i]>$ms)
+ { printf "invalid: %d>possible ($ms)\n",@rscores[$i];
+ $sc_ntrd=$undefined;
+ }
+ }
+ }
+@ %def $sclist @rscores $ms $sc_ntrd | STDIN $mult @rdists $undefined
+\subsection{Storing the data}
+The dbm entries are created in a fairly naive fashion at the moment.
+The round name and scores are turned into a CSV string. Future versions
+will almost certainly use templates and packing to reduce the amount
+of information that is stored.
+
+<<create...>>=
+ $entry=join(',',$round,@rscores);
+ @scores{$dindex}=$entry;
+@ %def $entry @scores | $round @rscores $dindex
+\subsection{Prompt the user}
+Now we prompt the user to see if they want to enter another score.
+The default answer (ie just pressing [[RETURN]]) is yes on the
+assumption that more than one score will be entered at a time. It
+will be changed so that a score entered with today's date will
+change the default to no on the assumption that the rest of the
+database is up to date.
+
+<<prompt...>>=
+ $loopagain=&yesno("Another score",'y');
+ last unless $loopagain;
+ undef $sc_ntrd;
+@ %def $loopagain | &yesno() $sc_ntrd
+\section{Subroutines}
+\subsection{[[retime]]}
+This subroutine is supposed to convert a date in dd-mm-yyyy form into
+the number of \musecs\ since 1-1-1970, but it sometimes gets it
+mysteriously wrong, so we don't use it for indexing yet.
+
+<<Subroutines>>=
+sub retime
+{ local($d,$m,$y)=@_;
+ local($wm,$md,$yd);
+
+ $wm=$m-3;
+ if($wm<0) { $wm+=12; $y--; } # modified month number
+ $md=int(30.6*$wm+.5); # month day
+ $yd=int(365.25*($y-1970)+$md+$d)+60; # actual day number
+ 86400*$yd;
+}
+@ %def $d $m $y $wm $md $yd
+\section{Things to do}
+\itemize
+\item
+The way the rounds are stored and accessed needs to be changed.
+`Compiling' the rounds into a more compact form would save space,
+and possibly make things a little faster.
+
+\item
+A better user interface would also be a good idea. Possibly making
+the program run under a different screen mode for larger text.
+
+\item
+Adding a confirm just before the data is inserted into the dbm database.
+
+\enditemize
+
+\chapter{Variables}
+\printindex{ids}
+\chapter{Modules}
+\printindex{mods}
diff --git a/web/noweb/contrib/partingr/email b/web/noweb/contrib/partingr/email
new file mode 100644
index 0000000000..d80033763c
--- /dev/null
+++ b/web/noweb/contrib/partingr/email
@@ -0,0 +1,2 @@
+Robert Partington <rjp@browser.org>
+
diff --git a/web/noweb/contrib/partingr/mm2mx63 b/web/noweb/contrib/partingr/mm2mx63
new file mode 100755
index 0000000000..41e7f3ca67
--- /dev/null
+++ b/web/noweb/contrib/partingr/mm2mx63
@@ -0,0 +1,160 @@
+#!/usr/common/bin/perl
+do "getopts.pl" || die "$!";
+do Getopts('imnd:l:');
+
+do "TeXthings";
+
+$sectionref='aaa'; $i=0;
+if($opt_l)
+ { open(LOGFILE,">$opt_l") || die "$!"; }
+
+while(<>)
+{
+# s/\n$//;
+ s/^@//;
+# expand wildcard references here, then process as normal
+ if(/^(use|defn) (.*)\.{3}$/)
+ { print LOGFILE "Wildcard `$2...', expands to " if $opt_l;
+ @matches=grep(/^$2.*/i,split(/¤/,$known));
+ if($#matches>0)
+ {
+ print LOGFILE "[",join('][',@matches),"] " if $opt_l;
+ print STDERR "Ambiguous module name `$mod...', line $i\n";
+ print STDERR "Matches: [",join('][',@matches),"]\n";
+ print STDERR "Using `",@matches[0],"'\n";
+ #die "\nAmbiguous module name `$mod...', line $i";
+ }
+ elsif($#matches==-1)
+ {
+ die "\nNo match for name `$mod...', line $i";
+ }
+ $mn=@matches[0];
+ if($mn=~/\[\[/) { $mn=&convquotes($mn); }
+ print LOGFILE $mn,"\n" if $opt_l;
+ $_="$1 $mn";
+ }
+
+# process a <<defn>>=
+ if(/^defn (.*)$/)
+ { print LOGFILE "Defining chunk `$1' with macro $sectionref\n" if $opt_l;
+ $md=$1; $mn=$1; if($opt_n) { $md=~tr/A-Z/a-z/; }
+ $mt=$md;
+ $mt=~s/([*+.?{}()])/\\\1/g;
+ if($known!~/¤$mt/) { $known=$known . "¤$md"; }
+ @names{$md}=1; $currentmod=$md;
+ @defines{$md}=@defines{$md} . "\\\\{\\xp\\$sectionref}";
+ #if($mn=~/\[\[/) { $mn=&convquotes($mn); }
+ @lines[$i]="defn $sectionref $mn\n"; $oldref=$sectionref;
+ $sectionref++;
+ push(@uses,$i);
+ $indxing=0;
+ }
+# process a <<use>>
+ elsif(/^use (.*)$/)
+ { print LOGFILE "Using chunk `$1' in chunk $oldref\n" if $opt_l;
+ $md=$1; $mn=$1; if($opt_n) { $md=~tr/A-Z/a-z/; }
+ $mt=$md;
+ $mt=~s/([*+.?{}()])/\\\1/g;
+ if($known!~/¤$mt/) { $known=$known . "¤$md"; }
+ @reference{$md}=@reference{$md} . "\\\\{\\xp\\$oldref}";
+ #if($mn=~/\[\[/) { $mn=&convquotes($mn); }
+ @lines[$i]="use $oldref $mn\n";
+ push(@uses,$i);
+ $indxing=0;
+ }
+# process identifier information
+ elsif(/^index (nl|defn |use )(.*)/)
+ {
+ if($2 eq '|') { $indxing=1; }
+ else
+ { if($2)
+ { print LOGFILE "Identifier `$2' indexed as " if $opt_l;
+ if($1 eq "defn " && !$indxing)
+ { print LOGFILE "defined [$oldref]\n" if $opt_l;
+ $style="";
+ }
+ else
+ { print LOGFILE "used [$oldref]\n" if $opt_l;
+ $style="\\it";
+ }
+ @variables{$2}=@variables{$2} . ",\\thinspace{$style\\xp\\$oldref}";
+ }
+ }
+ $i--; # don't put this line in the file here
+ }
+# stick the line in the array
+ else
+ { @lines[$i]=$_; }
+ $i++;
+}
+
+if($opt_l)
+ {
+ print LOGFILE "\n\nList of modules currently defined\n";
+ print LOGFILE join("\n",sort keys(defines));
+ print LOGFILE "\n\nList of modules currently referenced\n";
+ print LOGFILE join("\n",sort keys(reference));
+ print LOGFILE "\n\n";
+ }
+
+foreach(keys(reference))
+ { @longlist{$_}=@reference{$_}; }
+
+foreach(keys(defines))
+ { @longlist{$_}=@longlist{$_} . ('%' . @defines{$_}); }
+
+foreach(@uses)
+ {
+ $ref=@lines[$_];
+ $ref=~/^(use|defn) (...) (.*)/;
+ $mn=$3; $dr=$2; $ac=$1;
+ $defns=@defines{$mn};
+ print LOGFILE "Module $mn " if $opt_l;
+ if($ac eq 'defn')
+ { $uses=@reference{$mn}; $uses="{$uses}|";
+ print LOGFILE "defined at line $_, $uses\n" if $opt_l;
+ }
+ else
+ { $uses='';
+ print LOGFILE "referenced at line $_\n" if $opt_l;
+ }
+ print LOGFILE "Line $_ modified to `$ac $dr {$defns} $uses$mn'\n" if $opt_l;
+ $mn=&convquotes($mn);
+ @lines[$_]="$ac $dr|{$defns}|$uses $mn\n";
+ }
+
+print STDOUT "header tex \n",@lines;
+
+# now @longlist{MOD} contains a list of all the references to <MOD>
+# sort them to make them look pretty
+
+if($opt_m)
+ {
+ print LOGFILE "Making module index...\n" if $opt_l;
+ print "index mods\n";
+ foreach(sort keys(longlist))
+ {
+ $defns=@defines{$_};
+ $defns=~s/^,\\\\thinspace//;
+ print LOGFILE "Module <$_ $defns> ",@reference{$_},"\n" if $opt_l;
+ # first we print the module name and defining numbers
+ print "entry {\\LA ",&convquotes($_),"\\ \\xwp{$defns}\\RA}\\quad";
+ # now we print the bit after that : assume foot=cmr8
+ print "{\\foot\\xtc{",@reference{$_},"}}\n";
+ }
+ print "end index\n";
+ }
+
+if($opt_i)
+ {
+ print "index ids\n";
+ foreach(sort keys(variables))
+ {
+ $vars=@variables{$_};
+ $vars=~s/^,\\thinspace//;
+ print "entry {\\code ",&TeXliteral($_),"\\edoc} :\\quad",$vars,"\n";
+ }
+ print "end index\n";
+ }
+
+print STDOUT "trailer tex\n";
diff --git a/web/noweb/contrib/partingr/mm2mx64 b/web/noweb/contrib/partingr/mm2mx64
new file mode 100755
index 0000000000..58f26356b5
--- /dev/null
+++ b/web/noweb/contrib/partingr/mm2mx64
@@ -0,0 +1,173 @@
+#!/usr/common/bin/perl
+do "getopts.pl" || die "$!";
+do Getopts('imnd:l:');
+
+do "TeXthings";
+
+$sectionref='a'; $i=0;
+if($opt_l)
+ { open(LOGFILE,">$opt_l") || die "$!"; }
+
+while(<>)
+{
+# s/\n$//;
+ s/^@//;
+# expand wildcard references here, then process as normal
+ if(/^(use|defn) (.*)\.{3}$/)
+ { print LOGFILE "Wildcard `$2...', expands to " if $opt_l;
+ @matches=grep(/^$2.*/i,split(/¤/,$known));
+ if($#matches>0)
+ {
+ print LOGFILE "[",join('][',@matches),"] " if $opt_l;
+ print STDERR "Ambiguous module name `$mod...', line $i\n";
+ print STDERR "Matches: [",join('][',@matches),"]\n";
+ print STDERR "Using `",@matches[0],"'\n";
+ #die "\nAmbiguous module name `$mod...', line $i";
+ }
+ elsif($#matches==-1)
+ {
+ die "\nNo match for name `$mod...', line $i";
+ }
+ $mn=@matches[0];
+ if($mn=~/\[\[/) { $mn=&convquotes($mn); }
+ print LOGFILE $mn,"\n" if $opt_l;
+ $_="$1 $mn";
+ }
+
+# process a <<defn>>=
+ if(/^defn (.*)$/)
+ { print LOGFILE "Defining chunk `$1' with macro $sectionref\n" if $opt_l;
+ $md=$1; $mn=$1; if($opt_n) { $md=~tr/A-Z/a-z/; }
+ $mt=$md;
+ $mt=~s/([*+.?{}()])/\\\1/g;
+ if($known!~/¤$mt/) { $known=$known . "¤$md"; }
+ @names{$md}=1; $currentmod=$md;
+ @defines{$md}=@defines{$md} . "\\\\{\\xp\\z$sectionref}";
+ #if($mn=~/\[\[/) { $mn=&convquotes($mn); }
+ @lines[$i]="defn z$sectionref $mn\n"; $oldref=$sectionref;
+ $sectionref++;
+ push(@uses,$i);
+ $indxing=0;
+ }
+# process a <<use>>
+ elsif(/^use (.*)$/)
+ { print LOGFILE "Using chunk `$1' in chunk $oldref\n" if $opt_l;
+ $md=$1; $mn=$1; if($opt_n) { $md=~tr/A-Z/a-z/; }
+ $mt=$md;
+ $mt=~s/([*+.?{}()])/\\\1/g;
+ if($known!~/¤$mt/) { $known=$known . "¤$md"; }
+ @reference{$md}=@reference{$md} . "\\\\{\\xp\\z$oldref}";
+ #if($mn=~/\[\[/) { $mn=&convquotes($mn); }
+ @lines[$i]="use z$oldref $mn\n";
+ push(@uses,$i);
+ $indxing=0;
+ }
+# process identifier information
+ elsif(/^index (nl|defn |use )(.*)/)
+ {
+ if($2 eq '|') { $indxing=1; }
+ else
+ { if($2)
+ { print LOGFILE "Identifier `$2' indexed as " if $opt_l;
+ if($1 eq "defn " && !$indxing)
+ { print LOGFILE "defined [$oldref]\n" if $opt_l;
+ $style="";
+ }
+ else
+ { print LOGFILE "used [$oldref]\n" if $opt_l;
+ $style="\\it";
+ }
+ @variables{$2}=@variables{$2} . ",\\thinspace{$style\\xp\\z$oldref}";
+ }
+ }
+ $i--; # don't put this line in the file here
+ }
+# stick the line in the array
+ else { @lines[$i]=$_; }
+ $i++;
+}
+
+if($opt_l)
+ {
+ print LOGFILE "\n\nList of modules currently defined\n";
+ print LOGFILE join("\n",sort keys(defines));
+ print LOGFILE "\n\nList of modules currently referenced\n";
+ print LOGFILE join("\n",sort keys(reference));
+ print LOGFILE "\n\n";
+ }
+
+foreach(keys(reference))
+ { @longlist{$_}=@reference{$_}; }
+
+foreach(keys(defines))
+ { @longlist{$_}=@longlist{$_} . ('%' . @defines{$_}); }
+
+foreach(@uses)
+ {
+ $ref=@lines[$_];
+ $ref=~/^(use|defn) (z[a-z]+) (.*)/;
+ $mn=$3; $dr=$2; $ac=$1;
+ $defns=@defines{$mn};
+ print LOGFILE "Module $mn " if $opt_l;
+ if($ac eq 'defn')
+ { $uses=@reference{$mn}; $uses="{$uses}|";
+ print LOGFILE "defined at line $_, $uses\n" if $opt_l;
+ }
+ else
+ { $uses='';
+ print LOGFILE "referenced at line $_\n" if $opt_l;
+ }
+ print LOGFILE "Line $_ modified to `$ac $dr {$defns} $uses$mn'\n" if $opt_l;
+ $mn=&convquotes($mn);
+ @lines[$_]="$ac $dr|{$defns}|$uses $mn\n";
+ }
+
+print STDOUT "header tex \n",@lines;
+
+# now @longlist{MOD} contains a list of all the references to <MOD>
+# sort them to make them look pretty
+
+if($opt_m)
+ {
+ print LOGFILE "Making module index...\n" if $opt_l;
+ print "index mods\n";
+ foreach(sort keys(longlist))
+ {
+ $defns=@defines{$_};
+ $defns=~s/^,\\\\thinspace//;
+ print LOGFILE "Module <$_ $defns> ",@reference{$_},"\n" if $opt_l;
+ # first we print the module name and defining numbers
+ print "entry {\\LA ",&convquotes($_),"\\ \\xwp{$defns}\\RA}\\quad";
+ # now we print the bit after that : assume foot=cmr8
+ print "{\\foot\\xtc{",@reference{$_},"}}\n";
+ }
+ print "end index\n";
+ }
+
+if($opt_i)
+ {
+ print "index ids\n";
+ foreach(sort keys(variables))
+ {
+ $vars=@variables{$_};
+ $vars=~s/^,\\thinspace//;
+ print "entry {\\code ",&TeXliteral($_),"\\edoc} :\\quad",$vars,"\n";
+ }
+ print "end index\n";
+ }
+
+print STDOUT "trailer tex\n";
+
+sub usage_info
+{
+ local($line)=@_;
+ @ixrefs=sort(split(/%/,@reference{$line}));
+ if($#ixrefs==-1)
+ { return "This code is never referenced. It may be a root module.";}
+ elsif($#ixrefs==0)
+ { return "This code is used in section ",@ixrefs[0]; }
+ else
+ { $lastref=pop(@ixrefs);
+ return "This code is used in sections ",join(",\\,",@ixrefs)," and $lastref";
+ }
+}
diff --git a/web/noweb/contrib/partingr/mm2mx65 b/web/noweb/contrib/partingr/mm2mx65
new file mode 100755
index 0000000000..7c7809b4b8
--- /dev/null
+++ b/web/noweb/contrib/partingr/mm2mx65
@@ -0,0 +1,179 @@
+#!/usr/common/bin/perl
+do "getopts.pl" || die "$!";
+do Getopts('imnd:l:');
+
+do "TeXthings";
+
+$sectionref='aaa'; $i=0;
+if($opt_l)
+ { open(LOGFILE,">$opt_l") || die "$!"; }
+
+while(<>)
+{
+# s/\n$//;
+ s/^@//;
+ if(/@</)
+ { ($pre,$mid,$end)=&convxrefs($_);
+ @lines[$i]=$pre; $i++;
+ $_=$mid; # need to expand the module name here
+ }
+# expand wildcard references here, then process as normal
+ if(/^(use|defn) (.*)\.{3}$/)
+ { print LOGFILE "Wildcard `$2...', expands to " if $opt_l;
+ @matches=grep(/^$2.*/i,split(/¤/,$known));
+ if($#matches>0)
+ {
+ print LOGFILE "[",join('][',@matches),"] " if $opt_l;
+ print STDERR "Ambiguous module name `$mod...', line $i\n";
+ print STDERR "Matches: [",join('][',@matches),"]\n";
+ print STDERR "Using `",@matches[0],"'\n";
+ #die "\nAmbiguous module name `$mod...', line $i";
+ }
+ elsif($#matches==-1)
+ {
+ die "\nNo match for name `$mod...', line $i";
+ }
+ $mn=@matches[0];
+ if($mn=~/\[\[/) { $mn=&convquotes($mn); }
+ print LOGFILE $mn,"\n" if $opt_l;
+ $_="$1 $mn";
+ }
+
+# process a <<defn>>=
+ if(/^defn (.*)$/)
+ { print LOGFILE "Defining chunk `$1' with macro $sectionref\n" if $opt_l;
+ $md=$1; $mn=$1; if($opt_n) { $md=~tr/A-Z/a-z/; }
+ $mt=$md;
+ $mt=~s/([*+.?{}()])/\\\1/g;
+ if($known!~/¤$mt/) { $known=$known . "¤$md"; }
+ @names{$md}=1; $currentmod=$md;
+ @defines{$md}=@defines{$md} . "\\\\{\\xp\\$sectionref}";
+ #if($mn=~/\[\[/) { $mn=&convquotes($mn); }
+ @lines[$i]="defn $sectionref $mn\n"; $oldref=$sectionref;
+ $sectionref++;
+ push(@uses,$i);
+ $indxing=0;
+ }
+# process a <<use>>
+ elsif(/^use (.*)$/)
+ { print LOGFILE "Using chunk `$1' in chunk $oldref\n" if $opt_l;
+ $md=$1; $mn=$1; if($opt_n) { $md=~tr/A-Z/a-z/; }
+ $mt=$md;
+ $mt=~s/([*+.?{}()])/\\\1/g;
+ if($known!~/¤$mt/) { $known=$known . "¤$md"; }
+ @reference{$md}=@reference{$md} . "\\\\{\\xp\\$oldref}";
+ #if($mn=~/\[\[/) { $mn=&convquotes($mn); }
+ @lines[$i]="use $oldref $mn\n";
+ push(@uses,$i);
+ $indxing=0;
+ }
+# process identifier information
+ elsif(/^index (nl|defn |use )(.*)/)
+ {
+ if($2 eq '|') { $indxing=1; }
+ else
+ { if($2)
+ { print LOGFILE "Identifier `$2' indexed as " if $opt_l;
+ if($1 eq "defn " && !$indxing)
+ { print LOGFILE "defined [$oldref]\n" if $opt_l;
+ $style="";
+ }
+ else
+ { print LOGFILE "used [$oldref]\n" if $opt_l;
+ $style="\\it";
+ }
+ @variables{$2}=@variables{$2} . ",\\thinspace{$style\\xp\\$oldref}";
+ }
+ }
+ $i--; # don't put this line in the file here
+ }
+# stick the line in the array
+ else
+ { @lines[$i]=$_; }
+ $i++;
+ if($end) { @lines[$i]=$end; $i++; undef $end; }
+}
+
+if($opt_l)
+ {
+ print LOGFILE "\n\nList of modules currently defined\n";
+ print LOGFILE join("\n",sort keys(defines));
+ print LOGFILE "\n\nList of modules currently referenced\n";
+ print LOGFILE join("\n",sort keys(reference));
+ print LOGFILE "\n\n";
+ }
+
+foreach(keys(reference))
+ { @longlist{$_}=@reference{$_}; }
+
+foreach(keys(defines))
+ { @longlist{$_}=@longlist{$_} . ('%' . @defines{$_}); }
+
+foreach(@uses)
+ {
+ $ref=@lines[$_];
+ $ref=~/^(use|defn) (...) (.*)/;
+ $mn=$3; $dr=$2; $ac=$1;
+ $defns=@defines{$mn};
+ print LOGFILE "Module $mn " if $opt_l;
+ if($ac eq 'defn')
+ { $uses=@reference{$mn}; $uses="{$uses}|";
+ print LOGFILE "defined at line $_, $uses\n" if $opt_l;
+ }
+ else
+ { $uses='';
+ print LOGFILE "referenced at line $_\n" if $opt_l;
+ }
+ print LOGFILE "Line $_ modified to `$ac $dr {$defns} $uses$mn'\n" if $opt_l;
+ $mn=&convquotes($mn);
+ @lines[$_]="$ac $dr|{$defns}|$uses $mn\n";
+ }
+
+print STDOUT "header tex \n",@lines;
+
+# now @longlist{MOD} contains a list of all the references to <MOD>
+# sort them to make them look pretty
+
+if($opt_m)
+ {
+ print LOGFILE "Making module index...\n" if $opt_l;
+ print "index mods\n" if $opt_l;
+ foreach(sort keys(longlist))
+ {
+ $defns=@defines{$_};
+ $defns=~s/^,\\\\thinspace//;
+ print LOGFILE "Module <$_ $defns> ",@reference{$_},"\n" if $opt_l;
+ # first we print the module name and defining numbers
+ print "entry {\\LA ",&convquotes($_),"\\ \\xwp{$defns}\\RA}\\quad";
+ # now we print the bit after that : assume foot=cmr8
+ print "{\\foot\\xtc{",@reference{$_},"}}\n";
+ }
+ print "end index\n";
+ }
+
+if($opt_i)
+ {
+ print "index ids\n";
+ foreach(sort keys(variables))
+ {
+ $vars=@variables{$_};
+ $vars=~s/^,\\thinspace//;
+ print "entry {\\code ",&TeXliteral($_),"\\edoc} :\\quad",$vars,"\n";
+ }
+ print "end index\n";
+ }
+
+print STDOUT "trailer tex\n";
+
+sub convxrefs
+ {
+ local($l)=@_;
+ local($found,$output);
+ $found=index($l,'@<');
+ $lost=index($l,'@>',$found);
+ $pre=substr($l,0,$found) . "\n"; # before the use
+ $mid="use " . substr($l,$found+2,$lost-$found-2) . "\n";
+ $end="text " . substr($l,$lost+2);
+ substr($l,$found,$lost+2-$found)="";
+ return $pre,$mid,$end;
+ }
diff --git a/web/noweb/contrib/partingr/mm2tex b/web/noweb/contrib/partingr/mm2tex
new file mode 100755
index 0000000000..79fd7a9c3d
--- /dev/null
+++ b/web/noweb/contrib/partingr/mm2tex
@@ -0,0 +1,41 @@
+#!/usr/common/bin/perl
+do "TeXthings" || die "$!";
+print "\\input nwmac ";
+while(<>)
+{
+ if(/^@begin code (.*)$/) { print "\\nwbegincode{$1}"; $code=1; $text=5; }
+ elsif(/^@end code/) { print "\\nwendcode{}\\filbreak$defing"; $code=0; }
+ elsif(/^@begin docs (.*)$/) { print "\\nwbegindocs{$1}"; $text=0; $textmode=0; }
+ elsif(/^@end docs/) { print "\\nwenddocs{}"; }
+ elsif(/^@text (.*)$/)
+ { $text+=length $1;
+ if($code==1) { print &escapebslash($1); }
+ elsif($quoting==1) { print &TeXliteral($1); }
+ else { print $1; }
+ $textmode=1 if $text>0;
+ }
+ elsif(/^@nl$/)
+ { if($code==0)
+ { if($text==0)
+ { if($textmode==1) { print "\\nwdocspar\\noindent\n"; }
+ else { print "\n"; }
+ $textmode=1; $text=1;
+ }
+ else { print "\n"; }
+ }
+ elsif($quoting) { print "\\nwnewline"; }
+ else { if($text>0) { print "\n"; } }
+ }
+ elsif(/^@defn (.*)$/)
+ { $name=$1;
+ print "\\moddef{",&convquotes($name),"}\\",@defns{$name},"endmoddef";
+ @defns{$name}='plus';
+ }
+ elsif(/^@use (.*)$/)
+ { print "\\LA{}",&convquotes($1),"\\RA{}"; }
+ elsif(/^@quote$/) { $quoting=1; print "{\\tt "; }
+ elsif(/^@endquote$/) { $quoting=0; print "}"; $textmode=0; }
+ elsif(/^@file (.*)$/) { $filename=$1; print "\\filename{$filename}"; }
+ elsif(/^@literal (.*)$/) { print "$1"; }
+}
+print "\\bye\n";
diff --git a/web/noweb/contrib/partingr/mx2tex31 b/web/noweb/contrib/partingr/mx2tex31
new file mode 100755
index 0000000000..e7e3ef674d
--- /dev/null
+++ b/web/noweb/contrib/partingr/mx2tex31
@@ -0,0 +1,130 @@
+#!/usr/common/bin/perl
+do "TeXthings";
+do "getopts.pl" || die "$!";
+do Getopts('n:idf:hqst');
+
+if($opt_h)
+ {
+ print STDERR <<ENDOFHELP;
+
+Usage: mx2tex [options]
+
+mx2tex takes a file created by mm2mx and converts it into TeX.
+
+Options: d debugging information
+ f <name> use this file for the job (from <name>.mx to <name>.tex/texnique)
+ h this help text
+ i create the indexes
+ n <name> use this as the name for the output files
+ default: woven
+ q operate quietly (no output)
+ s only have full list of defines for first chunk
+ENDOFHELP
+ exit;
+ }
+
+unless($opt_q)
+ {
+ print STDERR "mx2tex version 3, 1994 by Rob Partington\n";
+ if($opt_d) { push(@options,"debugging"); }
+ if($opt_f) { push(@options,"file:$opt_f"); }
+ if($opt_i) { push(@options,"indexes"); }
+ if($opt_n) { push(@options,"name:$opt_n"); }
+ if($opt_s) { push(@options,"first define"); }
+ if($opt_t) { push(@options,"force write"); }
+ print STDERR "Options:",sort(join(' + ',@options)),"\n";
+ undef @options;
+ }
+
+$macrofile="nwindex"; if($opt_d) { $macrofile="nwidxmac"; }
+
+$filename=$opt_f; if($opt_n) { $filename=$opt_n; }
+
+open(TEX,">$filename.texnique") || die "$!";
+
+if($opt_f) { push(@ARGV,"$filename.markup"); }
+
+unless(-e "$filename.tex" && !$opt_t)
+ {
+ open(TEXCNTL,">$filename.tex") || die "$!";
+ print TEXCNTL <<EOTEX;
+\\input $macrofile
+\\def\\defined{}\\init\\output={\\plainoutput\\global\\subpageref=97}
+{\\def\\shipout{\\message{[p\\the\\pageno]}\\setbox0}
+\\input \\jobname.texnique \\vfill\\supereject}
+\\init{\\gdef\\passtwo{}\\input \\jobname.texnique }
+\\end
+EOTEX
+ close(TEXCNTL);
+ }
+
+
+$code=0; $text=1; $ignore=0;
+whileloop:
+while(<>)
+{
+ if(/^begin code (.*)$/) { $delayed="\\nwbegincode{$1}"; $code=1; $text=5; }
+ elsif(/^end code/) { print TEX "\\nwendcode{}\\filbreak$defing"; $code=0; }
+ elsif(/^begin docs (.*)$/) { print TEX "\\nwbegindocs{$1}"; $text=0; $textmode=0; }
+ elsif(/^end docs/) { print TEX "\\nwenddocs{}"; }
+ elsif(/^text (.*)$/)
+ { $text+=length $1;
+ if($code==1) { print TEX &escapebslash($1); }
+ elsif($quoting==1) { print TEX &TeXliteral($1); }
+ else { print TEX $1; }
+ $textmode=1 if $text>0;
+ }
+ elsif(/^nl$/)
+ { if($code==0)
+ { if($text==0)
+ { if($textmode==1) { print TEX "\\nwdocspar\\noindent\n"; }
+ else { print TEX "\n"; }
+ $textmode=1; $text=1;
+ }
+ else { print TEX "\n"; }
+ }
+ elsif($quoting) { print TEX "\\nwnewline"; }
+ else { if($text>0) { print TEX "\n"; } }
+ }
+ elsif(/^defn ([a-z]+)\|(.*)\|(.*)\| (.*)$/)
+ { $xref=$1; $name=$2;
+ $defing="\\makeref{$1}";
+ $deflist=$2; $uselist=$3;
+ if($opt_s && @defns{$name} eq 'plus')
+ {
+ if(($firstr=index($deflist,'}\\'))!=-1)
+ { $deflist=substr($deflist,0,$firstr) . '}}'; }
+ if(($firstr=index($uselist,'}\\'))!=-1)
+ { $uselist=substr($uselist,0,$firstr) . '}}'; }
+ }
+
+ print TEX "$delayed\\def\\list$deflist\\def\\ulist$uselist",
+ "\\moddef{\\xp{\\$1}}{",&convquotes($4),"}",
+ "\\inmodname\\",@defns{$name},"endmoddef";
+ $ignore=1;
+ @defns{$name}='plus';
+ }
+ elsif(/^use ([a-z]+)\|(.*)\| (.*)$/)
+ {
+ $deflist=$2;
+ if($opt_s)
+ { $deflist=~s/^({\\\\\{.*\}).*\}$/\1\}/;}
+ print TEX "\\LA{}",&convquotes($3),"\\def\\list",$deflist,"\\inmodname\\RA{}";
+ }
+ elsif(/^quote$/) { $quoting=1; print TEX "{\\tt "; }
+ elsif(/^endquote$/) { $quoting=0; print TEX "}"; $textmode=0; }
+ elsif(/^file (.*)$/) { print TEX "\\filename{$1}"; }
+ elsif(/^literal (.*)$/) { print TEX "$1"; }
+ elsif(/^entry (.*)$/ && $opt_i) { print INDEX "$1\n"; }
+ elsif(/^index (.*)$/ && $opt_i)
+ { print STDERR "creating index `$filename.$1'\n" unless $opt_q;
+ open(INDEX,">$filename.$1");
+ print INDEX "\\begingroup\\parindent=0pt\\obeylines%\n";
+ }
+ elsif(/^end index$/ && $opt_i)
+ {
+ print INDEX "\\endgroup\n";
+ close(INDEX);
+ }
+}
+print TEX "\\passfin\n";
diff --git a/web/noweb/contrib/partingr/nwindex.tex b/web/noweb/contrib/partingr/nwindex.tex
new file mode 100644
index 0000000000..bff95acd7b
--- /dev/null
+++ b/web/noweb/contrib/partingr/nwindex.tex
@@ -0,0 +1,134 @@
+\ifx\NwInDeXLoaded\undefined\relax\else\endinput\fi
+\def\NwInDeXLoaded{}
+\ifx\moddef\undefined\input nwmac \fi
+
+% last minute panic comments
+
+% font for cross references
+\font\foot=cmr8
+
+% \init re-initialises stuff for each pass
+\def\initnwindex{\global\pageno=1\global\subpageref=97}
+\let\init=\initnwindex
+
+% macros to place information in the left margin
+% from The TeXBook
+\def\strutdepth{\dp\strutbox}
+\def\marginalnote#1{\strut\vadjust{\kern-\strutdepth\specialstar{#1}}}
+\def\specialstar#1{\vtop to \strutdepth{
+ \baselineskip\strutdepth
+ \vss\llap{#1\quad}\null}}
+
+% redefine moddef to take an argument (this section's code)
+\def\moddef#1{\vskip3pt\leavevmode\marginalnote{{\bf#1}}\kern-\codemargin \LA}
+
+% make the contents file immediately open
+\immediate\openout\cont=\contentsfile
+\immediate\write\cont{\string\catcode`\string\@=11}% a hack to make contents
+ % take stuff in plain.tex
+
+% redefine \nwendcode to provide the \aftercode hook
+\def\nwendcode{\aftercode{}\endgroup}
+
+% \subpageref is the letter part of the code
+\newcount\subpageref \subpageref=97
+
+% an entry in an index (AFAIK this is unused)
+\def\index#1#2{\line{\hskip.5in{\vbox{{\ignorespaces#1}\hskip4pt #2.}\hss}}}
+
+% advance the \subpageref, going to 'A' if 'z' was the last one
+\def\nextref{\global\advance\subpageref by 1\ifnum\subpageref=123\subpageref=65\fi}
+
+% \xp expands to #1 if #1 is defined or \relax if it is not
+\def\xp#1{\ifx#1\undefined\relax\else#1\fi}
+
+% AFAIK this is unused
+\let\ag=\aftergroup
+
+% \xref is called each time a code is defined - sort of a hook
+\def\xref#1{}
+
+% \defined is a defined macro!
+\def\defined{}
+
+% AFAIK this is unused
+\def\killpage{\setbox0=\box255\deadcycles=0 \global\subpageref=97\global\advance\pageno by 1}
+
+% a big macro for the end of a pass
+\def\passfin{%
+ \ifx\passtwo\defined
+ \write\cont{}% ensure that the contents file isn't empty after pass2
+ \closeout\cont
+ \vfil\eject\pageno=-1 % new page causes contents to be really closed
+ \topofcontents\readcontents\botofcontents
+ \else
+ \vfill\supereject
+ \fi
+}
+
+% define a reference on pass one only
+\def\makeref#1{\ifx\passtwo\undefined
+ \edef\next{\gdef\csname#1\endcsname{\folio\char\the\subpageref}}
+ \next\xref{\csname#1\endcsname}\nextref\fi}
+
+% list macros from appendix D, The TeXBook
+\toksdef\ta=0 \toksdef\tb=2 %
+\long\def\leftappenditem#1\to#2{\ta={\\{#1}}\tb=\expandafter{#2}%
+ \edef#2{\the\ta\the\tb}}
+
+\def\lop#1\to#2{\expandafter\lopoff#1\lopoff#1#2}
+
+\long\def\lopoff\\#1#2\lopoff#3#4{\def#4{#1}\def#3{#2}}
+
+\def\cardinality#1\to#2{#2=0 \long\def\\##1{\global\advance#2 by 1}#1}
+\def\list{}
+\def\ulist{}
+\newcount\listlength
+
+% write out a nicely formatted list
+\def\writeoutlist#1#2#3{\cardinality#1\to\listlength
+\def\\##1{\advance\listlength by -1\relax##1\ifnum\listlength>1 #2%
+\else\ifnum\listlength=1 #3\fi\fi}#1}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \prettylist{list}{one}{many}{between}{end}
+% 1 -> {one}E1
+% 2 -> {many}E1{end}E2
+% 3 -> {many}E1{between}E2{end}E3
+% etc.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\def\prettylist#1#2#3#4#5{%
+\cardinality#1\to\listlength\ifnum\listlength>1 #3\else#2\fi
+\writeoutlist{#1}{#4}{#5}}
+
+\def\writeplain#1{\prettylist#1{}{}{,\thinspace{}}{,\thinspace{}}}
+\def\writelist#1{\prettylist#1{}{}{,\thinspace{}}{ and }}
+\def\writesections#1{\prettylist#1{section }{sections }{,\thinspace }{\ and }}
+
+\def\usage#1{This code is used in \writesections#1.}
+\def\defs#1{\cardinality#1\to\listlength\ifnum\listlength>1{%
+{\lop#1\to\hello This definition is continued in \writesections#1.}}
+\fi}
+
+\def\first#1{\ifx\list\defined\else\ {{\lop#1\to\hello \hello}}\fi}
+\def\thiscode#1{\ifx#1\defined Root module (never referenced in this document)%
+\else\usage#1\fi}
+
+% \thiscode and \writeplain can't take direct lists as parameters, so
+% fake it with these two
+\def\xtc#1{\def\list{#1}\thiscode\list}
+\def\xwp#1{\def\list{#1}\writeplain\list}
+
+% hooks for cross-references
+\def\inmodname{\ifx\list\defined\else\thinspace{\foot\first\list}\fi}
+\def\beforecode{}
+\def\aftercode{\vbox{\kern3pt\hbox{{\foot\defs\list}}\kern-2pt\hbox{{\foot\thiscode\ulist}}\kern3pt}}
+
+% \printindex - check for file existing before \input'ing it
+\newwrite\filecheck
+\def\printindex#1{\openin\filecheck=\jobname.#1
+\ifeof\filecheck\message{[#1 file missing]}{\tt noweb} has no index `#1'\else
+\closein\filecheck\input \jobname.#1
+\fi
+}
diff --git a/web/noweb/contrib/partingr/nwnweave b/web/noweb/contrib/partingr/nwnweave
new file mode 100755
index 0000000000..d78a2af3af
--- /dev/null
+++ b/web/noweb/contrib/partingr/nwnweave
@@ -0,0 +1,2 @@
+#!/bin/csh
+markup $1.nw | mm2mx63 -n -i -m | mx2tex31 -i -n $1 -s
diff --git a/web/noweb/contrib/partingr/nwtangle b/web/noweb/contrib/partingr/nwtangle
new file mode 100755
index 0000000000..b9b115bd01
--- /dev/null
+++ b/web/noweb/contrib/partingr/nwtangle
@@ -0,0 +1,2 @@
+#!/bin/csh
+markup $1.nw | nt -R'$2'
diff --git a/web/noweb/contrib/partingr/nwweave b/web/noweb/contrib/partingr/nwweave
new file mode 100755
index 0000000000..0108ccf4aa
--- /dev/null
+++ b/web/noweb/contrib/partingr/nwweave
@@ -0,0 +1,2 @@
+#!/bin/csh
+markup $1.nw | mm2mx63 -i -m | mx2tex31 -i -n $1 -s
diff --git a/web/noweb/contrib/partingr/xpand b/web/noweb/contrib/partingr/xpand
new file mode 100755
index 0000000000..772375ff54
--- /dev/null
+++ b/web/noweb/contrib/partingr/xpand
@@ -0,0 +1,20 @@
+#!/usr/common/bin/perl
+while(<>)
+{
+# expand wildcard references here, then process as normal
+ if(/^@(use|defn) (.*)$/)
+ {
+ $action=$1;
+ if($2=~/\.{3}$/)
+ { @matches=grep(/^$2.*/i,split(/¤/,$known));
+ if($#matches>0)
+ { die "\nAmbiguous module name `$mod...'"; }
+ elsif($#matches==-1)
+ { die "\nNo match for name `$mod...',line $i "; }
+ else
+ { $mn=@matches[0]; $_="@$action $mn\n"; }
+ }
+ else { $known=$known . "¤$2"; }
+ }
+ print STDOUT $_;
+}
diff --git a/web/noweb/contrib/rsc/README b/web/noweb/contrib/rsc/README
new file mode 100644
index 0000000000..76e57bbd0c
--- /dev/null
+++ b/web/noweb/contrib/rsc/README
@@ -0,0 +1 @@
+These scripts support use of Noweb under Plan 9.
diff --git a/web/noweb/contrib/rsc/email b/web/noweb/contrib/rsc/email
new file mode 100644
index 0000000000..2e53c38912
--- /dev/null
+++ b/web/noweb/contrib/rsc/email
@@ -0,0 +1 @@
+Russ Cox <rsc@plan9.bell-labs.com>
diff --git a/web/noweb/contrib/rsc/rc/cpif.nw b/web/noweb/contrib/rsc/rc/cpif.nw
new file mode 100644
index 0000000000..e4bb15e512
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/cpif.nw
@@ -0,0 +1,47 @@
+<<cpif>>=
+#!/bin/rc
+#
+# Based on shell script by Norman Ramsey
+# Translated from sh to rc by Russ Cox
+#
+# see /sys/src/cmd/noweb/COPYRIGHT
+#
+# cpif [ -eq -ne ] file...
+# copy standard input to each of the named files
+# if new * old is true or old doesn't exist;
+# * defaults to -ne
+
+rfork en
+
+# set -x
+op=-ne
+if(~ $1 -eq -ne){
+ op=$1
+ shift
+}
+if(~ $1 -* || ~ $#* 0) {
+ echo 'Usage: '$0' [-eq -ne] file...' >[1=2]
+ exit usage
+}
+
+new=$(mktemp) || { echo "$0: Cannot create temporary file" >&2; exit 1; }
+
+# trap 'rm -f $new; exit 1' 1 2 15 # clean up files
+
+cat >$new
+for(i) {
+ cmp -s $new $i
+
+ switch($op^$status) {
+ # differed but we wanted same
+ case -eq*differ
+ ;
+ # didn't differ but we wanted different
+ case -ne
+ ;
+ # got what we wanted or perhaps an error
+ case *
+ cp $new $i
+ }
+}
+rm -f $new
diff --git a/web/noweb/contrib/rsc/rc/emptydefn.nw b/web/noweb/contrib/rsc/rc/emptydefn.nw
new file mode 100644
index 0000000000..33901008d0
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/emptydefn.nw
@@ -0,0 +1,10 @@
+<<emptydefn>>=
+#!/bin/rc
+#
+# notangle filter that makes the definition of an empty chunk @<<>>=
+# stand for a continuation of the previous chunk definition.
+
+awk 'BEGIN { lastdefn = "@defn " }
+/^@defn $/ { print lastdefn; next }
+/^@defn / { lastdefn = $0 }
+{ print }' $*
diff --git a/web/noweb/contrib/rsc/rc/mkfile b/web/noweb/contrib/rsc/rc/mkfile
new file mode 100644
index 0000000000..a2165adb42
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/mkfile
@@ -0,0 +1,28 @@
+
+RCTARG=cpif noroots noweave notangle nountangle
+RCLIBTARG=emptydefn noidx noindex toascii tohtml totex unmarkup noweb
+AWKTARG=noidx.awk noindex.awk toascii1.awk toascii2.awk tohtml.awk
+
+%: %.nw
+ notangle -R$stem $stem.nw >$stem
+
+%2.awk: %.nw
+ notangle -R$target $stem.nw >$target
+%1.awk: %.nw
+ notangle -R$target $stem.nw >$target
+%.awk: %.nw
+ notangle -R$target $stem.nw >$target
+
+TARG=$RCTARG $RCLIBTARG $AWKTARG
+
+default:V: $TARG
+
+clean:V:
+ rm $TARG
+
+install:V:
+ cp $RCTARG /rc/bin
+ cp $RCLIBTARG /sys/lib/noweb/bin/rc
+ chmod 775 /rc/bin/^($RCTARG)
+ chmod 775 /sys/lib/noweb/bin/rc/^($RCLIBTARG)
+ cp $AWKTARG /sys/lib/noweb
diff --git a/web/noweb/contrib/rsc/rc/noidx.nw b/web/noweb/contrib/rsc/rc/noidx.nw
new file mode 100644
index 0000000000..672badb84f
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/noidx.nw
@@ -0,0 +1,432 @@
+\documentstyle[noweb]{article}
+\pagestyle{noweb}
+\begin{document}
+@
+\section{Cross-reference and index support}
+Here is is.
+<<noidx>>=
+#!/bin/rc
+#
+# Translated to rc by Russ Cox
+# bugs -> rsc@plan9.bell-labs.com
+
+delay=0
+anchordist=0
+while(! ~ $#* 0) {
+ switch($1){
+ case -delay
+ delay=1
+ case -docanchor
+ anchordist=$2
+ shift
+ case *
+ echo 'cannot happen -- '^$1^' passed to noidx' >[1=2]
+ exit cannothappen
+ }
+ shift
+}
+awk -f /sys/lib/noweb/noidx.awk -v 'delay='$delay -v 'anchordist='$anchordist
+@
+<<noidx.awk>>=
+<<functions>>
+BEGIN { <<initialization>> nextline = 0 }
+<<first pass>>
+{ lines[nextline] = $0; nextline++ }
+END {
+ for (i = 0; i < nextline; i ++) {
+ <<second pass over [[lines[i]]]>>
+ delete lines[i]
+ }
+ if (!delay) <<write trailers>>
+}
+@ %def lines nextline
+<<initialization>>=
+curfile = "standard input?"
+lastchunkbegin = "never any chunks?" ;
+<<initialization>>=
+allchunks[0] = 0 ; allidents[0] = 0 ; indexlabels[0] = 0
+defanchors[0] = 0 ; uses[0] = 0 ; anchorlabel[0] = 0 ; indexanchorlabel[0] = 0
+@ %def allchunks allidents indexlabels defanchors uses anchorlabel indexancho
+label
+<<first pass>>=
+/^@file / { curfile = uniqueid(substr($0, 7)) }
+/^@begin / { lastchunkbegin = $0 }
+/^@end docs / { if (anchordist > 0) <<insert and set [[lastanchorlabel]]>> }
+/^@end code / { lastanchorlabel = "" }
+@ %def curfile lastchunkbegin lastanchorlabel
+<<first pass>>=
+/^@defn / { arg = substr($0, 7)
+ allchunks[arg] = 1
+ lastdefnlabel = newdefnlabel(arg)
+ slipin("@xref label " lastdefnlabel)
+ if (lastanchorlabel == "") lastanchorlabel = lastdefnlabel
+ if (anchorlabel[arg] == "") anchorlabel[arg] = lastanchorlabel
+ addlabel(defanchors, arg, lastanchorlabel)
+ addud(chunkud, "defn", arg, lastanchorlabel)
+ thisusecount = 0
+ }
+/^@use / { if (lastchunkbegin ~ /^@begin code /) {
+ arg = substr($0, 6)
+ allchunks[arg] = 1
+ slipin("@xref label " lastdefnlabel "-u" (++thisusecount))
+ addlabel(uses, arg, lastanchorlabel)
+ addud(chunkud, "use", arg, lastanchorlabel)
+ }
+ }
+@ %def allchunks lastdefnlabel
+<<first pass>>=
+/^@index use / { arg = substr($0, 12)
+ allidents[arg] = 1
+ if (lastanchorlabel != "") addud(indexud, "use", arg, lastan
+horlabel)
+ }
+/^@index defn / { arg = substr($0, 13)
+ <<handle index definition of [[arg]]>>
+ }
+/^@index localdefn / { arg = substr($0, 18)
+ <<handle index definition of [[arg]]>>
+ }
+<<handle index definition of [[arg]]>>=
+allidents[arg] = 1
+if (lastanchorlabel != "") {
+ l = lastanchorlabel
+} else {
+ l = newdocslabel()
+ slipin("@xref label " l)
+}
+addud(indexud, "defn", arg, l)
+if (indexanchorlabel[arg] == "") indexanchorlabel[arg] = l
+slipin("@xref ref " l) # bug fix
+@ %def allidents indexanchorlabel
+The bug fix\label{multi-def-bug}
+alluded to above occurs when there are multiple definitions of an identifier.
+In this case, we can't just use [[indexanchorlabel[id]]], because that refers
+nly to
+the first definition. In the {\TeX} back end, that leads to bogus
+tags like \hbox{\it x \small\rm 7b 7b 7b} instead of \hbox{\it x
+\small\rm 7b 9 12a}; the first tag is repeated again and again.
+Because the tag for the current [[@defn]] is lost by the time pass~2
+rolls around, we have to slip it in on pass~1.
+@
+<<insert and set [[lastanchorlabel]]>>=
+{ n = anchordist
+ lastanchorlabel = newdocslabel()
+ for(i = nextline - 1; i >= 0; i--) {
+ if (n == 0 || lines[i] ~ /^@begin docs /) {
+ insertafter(i, "@xref label " lastanchorlabel)
+ i = -1 # cause loop to terminate
+ } else if (lines[i] == "@nl") {
+ n--
+ }
+ }
+}
+<<functions>>=
+function insertafter(i, s, n) {
+ for(n = nextline++; n - 1 > i; n--) lines[n] = lines[n-1]
+ lines[n] = s
+}
+@
+In the awk version, [[slipin]] is called {\em before} the current line is
+added to [[lines]].
+<<functions>>=
+function slipin(s) {
+ lines[nextline++] = s
+}
+<<initialization>>=
+thesedefns[0] = 0; theseuses[0] = 0 ;
+<<second pass over [[lines[i]]]>>=
+line = lines[i]
+if (line ~ /^@begin /) {
+ if (delay && lastchunkbegin == line) <<write trailers>>
+ print line
+ for (x in thesedefns) delete thesedefns[x]
+ for (x in theseuses) delete theseuses[x]
+ thischunk = ""
+} else if (line ~ /^@defn /) {
+ thischunk = substr(line, 7)
+ printf "@xref ref %s\n", anchorlabel[thischunk]
+ print line
+} else if (line ~ /^@use /) {
+ arg = substr(line, 6)
+ printf "@xref ref %s\n", (anchorlabel[arg] == "" ? "nw@notdef" : anchorlab
+l[arg])
+ print line
+} else if (line ~ /^@index defn /) {
+ arg = substr(line, 13)
+ thesedefns[arg] = 1
+ # no xref ref because of bug fix
+ # if (indexanchorlabel[arg] != "")
+ # printf "@xref ref %s\n", indexanchorlabel[arg]
+ print line
+} else if (line ~ /^@index localdefn /) {
+ arg = substr(line, 18)
+ thesedefns[arg] = 1
+ # no xref ref because of bug fix
+ # if (indexanchorlabel[arg] != "")
+ # printf "@xref ref %s\n", indexanchorlabel[arg]
+ print line
+} else if (line ~ /^@index use /) {
+ arg = substr(line, 12)
+ theseuses[arg] = 1
+ if (indexanchorlabel[arg] != "")
+ printf "@xref ref %s\n", indexanchorlabel[arg]
+ print line
+} else if (line ~ /^@end code/) {
+ <<write cross-reference>>
+ print line
+} else if (line ~ /^@text /) {
+ # grotesque hack to get indexes in HTML
+ if (thischunk == "") { # docs mode
+ arg = substr(line, 7)
+ if (arg == "<nowebchunks>") lognowebchunks()
+ else if (arg == "<nowebindex>") lognowebindex()
+ else print line
+ } else {
+ print line
+ }
+} else {
+ print line
+}
+@ %def thesedefns theseuses
+The case of the [[@index defn]] is the one case where we don't emit a
+reference, because the reference has to go in earlier. See
+page~\pageref{multi-def-bug} for an explanation.
+<<write cross-reference>>=
+defout[thischunk]++
+<<write index cross-reference>>
+if (defout[thischunk] == 1) {<<write chunk cross-reference>>}
+if (defout[thischunk] > 1)
+ printf "@xref prevdef %s\n", listget(defanchors[thischunk], defout[thischunk
+-1)
+if (defout[thischunk] < defcount[thischunk])
+ printf "@xref nextdef %s\n", listget(defanchors[thischunk], defout[thischunk
++1)
+<<write index cross-reference>>=
+for (x in thesedefns)
+ delete theseuses[x]
+delete thesedefns[0]
+n = alphasort(thesedefns)
+if (n > 0) {
+ print "@index begindefs"
+ for (j = 0; j < n; j++) {
+ m = split(indexud[sorted[j]], a)
+ for (k = 1; k <= m; k++)
+ if (a[k] ~ /^use/)
+ printf "@index isused %s\n", substr(a[k], 5, length(a[k])-5)
+ printf "@index defitem %s\n", sorted[j]
+ delete sorted[j]
+ }
+ print "@index enddefs"
+}
+<<write index cross-reference>>=
+delete theseuses[0]
+n = alphasort(theseuses)
+if (n > 0) {
+ print "@index beginuses"
+ for (j = 0; j < n; j++) {
+ m = split(indexud[sorted[j]], a)
+ for (k = 1; k <= m; k++)
+ if (a[k] ~ /^defn/)
+ printf "@index isdefined %s\n", substr(a[k], 6, length(a[k])-6)
+ printf "@index useitem %s\n", sorted[j]
+ delete sorted[j]
+ }
+ print "@index enduses"
+}
+<<write chunk cross-reference>>=
+if (defcount[thischunk] > 1) {
+ print "@xref begindefs"
+ n = split(defanchors[thischunk], a)
+ for (j = 2; j <= n; j++) printf "@xref defitem %s\n", a[j]
+ print "@xref enddefs"
+
+}
+if (uses[thischunk] != "") {
+ print "@xref beginuses"
+ n = split(uses[thischunk], a)
+ for (j = 1; j <= n; j++) printf "@xref useitem %s\n", a[j]
+ print "@xref enduses"
+} else {
+ printf "@xref notused %s\n", thischunk
+}
+<<functions>>=
+function newdefnlabel(arg, label) {
+ defcount[arg] = defcount[arg] + 1
+ label = "NW" curfile "-" uniqueid(arg) "-" alphacode(defcount[arg])
+ return label
+}
+@ %def newdefnlabel
+<<initialization>>=
+defcount[0] = 0 ;
+<<functions>>=
+function newdocslabel() {
+ newdocslabelcount++
+ return "NWD" alphacode(newdocslabelcount)
+}
+@ %def newdocslabel
+<<functions>>=
+function addlabel(tbl, arg, label, marker) {
+ marker = " " label
+ if (!tailmatch(tbl[arg], marker))
+ tbl[arg] = tbl[arg] marker
+ return label
+}
+@ %def addlabel
+<<functions>>=
+function tailmatch(string, tail, pos) {
+ pos = length(string) - length(tail) + 1
+ if (pos > 0 && substr(string, pos) == tail)
+ return 1
+ else
+ return 0
+}
+@ %def tailmatch
+<<functions>>=
+function addud(udlist, name, arg, label, s) {
+ s = " " name "{" label "}"
+ if (!tailmatch(udlist[arg], s))
+ udlist[arg] = udlist[arg] s
+}
+@ %def addud
+<<functions>>=
+function listget(l, i, n, a) {
+ n = split(l, a)
+ return a[i]
+}
+@ %def listget
+<<initialization>>=
+udlist[0] = 0 ;
+@
+[[uniqueid]] eliminates both {\TeX} and HTML specials.
+Escaping the [[/]] in the character class in the regexp pattern works
+around a bug in many awks.
+Unpalatable, but what can one do?
+<<functions>>=
+function uniqueid(name, key) {
+ if (uidtable[name] == "") {
+ key = make_key(name)
+ # gsub(/[\]\[ \\{}`#%&~_^<>"-]/, "*", key) # old
+ gsub(/[^a-zA-Z0-9!$()*+,.\/:;=?@|]/, "*", key)
+ keycounts[key] = keycounts[key] + 1
+ uidtable[name] = key
+ if (keycounts[key] > 1)
+ uidtable[name] = uidtable[name] "." alphacode(keycounts[key])
+ }
+ return uidtable[name]
+}
+@ %def uniqueid
+<<functions>>=
+function make_key(name, key, l) {
+ l = length(name)
+ sub(/^.*\//, "", name)
+ key = substr(name, 1, 3)
+ if (l >= 3) key = key alphacode(l)
+ return key
+}
+<<initialization>>=
+uidtable[0] = 0
+keycounts[0] = 0 ;
+<<write trailers>>=
+{ print "@nl"
+ print "@nl"
+ lognowebchunks()
+ lognowebindex()
+}
+@
+Now, a special hack, so we can write this stuff in the right place on pass 2.
+<<functions>>=
+function lognowebchunks(l, j, n, x) {
+ if (loggednowebchunks > 0) return
+ loggednowebchunks = 1
+ delete allchunks[0]
+ n = alphasort(allchunks)
+ print "@xref beginchunks"
+ for (j = 0; j < n; j++) {
+ name = sorted[j]; delete sorted[j]
+ printf "@xref chunkbegin %s %s\n",
+ (anchorlabel[name] != "" ? anchorlabel[name] : "nw@notdef"), name
+ m = split(chunkud[name], a)
+ for (k = 1; k <= m; k++)
+ if (a[k] ~ /^use/)
+ printf "@xref chunkuse %s\n", substr(a[k], 5, length(a[k])-5)
+ else if (a[k] ~ /^defn/)
+ printf "@xref chunkdefn %s\n", substr(a[k], 6, length(a[k])-6)
+ print "@xref chunkend"
+ }
+ print "@xref endchunks"
+}
+@ %def lognowebchunks
+<<functions>>=
+function lognowebindex(l, j, n, x) {
+ if (loggednowebindex > 0) return
+ loggednowebindex = 1
+ delete allidents[0]
+ n = alphasort(allidents)
+ print "@index beginindex"
+ for (j = 0; j < n; j++) {
+ name = sorted[j]; delete sorted[j]
+ printf "@index entrybegin %s %s\n",
+ (indexanchorlabel[name] != "" ? indexanchorlabel[name] : "nw@notdef"),
+ame
+ m = split(indexud[name], a)
+ for (k = 1; k <= m; k++)
+ if (a[k] ~ /^use/)
+ printf "@index entryuse %s\n", substr(a[k], 5, length(a[k])-5)
+ else if (a[k] ~ /^defn/)
+ printf "@index entrydefn %s\n", substr(a[k], 6, length(a[k])-6)
+ print "@index entryend"
+ }
+ print "@index endindex"
+}
+@ %def lognowebindex
+<<functions>>=
+function alphasort(a, x, n) {
+ n = 0
+ for (x in a)
+ n = insertitem(x, n)
+ return n
+}
+function insertitem(x, n, i, tmp) {
+ sorted[n] = x
+ sortkeys[n] = sortkey(x)
+ i = n
+ while (i > 0 && (sortkeys[i] < sortkeys[i-1] ||
+ sortkeys[i] == sortkeys[i-1] && sorted[i] < sorted[i-1])) {
+ tmp = sortkeys [i]; sortkeys [i] = sortkeys [i-1]; sortkeys [i-1] = tmp
+ tmp = sorted[i]; sorted[i] = sorted[i-1]; sorted[i-1] = tmp
+ i = i - 1
+ }
+ return n + 1
+}
+@ %def alphasort insertitem
+<<initialization>>=
+sorted[0] = 0; sortkeys[0] = 0;
+<<functions>>=
+function sortkey(name, s) {
+ s = name
+ gsub(/[^a-zA-Z ]/, "", s)
+ return s
+}
+@ %def sortkey
+<<functions>>=
+function alphacode(n) {
+ if (n < 0)
+ return "-" alphacode(-n)
+ else if (n >= alphacodelen)
+ return alphacode(n / alphacodelen) alphacode(n % alphacodelen)
+ else
+ return substr(alphacodes, n+1, 1)
+}
+@ %def alphacode
+<<initialization>>=
+alphacodes = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+alphacodelen = length(alphacodes) ;
+@
+\section{List of chunks}
+\nowebchunks
+
+\twocolumn
+\section{Index}
+\nowebindex
+@
+\end{document}
diff --git a/web/noweb/contrib/rsc/rc/noindex.nw b/web/noweb/contrib/rsc/rc/noindex.nw
new file mode 100644
index 0000000000..193f2c6429
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/noindex.nw
@@ -0,0 +1,194 @@
+This program is similar to [[makeindex]] in that it grovels through [[.aux]]
+files looking for index information, which it writes to a [[.nwi]] file.
+It's used when [[noweave -indexfrom]] is used on many files separately;
+it combines the separate indices into a single, correctly sorted index.
+That index file is read by [[\nowebindex*]].
+<<noindex>>=
+#!/bin/rc
+#
+# Translated to rc by Russ Cox
+# bugs -> rsc@plan9.bell-labs.com
+
+if(! ~ $#* 1) {
+ echo 'Usage: '^`{basename $0}^' file[.tex]' >[1=2]
+ exit usage
+}
+
+awk -f /sys/lib/noweb/noindex.awk >[1=2]
+
+<<noindex.awk>>=
+BEGIN { infile="'"$1"'"
+ <<main code>>
+ exit
+}
+<<functions>>
+<<main code>>=
+if (infile ~ /\.tex$/) {
+ infile = substr(infile, 1, length(infile)-4) ".aux"
+} else if (infile !~ /\.aux$/) {
+ infile = infile ".aux"
+}
+idx[0] = ""
+delete idx[0]
+gobble(infile)
+alphasort(idx)
+outname = substr(infile, 1, length(infile)-4) ".nwi"
+last = ""
+for (i = 0; i < count; i++) {
+ out = stripcount(sorted[i])
+ if (last != out) {
+ print out > outname
+ last = out
+# <show sort key [[i]]>
+ }
+}
+<<show sort key [[i]]>>=
+key = sortkeys[i]
+sub(/^\n+/, "", key)
+sub(/\n.*$/, "", key)
+print "% " key > outname
+<<functions>>=
+function gobble(name, infile, rc, tag) {
+ for (rc = (getline line < name); rc > 0; rc = (getline line < name)) {
+ if (line ~ /^\\@input{[^}]*}$/)
+ gobble(substr(line, 9, length(line)-9))
+ else if (line ~ /^\\nwixadds{/) {
+ count++
+ tag = "000000" count
+ tag = substr(tag, length(tag)-6+1)
+ idx[count] = tag " " substr(line, 11)
+ }
+ }
+ if (rc < 0) print "No file " name "."
+ else close(name)
+ return
+}
+<<functions>>=
+function stripcount(s) {
+ sub(/^[0-9]+/, "", s)
+ sub(/ +/, "", s)
+ return "\\nwixaddsx{" s
+}
+<<functions>>=
+function alphasort(a, x, n) {
+ n = 0
+ for (x in a)
+ n = insertitem(a[x], n)
+ finish_sorting(n)
+ return n
+}
+function insertitem(x, n, i, tmp) {
+ sorted[n] = x
+ sortkeys[n] = sortkey(x)
+ return n+1
+}
+<<functions>>=
+function finish_sorting(n) {
+ firstwork = nextwork = 0
+ addquick(0, n)
+ while(nextwork > firstwork)
+ qsort()
+}
+<<functions>>=
+function addquick(l, r) {
+ workq[nextwork++] = l
+ workq[nextwork++] = r
+}
+<<get [[l]] and [[r]] out of work queue>>=
+l = workq[firstwork]
+delete workq[firstwork]
+firstwork++
+r = workq[firstwork]
+delete workq[firstwork]
+firstwork++
+<<functions>>=
+function qsort(l, r, mid, i, last) {
+ <<get [[l]] and [[r]] out of work queue>>
+ if (r - l < 10)
+ isort(l, r)
+ else {
+ mid = l + int((r - l) * rand())
+ swap(l, mid)
+ last = l
+ for (i = l+1; i < r; i++)
+ if (sortkeys[i] < sortkeys[l] ||
+ sortkeys[i] == sortkeys[l] && sorted[i] < sorted[l])
+ swap(++last, i)
+ swap(l, last)
+ addquick(l, last)
+ addquick(last+1, r)
+ }
+}
+<<functions>>=
+function isort(l, r, n) {
+ for (n = l + 1; n < r; n++)
+ for (i = n; i > l && (sortkeys[i] < sortkeys[i-1] ||
+ sortkeys[i] == sortkeys[i-1] && sorted[i] < sorted[i
+1]); i--)
+ swap(i, i-1)
+}
+<<functions>>=
+function swap(i, j, tmp) {
+ tmp = sortkeys [i]; sortkeys [i] = sortkeys [j]; sortkeys [j] = tmp
+ tmp = sorted[i]; sorted[i] = sorted[j]; sorted[j] = tmp
+}
+<<functions>>=
+function sortkey(s, count) {
+ match(s, /^[0-9]+/)
+ count = substr(s, RSTART, RLENGTH)
+ sub(/^[0-9]+ */, "", s)
+ if (s ~ /c}/) {
+ return firstkey(substr(s, 3)) "\n" count
+ } else if (s ~ /i}/) {
+ return firstkey(substr(s, 3)) "\n" count
+ } else {
+ print "sortkey handed non-chunk and non-index: " s
+ exit 1
+ }
+}
+<<functions>>=
+function firstkey(s, r, openbrace) {
+ if (s !~ /^{{/) {
+ <<complain about format and exit>>
+ }
+ sub (/^{{/, "", s)
+ gsub(/\\([a-zA-Z]+|.) */, "", s) # kill control sequences
+ openbrace = 1
+ r = ""
+ while (openbrace > 0)
+ if (match(s, /^[^{}]*/) <= 0)
+ openbrace--
+ else {
+ r = r substr(s, RSTART, RLENGTH)
+ c = substr(s, RSTART+RLENGTH, 1)
+ s = substr(s, RSTART+RLENGTH+1)
+ if (c == "}") openbrace--
+ else openbrace++
+ if (openbrace > 0) r = r c
+ }
+ return alphabet(r) "\n" r
+}
+<<complain about format and exit>>=
+print "key \"" substr(s, 1, 6) "...\" is ill-formatted"
+exit 1
+<<functions>>=
+function alphabet(s, r) {
+ r = ""
+ while (match(s, /[a-zA-Z \t]/) > 0) {
+ s = substr(s, RSTART)
+ c = substr(s, 1, 1)
+ if (c == " " || c == "\t") {
+ r = r " "
+ sub(/^[ \t]+/, "", s)
+ } else {
+ match(s, /^[a-zA-Z]+/)
+ r = r substr(s, RSTART, RLENGTH)
+ s = substr(s, RSTART+RLENGTH)
+ }
+ }
+ sub(/^ +/, "", r)
+ return r
+}
+@
+\section{Index}
+\nowebindex
diff --git a/web/noweb/contrib/rsc/rc/noroots.nw b/web/noweb/contrib/rsc/rc/noroots.nw
new file mode 100644
index 0000000000..74f4a792a1
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/noroots.nw
@@ -0,0 +1,16 @@
+<<noroots>>=
+#!/bin/rc
+#
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file /sys/src/cmd/noweb/COPYRIGHT for more information.
+#
+# set -x
+/sys/lib/noweb/bin/$objtype/markup $* | awk '
+/^@quote$/,/^@endquote$/ { next }
+/^@defn / { chunk=substr($0,7) ; defined[chunk]=1 }
+/^@use / { chunk=substr($0,6) ; used[chunk]=1 }
+END {
+ for (chunk in defined) {
+ if (defined[chunk]==1 && used[chunk]==0) printf "@<<%s>>\n", chunk
+ }
+}'
diff --git a/web/noweb/contrib/rsc/rc/notangle.nw b/web/noweb/contrib/rsc/rc/notangle.nw
new file mode 100644
index 0000000000..476534ca27
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/notangle.nw
@@ -0,0 +1,51 @@
+<<notangle>>=
+#!/bin/rc
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file /sys/src/cmd/noweb/COPYRIGHT for more information.
+#
+# Translated from sh to rc by Russ Cox
+# bugs -> rsc@plan9.bell-labs.com
+#
+
+rfork en
+bind -b /sys/lib/texmf/bin/$objtype /bin
+bind -b /sys/lib/texmf/bin/rc /bin
+
+LIB=/sys/lib/texmf/noweb
+markup=markup
+opt=()
+arg=()
+markopt=()
+filters=()
+
+while(! ~ $#* 0) {
+ switch($1) {
+ case -m -m3 -awk -icn -icon -pascal -c -c++ -f77 -f90 -tex -w[0-9][0-9]
+
+ ;
+ case -t
+ ;
+ case -t*
+ markopt=($markopt -t)
+ opt=($opt $1)
+ case -filter
+ filters=($filters $2)
+ shift
+ case -markup
+ markup=$2
+ shift
+ case -
+ arg=($arg $1)
+ case -L*
+ opt=($opt -t $1)
+ markopt=($markopt -t)
+ case -*
+ opt=($opt $1)
+ case *
+ arg=($arg $1)
+ }
+ shift
+}
+
+$markup $markopt $arg | $filters nt $opt
+exit $status
diff --git a/web/noweb/contrib/rsc/rc/nountangle.nw b/web/noweb/contrib/rsc/rc/nountangle.nw
new file mode 100644
index 0000000000..207eb5e08c
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/nountangle.nw
@@ -0,0 +1,93 @@
+<<nountangle>>=
+#!/bin/rc
+#
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file /sys/src/cmd/noweb/COPYRIGHT for more information.
+#
+# Translated to rc by Russ Cox
+# bugs -> rsc@plan9.bell-labs.com
+
+# set -x
+rfork en
+bind -b /sys/lib/noweb/bin/$objtype /bin
+bind -b /sys/lib/noweb/bin/rc /bin
+
+markup=markup
+opt=''
+arg=''
+filters=''
+width=72
+subst='gsub("\\*/", "* /", s)'
+format='/* %%-%ds */'
+
+while(! ~ $#* 0) {
+ switch($1) {
+ case -ml -m3
+ format='(* %%-%ds *)'
+ subst='gsub("\\*\\)", "* )", s) gsub("\\(\\*", "( *", s)'
+ case -awk -icn -icon
+ format='# %%-%ds' ; subst=' '
+ case -lisp -scm
+ format=';;; %%-%ds' ; subst=' '
+ case -c++
+ format='// %%-%ds' ; subst=' '
+ case -c
+ format='/* %%-%ds */' subst='gsub("\\*/", "* /", s)'
+ case -pascal
+ format='{ %%-%ds }' ; subst='gsub("[{}]", "-", s)'
+ case -f77
+ format='C %%-%ds' ; subst=' ' ;;
+ case -f90
+ format='! %%-%ds' ; subst=' ' ;;
+ case -tex
+ format='%%%% %%-%ds' ; subst=' ' ;;
+ case -L*
+ # deliberately ignore requests for #line
+ case -w[0-9][0-9]*; width=`{echo $1 | sed 's/^-w//'} ;;
+ case -filter; filters=' | '$filters' '$2 ; shift ;;
+ case -markup; markup=$2; shift ;;
+ case -; arg=$arg' '$1;;
+ case -*; opt=$opt' '$1 ;;
+ case *; arg=$arg' '$1 ;;
+ }
+ shift
+}
+
+eval $markup^' '^$arg^' '^$filters |
+awk 'BEGIN { line = 0; capture = 0; format=sprintf("'$format'",'$width') }
+
+function comment(s) {
+ '$subst'
+ return sprintf(format,s)
+}
+
+function grab(s) {
+ if (capture==0) print
+ else holding[line] = holding[line] s
+}
+
+/^@end doc/ { capture = 0; holding[++line] = "" ; next }
+/^@begin doc/ { capture = 1; next }
+
+/^@text / { grab(substr($0,7)); next}
+/^@quote$/ { grab("[[") ; next}
+/^@endquote$/ { grab("]]") ; next}
+
+/^@nl$/ { if (capture !=0 ) {
+ holding[++line] = ""
+ } else if (defn_pending != 0) {
+ print "@nl"
+ for (i=0; i<=line && holding[i] ~ /^ *$/; i++) i=i
+ for (; i<=line; i++) printf "@text %s\n@nl\n", comment(holding[i])
+ line = 0; holding[0] = ""
+ defn_pending = 0
+ } else print
+ next
+ }
+
+/^@defn / { holding[line] = holding[line] "<"substr($0,7)">=" # (line should b
+ blank)
+ print ; defn_pending = 1 ; next }
+{ print }' |
+eval nt^' '^$opt
+
diff --git a/web/noweb/contrib/rsc/rc/noweave.nw b/web/noweb/contrib/rsc/rc/noweave.nw
new file mode 100644
index 0000000000..46b49ae81e
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/noweave.nw
@@ -0,0 +1,594 @@
+\section{Weaving a {\tt noweb} file into a \TeX file}
+The copyright applies both to the {\tt noweb} source and to the
+generated shell script.
+<<copyright notice>>=
+# Copyright 1991-1997 by Norman Ramsey. All rights reserved.
+# See file /sys/src/cmd/noweb/COPYRIGHT for more information.
+# $Id: noweave.nw,v 1.6 1998/08/17 00:10:34 nr Exp nr $
+#
+# Translated from sh to rc by Russ Cox
+# bugs -> rsc@plan9.bell-labs.com
+@
+Here's the organization of the source:
+<<noweave>>=
+#!/bin/rc
+<<copyright notice>>
+rfork en
+<<initialization>>
+<<set up /bin union>>
+<<scan options and arguments>>
+{
+ <<emit markup on standard output>>
+ status=''
+} | {
+ args=(`{echo $noindex $delay $shortxref})
+ eval $backend $args
+}
+exit $status
+<<if verbose, show back end>>=
+if(! ~ $verbose '')
+ echo $backend $noindex $delay $shortxref >[1=2]
+@
+The first item of initialization is to locate the {\tt noweb} library.
+<<initialization>>=
+LIB=/sys/lib/noweb
+@
+We need to add the {\tt noweb} bin directories to the union mount on {\tt /bin
+.
+<<set up /bin union>>=
+bind -b $LIB/bin/$objtype /bin
+bind -b $LIB/bin/rc /bin
+@
+We continue with initialization.
+We use strings throughout rather than {\tt rc} lists,
+since we're just going to echo it anyway, and it makes
+keeping the filterlist easy.
+<<initialization>>=
+markup=markup
+backend=totex
+wrapper=''
+delay=''
+args=''
+markopts=''
+noweboptions=''
+autodefs=''
+verbose=''
+shortxref=''
+noquote=-noquote
+docanchor=''
+noindex=-noindex
+filterlist=()
+# following supported by change in totex back end
+noquote=''
+@
+I make two passes over the arguments so as not to require that options
+be given in a certain order
+<<scan options and arguments>>=
+saveargs=($*)
+arg=''
+while(! ~ $#* 0) {
+ switch($1) {
+ <<first pass {\tt noweave} options>>
+ case -
+ arg=$arg^' '$1
+ case -*
+ echo $0': unrecognized option '$1 >[1=2]
+ <<show usage>>
+ exit usage
+ case *
+ arg=$arg^' '$1
+ }
+ shift
+}
+<<insist first-pass options are self-consistent>>
+if(~ $wrapper '')
+ wrapper=latex
+
+*=$saveargs
+shift
+
+while(! ~ $#* 0) {
+ switch($1) {
+ <<second pass {\tt noweave} options>>
+ }
+ shift
+}
+
+<<add [[$newopt]] to [[noweboptions]]>>=
+if(~ $noweboptions '')
+ noweboptions=$newopt
+if not
+ noweboptions=$noweboptions','$newopt
+
+<<first pass {\tt noweave} options>>=
+case -latex
+ if(! ~ $wrapper none)
+ wrapper=latex
+case -tex
+ wrapper=tex
+case -html
+ if(! ~ $wrapper none)
+ wrapper=html
+ backend='tohtml -localindex'
+ noquote=''
+ docanchor='-docanchor 10'
+case -latex+html
+ if(! ~ $wrapper none)
+ wrapper=latex
+ backend='tohtml -localindex -raw'
+ noquote=''
+ docanchor='-docanchor 10'
+case -ascii
+ wrapper=none
+ backend=toascii
+case -troff
+ backend=toroff
+case -n
+ wrapper=none
+case -backend
+ backend=$2
+ shift
+case -markup
+ markup=$2
+ shift
+@
+Note some versions of echo break on [[echo "-n..."]], echoing nothing
+at all. The leading space is claimed to prevent this problem.
+<<option printout for usage>>=
+echo '-latex Emit LaTeX with headers and trailers (default).' >[1=2]
+echo '-tex Emit plain TeX with headers and trailers.' >[1=2]
+echo '-html Emit HTML with headers and trailers.' >[1=2]
+echo '-latex+html Assume LaTeX in documentation, but use HTML in code.' >
+1=2]
+# echo '-ascii Emit ASCII.' >[1=2]
+echo '-troff Emit troff (actually GNU groff).' >[1=2]
+echo ' -n Don''t use any header or trailer.' >[1=2]
+echo '-markup frontend Parse input with frontend (e.g., numarkup).' >[1=2]
+@ \iffalse
+<<noweave man page option table>>=
+.TP
+.B \-latex
+Emit LaTeX, including wrapper in
+.B article
+style with the
+.B noweb
+package and page style. (Default)
+.TP
+.B \-tex
+Emit plain TeX, including wrapper with
+.B nwmac
+macros.
+.TP
+.B \-html
+Emit HTML, using HTML wrapper.
+The output is uninteresting without \fB-index\fP or \fB-x\fP.
+The tags \fB<nowebchunks>\fP and \fB<nowebindex>\fP, on lines by themselves,
+produce a list of chunks and an index of identifiers, respectively.
+If these tags are not present, the list and index are placed at the end of the
+file.
+.TP
+.B \-latex+html
+Assume documentation chunks are LaTeX, but generate HTML for code chunks,
+suitably marked so conversion with
+.I latex2html(1)
+yields reasonable output.
+A LaTeX wrapper is implied, but can be turned off with \fB-n\fP.
+.I Use of this option is
+.B deprecated;
+use
+.B \-html
+with
+.B "\-filter l2h"
+instead.
+<<noweave man page option table>>=
+.TP
+.B \-troff
+Emit
+.IR troff (1)
+markup (with no wrapper).
+The result should be processed with
+.IR noroff (1).
+Bug reports for
+.B \-troff
+to Arnold Robbins
+.B <arnold@skeeve.com>.
+<<bogus noweave man page option table>>=
+.TP
+.B \-ascii
+Emit ASCII (with no wrapper).
+Bug reports for
+.B \-ascii
+to Phil Bewig
+.B <pbewig@netcom.com>.
+<<noweave man page option table>>=
+.TP
+.B \-n
+Don't use any wrapper (header or trailer).
+This option is useful when \fInoweave\fP's output will be
+a part of a larger document.
+See also
+.B \-delay.
+@ \fi
+A common bug seems to be using both [[-x]] and [[-index]] on the same
+command line, so I complain about it.
+<<insist first-pass options are self-consistent>>=
+if(! ~ $using_xref '' && ! ~ $using_index '') {
+ echo $0': you may not use -x with -index or -indexfrom (drop the -x)' >
+1=2]
+ exit -x-index
+}
+<<initialization>>=
+using_index=''
+using_xref=''
+@
+<<first pass {\tt noweave} options>>=
+case -filter
+ shift
+case -x
+ using_xref=1
+case -index
+ noindex=''
+ using_index=1
+case -indexfrom
+ shift
+ noindex=''
+ using_index=1
+<<second pass {\tt noweave} options>>=
+case -filter
+ newfilter=$2
+ shift
+ <<add [[$newfilter]]>>
+case -x
+ newfilter='finduses noquote'
+ <<add [[$newfilter]]>>
+case -index
+ newfilter='finduses '^$noquote
+ <<add [[$newfilter]]>>
+ newfilter='noidx '^$docanchor^' '^$delay
+ <<add [[$newfilter]]>>
+case -indexfrom
+ newfilter='finduses '^$noquote^' '^$2
+ <<add [[$newfilter]]>>
+ newfilter='noidx '^$docanchor^' '^$delay
+ <<add [[$newfilter]]>>
+ shift
+<<option printout for usage>>=
+echo '-x Use the default cross-referencer (needs LaTeX or HTML).
+ >[1=2]
+echo '-index Create index using identifiers defined in input files.'
+ >[1=2]
+echo '-indexfrom defs Create index of identifers listed in file defs.' >[1=2
+
+echo '-filter cmd Filter through ''cmd'' before weaving; cmd could pretty
+rint' >[1=2]
+echo ' or perform other functions.' >[1=2]
+@ \iffalse
+<<noweave man page indexing options>>=
+.TP
+.B \-x
+For
+.I LaTeX,
+add a page number to each chunk name identifying the location of that
+chunk's definition, and emit cross-reference information relating definitions
+nd uses.
+For
+.I HTML,
+create hypertext links between uses and definitions of chunks.
+When
+.B noweave -x
+is used with
+.I LaTeX,
+the control sequence
+.B "\\\\nowebchunks"
+expands to a sorted list of all code chunks.
+.TP
+.B \-index
+Build cross-reference information (or hypertext links) for identifiers defined
+by
+.br
+.B "@ %def"
+.I identifiers
+.br
+Definitions are those found in input files.
+Requires
+.I LaTeX
+or
+.I HTML.
+.B \-index
+implies
+.B \-x;
+including both will generate strange-looking output.
+.I noweave
+does not generate
+cross-references to identifiers that appear in quoted code (\fB@[[\fP...\fB@]]
+fP),
+but it does generate hypertext links.
+When
+.B noweave -index
+is used with
+.I LaTeX,
+the control sequence
+.B "\\\\nowebindex"
+expands to an index of identifiers.
+.TP
+.B \-indexfrom \fIindex\fP
+Like
+.B \-index,
+but the identifiers to be indexed are taken from file \fIindex\fP.
+See
+.I noindex(1).
+<<noweave man page option table>>=
+.TP
+.B \-filter \fIcmd\fP
+Filters the
+.I noweb
+source through
+.I cmd
+after converting it to tool form and before converting to
+.I TeX.
+.I noweave
+looks for
+.I cmd
+first on the user's
+.B PATH,
+then in
+.B |LIBDIR|.
+Such filters
+can be used to add features to
+.I noweave;
+for an example, see
+.B |LIBDIR|/noxref.krom.
+.I Noweave
+supports up to four filters; one can get more by shell trickery,
+for example, \fB-filter "icon.filter | noidx"\fP.
+The \fB-autodefs\fP,
+\fB-x\fP, \fB-index\fP, and \fB-indexfrom\fP options are implemented as filter
+.
+Filters are executed with the shell's
+.B eval
+command, so
+.I cmd
+should be quoted accordingly.
+<<description of -markup option>>
+@ \fi
+Note that it would be appropriate to look for autodefs
+using [[[ -x $newfilter ]]],
+but that stupid DEC Ultrix doesn't support [[test -x]], so the best I can
+do in a portable way is [[test -r]].
+<<first pass {\tt noweave} options>>=
+case -autodefs
+ newfilter='autodefs.'^$2
+ if(test -r $newfilter) {
+ <<add [[$newfilter]]>>
+ }
+ if not {
+ echo $0^': don''t know how to find definitions for '^$2
+ exit defns
+ }
+ shift
+
+case -showautodefs
+ <<print all legal [[-autodefs]] or complain>>
+ exit complain
+<<option printout for usage>>=
+echo '-autodefs lang Source is in language ''lang''; find definitions automa
+ically.' >[1=2]
+echo '-showautodefs List languages that can be used with -autodefs' >[1=2]
+@ \iffalse
+<<noweave man page indexing options>>=
+.TP
+.B \-autodefs \fIlang\fP
+Discover identifier definitions automatically.
+Code in chunks must be in language \fIlang\fP.
+Permissible \fIlang\fPs vary but may include
+.B tex
+or
+.B icon.
+Useless without
+.B \-index,
+which it must precede.
+.TP
+.B \-showautodefs
+Show values of \fIlang\fP usable with \fB-autodefs\fP.
+@ \fi
+Same note as above regarding [[test -x]] vs [[test -r]].
+<<print all legal [[-autodefs]] or complain>>=
+foundautodefs=no
+for(i in $LIB/autodefs.*) {
+ if(test -r $i) {
+ echo 'Supports -autodefs '^$i | sed 's!$LIB/autodefs\.!!' >[1=2
+
+ foundautodefs=yes
+ }
+}
+if(~ $foundautodefs no)
+ echo 'Does not support -autodefs' >[1=2]
+@
+Here's an embarrassing hack --- if we spot \verb+-option shortxref+
+or \verb+-option longxref+ on the
+command line, we pass something suitable to the back end, in case we're doing
+HTML.
+<<first pass {\tt noweave} options>>=
+case -option
+ newopt=$2
+ shift
+ if(~ $newopt shortxref)
+ shortxref=-shortxref
+ if(~ $newopt longxref)
+ shortxref=-longxref
+ <<add [[$newopt]] to [[noweboptions]]>>
+<<option printout for usage>>=
+echo '-option opt Add \noweboptions{opt} to header (latex only)' >[1=2]
+@ \iffalse
+<<noweave man page option table>>=
+.TP
+.B \-option \fIopt\fP
+Adds \fB\enoweboptions{\fP\fIopt\fP\fB}\fP to the
+.I LaTeX
+header.
+See
+.I nowebstyle(1)
+for values of
+.I opt.
+Normally useful only with the
+.B \-latex
+option, but
+.B "\-option longxref"
+works black magic with
+.B \-html.
+@ \fi
+<<first pass {\tt noweave} options>>=
+# case -nodelay
+# delay=''
+case -delay
+ delay=-delay
+ wrapper=none
+<<option printout for usage>>=
+echo '-delay Delay markup until after first documentation chunk.' >[
+=2]
+@ \iffalse
+<<noweave man page option table>>=
+.TP
+.B \-delay
+By default,
+.I noweave
+puts file-name and other information into the output before the first chunk
+of the program.
+.B \-delay
+delays that information until after the first documentation chunk, making
+act a little bit like the
+.I WEB
+``limbo.''
+The option is typically used to enable a user to put a specialized
+.I LaTeX
+.B "\\\\documentclass"
+command and other preamble material in the first documentation chunk.
+This option also forces trailing cross-referencing information to be emitted
+just before the final chunk, instead of at the end of the document;
+the final chunk is expected to contain
+.B "\\\\end{document}."
+The
+.B \-delay
+option implies the
+.B \-n
+option.
+@ \fi
+% .TP
+% .B \-nodelay
+% Don't delay, put file-name and other information right after header. (Defaul
+)
+% @ \fi
+<<first pass {\tt noweave} options>>=
+case -t*
+ markopts=$markopts' '$1
+<<option printout for usage>>=
+echo '-tk Expand tab stops every k columns' >[1=2]
+echo '-t Copy tabs to the output' >[1=2]
+@ \iffalse
+<<noweave man page option table>>=
+.TP
+.B \-t\fIk\fP
+Expand tabs with stops every \fIk\fP columns.
+(Default is to expand every 8 columns.)
+.TP
+.B \-t
+Copy tabs to the output.
+@ \fi
+<<first pass {\tt noweave} options>>=
+case -v
+ echo 'RCS id $Id: noweave.nw,v 1.6 1998/08/17 00:10:34 nr Exp nr $' >[1
+2]
+ verbose=1
+<<option printout for usage>>=
+echo '-v Print pipeline and RCS info on standard error' >[1=2]
+@ \iffalse
+<<noweave man page option table>>=
+.TP
+.B \-v
+Print the pipeline and RCS info on standard error.
+@ \fi
+\iffalse
+<<man page: WEAVING section>>=
+Output from \fInoweave\fP can
+be used in \fITeX\fP documents that
+.B "\\\\input nwmac,"
+in \fILaTeX\fP documents that use the
+.B noweb
+package (see \fInowebstyle(1)\fP),
+and in \fIHTML\fP documents to be browsed with
+.I Mosaic(1).
+.I Noweave
+treats code chunks somewhat like
+.I LaTeX list environments.
+If the ``\fB@ \fP'' that terminates a code chunk is followed immediately by te
+t,
+that text follows the code chunk without a paragraph break.
+If the rest of the line is blank,
+.I noweave
+puts
+.I TeX
+into ``vertical mode,'' and later text starts a fresh, indented paragraph.
+.PP
+No page breaks occur in the middle of code chunks unless necessary to avoid
+an overfull vbox.
+The documentation chunk immediately preceding a code chunk appears on
+the same page as that code chunk unless doing so would violate the previous ru
+e.
+.PP
+.I Noweave
+inserts no extra newlines in its \fITeX\fP output, so the line numbers given
+in
+.I TeX
+error messages are the same as those in the input file.
+.PP
+.I noweave
+has
+options that dictate choice of
+formatter
+and that support different formatting idioms and tools.
+Basic options are described here; options related to index
+and cross-reference information are described in the
+INDEXING AND CROSS-REFERENCE section.
+<<noweave man page option table>>
+@
+<<man page: INDEXING AND CROSS-REFERENCE section>>=
+
+@ \fi
+<<add [[$newfilter]]>>=
+filterlist=($filterlist $newfilter)
+<<show usage>>=
+echo 'Usage: '$0' [options] [files]' >[1=2]
+echo 'Options recognized are:' >[1=2]
+<<option printout for usage>>
+@
+To avoid inserting any extra newlines into the output,
+I use [[@literal]]to insert headers and trailers.
+<<emit markup on standard output>>=
+header=''
+# whatis wrapper
+# whatis arg
+switch($wrapper) {
+case none
+ ;
+case latex
+ header='@header '^$wrapper^' '^$noweboptions
+ trailer='@trailer '^$wrapper
+case *
+ header='@header '^$wrapper^$arg
+}
+if(! ~ $header '')
+ echo $header
+<<if verbose, make noise about pipeline>>
+<<if verbose, show back end>>
+if(~ $#filterlist 0)
+ filterlist=cat
+pipeline='| '^$filterlist
+pipeline=cat^$"pipeline
+
+# whatis pipeline
+argx=(`{echo $markopts $arg})
+# whatis argx
+$markup $argx | eval $pipeline
+if(! ~ $trailer '')
+ echo $trailer
+<<if verbose, make noise about pipeline>>=
diff --git a/web/noweb/contrib/rsc/rc/noweave.simple b/web/noweb/contrib/rsc/rc/noweave.simple
new file mode 100644
index 0000000000..2f2bb84a3e
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/noweave.simple
@@ -0,0 +1,56 @@
+#!/bin/rc
+
+rfork en
+
+LIB=/sys/lib/noweb
+
+bind -b /sys/lib/noweb/bin/$objtype /bin
+bind -b /sys/lib/noweb/bin/rc /bin
+
+files=()
+for(i) {
+ switch($i) {
+ case -*
+ ;
+ case *
+ files=($files $i)
+ }
+}
+
+markup $files | awk '
+BEGIN { code=0
+ print "\\documentstyle{article}"
+ print "\\newcommand{\\fragment}[1]{{\\sl$\\langle$#1\\/$\\ran
+le$}}"
+ print "\\begin{document}"
+ }
+END { if (code) print "\\end{trivlist}"
+ print "\\end{document}"
+ }
+/^@quote$/ { printf "\\verb@"}
+/^@endquote$/ { printf "@" }
+/^@begin code/ { if (!code) print "\\begin{trivlist}\\raggedright\\obeylines\\
+eftskip=2em\\small\\item[]%"; code=1 }
+/^@end code/ { }
+/^@begin docs/ { if (code) print "\\end{trivlist}"; code=0 }
+/^@end docs/ { }
+/^@defn / { gsub(/\[\[/, "\\verb@"); gsub(/]]/, "@")
+ name = substr($0,7)
+ printf "\\hspace{-2em}"
+ printf "\\fragment{%s}", name
+ defs[name] += 1
+ if (defs[name] > 1)
+ printf "$+\\!\\!\\equiv$"
+ else
+ printf "$\\equiv$"
+ printf "\\index{\\fragment{%s}}", name
+ }
+/^@use / { gsub(/\[\[/, "\\verb@"); gsub(/]]/, "@")
+ name = substr($0,6)
+ printf "\\fragment{%s}", name
+ printf "\\index{\\fragment{%s}}", name
+ }
+/^@literal / { printf "%s", substr($0, 10) }
+/^@nl$/ { print ""}
+/^@text / { if (code) printf "\\verb@%s@", substr($0,7)
+ else printf "%s", substr($0,7) }'
diff --git a/web/noweb/contrib/rsc/rc/noweb.nw b/web/noweb/contrib/rsc/rc/noweb.nw
new file mode 100644
index 0000000000..e790c47e42
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/noweb.nw
@@ -0,0 +1,63 @@
+<<noweb>>=
+#!/bin/rc
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file /sys/src/cmd/noweb/COPYRIGHT for more information.
+#
+# Translated to rc by Russ Cox
+# bugs -> rsc@plan9.bell-labs.com
+
+rfork en
+bind -b /sys/lib/noweb/bin/$objtype /bin
+bind -b /sys/lib/noweb/bin/rc /bin
+
+markup=markup
+mntopt=-L
+status=0
+tex=1
+output=1
+
+break=no
+while(! ~ $#* 0 && ~ $break no) {
+ switch($1) {
+ case -to -ot
+ tex=''
+ output=''
+ shift
+ case -t
+ tex=''
+ shift
+ case -o
+ output=''
+ shift
+ case -L*
+ mntopt=$1
+ shift
+ case -markup
+ markup=$2
+ shift
+ shift
+ case -*
+ echo unrecognized option $1 >[1=2]
+ exit usage
+ case *
+ break=yes
+ }
+}
+
+for(source) {
+ if(test -n $output) {
+ eval $markup' -t '$source' | mnt -t8 '$mntopt' -all' || status=
+
+ }
+ if(test -n $tex) {
+ texname=`{echo $source | sed '/\./s/\.[^.]*$//'}
+ texname=$texname.tex
+ eval $markup' '$source | finduses -noquote | noidx -delay |
+ awk '{print}
+ /^@defn [^ ]*$/ { print "@literal \\let\\nwnotused=\\nw
+utput{}" }' |
+ totex -delay | cpif $texname || status=1
+ }
+}
+
+exit $status
diff --git a/web/noweb/contrib/rsc/rc/toascii.nw b/web/noweb/contrib/rsc/rc/toascii.nw
new file mode 100644
index 0000000000..3805fa4bf2
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/toascii.nw
@@ -0,0 +1,279 @@
+[[Toascii]] is a [[noweb]] back end for formatting text as a plain ascii file.
+It was written by Phil Bewig (pbewig@netcom.com) on March 31, 1995, and
+contributed to Norman Ramsey's [[noweb]] literate programming system.
+@
+The main program is shown below. Option [[-delay]] is processed, for
+compatibility with other back ends, but ignored; since the initial document
+chunk used with [[-delay]] normally contains only [[TeX]] formatting commands
+in limbo, and since those commands will be deleted before formatting, there is
+no need to handle [[-delay]].
+<<toascii>>=
+#!/bin/rc
+#
+# Based on shell script by Phil Bewig
+# Translated to rc by Russ Cox
+# bugs -> rsc@plan9.bell-lab.scom
+#
+delay=0
+noindex=0
+for(i) {
+ switch($i){
+ case -delay
+ delay=1
+ case -noindex
+ noindex=1
+ case *
+ echo 'cannot happen' >[1=2]
+ exit coredump
+ }
+}
+<<arrange temporary files>>
+<<invoke first pass using parameter>>
+<<invoke second pass using file>>
+exit $status
+@ %def delay noindex
+[[Toascii]] uses two temporary files, one for storing the text between passes
+and one for communicating the conversion of labels to tags. The files are
+named here, and disposal of the file on exit from [[toascii]] is arranged.
+Also arranged here is a temporary file for storage of the awk program on an
+ugly system, as discussed below.
+<<arrange temporary files>>=
+awkfile=$(mktemp) || { echo "$0: Cannot create temporary file" >&2; exit 1; }
+textfile=$(mktemp ) || { echo "$0: Cannot create temporary file" >&2; exit 1; }
+tagsfile=$(mktemp ) || { echo "$0: Cannot create temporary file" >&2; exit 1; }
+@ %def textfile tagsfile awkfile
+The actual formatting of the text, code, and index entries is done by various
+unix text processing commands in pipelines. There are four formatting pipes:
+tfmt, which formats text, cfmt, which formats code, xfmt, which formats index
+entries within the running text, and zfmt, which formats the lists of chunks
+and identifiers at the end of the text. The formatters established below are
+only suggestions, and may be modified to suit local taste (and the presence of
+various text processing commands on the local machine!); in particular, [[c]]
+programmers may want to format code with cb or indent. The sed patterns below
+insert four blank spaces at the beginning of the line.
+<<initialize formatters>>=
+tfmt"detex | fmt -l 79"
+cfmt="cat"
+xfmt="cat"
+zfmt="cat"
+@ %def tfmt cfmt xfmt zfmt
+Forgiving systems allow the awk program to be specified as a parameter to the
+awk interpreter; ugly systems require that it be placed in a temporary file.
+The chunks below implement both options.
+<<invoke first pass using parameter>>=
+awk '<<first pass>>'
+<<invoke second pass using parameter>>=
+awk '<<second pass>>' -v 'noindex='$noindex $textfile
+<<toascii1.awk>>=
+<<first pass>>
+<<invoke first pass using file>>=
+awk -f toascii1.awk
+<<toascii2.awk>>=
+<<second pass>>
+<<invoke second pass using file>>=
+awk -f /sys/lib/noweb/toascii2.awk -v 'noindex='$noindex $textfile
+@
+The first pass is responsible for extracting [[label]]s and assigning them
+section numbers, which are used for cross-referencing in the second pass. The
+first pass also removes from the input file those lines which are not used by
+the second pass.
+The environment is gotten from the associative array [[ENVIRON]].
+<<initialize environment>>=
+textfile=ENVIRON["textfile"]
+tagsfile=ENVIRON["tagsfile"]
+<<first pass>>=
+BEGIN { <<initialize environment>> }
+/^@begin code/ { ++secno }
+/^@xref label/ { print $3, secno >tagsfile }
+/^@((begin|end) (docs|code))/ { print >textfile }
+/^@(text|nl|defn|use)/ { print >textfile }
+/^@xref (ref|notused)/ { print >textfile }
+/^@xref (begin|end)(defs|uses)/ { print >textfile }
+/^@xref (def|use)item/ { print >textfile}
+/^@xref ((begin|end)chunks)|(chunk(begin|use|defn|end))/ { print >textfile }
+/^@index (begin|end)(defs|uses)/ { print >textfile }
+/^@index (is(us|defin)ed)|((def|use)item)/ { print >textfile }
+/^@index ((begin|end)index)|(entry(begin|use|defn|end))/ { print >textfile }
+@
+The second pass performs formatting. After looking up the temp file names and
+formatters in the environment and reading the [[tagsfile]] created in the firs
+
+pass, the second pass processes each input command in the body of the awk
+[[pattern-action]] processing loop.
+<<second pass>>=
+BEGIN {
+ <<initialize environment>>
+ <<initialize formatters>>
+ while (getline <tagsfile > 0)
+ tag[$1] = $2
+ close(tagsfile)
+}
+<<process [[noweb]] commands>>
+/^@fatal / { exit 1 }
+END {
+ close(out)
+}
+<<functions>>
+@ %def tag
+The rest of the program consists of a series of awk [[pattern-action]]
+statements which each process a particular type of [[noweb]] pipeline command.
+They are discussed in related groups, and all collected in a single chunk. We
+begin with the commands that process the text of the document and code chunks.
+The basic strategy is always write text to [[out]] and open and close various
+pipes as needed. Variable [[code]] is true only within code chunks, and
+[[secno]] numbers the sections as they appear. Function [[endcode()]] closes
+the code pipeline at the end of a code section or whenever the first indexing
+command appears.
+<<process [[noweb]] commands>>=
+/^@begin docs/ { out = tfmt }
+/^@end docs/ { close(out) }
+/^@begin code/ { out = cfmt; code = 1; ++secno }
+/^@end code/ { endcode(); close(out); printf "\n" }
+/^@text/ { printf "%s", substr($0, 7) | out }
+/^@nl/ { # printf "(->%s)", formatname(out) | out ;
+ printf "\n" | out }
+@ %def out secno code
+<<functions>>=
+function endcode() {
+ if (code == 1) {
+ code = 0
+ close(out)
+ out = xfmt
+ printf "\n" | out } }
+@ %def endcode
+Definitions and uses of code chunks are handled below. Variable [[defn[name]]
+
+is set to a plus sign after a definition is printed, so that continuations of
+the definition are properly identified. Variable [[lastxrefref]] is the tag
+associated with the most-recently-seen cross-reference label, and refers to th
+
+section number of the original definition of the code chunk. Definition lines
+are printed directly, without passing through any of the formatters defined
+above.
+<<process [[noweb]] commands>>=
+/^@xref ref/ { lastxrefref = tag[substr($0, 11)] }
+/^@defn/ { name = convquote(substr($0, 7))
+ printf "\n### %d ### %s%s=",
+ secno, chunkname(name, lastxrefref), defn[name]
+ defn[name] = "+" }
+/^@use/ { name = convquote(substr($0, 6))
+ printf "%s", chunkname(name, lastxrefref) | out }
+@ %def lastxref name defn
+There are three messages related to the definition and use of code chunks whic
+
+may appear in the output: "This definition continued in ...", "This code used
+in ...", and "This code not used in this document." These messages are printe
+
+by the following code.
+<<process [[noweb]] commands>>=
+/^@xref begindefs/ { endcode()
+ printf "This definition continued in" | out }
+/^@xref beginuses/ { endcode()
+ printf "This code used in" | out }
+/^@xref notused/ { endcode()
+ print "This code not used in this document." | out }
+/^@xref (def|use)item/ { addlist(tag[$3]) }
+/^@xref end(defs|uses)/ { printlist() }
+@
+Processing of the [[noweb]] commands which produce the identifier definition
+message "Defines: ... used in ..." is performed by the following code. The
+[[if]] in [[@index isused]] prevents index definitions from pointing to
+themselves.
+<<process [[noweb]] commands>>=
+$0 ~ /^@index begindefs/ && !noindex {
+ endcode()
+ print "Defines:" | out }
+
+$0 ~ /^@index isused/ && !noindex {
+ if (tag[$3] != lastxrefref) addlist(tag[$3]) }
+
+$0 ~ /^@index defitem/ && !noindex {
+ printf " %s,", $3 | out
+ if (nlist == 0) printf " not used in this document.\n" | out
+ else { printf " used in" | out; printlist() } }
+@
+Processing of the [[noweb]] commands which produce the identifier usage messag
+
+"Uses ..." is performed by the following code.
+<<process [[noweb]] commands>>=
+$0 ~ /^@index beginuses/ && !noindex { endcode(); printf "Uses" | out }
+$0 ~ /^@index isdefined/ && !noindex { lastuse = tag[$3] }
+$0 ~ /^@index useitem/ && !noindex { addlist(sprintf("%s %s", $3, lastuse))
+
+$0 ~ /^@index enduses/ && !noindex { printlist() }
+@ %def lastuse
+The [[noweb]] commands which print the list of chunks at the end of the
+document are processed by the following code.
+<<process [[noweb]] commands>>=
+/^@xref beginchunks/ { close(out); out = zfmt
+ print "List of code chunks\n" | out }
+/^@xref chunkbegin/ { name = convquote(substr($0, length($3) + 19))
+ printf "%s\n", chunkname(name, tag[$3]) | out }
+/^@xref chunkuse/ { addlist(tag[$3]) }
+/^@xref chunkdefn/ { }
+/^@xref chunkend/ { if (nlist == 0)
+ print " Not used in this document." | out
+ else { printf " Used in" | out; printlist() } }
+/^@xref endchunks/ { }
+@
+The [[noweb]] commands which print the list of identifiers at the end of the
+document are processed by the following code.
+<<process [[noweb]] commands>>=
+$0 ~ /^@index beginindex/ && !noindex { print "\nList of identifiers (defini"
+
+ "tion in parentheses)\n" | out }
+$0 ~ /^@index entrybegin/ && !noindex { name = substr($0, length($3 + 19))
+ lastdefn = tag[$3]
+ printf "%s: ", $4 | out }
+$0 ~ /^@index entryuse/ && !noindex { addlist(tag[$3]) }
+$0 ~ /^@index entrydefn/ && !noindex { }
+$0 ~ /^@index entryend/ && !noindex { for (i = 1; i <= nlist; i++)
+ if (list[i] == lastdefn)
+ sub(/.*/, "(&)", list[i])
+ if (nlist == 0)
+ print "Not used." | out
+ else printlist() }
+$0 ~ /^@index endindex/ && !noindex { }
+@
+Several of the cross-reference and indexing commands use the [[addlist(s)]] an
+
+[[printlist()]] functions to manage the printing of lists of code sections and
+variable names: [[addlist(s)]] adds string [[s]] to a queued [[list]] waiting
+to be printed and [[printlist()]] prints the [[list]], appropriately formatted
+with commas. These two functions are described below.
+<<functions>>=
+function addlist(s, i) {
+ for (i = 1; i <= nlist; i++)
+ if (s == list[i]) return
+ list[++nlist] = s }
+
+function printlist( i) {
+ if (nlist == 1) printf " %s.\n", list[1] | out
+ else if (nlist == 2) printf " %s and %s.\n", list[1], list[2] | out
+ else {
+ for (i = 1; i < nlist; i++)
+ printf " %s,", list[i] | out
+ printf " and %s.\n", list[nlist] | out }
+ for (i in list) delete list[i]
+ nlist = 0 }
+@ %def list nlist addlist printlist
+Chunk names which appear in definitions and uses of chunks consist of text
+which may contain quoted code embedded between double square brackets. Quoted
+code in text chunks are handled by the [[@quote ... @endquote]] mechanism, but
+quoted code in chunk names must be handled explicitly by the back end. The
+function below does what is needed.
+<<functions>>=
+function convquote(s) { gsub(/\[\[|\]\]/, "", s); return s }
+@ %def convquote
+
+<<functions>>=
+function chunkname(name, number) {
+ if (number == 0)
+ return sprintf("<%s>", name)
+ else
+ return sprintf("<%s %d>", name, number)
+}
+@ %def chunkname
+@
+<nowebchunks>
+<nowebindex>
diff --git a/web/noweb/contrib/rsc/rc/tohtml.nw b/web/noweb/contrib/rsc/rc/tohtml.nw
new file mode 100644
index 0000000000..46b1bc3e3b
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/tohtml.nw
@@ -0,0 +1,362 @@
+\documentstyle[noweb]{article}
+\pagestyle{noweb}
+\begin{document}
+\section{Converting {\tt noweb} markup to {\tt HTML}}
+This copyright applies both to the {\tt noweb} source and to the
+generated shell script.
+Thanks to Bill Trost for getting me started with an early version.
+<<copyright notice>>=
+# Copyright 1994 by Norman Ramsey. All rights reserved.
+# See file /sys/src/cmd/noweb/COPYRIGHT for more information.
+#
+# Translated to rc by Russ Cox
+# bugs -> rsc@plan9.bell-labs.com
+
+<<tohtml>>=
+#!/bin/rc
+<<copyright notice>>
+# Do not try to understand this file! Look at lib/tohtml.nw in the noweb sour
+e!
+
+delay=0
+raw=0
+localindex=0
+noindex=0
+for(i) {
+ switch($i) {
+ case -delay
+ delay=1
+ case -raw
+ raw=1
+ case -localindex
+ if(~ $noindex 0)
+ localindex=1
+ case -noindex
+ localindex=0
+ noindex=1
+ }
+}
+
+awk -f /sys/lib/noweb/tohtml.awk \
+ -v 'delay='$delay -v 'raw='$raw -v 'localindex='$localindex -v 'noindex
+'$noindex
+<<tohtml.awk>>=
+<<awk program for conversion to {\tt HTML}>>
+@
+The [[-raw]] option brackets HTML with [[\begin{rawhtml}]] and
+[[\end{rawhtml}]]; the purpose is to embed HTML in a {\LaTeX}
+document before converting the document with {\tt latex2html}.
+[[braw]] and [[eraw]] hold those delimiters (or else empty strings).
+<<awk program for conversion to {\tt HTML}>>=
+<<functions>>
+BEGIN { <<initialization>> }
+!doneraw { # do not do in BEGIN because not all awks assign variables yet
+ if (raw) { braw = "\\begin{rawhtml}"; eraw = "\\end{rawhtml}" }
+ else braw = eraw = ""
+ doneraw = 1
+}
+<<patterns>>
+END { print "" }
+@
+[[ecode]] is the marker used at the end of the current code chunk.
+If there is no cross-reference stuff at the end, we just use [[</pre>]];
+otherwise we terminate whatever environment is used for the cross-reference st
+ff.
+<<patterns>>=
+/^@begin code / { code = 1; printf "%s<pre>", braw; ecode = "</pre>" }
+/^@end code / { code = 0; previscode = 1; <<dump pending cross-reference inf
+>>
+ printf "%s%s", ecode, eraw
+ }
+@
+We want to try to avoid emitting paragraph elements when the
+preceding chunk is a code chunk, as tracked by [[previscode]].
+Also, if we do slip in a paragraph, we may use the {\LaTeX} style.
+<<patterns>>=
+/^@begin docs / { if (previscode) printf "%s", (raw ? "\\par" : "<p>")
+ previscode = text = 0
+ }
+@
+Sometimes it happens that a document-chunk anchor is put in a document chunk t
+at
+contains no text. In that case, we put in a phony anchor at the end of the ch
+nk so
+we won't lose the cross-reference.
+<<patterns>>=
+/^@end docs / { if (lastxreflabel != "")
+ printf "%s%s%s\n", braw, linklabel(lastxreflabel, "*"), er
+w
+ lastxreflabel = ""
+ }
+@
+Normally, if there's a pending anchor, we put it on the first available text l
+ne.
+<<patterns>>=
+/^@text / { line = substr($0, 7); text += length(line)
+ if (code) {
+ if (lastindexref != "" && line ~ /[^ \t]/) {
+ printf "%s", linkto(lastindexref, line)
+ lastindexref = ""
+ } else {
+ printf "%s", escapeSpecials(line)
+ }
+ } else if (quoting) {
+ if (line ~ /[^ \t]/) {
+ printf "%s", linklabelto(lastxreflabel, lastindexref,
+ escapeSpecials(line))
+ lastindexref = lastxreflabel = ""
+ } else {
+ printf "%s", escapeSpecials(line)
+ }
+ } else {
+ if (lastxreflabel != "" && line ~ /[^ \t]/) {
+ <<print docs anchor>>
+ lastxreflabel = ""
+ } else {
+ printf "%s", line
+ }
+ }
+ }
+@
+We anchor on the first nonblank character of the line, unless that's
+a \TeX\ control sequence or an SGML tag.
+In that case we insert a {\tt*} to anchor to.
+None of this crap would be necessary if HTML could anchor to empty text.
+<<print docs anchor>>=
+match(line, /^[ \t]*/)
+blanks = substr(line, RSTART, RLENGTH)
+line = substr(line, RSTART+RLENGTH)
+if (line ~ /^[{}\\<&]/) {
+ char = "*"
+} else {
+ char = substr(line, 1, 1)
+ line = substr(line, 2)
+}
+printf "%s%s%s%s%s", braw, blanks, linklabel(lastxreflabel, char), eraw, line
+if (lastxreflabel != "") defns_above[lastxreflabel] = 1
+<<patterns>>=
+/^@nl$/ { print "" }
+/^@defn / { thischunk = name = substr($0, 7)
+ if (lastxreflabel != "") defns_above[lastxreflabel] = 1
+ writechunk(lastxreflabel, lastxrefref, "dfn", name, defns[name] "=
+)
+ <<clear [[lastxref*]]>>
+ defns[name] = "+"
+ }
+<<initialization>>=
+defns[0] = 0
+defns_above[0] = 0
+<<patterns>>=
+/^@use / { writechunk(lastxreflabel, lastxrefref, "i", substr($0, 6), "") }
+@
+Writing a chunk involves creating an anchor for it.
+<<functions>>=
+function writechunk(label, ref, tag, name, suffix) {
+ printf "%s",
+ linklabelto(label, ref, sgmlwrap(tag, "&lt;" convquotes(name) "&gt;" suffi
+))
+}
+@
+<<patterns>>=
+/^@quote$/ { quoting = 1 ; printf "%s<code>", braw }
+/^@endquote$/ { quoting = 0 ; printf "</code>%s", eraw }
+/^@file / { filename = substr($0, 7); <<clear [[lastxref*]]>> }
+/^@literal / { printf "%s", substr($0, 10) }
+/^@header html / { <<write HTML header>> }
+/^@trailer html$/ { <<write HTML trailer>> }
+@
+<<write HTML header>>=
+printf "<html><head><title>%s</title></head><body>", substr($0, 14)
+
+<<write HTML trailer>>=
+print "</body></html>"
+@
+<<patterns>>=
+/^@xref label / { lastxreflabel = substr($0, 13) }
+/^@xref ref / { lastxrefref = substr($0, 11) }
+/^@xref prevdef/ { pendingprev = substr($0, 15) }
+/^@xref nextdef/ { pendingnext = substr($0, 15) }
+/^@xref beginuses/ { useitems = "" }
+/^@xref useitem / { useitems = useitems " " substr($0, 15) }
+/^@xref enduses/ { useitemstab[thischunk] = useitems }
+/^@xref notused / { <<code-to-blockquote>>
+ printf "This code is written to a file (or else not used
+.<p>"
+ }
+<<initialization>>=
+useitemstab[0] = 0
+<<clear [[lastxref*]]>>=
+lastxreflabel = lastxrefref = ""
+<<dump pending cross-reference info>>=
+useitemscount = split(useitemstab[thischunk], a)
+if (pendingprev != "" || pendingnext != "" || useitemscount > 0) {
+ <<code-to-blockquote>>
+ <<write out uses with links>>
+ if (useitemscount > 0 && (pendingprev != "" || pendingnext != ""))
+ printf "; "
+ p = useitemscount > 0 ? "previous" : "Previous"
+ n = useitemscount > 0 ? "next" : "Next"
+ if (pendingprev != "")
+ if (pendingnext != "")
+ printf "%s and %s definitions", linkto(pendingprev, p), linkto(pendingne
+t, "next")
+ else
+ printf "%s definition", linkto(pendingprev, p)
+ else
+ if (pendingnext != "")
+ printf "%s definition", linkto(pendingnext, n)
+ pendingprev = pendingnext = ""
+ useitems = ""
+ print ".<p>"
+}
+<<write out uses with links>>=
+useprefix = "Used "
+for (j = 1; j <= useitemscount; j++) {
+ if (defns_above[a[j]] > 0)
+ usedir = "above"
+ else
+ usedir = "below"
+ printf "%s%s", useprefix, linkto(a[j], usedir (useitemscount > 1 ? " (" j ")
+ : ""))
+ useprefix = ", "
+}
+@
+The hack here is to put the supplementary information in a blockquote area
+after the code.
+<<code-to-blockquote>>=
+if (ecode == "</pre>") {
+ printf "</pre><blockquote>"
+ ecode = "</blockquote>"
+}
+@
+The HTML back end ignores [[@xref begindefs]], [[@xref defitem]], and
+[[@xref enddefs]]; it uses the [[nextdef]] and [[prevdef]] links instead.
+<<patterns>>=
+/^@xref (begindefs|defitem|enddefs)/ { }
+/^@xref beginchunks$/ { printf "%s<ul>\n", braw }
+/^@xref chunkbegin / { label = $3; name = substr($0, 19 + length(label))
+ printf "<li>"; comma = ": "; count = 0
+ writechunk("", label, "i", name, "")
+ }
+/^@xref chunkuse / { printf "%s%s", comma, linkto(substr($0, 16), "U" ++cou
+t)
+ comma = ", "
+ }
+/^@xref chunkdefn / { printf "%s%s", comma, linkto(substr($0, 17), "D" ++cou
+t)
+ comma = ", "
+ }
+/^@xref chunkend$/ { print "" }
+/^@xref endchunks$/ { printf "</ul>%s\n", eraw }
+<<patterns>>=
+/^@index beginindex$/ { if (!noindex) { printf "%s<ul>\n", braw } }
+/^@index entrybegin / { if (!noindex) {
+ label = $3; name = substr($0, 20 + length(label))
+ printf "<li>"; comma = ": "; count = 0
+ printf "%s",
+ linklabelto("NWI-" escapeSpecials(name), label, na
+e)
+
+ } }
+/^@index entryuse / { if (!noindex) {
+ printf "%s%s", comma, linkto(substr($0, 17), "U" ++co
+nt)
+ comma = ", "
+ } }
+/^@index entrydefn / { if (!noindex) {
+ printf "%s%s", comma, linkto(substr($0, 18), "D" ++
+ount)
+ comma = ", "
+ } }
+/^@index entryend$/ { if (!noindex) { print "" } }
+/^@index endindex$/ { if (!noindex) { printf "</ul>%s\n", eraw } }
+@
+The local identifier cross-reference doesn't show each use; it just shows
+the identifiers that are defined, with links to the full index.
+<<patterns>>=
+/^@index use/ { lastindexref = lastxrefref; lastxrefref = "" }
+/^@index defn/ { <<clear [[lastxref*]]>> }
+/^@index localdefn/ { <<clear [[lastxref*]]>> }
+/^@index nl/ { } # do nothing -- destroys line numbering
+/^@index begindefs/ { if (localindex) {
+ <<code-to-blockquote>>; printf "Defines"; comma = " "
+} }
+/^@index isused / { }
+/^@index defitem / { if (localindex) {
+ arg = substr($0, 16)
+ printf "%s%s", comma,
+ linkto("NWI-" escapeSpecials(arg), sgmlwrap("code", escapeSpecials(arg)
+)
+ comma = ", "
+} }
+/^@index enddefs/ { if (localindex) { printf " (links are to index).<p>\n" }
+}
+/^@index (beginuses|isdefined|useitem|enduses)/ { } # use local links
+@
+\subsection{Support functions}
+Here's all our anchor support goo.
+<<functions>>=
+function linklabelto(label, ref, contents, s) {
+ s = label != "" || ref != "" ? "<a" : ""
+ if (label != "") s = s " name=" image(label)
+ if (ref != "") s = s " href=" image("#" ref)
+ s = s (label != "" || ref != "" ? ">" : "")
+ s = s contents
+ s = s (label != "" || ref != "" ? "</a>" : "")
+ return s
+}
+
+function linkto(ref, contents) {
+ return linklabelto("", ref, contents)
+}
+
+function linklabel(label, contents) {
+ return linklabelto(label, "", contents)
+}
+@
+Another support function is used for wrapping tags around text:
+<<functions>>=
+function sgmlwrap(tag, s) {
+ return "<" tag ">" s "</" tag ">"
+}
+<<functions>>=
+function image(s) {
+ gsub(/"/, "\\\"", s)
+ return "\"" s "\""
+}
+@
+Lucky for us, {\tt HTML} has few special characters. Unlucky for us,
+we have to deal with each one seperately. Nothing much to whine
+about, really.
+<<functions>>=
+function escapeSpecials (l) {
+ gsub(/&/, "\\&amp;", l)
+ gsub(/</, "\\&lt;", l)
+ gsub(/>/, "\\&gt;", l)
+ gsub(/"/, "\\&quot;", l)
+ return l
+}
+@
+A special function is used to implement {\tt noweb}'s quoting
+convention within chunk names.
+<<functions>>=
+function convquotes(s, r, i, line) {
+ r = ""
+ while (i = index(s, "[[")) {
+ r = r substr(s, 1, i-1) "<code>"
+ s = substr(s, i+2)
+ if (i = match(s, "\\]\\]+")) {
+ line = substr(s, 1, i-1+RLENGTH-2)
+ # line = escapeSpecials(line) # destroys internal markup --- do not cal
+
+ r = r line "</code>"
+ s = substr(s, i+RLENGTH)
+ } else {
+ r = r s "</code>"
+ s = ""
+ }
+ }
+ return r s
+}
+@
+\end{document}
diff --git a/web/noweb/contrib/rsc/rc/totex.nw b/web/noweb/contrib/rsc/rc/totex.nw
new file mode 100644
index 0000000000..160a364341
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/totex.nw
@@ -0,0 +1,312 @@
+\section{Converting {\tt noweb} markup to {\TeX} markup}
+The copyright applies both to the {\tt noweb} source and to the
+generated shell script.
+<<copyright notice>>=
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file /sys/src/cmd/noweb/COPYRIGHT for more information.
+#
+# Translated to rc by Russ Cox
+# bugs -> rsc@plan9.bell-labs.com
+
+<<totex>>=
+#!/bin/rc
+<<copyright notice>>
+# Don't try to understand this file! Look at lib/totex.nw in the noweb source
+
+delay=0
+noindex=0
+for(i) {
+ switch($i) {
+ case -delay
+ delay=1
+ case -noindex
+ noindex=1
+ case *
+ echo 'This can''t happen -- '$i' passed to totex' >[1=2]
+ exit cannothappen
+ }
+}
+<<invoke awk program using file>>
+@
+On a forgiving system, we make the awk program an argument:
+<<invoke awk program using parameter>>=
+awk '<<awk program for conversion to {\TeX}>>' -v 'delay='$delay -v 'noindex='
+noindex
+@
+On an ugly system, we have to put it in a file.
+<<invoke awk program using file>>=
+awk -f /sys/lib/noweb/totex.awk -v 'delay='$delay -v 'noindex='$noindex
+<<totex.awk>>=
+<<awk program for conversion to {\TeX}>>
+@
+The markup carefully adds no newlines not already present in the input,
+so that the line numbers of the {\TeX} file will be the same as the
+numbers of the corresponding {\tt noweb} file.
+The variables are:
+\begin{description}
+\item[\tt code] Nonzero if converting a code chunk.
+\item[\tt quoting] Nonzero if quoting code in documentation.
+\item[\tt text] Number of characters written since start of
+ documentation chunk.
+\end{description}
+[[text]] is used to write [[\par]] if a newline appears at the
+beginning of a documentation chunk without any intervening text.
+This subtle trick preserves new-paragraph semantics without requiring
+the insertion of a blank line that would throw off the line count.
+<<awk program for conversion to {\TeX}>>=
+BEGIN { code=0 ; quoting=0 ; text=1; <<initialization>> }
+/^@begin code/ { code=1 ; printf "\\nwbegincode{%s}", substr($0, 13) }
+/^@end code/ { code=0 ; printf "\\nwendcode{}"; lastdefnlabel = "" }
+<<special patterns for document chunk 0>>
+/^@begin docs/ { text=0 ; printf "\\nwbegindocs{%s}", substr($0, 13
+ }
+/^@end docs/ { printf "\\nwenddocs{}" }
+/^@text / { line = substr($0, 7) ; text += length - 6
+ if (code) printf "%s", escape_brace_bslash(line)
+ else if (quoting) printf "%s", TeXliteral(line)
+ else printf "%s", line
+ }
+/^@nl$/ { if (!code) {<<print [[\nwdocspar]] if no text>>}
+ if (quoting) printf "\\nwnewline"
+ printf "\n"
+ }
+/^@defn / { name = substr($0, 7); <<defn of [[name]], with cross-refe
+ence>> }
+/^@use / { printf "\\LA{}%s%s\\RA{}",
+ convquotes(substr($0, 6)), <<optional ref tag>>
+ }
+/^@quote$/ { quoting = 1 ; printf "{\\tt{}" }
+/^@endquote$/ { quoting = 0 ; printf "}" }
+/^@file / { filename = substr($0, 7); <<clear [[lastxref*]]>>
+ if (!delay) printf "\\nwfilename{%s}", filename
+ }
+/^@literal / { printf "%s", substr($0, 10) }
+/^@header latex / { <<write {\LaTeX} header>> }
+/^@header tex / { printf "\\input nwmac " }
+/^@trailer latex$/ { print "\\end{document}" }
+/^@trailer tex$/ { print "\\bye" }
+<<xref patterns>>
+<<index patterns>>
+END { printf "\n" }
+<<functions>>
+@
+<<print [[\nwdocspar]] if no text>>=
+if (text==0) printf "\\nwdocspar"
+text=1
+@
+Delaying markup is handled by special patterns for the first document chunk.
+Because several {\tt noweb} files can be marked up at once, there can be
+several document chunks numbered 0.
+The later ones are given no special treatment by the simple expedient of
+turning [[delay]] off after the first one.
+<<special patterns for document chunk 0>>=
+/^@begin docs 0$/ { if (delay) next }
+/^@end docs 0$/ { if (delay) {
+ printf "\\nwfilename{%s}", filename; delay=0; next
+ } }
+@
+<<defn of [[name]], with cross-reference>>=
+if (lastxreflabel != "") {
+ printf "\\sublabel{%s}", lastxreflabel
+ printf "\\nwmargintag{%s}", label2tag(lastxreflabel)
+}
+printf "\\moddef{%s%s}\\%sendmoddef", convquotes(name), <<optional ref tag>>,
+efns[name]
+lastdefnlabel = lastxreflabel
+<<clear [[lastxref*]]>>
+defns[name] = "plus"
+<<optional ref tag>>=
+(lastxrefref != "" ? ("~" label2tag(lastxrefref)) : "")
+<<functions>>=
+function label2tag(label) {
+ return "{\\nwtagstyle{}\\subpageref{" label "}}"
+}
+<<initialization>>=
+defns[0] = 0
+@
+<<write {\LaTeX} header>>=
+printf "\\documentclass{article}\\usepackage{noweb}\\pagestyle{noweb}\\nowebop
+ions{%s}%s",
+ substr($0, 15), "\\begin{document}"
+@
+\subsection{Cross-reference and index support}
+<<xref patterns>>=
+/^@xref label / { lastxreflabel = substr($0, 13) }
+/^@xref ref / { lastxrefref = substr($0, 11) }
+/^@xref begindefs$/ { printf "\\nwalsodefined{" }
+/^@xref defitem / { printf "\\\\{%s}", substr($0, 15) }
+/^@xref enddefs$/ { printf "}" }
+/^@xref beginuses$/ { printf "\\nwused{" }
+/^@xref useitem / { printf "\\\\{%s}", substr($0, 15) }
+/^@xref enduses$/ { printf "}" }
+/^@xref notused / { printf "\\nwnotused{%s}", TeXliteral(substr($0, 15)) }
+/^@xref nextdef / { }
+/^@xref prevdef / { }
+<<clear [[lastxref*]]>>=
+lastxreflabel = lastxrefref = ""
+<<index patterns>>=
+/^@index nl$/ { print (code ? "\\eatline" : "%") }
+/^@index defn / {
+ if (!noindex) { arg = substr($0, 13); <<handle index defn of [[arg]]>
+ } }
+/^@index localdefn / {
+ if (!noindex) { arg = substr($0, 18); <<handle index defn of [[arg]]>
+ } }
+/^@index use / {
+ if (!noindex) { arg = substr($0, 12); <<handle index use of [[arg]]>>
+} }
+@
+Nothing is involved in handling definitions and uses unless there are cross-re
+erence
+labels pending.
+An index definition or use has its own [[@xref label]] only if it's in documen
+ation;
+if it's in code, we use the anchor label of the definition.
+(You don't have to know that to understand what happens here, but I thought yo
+
+might like to.)
+<<handle index defn of [[arg]]>>=
+if (lastxreflabel != "") printf "\\nosublabel{%s}", lastxreflabel
+if (lastxrefref != "")
+ printf "\\nwindexdefn{%s}{%s}{%s}", TeXliteral(arg), indexlabel(arg), lastxr
+fref
+<<clear [[lastxref*]]>>
+@
+The {\LaTeX} back end ignores uses in code; they get bundled up by a previous
+ilter
+(the cross-referencer) and handled elsewhere.
+<<handle index use of [[arg]]>>=
+if (!code) {
+ if (lastxreflabel != "") printf "\\protect\\nosublabel{%s}", lastxreflabel
+ if (lastxrefref != "")
+ printf "\\protect\\nwindexuse{%s}{%s}{%s}",
+ TeXliteral(arg), indexlabel(arg), lastxrefref
+}
+<<clear [[lastxref*]]>>
+@
+Here's the local identifier cross-reference that appears at the end of a code
+hunk.
+We guard everything with \LA{}SI\RA, as before.
+<<index patterns>>=
+/^@index begindefs$/ { if (!noindex) { printf "\\nwidentdefs{" } }
+/^@index isused / { if (!noindex) { } } # handled by latex
+/^@index defitem / { if (!noindex) { i = substr($0,16); <<write [[i]] with [
+\\]]>> } }
+/^@index enddefs$/ { if (!noindex) { printf "}" } }
+/^@index beginuses$/ { if (!noindex) { printf "\\nwidentuses{"; ucount = 0 } }
+/^@index isdefined / { if (!noindex) { } } # latex finds the definitions
+/^@index useitem / { if (!noindex) { i = substr($0, 16); <<write [[i]] with
+[\\]]>>
+ ulist[ucount++] = i
+ } }
+/^@index enduses$/ { if (!noindex) { printf "}"; <<write [[ulist]]>> } }
+<<initialization>>=
+ulist[0] = 0
+<<write [[i]] with [[\\]]>>=
+printf "\\\\{{%s}{%s}}", TeXliteral(i), indexlabel(i)
+<<write [[ulist]]>>=
+if (lastdefnlabel != "") {
+ for (j = 0; j < ucount; j++)
+ printf "\\nwindexuse{%s}{%s}{%s}",
+ TeXliteral(ulist[j]), indexlabel(ulist[j]), lastdefnlabel
+}
+@
+\subsubsection{The list of chunks and the index}
+The treatments of the list of chunks and the index are similar.
+Both use [[\nwixlogsorted]], which writes magic goo into the {\tt .aux} file.
+The real cross-referencing is done by the underlying {\LaTeX} code.
+<<xref patterns>>=
+/^@xref beginchunks$/ { }
+/^@xref chunkbegin / { label = $3; name = substr($0, 19 + length(
+abel))
+ printf "\\nwixlogsorted{c}{{%s}{%s}{",
+ convquotes(name), label
+ }
+/^@xref chunkuse / { printf "\\nwixu{%s}", substr($0, 16) }
+/^@xref chunkdefn / { printf "\\nwixd{%s}", substr($0, 17) }
+/^@xref chunkend$/ { print "}}%" }
+/^@xref endchunks$/ { }
+<<index patterns>>=
+/^@index beginindex$/ { if (!noindex) { } }
+/^@index entrybegin / { if (!noindex) { label = $3; name = substr($0, 20 + len
+th(label))
+ printf "\\nwixlogsorted{i}{{%s}{%s}}%%\n",
+
+ TeXliteral(name), indexlabel(name)
+ } }
+/^@index entryuse / { if (!noindex) { } } # handled by latex
+/^@index entrydefn / { if (!noindex) { } } # handled by latex
+/^@index entryend$/ { if (!noindex) { } }
+/^@index endindex$/ { if (!noindex) { } }
+
+@
+\subsection{Miscellany}
+I first insert a newline before the special characters, then change the
+newline to a backslash. I can't do the backslash directly because
+[[\&]] means a literal ampersand.
+<<functions>>=
+function escape_brace_bslash(line) {
+ gsub(/[\\{}]/, "\n&", line)
+ gsub(/\n/, "\\", line)
+ return line
+}
+@
+A special function is used to implement {\tt noweb}'s quoting
+convention within chunk names.
+<<functions>>=
+function convquotes(s, r, i) {
+ r = ""
+ while (i = index(s, "[[")) {
+ r = r substr(s, 1, i-1) "\\code{}"
+ s = substr(s, i+2)
+ if (i = match(s, "\\]\\]+")) {
+ r = r TeXliteral(substr(s, 1, i-1+RLENGTH-2)) "\\edoc{}"
+ s = substr(s, i+RLENGTH)
+ } else {
+ r = r s "\\edoc{}"
+ s = ""
+ }
+ }
+ return r s
+}
+<<functions>>=
+function indexlabel(ident, l) {
+ l = ident
+ gsub(/:/, ":col", l) # must be first (colon)
+ gsub(/ /, ":sp", l) # space
+ gsub(/#/, ":has", l) # hash
+ gsub(/\$/, ":do", l) # dollar
+ gsub(/%/, ":pe", l) # percent
+ gsub(/&/, ":am", l) # ampersand
+ gsub(/,/, ":com", l) # commad
+ gsub(/\\/, ":bs", l) # backslash
+ gsub(/\^/, ":hat", l) # hat
+ gsub(/_/, ":un", l) # underscore
+ gsub(/{/, ":lb", l) # left brace
+ gsub(/}/, ":rb", l) # right brace
+ gsub(/~/, ":ti", l) # tilde
+ return l
+}
+@ %def indexlabel
+@
+Because latex2e uses [[`]] as an active character, I have to use
+decimal character codes for the specials.
+<<functions>>=
+function TeXliteral(arg) {
+ gsub(/\\/, "<\\char92>", arg)
+ gsub(/}/, "<\\char125}", arg)
+ gsub(/{/, "{\\char123}", arg)
+ gsub(/<\\char/, "{\\char", arg)
+ gsub(/{\\char92>/, "{\\char92}", arg)
+ gsub(/\$/, "{\\char36}", arg)
+ gsub(/&/, "{\\char38}", arg)
+ gsub(/#/, "{\\char35}", arg)
+ gsub(/\^/, "{\\char94}", arg)
+ gsub(/_/, "{\\char95}", arg)
+ gsub(/%/, "{\\char37}", arg)
+ gsub(/~/, "{\\char126}", arg)
+ gsub(/ /, "\\ ", arg)
+ return arg
+}
+@ %def TeXliteral
+
diff --git a/web/noweb/contrib/rsc/rc/unmarkup.nw b/web/noweb/contrib/rsc/rc/unmarkup.nw
new file mode 100644
index 0000000000..9d04b3389d
--- /dev/null
+++ b/web/noweb/contrib/rsc/rc/unmarkup.nw
@@ -0,0 +1,53 @@
+<<unmarkup>>=
+#!/bin/rc
+#
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file /sys/src/cmd/noweb/COPYRIGHT for more information.
+#
+# Translated to rc by Russ Cox
+# bugs -> rsc@plan9.bell-labs.com
+#
+
+awk '
+BEGIN {
+ rcsid = "$Id: unmarkup,v 1.5 1999/02/16 21:11:54 nr Exp nr $"
+ rcsname = "$Name: v2_9a $"
+}
+/^@begin docs 0$/ { next }
+/^@begin docs / { printf "@ " }
+/^@begin code / { code = 1 }
+/^@end [cd]o[dc][es] / {
+ code = 0
+ if (dangling_text) printf "\n"
+ dangling_text = 0
+ printf "%s", deflines
+ if (defline != "") printf "%s\n", defline
+ deflines = "" ; defline = ""
+ }
+/^@defn / { printf "@<<%s>>=", substr($0,7) }
+/^@text $/ {next}
+/^@text / {
+ gsub("@<<", "@@<<");
+ gsub("@>>", "@@>>");
+ if (!(code || quoting)) {
+ gsub(/\[\[/, "@[[");
+ gsub(/\]\]/, "@]]");
+ }
+ printf "%s", substr($0,7)
+ dangling_text = 1
+}
+/^@quote$/ { printf("[["); dangling_text = 1; quoting = 1 }
+/^@endquote$/ { printf("]]"); dangling_text = 1; quoting = 0 }
+/^@nl$/ { printf "\n"; dangling_text = 0}
+
+/^@index defn / {
+ if (defline == "") defline = "@ %def"
+ defline = defline " " substr($0, 13)
+}
+/^@index nl$/ {
+ deflines = deflines defline "\n"
+ defline = ""
+}
+/^@use / { printf "@<<%s>>", substr($0,6)
+ dangling_text = 1
+ }' $* | sed 's/^@ $/@/'
diff --git a/web/noweb/contrib/ydirson/Makefile b/web/noweb/contrib/ydirson/Makefile
new file mode 100644
index 0000000000..a6a6dadc99
--- /dev/null
+++ b/web/noweb/contrib/ydirson/Makefile
@@ -0,0 +1,11 @@
+LIB=/dev/null # to be overridden
+
+FILTERS = guesslang inheritlang enscript-html
+
+# nothing to tangle or weave
+all:
+source:
+clean:
+
+install:
+ cp -p $(FILTERS) $(LIB)
diff --git a/web/noweb/contrib/ydirson/README b/web/noweb/contrib/ydirson/README
new file mode 100644
index 0000000000..54b5b43c71
--- /dev/null
+++ b/web/noweb/contrib/ydirson/README
@@ -0,0 +1,32 @@
+guesslang <list of root chunks>
+ Attempts to set the @language of given root chunks.
+ Note: Currently only inspects '#!' lines, not filename.
+inheritlang
+ Propagates @language to non-root chunks.
+enscript-html <enscript flags>
+ Uses enscript(1) to pretty-print chunks in HTML according to @language.
+ Most useful enscript flags include --color and --style=...
+
+ Note: Should ultimately work with all languages
+ supported by enscript, but needs extra info about how
+ to mangle @use clauses. If it complains "Don't know
+ how to mangle @use" for your language, you can edit
+ mangle_use() and demangle_use() to turn the @use
+ clause into a meaningfull language clause, and then
+ convert back in @use form.
+
+ Note: Supports all highlighting styles of enscript
+ 1.6.4, but the regexp in demangle_use() may need to be
+ adapted in the future.
+
+Typical use lokks like:
+ noweave -html \
+ -filter "guesslang ${NOWEBOUTSRC} | inheritlang | enscript-html" \
+ -x <your.nw>
+
+Be sure to specify -x or possibly other filters *after* the -filter,
+since the pretty-printer does not preserve the position of remaining
+directives (esp. @xref) within code chunks.
+
+Sample output is viewable at
+http://ydirson.free.fr/en/software/noweb/dh-kpatches.html
diff --git a/web/noweb/contrib/ydirson/email b/web/noweb/contrib/ydirson/email
new file mode 100644
index 0000000000..4d569e5f14
--- /dev/null
+++ b/web/noweb/contrib/ydirson/email
@@ -0,0 +1 @@
+ydirson@altern.org
diff --git a/web/noweb/contrib/ydirson/enscript-html b/web/noweb/contrib/ydirson/enscript-html
new file mode 100755
index 0000000000..1f179bef8a
--- /dev/null
+++ b/web/noweb/contrib/ydirson/enscript-html
@@ -0,0 +1,150 @@
+#!/usr/bin/perl -w
+
+# Noweb filter which calls enscript to prettyprint according to
+# @language directives (see guesslang and inheritlang filters to have
+# those directive automatically generated).
+
+# Copyright (c) 2003 by Yann Dirson <ydirson@altern.org>
+
+# Distribute under the terms of the GNU General Public Licence,
+# version 2.
+
+# FIXME:
+# - @use in code chunks is not supported for all @language's yet
+# => find a way to plug external data ?
+# - when a perl chunk ends with comment lines, we get enscript
+# trailers in woven output
+
+use strict;
+use File::Temp qw(tempfile);
+
+my $mangledID='__NOWEB__mangled__use__';
+sub mangle_use {
+ my ($usedchunk, $lang) = @_;
+
+ if (grep { $lang eq $_ } ('perl', 'c', 'c++') ) {
+ return "$mangledID (\"$usedchunk\")\n";
+ } else {
+ die "Don't know how to mangle \@use for language $lang";
+ }
+}
+
+sub demangle_use {
+ my ($mangled, $lang) = @_;
+
+ if (grep { $lang eq $_ } ('perl', 'c', 'c++') ) {
+ $mangled =~ m|^(.*)$mangledID \((?:<B>)?(?:<FONT.*>)?\&quot;(.*)\&quot;(?:</FONT>)?(?:</B>)?\)(.*)$|;
+ return ($1, $2, $3);
+ } else {
+ die "Don't know how to demangle \@use for language $lang";
+ }
+}
+
+
+# Find out languages supported by the available version of enscript
+
+my @knownlangs;
+open (LANGS, 'enscript --help-highlight | grep ^Name: |') or
+ die "enscript --help-highlight failed: $!";
+while (<LANGS>) {
+ chomp;
+ @_ = split /\s+/;
+ push @knownlangs, $_[1];
+}
+
+
+while (<STDIN>) {
+ if (m/^\@begin code/) {
+
+ # we found a code chunk, now bufferize its contents until
+ # @language, or until @end if no @language is there. Store in
+ # $event which of these 2 events just occured
+
+ my (@buffer, $event);
+ push @buffer, $_;
+ while (defined($_ = <STDIN>) and
+ not ((m/^\@end code / and $event = [1]) or
+ (m/^\@language (.*)/ and $event = [2, $1])) ) {
+ push @buffer, $_;
+ }
+ die "$0 hit EOF before seing \@end code or \@language" unless defined $event;
+
+ if ($event->[0] == 1) {
+ # we got @end first, everything read goes through unmodified
+
+ push @buffer, $_; # the @end line
+ # no declared language: dump @buffer
+ foreach (@buffer) { print; }
+ } else {
+ # we found @language...
+
+ # check that language is supported
+ my $lang = $event->[1];
+ if (grep { $_ eq $lang } @knownlangs ) {
+ # language is supported
+
+ # (implicitely) drop @language from output, read remainder
+ my $chunknum;
+ while (defined($_ = <STDIN>) and not (m/^\@end code (.*)/ and $chunknum = $1)) {
+ push @buffer, $_;
+ }
+ # we don't want "@end code" in the buffer, delay its output
+ my $endcode = $_;
+
+ # transform the code chunk to be accepted by enscript, and
+ # store it into an auto-unlinked temporary file
+
+ my $tmp = new File::Temp();
+ # demangle @-directives into something suitable for enscript
+ foreach (@buffer) {
+ if (m/^\@text (.*)/ ) {
+ print $tmp $1;
+ } elsif (m/^\@nl$/) {
+ print $tmp "\n";
+ } elsif (m/^\@use (.*)/) {
+ print $tmp mangle_use ($1, $lang);
+ } else {
+ print;
+ }
+ }
+
+ # pipe, remangle
+ open PRETTY, "enscript --highlight=$lang --language=html " .
+ join (' ', @ARGV) .
+ " --silent -o - $tmp |" or
+ die "enscript failed: $!";
+ {
+ my $started = undef;
+ while (<PRETTY>) {
+ if (m|^<PRE>$|) {
+ $started = 1;
+ next;
+ }
+ if (m|^</PRE>$|) {
+ last;
+ }
+
+ if (m/$mangledID/) {
+ my ($prefix, $use, $suffix) = demangle_use ($_, $lang);
+ print "\@literal $prefix\n" if $prefix ne '';
+ print "\@use $use\n" ;
+ print "\@literal $suffix\n" if $suffix ne '';
+ next;
+ }
+ print "\@literal $_\@nl\n" if defined $started;
+ }
+ }
+ close PRETTY;
+ close $tmp; # auto-unlinked
+
+ print $endcode;
+ } else {
+ push @buffer, $_; # the @language line
+ # unsupported language: dump @buffer
+ foreach (@buffer) { print; }
+ }
+ }
+ } else {
+ print $_;
+ }
+}
diff --git a/web/noweb/contrib/ydirson/guesslang b/web/noweb/contrib/ydirson/guesslang
new file mode 100755
index 0000000000..d659e57ee2
--- /dev/null
+++ b/web/noweb/contrib/ydirson/guesslang
@@ -0,0 +1,57 @@
+#!/usr/bin/perl -w
+
+# Noweb filter which attempt to add @language directives to root
+# chunks named on command-line.
+
+# Copyright (c) 2003 by Yann Dirson <ydirson@altern.org>
+
+# Distribute under the terms of the GNU General Public Licence,
+# version 2.
+
+# TODO: Currently only look at the 1st line of the chunk, expecting to
+# find a standard UN*X "#!" declaration. Still has to look at file
+# names/suffixes as well.
+
+use strict;
+use File::Basename;
+
+my @roots = @ARGV;
+
+my %interpreters = (
+ '[gn]awk' => 'awk',
+ 'perl[0-9.]*' => 'perl',
+ 'python[0-9.]*' => 'python',
+ '(wish|tclsh)[0-9.]*' => 'tcl',
+ '(|k|ba|z)sh' => 'sh',
+ );
+
+while (<STDIN>) {
+ if (m/^\@defn (.*)$/ and grep (/^$1$/, @roots)) {
+ my $language;
+ my $defn = $_;
+
+ # FIXME: should lookup a filename-based hash first (or second ?)
+
+ # memorize all lines until we can guess the language
+ my @buffer;
+ while (defined($_ = <STDIN>) and not m/^\@text/) {
+ push @buffer, $_;
+ }
+ # we have found the 1st @text line in the file, go see if it's a hash-bang
+ if (m/^\@text #!\s*(\/\S+)/) {
+ my $interp = basename ($1);
+
+ # lookup in our knowledge base
+ foreach my $re (keys %interpreters) {
+ $language=$interpreters{$re} if $interp =~ m/^$re$/;
+ }
+ # default to interpreter's name (FIXME: ugly, should be optional)
+ $language = $interp unless defined $language;
+ }
+ #
+ print $defn;
+ print "\@language $language\n" if defined $language;
+ print @buffer;
+ }
+ print $_;
+}
diff --git a/web/noweb/contrib/ydirson/inheritlang b/web/noweb/contrib/ydirson/inheritlang
new file mode 100755
index 0000000000..f71cce0a61
--- /dev/null
+++ b/web/noweb/contrib/ydirson/inheritlang
@@ -0,0 +1,76 @@
+#!/usr/bin/perl -w
+
+# Noweb filter to propagate @language directive from a chunk to used
+# chunks. Assumes that root chunks already have a @language directive
+# (see guesslang filter). Takes no argument.
+
+# Copyright (c) 2003 by Yann Dirson <ydirson@altern.org>
+
+# Distribute under the terms of the GNU General Public Licence,
+# version 2.
+
+use strict;
+
+my (%chunklangs, %chunkchildren);
+
+# FIXME: we could bufferize as needed, if we want to grow more complex
+my @data = <STDIN>;
+
+# register the chunk hierarchy
+{
+ my $thischunk = undef;
+ foreach (@data) {
+ if (m/^\@end code/) { # this one first to limit to code chunks
+ $thischunk = undef;
+ } elsif (m/^\@use (.*)$/) {
+ push @{$chunkchildren{$thischunk}}, $1 if defined $thischunk;
+ } elsif (m/^\@defn (.*)$/) {
+ $thischunk = $1;
+ } elsif (m/^\@language (.*)$/) {
+ die "\@language without a \@defn: $_" unless defined $thischunk;
+ $chunklangs{$thischunk} = $1;
+ }
+ }
+}
+
+# propagate to argument's children
+sub propagate {
+ my ($thischunk) = @_;
+ if (defined $chunklangs{$thischunk}) {
+ foreach my $child (@{$chunkchildren{$thischunk}}) {
+ if (defined $chunklangs{$child}) {
+ if ($chunklangs{$child} eq $chunklangs{$thischunk}) {
+ print STDERR "Notice: chunk used more than once: \`$child'\n";
+ } else {
+ die "Chunk cannot inherits languages \`$chunklangs{$child}' and " .
+ "\`$chunklangs{$thischunk}': \`$child'\n";
+ }
+ } else {
+ $chunklangs{$child} = $chunklangs{$thischunk};
+ }
+
+ # recurse
+ propagate($child);
+ }
+ } else {
+ print STDERR "Warning: could not infer language for \`$thischunk'\n";
+ }
+}
+
+# propagate from all known chunks
+foreach my $chunk (keys %chunklangs) {
+ propagate($chunk);
+}
+
+# output
+foreach (@data) {
+ if (m/^\@defn (.*)$/) {
+ print $_;
+ print "\@language $chunklangs{$1}\n" if (defined $chunklangs{$1})
+ } elsif (m/^\@language /) {
+ # Do not output twice. Since we already asserted consistency we can
+ # simply ignore this one.
+ } else {
+ print $_;
+ }
+}
diff --git a/web/noweb/echo b/web/noweb/echo
new file mode 100755
index 0000000000..447731d216
--- /dev/null
+++ b/web/noweb/echo
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# version of echo that does -n
+
+if [ "x$1" = "x-n" ]; then
+ shift
+ cat << echoEOF | tr -d '\012'
+$*
+echoEOF
+
+else
+ cat << echoEOF
+$*
+echoEOF
+
+fi
+
+exit 0
+
+
+if [ -x /bin/echo ]; then
+ exec /bin/echo "$@"
+elif [ -x /usr/bin/echo ]; then
+ exec /usr/bin/echo "$@"
+else
+ echo "$@"
+fi
diff --git a/web/noweb/examples/Makefile b/web/noweb/examples/Makefile
new file mode 100644
index 0000000000..9295cf54fc
--- /dev/null
+++ b/web/noweb/examples/Makefile
@@ -0,0 +1,55 @@
+WWW=$(HOME)/www/noweb/examples
+SHELL=/bin/sh
+NOTANGLE=nountangle -m3
+NOWEAVE=noweave
+
+.SUFFIXES: .i3 .m3 .nw .tex .dvi .html
+.nw.html: ; $(NOWEAVE) -filter l2h -filter btdefn -index -html $*.nw > $*.html
+.nw.tex: ; $(NOWEAVE) -index -filter btdefn $*.nw > $*.tex
+.nw.i3: ; $(NOTANGLE) -Rinterface -L'<* LINE %L "%F" *>%N' $*.nw > $*.i3
+.nw.m3: ; $(NOTANGLE) -L'<* LINE %L "%F" *>%N' $*.nw > $*.m3
+.tex.dvi: ; latex '\scrollmode \input '"$*"; while grep -s 'Rerun to get cross-references right' $*.log; do latex '\scrollmode \input '"$*"; done
+
+HTML=breakmodel.html compress.html dag.html graphs.html mipscoder.html primes.html \
+ scanner.html test.html tree.html wc.html wcni.html
+
+
+www: $(HTML)
+ copy -v $(HTML) $(WWW)
+ copy -v README.h $(WWW)/index.html
+
+clean:
+ rm -f *~ *.aux *.tex *.dvi *.log *.html *.toc
+
+clobber: clean
+
+compress.html: compress.nw
+ $(NOWEAVE) -filter l2h -index -autodefs c -html compress.nw > compress.html
+compress.tex: compress.nw
+ $(NOWEAVE) -index -autodefs c compress.nw > compress.tex
+dag.html: dag.nw
+ $(NOWEAVE) -filter l2h -index -autodefs icon -html dag.nw > dag.html
+dag.tex: dag.nw
+ $(NOWEAVE) -index -autodefs icon dag.nw > dag.tex
+mipscoder.html: mipscoder.nw
+ $(NOWEAVE) -filter l2h -index -autodefs sml -html mipscoder.nw > mipscoder.html
+mipscoder.tex: mipscoder.nw
+ $(NOWEAVE) -autodefs sml -index mipscoder.nw > mipscoder.tex
+scanner.html: scanner.nw
+ $(NOWEAVE) -filter l2h -index -autodefs c -autodefs yacc -html scanner.nw > scanner.html
+scanner.tex: scanner.nw
+ $(NOWEAVE) -index -autodefs c -autodefs yacc scanner.nw > scanner.tex
+tree.html: tree.nw
+ $(NOWEAVE) -filter l2h -index -autodefs icon -html tree.nw > tree.html
+tree.tex: tree.nw
+ $(NOWEAVE) -index -autodefs icon tree.nw > tree.tex
+test.html: test.nw
+ $(NOWEAVE) -filter l2h -html test.nw > test.html
+test.tex: test.nw
+ $(NOWEAVE) test.nw > test.tex
+wc.html: wc.nw2html
+ $(NOWEAVE) -autodefs c -filter btdefn -index -html -n wc.nw2html > wc.html
+wcni.html: wc.nw2html
+ $(NOWEAVE) -filter btdefn -x -html -n wc.nw2html > wcni.html
+wc.tex: wc.nw
+ $(NOWEAVE) -autodefs c -filter btdefn -index wc.nw > wc.tex
diff --git a/web/noweb/examples/Makefile.awk b/web/noweb/examples/Makefile.awk
new file mode 100644
index 0000000000..304fe88baa
--- /dev/null
+++ b/web/noweb/examples/Makefile.awk
@@ -0,0 +1,58 @@
+WWW=$(HOME)/www/noweb/examples
+SHELL=/bin/sh
+NOTANGLE=nountangle -m3
+NOWEAVE=noweave
+
+.SUFFIXES: .i3 .m3 .nw .tex .dvi .html
+.nw.html: ; $(NOWEAVE) -filter btdefn -index -html $*.nw > $*.html
+.nw.tex: ; $(NOWEAVE) -index -filter btdefn $*.nw > $*.tex
+.nw.i3: ; $(NOTANGLE) -Rinterface -L'<* LINE %L "%F" *>%N' $*.nw > $*.i3
+.nw.m3: ; $(NOTANGLE) -L'<* LINE %L "%F" *>%N' $*.nw > $*.m3
+.tex.dvi: ; latex '\scrollmode \input '"$*"; while grep -s 'Rerun to get cross-references right' $*.log; do latex '\scrollmode \input '"$*"; done
+
+HTML=breakmodel.html compress.html dag.html graphs.html mipscoder.html primes.html \
+ scanner.html test.html tree.html wc.html wcni.html
+DVI=compress.dvi dag.dvi mipscoder.dvi scanner.dvi tree.dvi test.dvi wc.dvi
+
+
+texonly: $(DVI)
+
+www: $(HTML)
+ copy -v $(HTML) $(WWW)
+ copy -v README.h $(WWW)/index.html
+
+clean:
+ rm -f *~ *.aux *.tex *.dvi *.log *.html *.toc
+
+clobber: clean
+
+compress.html: compress.nw
+ $(NOWEAVE) -index -html compress.nw > compress.html
+compress.tex: compress.nw
+ $(NOWEAVE) -index compress.nw > compress.tex
+dag.html: dag.nw
+ $(NOWEAVE) -index -html dag.nw > dag.html
+dag.tex: dag.nw
+ $(NOWEAVE) -index dag.nw > dag.tex
+mipscoder.html: mipscoder.nw
+ $(NOWEAVE) -index -html mipscoder.nw > mipscoder.html
+mipscoder.tex: mipscoder.nw
+ $(NOWEAVE) -index mipscoder.nw > mipscoder.tex
+scanner.html: scanner.nw
+ $(NOWEAVE) -index -html scanner.nw > scanner.html
+scanner.tex: scanner.nw
+ $(NOWEAVE) -index scanner.nw > scanner.tex
+tree.html: tree.nw
+ $(NOWEAVE) -index -html tree.nw > tree.html
+tree.tex: tree.nw
+ $(NOWEAVE) -index tree.nw > tree.tex
+test.html: test.nw
+ $(NOWEAVE) -html test.nw > test.html
+test.tex: test.nw
+ $(NOWEAVE) test.nw > test.tex
+wc.html: wc.nw2html
+ $(NOWEAVE) -filter btdefn -index -html -n wc.nw2html > wc.html
+wcni.html: wc.nw2html
+ $(NOWEAVE) -filter btdefn -x -html -n wc.nw2html > wcni.html
+wc.tex: wc.nw
+ $(NOWEAVE) -filter btdefn -index wc.nw > wc.tex
diff --git a/web/noweb/examples/README b/web/noweb/examples/README
new file mode 100644
index 0000000000..3cf8e981a4
--- /dev/null
+++ b/web/noweb/examples/README
@@ -0,0 +1,49 @@
+All these examples have been set up to work with latex, although I
+often prefer plain TeX because latex's page breaking is so bad and so
+hard to control. breakmodel.nw is the only one that requires
+cross-referencing (noweave -x). I have included the nonstandard
+`multicol' style file, although it is readily available as part of the
+Mainz distribution.
+
+Except for breakmodel.nw, each example file is a fragment of a larger
+program. noweb itself is not a good example of literate programming.
+It is harder than most people realize to write a truly literate
+program, and noweb wasn't worth the effort.
+
+If you have installed noweb with LIBSRC=awk instead of LIBSRC=icon,
+you need to use Makefile.awk instead of Makefile.
+
+The files are:
+
+ Makefile Shows some sample default rules for use
+ in a Makefile. Try `make tree.tex tree.dvi'.
+ Makefile.awk Like Makefile but doesn't require Icon.
+ None of the HTML examples will be readable
+ without Icon.
+ breakmodel.nw A formal model of breakpoints using the
+ Promela modeling language.
+ dag.nw Fragment of an Icon program that compiles
+ patterns into decision-tree pattern-matching
+ code. tree.nw builds the decision trees;
+ dag.nw turns them into dags.
+ graphs.nw Several graphs written in jgraph (write
+ plank@cs.utk.edu for information about jgraph).
+ mipscoder.nw Part of the original MIPS code generator from
+ Standard ML of New Jersey. Writting in Standard ML.
+ primes.nw noweb version of DEK's original prime-number program.
+ scanner.nw Part of a student compiler project. Includes
+ C code and lex and yacc specifications, all in
+ a single file.
+ sharpline A noweb filter that makes noweb `see' #line directives
+ in a noweb file.
+ test.nw A simple test file.
+ tree.nw Fragment of an Icon program that compiles
+ patterns into decision-tree pattern-matching
+ code. tree.nw builds the decision trees;
+ dag.nw turns them into dags.
+ wc.nw A re-implementation in noweb of the CWEB
+ example from DEK's book. This example is
+ intended to be as exact a copy as possible; no
+ attempt was made to improve the code.
+ whitespace A noweb filter that makes whitespace insignificant
+ within chunk names.
diff --git a/web/noweb/examples/README.h b/web/noweb/examples/README.h
new file mode 100644
index 0000000000..0ff13d92e8
--- /dev/null
+++ b/web/noweb/examples/README.h
@@ -0,0 +1,72 @@
+<html>
+<head>
+<title>Examples programs written in <tt>noweb</tt></title>
+</head>
+<body>
+<h1>Noweb example programs</h1>
+All but one of
+these examples have had their documentation parts converted automatically
+from LaTeX to HTML.
+(Can you tell which one?)
+Except for <a href=breakmodel.html>breakmodel</a>,
+each example file is a fragment of a larger
+program.
+<p>
+The typical command line used to create one of these documents is:
+<pre>
+noweave -filter l2h -index -autodefs c -html compress.nw > compress.html
+</pre>
+for various values of <tt>c</tt> :-)
+<p>
+The example programs are:
+<dl>
+<dt><a href=breakmodel.html>breakmodel</a><dd>
+ A formal model of breakpoints using the
+ Promela modeling language.
+<dt><a href=compress.html>compress</a><dd>
+ A library that modifies the <t>open</t>, <t>close</t>, <t>read</t>,
+ and <t>write</t> system calls (along with some others) to
+ transparently read and write files in Unix <t>compress</t> format.
+ Graciously contributed by
+ <a href=http://www.cs.princeton.edu/~blume>Matthias Blume</a>
+<dt><a href=dag.html>dag</a><dd>
+ Fragment of an <a href=http://www.cs.arizona.edu/icon/>Icon</a>
+ program that compiles
+ patterns into decision-tree pattern-matching
+ code. tree.nw builds the decision trees;
+ dag.nw turns them into dags.
+<dt><a href=graphs.html>graphs</a><dd>
+ Several graphs written in
+ <a href=http://www.cs.utk.edu/~plank/plank/jgraph/jgraph.html>jgraph</a>.
+<dt><a href=mipscoder.html>mipscoder</a><dd>
+ Part of the original MIPS code generator from
+ Standard ML of New Jersey. Written in Standard ML.
+<dt><a href=primes.html>primes</a><dd>
+ noweb version of DEK's original prime-number program.
+ I got tired of typing and never entered all the text.
+<dt><a href=scanner.html>scanner</a><dd>
+ Part of a student compiler project. Includes
+ C code and lex and yacc specifications, all in
+ a single file.
+<dt><a href=solver.html>solver</a><dd>
+An equation solver, published in <em>Software---Practice &amp; Experience</em>.
+The <A href=/~nr/pubs/solver.ps>PostScript</a> is probably easier to read.
+<dt><a href=test.html>test</a><dd>
+ A simple test file.
+<dt><a href=tree.html>tree</a><dd>
+ Fragment of an <a href=http://www.cs.arizona.edu/icon/>Icon</a>
+ program that compiles
+ patterns into decision-tree pattern-matching
+ code. tree.nw builds the decision trees;
+ dag.nw turns them into dags.
+<dt><a href=wc.html>wc</a><dd>
+ An re-implementation of the example word-count program from Don
+ Knuth's book on literate programming.
+ This example is as exact a copy as possible; no
+ attempt was made to improve the code.
+ <a href="wcni.html">Here</a> is a version without identifier
+ cross-reference, which gives it a cleaner look.
+ <a href="wc.nw.html">Here</a> you can see a plain-text
+ rendering of the <tt>noweb</tt> source.
+</dl>
+</body>
diff --git a/web/noweb/examples/breakmodel.nw b/web/noweb/examples/breakmodel.nw
new file mode 100644
index 0000000000..284ad01719
--- /dev/null
+++ b/web/noweb/examples/breakmodel.nw
@@ -0,0 +1,459 @@
+% \global\def\begindocs#1{\relax}
+% \global\let\enddocs=\relax
+
+{\def\semifilbreak#1{\vskip0pt plus #1\penalty-200\vskip0pt plus -#1}
+\def\single{\def\baselinestretch{1.0}\small\normalsize}
+
+% l2h ignore semifilbreak {
+% l2h ignore single
+
+% l2h substitution LA &lt;
+% l2h substitution RA &gt;
+
+\section{A Formal Model of Breakpoints}
+\label{appendix:breakpoint-model}
+This appendix provides a formal model of {\tt ldb}'s follow-set breakpoints.
+The model takes the form of a PROMELA program~\cite{holzmann:design}.
+PROMELA programs define several threads of control that communicate by
+passing messages.
+Each thread of control runs a program written in a guarded-command
+language with a C-like syntax.
+Programs may be nondeterministic.
+PROMELA can simulate the execution of a program and
+search its state space for states violating assertions embedded in the
+program.
+The simulator also searches for states with no successors, i.e.,
+deadlocks.
+
+The PROMELA code in this appendix models {\tt ldb}'s implementation of
+breakpoints.
+Although {\tt ldb} does not work with multithreaded programs, the
+model uses multiple threads because a procedure call from {\tt ldb} to
+a target process effectively creates a new thread.
+The assertions embedded in the model specify that the debugger
+takes a breakpoint action just before any thread's
+successful execution of the instruction at the breakpoint.
+Breakpoints may be implemented either in the operating system or in
+the debugger itself; the choice does not affect the model used here.
+The model assumes it can plant trap instructions in
+the instruction stream of the target program, and that
+it will be notified when the target program encounters a trap.
+The model also suits a machine with a ``trace mode''
+ that causes a trap after the execution of every instruction.
+
+
+The model has a single
+breakpoint.
+To keep the state space small, the model has only two threads, so that
+ a single bit can represent thread [[id]]s.\label{noweb-sample-page-number}
+<<declarations>>=
+#define NTHREADS 2
+#define threadid bit
+@ \noindent
+The {\footnotesize\pageref{noweb-sample-page-number}} in
+\LA{}declarations~\footnotesize\pageref{noweb-sample-page-number}\RA{}
+is the page number on which the definition appears.
+
+\section{Modeling the program counter and execution}
+To keep things simple, I partition the possible values of the program
+counter into three sets:
+\begin{quote}
+\begin{tabular}{ll}
+ [[Break]]&the breakpoint itself,\\
+ [[Follow]]&the instruction(s) following the breakpoint,\\
+ [[Outside]]&outside the breakpoint.\\
+\end{tabular}
+\end{quote}
+\semifilbreak{2\baselineskip}
+\noindent The three sets are modeled by the following constants.
+<<declarations>>=
+#define NPCS 3
+#define Break 0 /* pc at the breakpoint */
+#define Follow 1 /* pc in breakpoint's follow set */
+#define Outside 2 /* all other pc's */
+@
+
+The ability to plant traps is modeled by the array [[trapped]], which
+records whether a trap instruction has been
+stored at a particular location:
+<<declarations>>=
+bool trapped[NPCS];
+@
+
+The model has five active components: two threads, a CPU that
+executes one thread at a time, the breakpoint, and the rest of the debugger.
+Here are the channels that are used for communication between the
+threads, the CPU, the breakpoint, and the debugger.
+Taking a breakpoint action is modeled by sending a message on the channel
+[[breakaction]].
+<<declarations>>=
+chan execute[NTHREADS] = [0] of {bit}; /* try to execute instruction */
+chan cont[NTHREADS] = [0] of {bit}; /* instruction executed */
+chan trap = [0] of {byte}; /* CPU trapped on id! */
+chan resume = [0] of {bit}; /* debugger resumed after trap */
+chan breakaction = [0] of {byte}; /* deliver breakpoint to debugger */
+@ \noindent [[[0]]] indicates that the channels are synchronous;
+ senders block until a receiver is ready and vice~versa.{\hfuzz=0.9pt\par}
+
+The communication structure is:
+\begin{center}
+\setlength{\unitlength}{0.01in}%
+\footnotesize
+\begin{picture}(580,180)( 50,-90)
+\thicklines
+\put(585, 0){\oval(90,60)}
+\put(402, 0){\oval(90,62)}
+\put(252, 0){\oval(90,60)}
+\put( 95, 60){\oval(90,60)}
+\put( 95,-60){\oval(90,60)}
+\put(295, 10){\vector( 1, 0){ 60}}
+\put(355,-10){\vector(-1, 0){ 60}}
+\put(450, 0){\vector( 1, 0){ 90}}
+\put(140, 55){\vector( 2,-1){ 70}}
+\put(205, 10){\vector(-2, 1){ 70}}
+\put(135,-45){\vector( 2, 1){ 70}}
+\put(210,-20){\vector(-2,-1){ 70}}
+\put(585, 0){\makebox(0,0){{\tt debugger()}}}
+\put(402, 0){\makebox(0,0){{\tt breakpoint()}}}
+\put(255, 0){\makebox(0,0){{\tt CPU()}}}
+\put( 95,-65){\makebox(0,0)[b]{{\tt thread(1)}}}
+\put( 95, 55){\makebox(0,0)[b]{{\tt thread(0)}}}
+\put(165,-21){\makebox(0,0)[rb]{{\tt execute[1]}}}
+\put(165, 16){\makebox(0,0)[rb]{{\tt cont[0]}}}
+\put(170,-50){\makebox(0,0)[lb]{{\tt cont[1]}}}
+\put(165, 50){\makebox(0,0)[lb]{{\tt execute[0]}}}
+\put(330,-20){\makebox(0,0)[b]{{\tt resume}}}
+\put(330, 15){\makebox(0,0)[b]{{\tt trap!id}}}
+\put(493, 5){\makebox(0,0)[b]{{\tt breakaction!id}}}
+\end{picture}
+\end{center}
+@
+
+\noindent The CPU repeats the following steps.
+\begin{enumerate}\single
+\item
+Wait for a thread to attempt to execute the instruction at [[pc]].
+\item
+If the instruction is a trap, notify the debugger.
+When the debugger tells the CPU to resume, [[pc]] is unchanged.
+\item
+If the instruction is not a trap, advance [[pc]].
+\item
+Ask the thread to continue executing.
+\end{enumerate}
+There is only one debugger, but there are multiple threads, and each
+one has its own [[pc]] and its own communication with the CPU.
+When the CPU notifies the debugger of a trap, it identifies the
+trapping thread.
+Other messages are used only for synchronization, so they send and
+receive the nonsense variable [[x]].
+<<declarations>>=
+bit x; /* junk variable for sending messages */
+@
+A [[proctype]] is a procedure that a thread can execute; this one
+models the CPU.
+ [[c?x]] receives the value [[x]] on channel [[c]]; [[c!x]] sends.
+Arrows ([[->]]) separate guards from commands.
+<<proctypes>>=
+proctype CPU(byte count) {
+ threadid id = 0;
+ do
+ :: execute[id]?x ->
+ if
+ :: trapped[pc[id]] -> trap!id ; resume?x
+ :: !trapped[pc[id]] -> <<advance [[pc[id]]]>>
+ fi;
+ cont[id]!x;
+ <<possible context switch (change of [[id]])>>
+ od
+}
+@ Context switching is discussed below.
+@
+\semifilbreak{1in} % page tuning
+@
+Since the program counter is an abstraction, advancing it does not
+mean incrementing it. A successful execution at [[Break]] is
+guaranteed to be followed by an attempt to execute [[Follow]];
+aside from that, any instruction can follow any other.
+<<advance [[pc[id]]]>>=
+if
+:: pc[id] == Break -> pc[id] = Follow
+:: pc[id] != Break -> /* any instruction can be next */
+ if
+ :: pc[id] = Outside
+ :: pc[id] = Break
+ :: pc[id] = Follow
+ fi
+fi
+@ \noindent
+The second [[if]] statement has no guards, so an alternative is
+chosen nondeterministically.
+
+All threads begin execution outside the breakpoint.
+<<declarations>>=
+byte pc[NTHREADS];
+<<initialize data for thread [[id]]>>=
+pc[id] = Outside;
+
+@
+\section{Counting events}
+The correctness criterion for the breakpoint implementation is that
+one breakpoint action must be taken for every
+successful execution of an instruction at [[Break]].
+[[threadcount[id]]] counts how many times thread~[[id]]
+has executed the breakpoint, and [[actioncount[id]]] counts how many
+breakpoint actions have been taken on behalf of thread~[[id]].
+<<declarations>>=
+byte threadcount[NTHREADS];
+byte actioncount[NTHREADS];
+<<initialize data for thread [[id]]>>=
+threadcount[id] = 0;
+actioncount[id] = 0;
+@
+\semifilbreak{0.75in} % page tuning
+@
+Here is the model of a thread, including the assertion that the thread
+and debugger counts are the same:
+<<proctypes>>=
+proctype thread(threadid id) {
+ do
+ :: if
+ :: pc[id] == Break -> execute[id]!x; cont[id]?x;
+ <<if successfully executed [[Break]], increment [[threadcount[id]]]>>
+ :: pc[id] != Break -> execute[id]!x; cont[id]?x
+ fi;
+ assert(pc[id] != Outside || threadcount[id] == actioncount[id])
+ od
+}
+@
+The corresponding model of the debugger is
+<<proctypes>>=
+proctype debugger() {
+ threadid id;
+ do
+ :: atomic { breakaction?id -> <<increment [[actioncount[id]]]>> }
+ od
+}
+@ \noindent
+[[atomic]] groups statements into a single atomic action.
+When the debugger takes a breakpoint action, it atomically increments
+[[actioncount[id]]].
+Without [[atomic]], it might delay incrementing the counter and
+invalidate the assertion above.
+
+A thread knows it has successfully executed [[Break]] if the [[pc]]
+has changed:
+<<if successfully executed [[Break]], increment [[threadcount[id]]]>>=
+if
+:: pc[id] != Break -> <<increment [[threadcount[id]]]>>
+:: pc[id] == Break -> skip
+fi
+@
+ To keep the state space small, I restrict the values of the
+counters to be in the range [[0..3]].
+<<increment [[threadcount[id]]]>>=
+threadcount[id] = (threadcount[id] + 1) % 4
+<<increment [[actioncount[id]]]>>=
+actioncount[id] = (actioncount[id] + 1) % 4
+@
+\section{Implementing the breakpoint}
+There is a long tradition of implementing breakpoints using traps
+and single stepping. To set a breakpoint at $I$, plant a trap
+at $I$. When the target program hits the trap, that's a breakpoint
+event.
+To resume execution after the breakpoint,
+ restore the original instruction to $I$,
+ single step the machine to execute just the instruction at $I$,
+and once again plant a trap at $I$ and continue execution.
+Not all machines have a single-step mode in hardware, but
+single stepping can be simulated in software by using more trap
+instructions.
+In my model, I eliminate single stepping entirely, working directly
+with trap instructions and a follow set
+(modeled by [[Follow]]).
+
+The simpler model does not preclude the use of hardware single stepping.
+One of the operations in the model is planting traps at the locations
+in the follow set of an instruction.
+This operation can be implemented either by computing the follow set
+and planting actual traps, or by setting a trace bit on a machine with
+hardware single stepping.
+
+\semifilbreak{3\baselineskip}
+
+An active breakpoint is trapped either on the instruction of the
+breakpoint itself or on that instruction's follow set.
+The breakpoint keeps track of which state it is in, with the following
+invariant.
+\begin{verbatim}
+ breakstate == Break && trapped[Break] = 1 && trapped[Follow] = 0
+|| breakstate == Follow && trapped[Break] = 0 && trapped[Follow] = 1
+\end{verbatim}
+<<declarations>>=
+byte breakstate = Break;
+<<initialization>>=
+trapped[Break] = 1;
+@ Changing the state preserves the invariant.\label{move-traps-page}
+<<move traps to [[Break]]>>=
+atomic { breakstate = Break; trapped[Break] = 1; trapped[Follow] = 0 }
+<<move traps to [[Follow]]>>=
+atomic { breakstate = Follow; trapped[Break] = 0; trapped[Follow] = 1 }
+@
+
+It's necessary to keep track of the state of each thread with respect
+to the breakpoint. A thread is ``in the breakpoint'' if it has
+trapped at [[Break]], and it does not ``leave the breakpoint'' until
+it traps at [[Follow]]. Threads are initially outside the breakpoint.
+<<declarations>>=
+bit inbreak[NTHREADS];
+<<initialize data for thread [[id]]>>=
+inbreak[id] = 0;
+@
+\semifilbreak{2in} % page tuning
+@
+One possible implementation just keeps track of the various states and
+delivers a breakpoint event at the right time:
+<<candidate breakpoint implementation>>=
+proctype breakpoint() {
+ threadid id;
+
+ do
+ :: trap?id ->
+ if
+ :: breakstate == Break ->
+ if
+ :: !inbreak[id] -> breakaction!id ; inbreak[id] = 1
+ :: inbreak[id] -> skip /* no event */
+ fi;
+ <<move traps to [[Follow]]>>
+ :: breakstate == Follow ->
+ if
+ :: inbreak[id] -> inbreak[id] = 0
+ :: !inbreak[id] -> skip
+ fi;
+ <<move traps to [[Break]]>>
+ fi;
+ resume!x
+ od
+}
+@
+This implementation works fine for a single thread.
+With two threads, the PROMELA state-space search finds the
+following erroneous execution sequence
+(attempted executions that trap are marked with a {*}):
+\begin{quote}\single
+\begin{tabular}{llcc}
+breakpoint (debugger)& CPU & thread 0 & thread 1\\
+& & [[Outside]]\\
+& & [[Break]]\rlap{*}\\
+%\multicolumn{3}{l}
+{\LA{}take breakpoint action\RA{}}\\
+{\LA{}move traps to [[Follow]]~\footnotesize\pageref{move-traps-page}\RA{}}\\
+resume\\
+&context switch\\
+ &&& [[Outside]]\\
+ &&& [[Break]]\\
+ &&& [[Follow]]\rlap{*}\\
+%\multicolumn{3}{l}
+{\LA{}take no action\RA{}}\\
+{\LA{}move traps to [[Break]]~\footnotesize\pageref{move-traps-page}\RA{}}\\
+resume\\
+ &&& [[Outside]]\\
+&context switch\\
+ && [[Follow]]\\
+ && [[Outside]]\\
+\end{tabular}
+\end{quote}
+In this execution sequence, thread~1 goes through the breakpoint
+without triggering a breakpoint action.
+In an earlier version of {\tt ldb}, this sequence could be provoked by
+executing a procedure call after the user's program hit a breakpoint;
+the user's program was thread~0, and the procedure call was thread~1.
+
+%%%% \semifilbreak{3in} % page tuning
+To prevent such an occurrence, the CPU must not be permitted to change
+contexts when a thread is in the middle of a breakpoint.
+If the CPU can change contexts only when [[noswitch == 0]], then the
+following breakpoint implementation works correctly.
+<<proctypes>>=
+proctype breakpoint() {
+ threadid id;
+
+ do
+ :: trap?id ->
+ if
+ :: breakstate == Break ->
+ if
+ :: !inbreak[id] -> breakaction!id ; inbreak[id] = 1
+ :: inbreak[id] -> assert(0)
+ fi;
+ noswitch = noswitch + 1;
+ <<move traps to [[Follow]]>>
+ :: breakstate == Follow ->
+ if
+ :: inbreak[id] -> inbreak[id] = 0
+ :: !inbreak[id] -> assert(0)
+ fi;
+ noswitch = noswitch - 1;
+ <<move traps to [[Break]]>>
+ fi;
+ resume!x
+ od
+}
+@ \noindent The ban on context switching makes it possible to strengthen
+ [[skip]] to [[assert(0)]].
+
+[[noswitch]] is declared to be a counter, not a bit, because that
+implementation generalizes to multiple breakpoints.
+<<declarations>>=
+byte noswitch = 0;
+@
+\semifilbreak{1.6in} % page tuning
+@
+The CPU code to do the context switching correctly is:
+<<possible context switch (change of [[id]])>>=
+if
+:: noswitch == 0 -> <<set [[id]] randomly>>
+:: noswitch > 0 -> skip
+fi
+<<set [[id]] randomly>>=
+atomic {
+ if
+ :: id = 0
+ :: id = 1
+ fi
+}
+@
+\section{Completing the model}
+The boilerplate needed to turn the model into
+a complete PROMELA specification is:
+<<*>>=
+<<declarations>>
+<<proctypes>>
+init {
+ threadid id;
+ atomic {
+ <<initialization>>
+ <<for $0 \le \tt id < NTHREADS$, initialize data for thread [[id]]>>;
+ run thread(0);
+ run thread(1);
+ run debugger();
+ run breakpoint();
+ run CPU (2)
+ }
+}
+@ \semifilbreak{1in}
+<<for $0 \le \tt id < NTHREADS$, initialize data for thread [[id]]>>=
+id = 0;
+do
+:: id < NTHREADS -> <<initialize data for thread [[id]]>>
+ if
+ :: id == NTHREADS - 1 -> break
+ :: id < NTHREADS - 1 -> id = id + 1
+ fi
+od
+@
+}
+@
+\section{List of chunks}
+\nowebchunks
diff --git a/web/noweb/examples/compress.nw b/web/noweb/examples/compress.nw
new file mode 100644
index 0000000000..9c24df13fe
--- /dev/null
+++ b/web/noweb/examples/compress.nw
@@ -0,0 +1,1637 @@
+\title{Transparent on-the-fly data compression {\tt COS595}}
+\author{Matthias Blume\\
+Dept.\ of Computer Science, Princeton University,\\
+Princeton, NJ 08544}
+
+\maketitle
+
+\tableofcontents
+
+\section{Introduction}
+
+The C library on UNIX provides functions for calling the operating
+system.
+Replacing those functions can provide a different program functionality
+without the need to make changes to the program text.
+
+Replacing the functions [[open]], [[creat]], [[close]], [[read]] and
+[[write]] along with a couple of other routines will change the file
+system interface.
+Since on today's computer systems most information are stored with a
+high redundancy, it seems to be useful to apply data compression
+algorithms to them.
+If the compression and uncompression is done by the file system
+interface itself, then it will become transparent to the programs
+using it.
+
+Although a truly general solution can only be done in the file system
+itself, it is nevertheless possible to approximate this to a high
+degree within the C library.
+I will show a sample implementation, which does this.
+
+\section{System call substitutes}
+
+Since I am going to replace the functions [[open]], [[read]],
+[[write]] etc. by my own versions, I will not be able to use them to do
+actual input and output.
+Therefore it is necessary to write new versions of the original C
+library function.
+The only things to change are the {\em names} of those routines.
+
+The following program text gives the implementation for MIPS-based
+machines.
+By using the {\em m4} macro processor, which is available on
+most UNIX systems, I take advantage of the fact, that the sequences of
+instructions needed for any of the functions follow a
+common pattern.
+
+<<mips-asm.m>>=
+# include <sys/syscall.h>
+# include <regdef.h>
+
+ .text
+
+ .globl _cerror
+
+define(sc,`
+ .globl _sys_$1
+ .ent _sys_$1
+_sys_$1:
+ li v0, SYS_$1
+ syscall
+ beq a3, zero, 9f
+ j _cerror
+9:$2
+ j ra
+ .end')
+
+sc(open)
+sc(creat)
+sc(close)
+sc(read)
+sc(write)
+sc(dup)
+sc(lseek)
+sc(pipe,` sw v0, 0 (a0)
+ sw v1, 4 (a0)')
+@
+The Second argument of the [[sc]] macro is necessary to implement the
+[[pipe]] system call, because it has to store two file descriptors
+into locations given as the argument of the call.
+
+@
+\section{Overall structure}
+
+My new versions of the file system interface functions are implemented
+in the file [[compress.c]].
+The structure of the file can be described as follows:
+
+<<compress.c>>=
+<<include files>>
+<<constant definitions>>
+<<type definitions>>
+<<external prototypes>>
+<<static prototypes>>
+<<static definitions>>
+<<initialization>>
+<<write compressed>>
+<<read compressed>>
+<<other io-substitutes>>
+<<replaced system calls>>
+@
+The necessary system header files are:
+
+<<include files>>=
+# include <stdlib.h>
+# include <stdio.h>
+# include <string.h>
+# include <assert.h>
+# include <fcntl.h>
+# include <errno.h>
+@
+
+\section{Replacing system calls}
+
+In this implementation I will give substitutes for the following
+functions:
+\begin{itemize}
+\item
+[[creat]] - creates a new file or truncates it to 0 bytes; opens for
+writing
+\item
+[[open]] - opens an existing file for reading or writing
+\item
+[[close]] - releases the association between a file descriptor and the
+corresponding file
+\item
+[[read]] - reads a number of bytes from an open file into a given buffer
+\item
+[[write]] - writes a number of bytes from a given buffer to an open file
+\item
+[[dup]] - duplicates a file descriptor
+\item
+[[lseek]] - provides random access to arbitrary positions within an
+open file (if supported)
+\item
+[[tell]] - this is not a true system call and could be simulated by
+[[lseek]]; it returns the current position in the file
+\item
+[[pipe]] - opens an inter-process communication channel known as a
+{\em pipe}; returns two file descriptors, one for reading from the
+pipe, one for writing into the pipe
+\end{itemize}
+
+The real file system interface will be driven by the external
+functions:
+<<external prototypes>>=
+extern _sys_open (const char *, int);
+extern _sys_creat (const char *, int);
+extern int _sys_close (int);
+extern int _sys_read (int, char *, int);
+extern int _sys_write (int, const char *, int);
+extern int _sys_dup (int fd);
+extern long _sys_lseek (int fd, long offset, int whence);
+extern int _sys_pipe (int [2]);
+@
+and the replaced system call functions are:
+<<replaced system calls>>=
+<<replaced creat>>
+<<replaced open>>
+<<replaced close>>
+<<replaced read>>
+<<replaced write>>
+<<replaced dup>>
+<<replaced tell>>
+<<replaced lseek>>
+<<replaced pipe>>
+@
+Data compression and uncompression will be done by the Lempel-Ziv
+algorithm.
+It is necessary to maintain several independent compression- or
+un\-com\-pres\-sion-``engines'', because there can be many files open.
+There is no fixed relationship between the number of characters read
+from or written to the real file system and the number of characters
+seen by the program.
+This means, both compression and uncompression must be able to stop
+``in the middle of the operation''.
+All the relevant variables, which constitute the ``state'' of the
+``engine'' have to be saved in a data structure, which in turn has to
+be associated with the file descriptor.
+
+The existence of the [[dup]] system call introduces some further requirements
+on the implementation.
+Basically this means, that the same ``engine'' can be associated with
+more than one file descriptor.
+
+Currently I restrict myself to at most [[MAXFILES]] open files.
+This can easily be changed by using [[getdtablesize]] to find out the
+maximum number of open files allowed by the operating system.
+
+<<constant definitions>>=
+# define MAXFILES 256
+@
+The states of ``engines'' are stored in structures of type [[struct cfd]].
+
+<<type definitions>>=
+typedef struct cfd *cfd;
+
+struct cfd {
+ struct methods *methods;
+ int nbits;
+ int shared;
+ <<other cfd members>>
+};
+@
+One crucial idea to deal with the complexity of the problem is to
+adopt some ``object-oriented'' techniques.
+I use the member [[methods]] to point to a collection of function
+pointers.
+Depending on whether a file is read or written, compressed or plain, I
+need different algorithms to access the file.
+Using the table of [[methods]] allows to do this without complicated
+{\em if-then-else} chains all over the place.
+
+<<type definitions>>=
+struct methods {
+ int (* read) (int, unsigned char *, int);
+ int (* write) (int, unsigned char *, int);
+ int (* close) (int);
+ long (* seek) (int, long, int);
+};
+@
+There will be a global file table [[filetab]], indexed by file
+descriptors, which contains pointers to structures of type [[struct cfd]].
+The contents of this table at a given position depends on the mode of
+operation used with the file descriptor under question.
+Possible modes are:
+\begin{itemize}
+\item
+the file is a plain file (no compression or uncompression)
+\item
+the file is written using compression
+\item
+the file is read using uncompression
+\item
+the file is opened for reading, but it is still unclear, whether it is
+compressed or not
+\item
+the file is opened for reading; the ``engine'' found, that the file is
+not compressed by reading the first few characters of the file;
+the program has not asked yet for all of those pre-read characters
+\item
+the file is unknown to the interface module---this usually happens, if
+the file descriptor is inherited from a parent process (e.g. the
+shell)
+\end{itemize}
+
+Descriptors for plain files and unknown file descriptors are
+passed directly to the real system calls.
+Therefore, these two modes are represented the same: by a [[NULL]]
+pointer in the corresponding position of the file table.
+
+We need two different method tables for reading or writing in
+compressed mode.
+A third table is necessary to deal with the remaining modes of operation.
+A compressed file is recognized by the first three characters in the
+file, which are known as the [[compress_prefix]].
+
+<<static definitions>>=
+<<file table>>
+<<method tables>>
+<<compress prefix>>
+@
+
+<<compress prefix>>=
+static unsigned char compress_prefix [] = { 0x1f, 0x9d, 0x10 };
+@
+
+<<file table>>=
+static cfd filetab [MAXFILES] = { NULL, };
+@
+The three collections of methods are:
+
+<<method tables>>=
+<<write-compressed table>>
+<<read-compressed table>>
+<<initial read table>>
+@
+For writing:
+
+<<write-compressed table>>=
+static struct methods cw_m = {
+ refuse_io,
+ write_compressed,
+ close_compressed_write,
+ refuse_seek,
+};
+@
+For reading:
+
+<<read-compressed table>>=
+static struct methods cr_m = {
+ read_compressed,
+ refuse_io,
+ close_compressed_read,
+ refuse_seek,
+};
+@
+For deciding, whether to read a compressed or a plain file:
+
+<<initial read table>>=
+static struct methods ir_m = {
+ read_prefix,
+ refuse_io,
+ close_prefix_read,
+ prefix_seek,
+};
+@
+To define the above tables, I need the following prototype definitions:
+
+<<static prototypes>>=
+static int read_compressed (int fd, unsigned char *buf, int n);
+static int read_prefix (int fd, unsigned char *buf, int n);
+static int write_compressed (int fd, unsigned char *buf, int n);
+static int refuse_io (int fd, unsigned char *buf, int n);
+
+static int close_compressed_read (int fd);
+static int close_prefix_read (int fd);
+static int close_compressed_write (int fd);
+
+static long refuse_seek (int fd, long offset, int whence);
+static long prefix_seek (int fd, long offset, int whence);
+@
+In order not to confuse other programs started by a combination of
+[[fork]] and [[exec]], I always use the real system call along with
+the replaced one.
+Therefore, the indices into [[filetab]] are real file descriptors
+provided by the operating system.
+
+[[creat]] always sets the mode of operation to ``write with
+compression'' by using the methods [[cw_m]].
+
+As a general rule, I set the member [[nbits]] to zero when opening a
+file.
+This signals, that the data structures have not been fully initialized yet.
+
+The member [[shared]] counts the number of [[filetab]] entries, which
+point to the same data structure.
+The routines for closing a file will use this to determine,
+whether the last connection to the file will be closed.
+Only in this case I can perform cleanup operations like freeing the
+data structures associated with the file.
+
+<<replaced creat>>=
+int creat (const char *path, int mode)
+{
+ int fd;
+
+ init ();
+
+ fd = _sys_creat (path, mode);
+
+ if (fd < 0 || fd > MAXFILES ||
+ (filetab [fd] = malloc (sizeof (struct cfd))) == NULL)
+ return fd;
+
+ filetab [fd]->nbits = 0;
+ filetab [fd]->methods = &cw_m;
+
+ filetab [fd]->shared = 1;
+
+ return fd;
+}
+@
+Opening a file for writing using [[open]] assumes, that the file
+already exists.
+Therefore it is not useful to write with compression, because the
+compressed data will interfere with what has already been in the file.
+As a consequence I leave the entry in [[filetab]] unchanged.
+
+It turns out, that new versions of the C library don't use [[creat]],
+but call [[open]] with some additional flags and parameters as
+specified by [[POSIX]].
+This means, that I have to simulate the desired behavior by calling
+[[creat]] from within [[open]] if necessary.
+
+Opening a file for reading is the most complex case.
+At some time I need to read the first few characters of the file to
+decide, whether the file is compressed or not.
+The most natural place to do this seems to be the [[open]] routine.
+Unfortunately, this would violate the semantics of [[open]].
+(Imagine opening a terminal file for reading!)
+The decision has to be delayed until the first call to [[read]] will
+be executed.
+[[open]] sets the mode of operation to ``unclear, whether to use
+decompression'' by using the method table [[ir_m]].
+
+<<replaced open>>=
+int open (const char *path, int how, int mode)
+{
+ int fd;
+
+ if (how == (O_WRONLY | O_CREAT | O_TRUNC))
+ return creat (path, mode);
+
+ init ();
+
+ fd = _sys_open (path, how);
+ if (fd < 0 || fd > MAXFILES || how != 0)
+ return fd;
+
+ if ((filetab [fd] = malloc (sizeof (struct cfd))) == NULL)
+ return fd;
+
+ filetab [fd]->nbits = 0;
+ filetab [fd]->methods = &ir_m;
+ filetab [fd]->shared = 1;
+
+ return fd;
+}
+@
+Most of the remaining substitutes for system call functions follow a
+common pattern:
+\begin{itemize}
+\item
+look, if the file descriptor points to non-[[NULL]] in [[filetab]]
+\item
+if not, then simply use the original system call
+\item
+otherwise call the appropriate function from the methods table
+\end{itemize}
+
+<<replaced close>>=
+int close (int fd)
+{
+ return (fd < 0 || fd > MAXFILES || filetab [fd] == NULL)
+ ? _sys_close (fd)
+ : (* filetab [fd]->methods->close) (fd);
+}
+@
+
+<<replaced read>>=
+int read (int fd, char *buf, int n)
+{
+ return (fd < 0 || fd > MAXFILES || filetab [fd] == NULL)
+ ? _sys_read (fd, buf, n)
+ : (* filetab [fd]->methods->read) (fd, (unsigned char *) buf, n);
+}
+@
+
+<<replaced write>>=
+int write (int fd, const char *buf, int n)
+{
+ return (fd < 0 || fd > MAXFILES || filetab [fd] == NULL)
+ ? _sys_write (fd, buf, n)
+ : (* filetab [fd]->methods->write) (fd, (unsigned char *) buf, n);
+}
+@
+[[dup]] simply copies, what is in [[filetab]] at a given place to
+another place.
+The [[cfd]]-member [[shared]] must be incremented.
+
+<<replaced dup>>=
+int dup (int fd)
+{
+ int res = _sys_dup (fd);
+
+ if (fd < 0 || fd > MAXFILES || filetab [fd] == NULL)
+ return res;
+ assert (res < MAXFILES);
+ assert (filetab [res] == NULL);
+ filetab [res] = filetab [fd];
+ filetab [res]->shared++;
+ return res;
+}
+@
+[[lseek]], again, follows the general pattern.
+There is one minor variation: if the arguments indicate, that no
+actual repositioning is asked for, [[tell]] gets called.
+
+<<replaced lseek>>=
+long lseek (int fd, long offset, int whence)
+{
+ if (offset == 0 && whence == 1)
+ return tell (fd);
+ return (fd < 0 || fd > MAXFILES || filetab [fd] == NULL)
+ ? _sys_lseek (fd, offset, whence)
+ : (* filetab [fd]->methods->seek) (fd, offset, whence);
+}
+@
+[[tell]] is not a real system call.
+I simulate it using [[lseek]] if necessary.
+For files in compressed mode I keep track of the file position myself.
+Note, that [[filepos]] is not initialized until the first [[read]] from
+or [[write]] to the file has been executed.
+
+<<other cfd members>>=
+long filepos;
+@
+
+<<replaced tell>>=
+long tell (int fd)
+{
+ return (fd < 0 || fd > MAXFILES || filetab [fd] == NULL)
+ ? _sys_lseek (fd, 0L, 1)
+ : (filetab [fd]->nbits < MINBITS)
+ ? 0
+ : filetab [fd]->filepos;
+}
+@
+Since [[pipe]] creates two file descriptors, I have to deal with two
+entries in [[filetab]].
+Writing to the pipe will be performed in compressed mode.
+This seems to imply, that reading has to use compressed mode as well,
+but this is not the case.
+The most common case of using pipes is in the context of [[fork]] and
+[[exec]].
+It is very likely, that the pipe will be written by another program,
+and I have to check, whether this program uses compression or not.
+
+<<replaced pipe>>=
+int pipe (int fd [2])
+{
+ cfd p0, p1;
+
+ init ();
+
+ if (_sys_pipe (fd) < 0)
+ return -1;
+
+ if (fd [0] > MAXFILES || fd [1] > MAXFILES)
+ return 0;
+ p0 = malloc (sizeof (struct cfd));
+ if (p0 == NULL)
+ return 0;
+ p1 = malloc (sizeof (struct cfd));
+ if (p1 == NULL) {
+ free (p0);
+ return 0;
+ }
+
+ p0->nbits = p1->nbits = 0;
+ p0->methods = &ir_m;
+ p1->methods = &cw_m;
+ p0->shared = p1->shared = 1;
+
+ filetab [fd [0]] = p0;
+ filetab [fd [1]] = p1;
+
+ return 0;
+}
+@
+
+\section{Initialization}
+
+The library function [[atexit]] provides a way to register a function,
+which will be called, when the program exits (i.e. when it calls [[exit]]).
+I use this to register a function, which closes all the open files
+found in [[filetab]].
+
+As you might have noticed, [[init]] will be called from any of the
+functions, which create non-[[NULL]] entries in [[filetab]].
+
+<<initialization>>=
+static void cleanup (void)
+{
+ int i;
+
+ for (i = 0; i < MAXFILES; i++)
+ if (filetab [i] != NULL)
+ (* filetab [i]->methods->close) (i);
+}
+@
+The registration of [[cleanup]] will be done exactly once.
+
+<<initialization>>=
+static void init (void)
+{
+ static int initialized = 0;
+
+ if (initialized == 0) {
+ atexit (cleanup);
+ initialized = 1;
+ }
+}
+@
+
+\section{Compression}
+
+Compression employs the adaptive Lempel-Ziv algorithm.
+Tables are constructed as data are written.
+Every sequence of characters ever seen by the algorithm (which uses a
+greedy heuristic to construct these sequences) is associated with a
+unique code.
+The [[cfd]]-member [[nextcode]] always holds the next available code
+to be associated with the next sequence.
+Because the algorithm writes data, which are not always aligned to
+byte-boundaries, I have to use a buffer, the size of which is a
+multiple of the current code size [[nbits]] and a multiple of eight.
+Since the maximum code size is sixteen, a buffer of at most 16 bytes
+is required.
+
+<<constant definitions>>=
+# define TABSIZE 8192
+# define MAXBITS 16
+# define MINBITS 9
+# define FIRSTCODE 256
+@
+
+I use [[struct cfd]] for both compress and uncompress.
+Some of the members in [[struct cfd]] are only used for either
+compression or uncompression, and not for both.
+In order to save some space, these members are placed into a union.
+
+<<other cfd members>>=
+unsigned long nextcode;
+unsigned char buf [MAXBITS];
+int bitpos;
+union {
+ struct {
+ <<compress-only members>>
+ } c;
+ struct {
+ <<uncompress-only members>>
+ } d;
+} u;
+@
+[[lastcode]] holds the code of the character sequence seen so far.
+[[codes]] is a hashtable, which is used to describe the mapping of
+strings to codes.
+
+<<compress-only members>>=
+struct centry **codes;
+unsigned long lastcode;
+@
+The hashtable used by this algorithm has fixed size and uses chaining
+to deal with collisions.
+The data structure for the chaining is described by:
+
+<<type definitions>>=
+struct centry {
+ unsigned short w;
+ unsigned char c;
+ unsigned short code;
+ struct centry *next;
+};
+@
+Here, [[w]] is the code for the string without the last character,
+[[c]] is the last character, [[code]] is the code for this sequence
+and [[next]] holds the next entry of the chain.
+
+<<write compressed>>=
+<<hashtable management>>
+<<writing bits>>
+<<writing character arrays>>
+<<finish writing>>
+@
+This is the hashtable management:
+
+<<hashtable management>>=
+<<hash function>>
+<<hashtable lookup>>
+@
+
+<<hash function>>=
+# define hash(x,y) (((x)<<8|(y))%TABSIZE)
+@
+There is not very much to say about hashtable lookup.
+The only important thing to note is, that I use a ``move-to-front''
+heuristic to speed things up.
+
+<<hashtable lookup>>=
+static struct centry *lookup (cfd fd, unsigned char c)
+{
+ unsigned lc = fd->u.c.lastcode;
+ struct centry **start =
+ &fd->u.c.codes [hash(lc, c)];
+ struct centry **cur = start;
+ struct centry *tmp;
+
+ while (*cur != NULL && ((*cur)->w != lc || (*cur)->c != c))
+ cur = & (*cur)->next;
+ if (*cur == NULL)
+ return NULL;
+ else {
+ tmp = *cur;
+ *cur = tmp->next;
+ tmp->next = *start;
+ *start = tmp;
+ return tmp;
+ }
+}
+@
+In order to write a number of bits it is necessary to use the [[buf]]
+member of the [[cfd]] structure, because I cannot write fractions of a
+byte.
+It is just a matter of shifting and masking bits correctly...
+
+I give the description of [[invmask]] here, although it is used only
+later for reading bits.
+
+<<writing bits>>=
+# define mask(x,n) ((x) & (~(~0 << (n))))
+# define invmask(x,n) ((x) & (~0 << (n)))
+@
+
+<<writing bits>>=
+static int output (cfd fd, int ifd)
+{
+ unsigned char *byte = fd->buf + fd->bitpos / 8;
+ int bit = fd->bitpos % 8;
+ unsigned code = fd->u.c.lastcode;
+
+ *byte = mask (*byte, bit) | code << bit;
+ byte++;
+ code >>= 8 - bit;
+ if (fd->nbits + bit > 16) {
+ *byte++ = code;
+ code >>= 8;
+ }
+ *byte = code;
+ fd->bitpos += fd->nbits;
+ if (fd->bitpos == 8 * fd->nbits) {
+ if (_sys_write (ifd, (char *) fd->buf, fd->nbits) < 0)
+ return -1;
+ fd->bitpos = 0;
+ }
+ return fd->bitpos;
+}
+@
+To be able to write arbitrary arrays of characters I need to suspend
+compression not after a certain amount of characters {\em written}, but
+after any amount of characters {\em seen}.
+This means, that character sequences, which are collapsed into one
+code, may extend across multiple calls to [[write]].
+
+[[write]] checks first, whether this is the very first call to
+[[write]] for this file and initializes the data structures.
+Remember, that [[creat]] and [[pipe]] set [[nbits]] to zero to
+indicate this situation.
+
+After using all possible codes no further entries to the hashtable are
+made---[[write]] has to live with what is in the table.
+
+<<writing character arrays>>=
+static int write_compressed (int ifd, unsigned char *buf, int n)
+{
+ cfd fd = filetab [ifd];
+ int i, h;
+ struct centry *tmp;
+ unsigned char c;
+
+ if (n == 0)
+ return 0;
+
+ <<write initialization>>
+
+ while (i-- > 0) {
+ c = *buf++;
+
+ if ((tmp = lookup (fd, c)) == NULL) {
+
+ <<output code for prefix>>
+ <<add code to table if necessary>>
+
+ fd->nextcode++;
+ fd->u.c.lastcode = c;
+
+ } else
+ fd->u.c.lastcode = tmp->code;
+ }
+
+ fd->filepos += n;
+
+ return n;
+}
+@
+A value of zero in [[nbits]] indicates, that the data structures have to be
+initialized.
+
+<<write initialization>>=
+if (fd->nbits == 0) {
+ if (_sys_write (ifd, (char *) compress_prefix,
+ sizeof (compress_prefix)) < 0)
+ return -1;
+ fd->nbits = MINBITS;
+ fd->nextcode = FIRSTCODE;
+ fd->bitpos = 0;
+ fd->u.c.codes = malloc (TABSIZE * sizeof (struct centry *));
+ if (fd->u.c.codes == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ for (i = 0; i < TABSIZE; i++)
+ fd->u.c.codes [i] = NULL;
+ fd->filepos = 0;
+ fd->u.c.lastcode = *buf++;
+ i = n - 1;
+} else
+ i = n;
+@
+<<output code for prefix>>=
+if (output (fd, ifd) < 0)
+ return -1;
+@
+As long as not all the possible codes have been used, codes for new
+sequences have to be introduces.
+
+<<add code to table if necessary>>=
+if (fd->nextcode < (1L << MAXBITS)) {
+ if ((tmp = malloc (sizeof (struct centry))) == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ tmp->w = fd->u.c.lastcode;
+ tmp->c = c;
+ tmp->code = fd->nextcode;
+
+ if (fd->nextcode == (1L << fd->nbits)) {
+ if (fd->bitpos > 0) {
+ if (_sys_write (ifd, (char *) fd->buf, fd->nbits) < 0)
+ return -1;
+ fd->bitpos = 0;
+ }
+ fd->nbits++;
+ }
+
+ h = hash (fd->u.c.lastcode, c);
+ tmp->next = fd->u.c.codes [h];
+ fd->u.c.codes [h] = tmp;
+}
+@
+
+An important thing to note, is that I cannot simply close a file using
+the operating system call.
+It may be the case (in fact, it is always the case) that there is
+still some accumulated code in [[lastcode]] that wants to be written
+out.
+I have to make sure, that I only really close the file, if the last
+reference to this file is going to be abandoned.
+
+Unlike during a switch from [[nbits]] to [[nbits]]+1, where I always
+flush the {\em entire} buffer [[buf]] (up to [[nbits]] bytes), I write
+only those parts of [[buf]] which really contain written bits when
+closing the file.
+This provides the necessary information about the end of the file to
+the uncompression algorithm.
+
+<<finish writing>>=
+static int close_compressed_write (int ifd)
+{
+ cfd fd = filetab [ifd];
+ int res, i;
+ struct centry *run, *next;
+
+ if (--fd->shared == 0 && fd->nbits > 0) {
+ for (i = 0; i < TABSIZE; i++)
+ if ((run = fd->u.c.codes [i]) != NULL)
+ do {
+ next = run->next;
+ free (run);
+ run = next;
+ } while (run != NULL);
+ free (fd->u.c.codes);
+ if (output (fd, ifd) < 0)
+ return -1;
+ if (fd->bitpos > 0 &&
+ _sys_write (ifd,
+ (char *) fd->buf,
+ (fd->bitpos + 7) / 8)
+ < 0)
+ return -1;
+ }
+ res = _sys_close (ifd);
+ if (fd->shared == 0)
+ free (fd);
+ filetab [ifd] = NULL;
+ return res;
+}
+@
+
+\section{Uncompression}
+
+The algorithm to uncompress compressed files looks a little bit more
+complicated.
+First, I need a stack (described by the members [[stack]],
+[[stacktop]] and [[stacksize]]) to reverse the sequence of characters,
+which I obtain from a code.
+The stack is realized as a rubber-band array, which is automatically
+expanded when necessary.
+Furthermore, [[buflen]] keeps track of the number of characters, which have
+actually been read from the file system---fewer characters than
+[[nbits]] indicate the end of the file.
+[[oldcode]] holds the last code that has been read and [[finchar]] is the
+final character produced from the last code.
+This is necessary to deal correctly with the {\em
+``AwAwA''}-phenomenon, where a code can be read, which is not in the
+table yet.
+
+The ``hashtable'' [[htab]] is a rubber-band array which contains for
+each code the associated prefix (i.e. the code for the string without
+the last character) together with that last character.
+Since entries are made in a sequential order, it is not
+necessary to use a hash function.
+The entry for a code {\em k} is at position {\em k-256}, because the
+first codes 0-255 stand for themselves and don't need to be stored
+into the table.
+
+Here are the missing members of [[struct cfd]]:
+
+<<uncompress-only members>>=
+long tabsize;
+struct { unsigned w; unsigned char c; } *htab;
+unsigned stacksize;
+unsigned stacktop;
+unsigned char *stack;
+int buflen;
+unsigned short oldcode;
+unsigned char finchar;
+@
+Uncompression is split into the following tasks:
+
+<<read compressed>>=
+<<stack management>>
+<<reading bits>>
+<<reading the first few bytes>>
+<<reading compressed files>>
+<<finish reading>>
+@
+The stack management maintains a rubber band array.
+The array can only expand, therefore ``popping'' items from the stack
+can be ``in-lined''.
+[[push]] is more complicated and gets its own function:
+
+<<constant definitions>>=
+# define STACKGROWTH 64
+@
+
+<<stack management>>=
+static int push (cfd fd, unsigned char c)
+{
+ if (fd->u.d.stacktop >= fd->u.d.stacksize) {
+ fd->u.d.stacksize += STACKGROWTH;
+ if ((fd->u.d.stack =
+ realloc (fd->u.d.stack, fd->u.d.stacksize))
+ == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+ fd->u.d.stack [fd->u.d.stacktop++] = c;
+ return 0;
+}
+@
+Reading the bits into the buffer is a little bit more trickier than
+writing.
+Consider a pipe: If the pipe contains fewer characters than required,
+then only those bytes are delivered.
+The system call blocks for empty pipes only.
+Therefore [[refill_buffer]] repeats the call to [[_sys_read]] until
+either the buffer is completely filled or [[_sys_read]] signals
+end-of-file or an error condition.
+
+<<reading bits>>=
+static int refill_buffer (cfd fd, int ifd)
+{
+ int n, r;
+
+ n = 0;
+ r = 0;
+ while (n < fd->nbits &&
+ (r = _sys_read (ifd,
+ (char *) (fd->buf + n),
+ fd->nbits - n))
+ > 0)
+ n += r;
+ if (r < 0)
+ return -1;
+ fd->u.d.buflen = 8 * n;
+ fd->bitpos = 0;
+ return 0;
+}
+@
+The [[input]]-function is very much like [[output]], except that it
+has to return an end-of-file condition when the end of the file has
+been reached.
+I use -1 to signal the end of the file and -2 to signal an error.
+[[buflen]] is used to describe, what is really in the buffer (the
+number of bits).
+
+<<reading bits>>=
+static int input (cfd fd, int ifd)
+{
+ unsigned char *byte;
+ int bit;
+ unsigned code;
+
+ if (fd->bitpos + fd->nbits > fd->u.d.buflen) {
+ if (refill_buffer (fd, ifd))
+ return -2;
+ if (fd->u.d.buflen == 0)
+ return -1;
+ }
+ byte = fd->buf + fd->bitpos / 8;
+ bit = fd->bitpos % 8;
+ code = invmask (*byte, bit) >> bit;
+ byte++;
+ bit = 8 - bit;
+ if (fd->nbits - bit >= 8) {
+ code |= *byte++ << bit;
+ bit += 8;
+ }
+ code |= mask (*byte, fd->nbits - bit) << bit;
+ fd->bitpos += fd->nbits;
+
+ return code;
+}
+@
+There is still the problem, that [[read]] has to check first, whether
+the contents of the file is compressed or not.
+If [[read]] detects, that the file is not compressed, than it has to
+arrange for {\em all} file descriptors associated with the file, that
+it is read using the plain operating system call.
+This is done using the function [[mark_uncompressed]].
+
+<<reading the first few bytes>>=
+static void mark_uncompressed (cfd fd)
+{
+ int i;
+
+ for (i = 0; i < MAXFILES; i++)
+ if (filetab [i] == fd)
+ filetab [i] = NULL;
+ free (fd);
+}
+@
+The first attempt to read a file will be used to check, whether the
+file is compressed.
+To do this, I try to read the first three characters in the file and
+compare them with [[compress_prefix]].
+If I don't get three characters or if those characters do not coincide
+with [[compress_prefix]], then the file is considered to be not
+compressed.
+Otherwise I simply change the method table to be [[cr_m]] and call
+[[read_compressed]].
+
+In the case that the file is not compressed, the characters read are
+part of the data and have to be placed into the buffer, which is the
+argument to read.
+After doing so, the file has to be marked being uncompressed.
+If [[read]] has asked for more than three characters, then
+[[_sys_read]] will try to get those.
+
+Difficulties arise, if [[read]] had asked for fewer characters than
+received by the first [[_sys_read]].
+These characters have to be kept for further calls to [[read]].
+(To reset the file pointer to the beginning might be impossible,
+because the file can be a terminal device or a pipe.)
+I set [[nbits]] to 1 to indicate, that the file has already proven to
+be in uncompressed state.
+In this case [[read_prefix]] fetches the characters from the buffer
+instead of reading them from the file system.
+When all the characters are ``eaten up'' I mark the file as being
+uncompressed.
+
+<<reading the first few bytes>>=
+static int read_prefix (int ifd, unsigned char *buf, int n)
+{
+ cfd fd = filetab [ifd];
+ int l;
+
+ if (n == 0)
+ return 0;
+
+ if (fd->nbits == 0) {
+ if ((l = _sys_read (ifd,
+ (char *) fd->buf,
+ sizeof compress_prefix))
+ < 0)
+ return -1;
+ if (l == sizeof (compress_prefix) &&
+ memcmp (fd->buf,
+ compress_prefix,
+ sizeof compress_prefix)
+ == 0) {
+ fd->methods = &cr_m;
+ return read_compressed (ifd, buf, n);
+ }
+ fd->nbits = 1;
+ fd->filepos = 0;
+ fd->bitpos = l;
+ }
+
+ if (n < fd->bitpos - fd->filepos) {
+ memcpy (buf, fd->buf + fd->filepos, n);
+ fd->filepos += n;
+ return n;
+ }
+
+ memcpy (buf, fd->buf + fd->filepos, fd->bitpos - fd->filepos);
+ if (n > fd->bitpos - fd->filepos) {
+ l = _sys_read (ifd, (char *) (buf + fd->bitpos - fd->filepos),
+ n - (fd->bitpos - fd->filepos));
+ if (l < 0)
+ l = 0;
+ n = l + fd->bitpos - fd->filepos;
+ }
+
+ mark_uncompressed (fd);
+
+ return n;
+}
+@
+This is the code for reading compressed files.
+Note, that the function initialized all the relevant data structures
+if [[nbits]] equals zero.
+Later it reads codes, constructs the corresponding character strings using the
+stack and places those characters into the buffer.
+Usually there will remain some characters, which have to be kept until
+the next call to [[read]].
+The table of codes is again constructed as the algorithm goes.
+The uncompress algorithm lags always one step behind, so it may
+happen, that a code is not yet in the table.
+In this case, the sequence of characters can be reconstructed using
+[[finchar]] and [[oldcode]].
+
+<<reading compressed files>>=
+static int read_compressed (int ifd, unsigned char *buf, int n)
+{
+ cfd fd = filetab [ifd];
+ int i = n;
+ unsigned incode, c;
+ int cin;
+
+ <<read initialization>>
+
+ for (;;) {
+ <<empty the stack>>
+ <<return or read next code>>
+
+ c = incode = cin;
+
+ <<special AwAwA case handling>>
+ <<analyse code and put bytes onto stack>>
+ <<enter code to table htab>>
+
+ fd->u.d.oldcode = incode;
+ }
+}
+@
+The first time [[read]] gets called for a compressed file, the following code
+will be executed:
+
+<<read initialization>>=
+if (fd->nbits == 0) {
+ if (n == 0)
+ return 0;
+
+ fd->nbits = MINBITS;
+ fd->nextcode = FIRSTCODE;
+ fd->bitpos = 8 * MINBITS;
+ fd->filepos = 0;
+ fd->u.d.tabsize = TABSIZE;
+ if ((fd->u.d.htab =
+ malloc (TABSIZE * sizeof (*fd->u.d.htab)))
+ == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ fd->u.d.stacksize = STACKGROWTH;
+ fd->u.d.stacktop = 0;
+ if ((fd->u.d.stack = malloc (STACKGROWTH)) == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ fd->u.d.buflen = 8 * MINBITS;
+ cin = input (fd, ifd);
+ if (cin < 0)
+ return cin == -1 ? 0 : -1;
+ *buf++ = cin;
+ --i;
+ fd->u.d.oldcode = cin;
+ fd->u.d.finchar = cin;
+}
+@
+First, [[read]] has to empty the stack:
+
+<<empty the stack>>=
+while (fd->u.d.stacktop > 0 && i > 0) {
+ *buf++ = fd->u.d.stack [--fd->u.d.stacktop];
+ --i;
+}
+@
+Then it can try to get another code, if necessary:
+
+<<return or read next code>>=
+if (i == 0 || (cin = input (fd, ifd)) == -1) {
+ fd->filepos += n - i;
+ return n - i;
+}
+
+if (cin < -1)
+ return -1;
+@
+It may happen, that a code is not in the table yet.
+[[oldcode]] and [[finchar]] contain enough information to deduce, what has to
+be in the table:
+
+<<special AwAwA case handling>>=
+if (c >= fd->nextcode) {
+ if (c > fd->nextcode) {
+ errno = EIO;
+ return -1;
+ }
+ if (push (fd, fd->u.d.finchar))
+ return -1;
+ c = fd->u.d.oldcode;
+}
+@
+A code is analyzed from right to left.
+Therefore, I need to use the stack to reverse the order of the characters:
+
+<<analyse code and put bytes onto stack>>=
+while (c >= FIRSTCODE) {
+ if (push (fd, fd->u.d.htab [c - FIRSTCODE].c))
+ return -1;
+ c = fd->u.d.htab [c - FIRSTCODE].w;
+}
+fd->u.d.finchar = c;
+if (push (fd, c))
+ return -1;
+@
+Unless all possible codes are already used, I have to insert the a new code
+into the table.
+
+<<enter code to table htab>>=
+if (fd->nextcode < (1L << MAXBITS)) {
+ if (fd->nextcode - FIRSTCODE >= fd->u.d.tabsize) {
+ fd->u.d.tabsize += TABSIZE;
+ if ((fd->u.d.htab =
+ realloc (fd->u.d.htab,
+ fd->u.d.tabsize * sizeof (*fd->u.d.htab)))
+ == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+ fd->u.d.htab [fd->nextcode - FIRSTCODE].c = c;
+ fd->u.d.htab [fd->nextcode - FIRSTCODE].w = fd->u.d.oldcode;
+
+ if (fd->nextcode == (1L << fd->nbits) - 1 &&
+ fd->nbits < MAXBITS) {
+ fd->nbits++;
+ if (refill_buffer (fd, ifd))
+ return -1;
+ }
+
+ fd->nextcode++;
+}
+@
+
+Closing a file, which has been read from is not as difficult as
+closing a file which has been written to, because no buffers have to
+be flushed.
+Nevertheless, it has to take care of freeing the data structures.
+I have two different routines for closing, one for [[cr_m]], the other
+for [[ir_m]].
+
+<<finish reading>>=
+static int close_compressed_read (int ifd)
+{
+ cfd fd = filetab [ifd];
+
+ if (--fd->shared == 0) {
+ if (fd->nbits > 0) {
+ free (fd->u.d.htab);
+ free (fd->u.d.stack);
+ }
+ free (fd);
+ }
+ filetab [ifd] = NULL;
+ return _sys_close (ifd);
+}
+@
+
+<<finish reading>>=
+static int close_prefix_read (int ifd)
+{
+ cfd fd = filetab [ifd];
+
+ if (--fd->shared == 0)
+ free (fd);
+ filetab [ifd] = NULL;
+ return _sys_close (ifd);
+}
+@
+
+\section{Miscellaneous IO-substitutes}
+
+Reading from a file, that has been opened for writing or vice versa is
+not allowed.
+
+<<other io-substitutes>>=
+static int refuse_io (int fd, unsigned char *buf, int n)
+{
+ errno = EINVAL;
+ return -1;
+}
+@
+As far as [[lseek]] is concerned, a compressed file (regardless
+whether read or written) behaves like a pipe, i.e. [[lseek]] returns -1.
+
+<<other io-substitutes>>=
+static long refuse_seek (int fd, long offset, int whence)
+{
+ errno = ESPIPE;
+ return -1;
+}
+@
+An attempt to [[lseek]] a file, that is opened for reading and has not
+(yet) proven to contain compressed data, will force to treat the file
+as a plain file.
+
+<<other io-substitutes>>=
+static long prefix_seek (int ifd, long offset, int whence)
+{
+ cfd fd = filetab [ifd];
+
+ mark_uncompressed (fd);
+ return _sys_lseek (ifd, offset, whence);
+}
+@
+
+\section{Examples}
+
+The remainder of the text gives a collection of sample code, which
+provides some evidence, that the implementation is correct.
+
+I start with a simple copy program.
+The program takes one or two command line arguments the first of
+which is the input file, while the second names the output file and
+defaults to the standard output.
+
+The most interesting property of this program is, that is can be used
+both as a substitute for [[compress]] and as a replacement for
+[[uncompress]].
+Further, it will also work on plain files.
+Consider:
+\begin{itemize}
+\item
+{\tt t plain-input compressed-output}
+\item
+{\tt t compressed-input compressed-output}
+\item
+{\tt t plain-input >plain-output}
+\item
+{\tt t compressed-input >plain-output}
+\end{itemize}
+
+<<t.c>>=
+# include <stdio.h>
+# include <errno.h>
+# include <string.h>
+
+int main (int argc, char **argv)
+{
+ FILE *in, *out;
+ int c;
+
+ if (argc != 3 && argc != 2) {
+ fprintf (stderr, "Usage: %s infile [ outfile ]\n", argv [0]);
+ exit (1);
+ }
+
+ if ((in = fopen (argv [1], "r")) == NULL) {
+ fprintf (stderr, "Cannot open file %s for reading: %s\n",
+ argv [1], strerror (errno));
+ exit (1);
+ }
+ if (argc == 2)
+ out = stdout;
+ else if ((out = fopen (argv [2], "w")) == NULL) {
+ fprintf (stderr, "Cannot open file %s for writing: %s\n",
+ argv [2], strerror (errno));
+ exit (1);
+ }
+
+ while ((c = getc (in)) != EOF)
+ putc (c, out);
+
+ fclose (in);
+ fclose (out);
+
+ return 0;
+}
+@
+The next example does the same thing while not using the
+standard library.
+Instead, it calls [[open]], [[read]] etc. directly.
+
+<<v.c>>=
+# include <stdio.h>
+# include <errno.h>
+# include <string.h>
+
+int main (int argc, char **argv)
+{
+ int ifd, ofd;
+ int n;
+ char buf [4096];
+
+ if (argc != 3 && argc != 2) {
+ fprintf (stderr, "Usage: %s infile [ outfile ]\n", argv [0]);
+ exit (1);
+ }
+
+ if ((ifd = open (argv [1], 0)) < 0) {
+ fprintf (stderr, "Cannot open file %s for reading: %s\n",
+ argv [1], strerror (errno));
+ exit (1);
+ }
+ if (argc == 2)
+ ofd = 1;
+ else if ((ofd = creat (argv [2], 0666)) < 0) {
+ fprintf (stderr, "Cannot open file %s for writing: %s\n",
+ argv [2], strerror (errno));
+ exit (1);
+ }
+
+ while ((n = read (ifd, buf, 512)) > 0)
+ write (ofd, buf, n);
+
+ close (ifd);
+ close (ofd);
+
+ return 0;
+}
+@
+The next example uses [[dup]] and performs interleaved writes to both
+file descriptors.
+Of course, this isn't necessary, but it shows, that [[dup]] works as
+expected.
+
+<<u.c>>=
+# include <stdio.h>
+# include <errno.h>
+# include <string.h>
+
+int main (int argc, char **argv)
+{
+ int ifd, oofd, dofd;
+ int n;
+ char buf [512];
+
+ if (argc != 3 && argc != 2) {
+ fprintf (stderr, "Usage: %s infile [ outfile ]\n", argv [0]);
+ exit (1);
+ }
+
+ if ((ifd = open (argv [1], 0)) < 0) {
+ fprintf (stderr, "Cannot open file %s for reading: %s\n",
+ argv [1], strerror (errno));
+ exit (1);
+ }
+ if (argc == 2)
+ oofd = 1;
+ else if ((oofd = creat (argv [2], 0666)) < 0) {
+ fprintf (stderr, "Cannot open file %s for writing: %s\n",
+ argv [2], strerror (errno));
+ exit (1);
+ }
+
+ dofd = dup (oofd);
+
+ while ((n = read (ifd, buf, 512)) > 0)
+ write (oofd, buf, n / 2),
+ write (dofd, buf + n / 2, n - n / 2);
+
+ close (ifd);
+ close (oofd);
+ close (dofd);
+
+ return 0;
+}
+@
+The following program is the most complex example.
+It shows the use of pipes in the framework of [[fork]] and [[exec]].
+By two times executing [[fork]] I create a sequential arrangement of
+three processes, which are connected by two pipes.
+Pipe [[p1]] connects the {\em child} with the {\em parent}, while [[p2]]
+provides a channel from the {\em grandchild} to the {\em child}.
+
+The {\em child} starts another program by calling either [[execl]] or
+[[execvp]], depending on what command line arguments are given.
+The idea is to pipe compressed data to a {\em filter} and read it
+back.
+Simple ``filters'' like [[cat]] or [[tee]] don't change the data.
+Therefore, the {\em parent} should see, what the {\em grandchild}
+wrote in this case.
+It is worth trying to put {\tt uncompress~-C} into the place of the filter.
+(The behavior should not change, because [[read]] automatically
+detects, that the data in [[p1]] are not in compressed format.)
+
+Note, that all calls to [[fork]] and [[exec]] have to be executed {\em
+before any actual input or output takes place}.
+
+<<w.c>>=
+# include <stdio.h>
+# include <assert.h>
+# include <errno.h>
+# include <string.h>
+
+# define check(x) \
+ ((x)<0?(fprintf(stderr,"%s(%d): (%s) < 0 (%s)\n", \
+ __FILE__, __LINE__, #x, strerror(errno)), \
+ exit(1)):0)
+
+int main (int argc, char **argv)
+{
+ char buf [512];
+ int n;
+ int p1 [2], p2 [2];
+ int f;
+
+ check (pipe (p1));
+
+ check (f = fork ());
+ if (f > 0) {
+ check (close (p1 [1]));
+ while (check (n = read (p1 [0], buf, 512)), n > 0)
+ check (write (1, buf, n));
+ putc ('\n', stderr);
+ check (close (p1 [0]));
+ check (wait (NULL));
+ exit (0);
+ } else {
+ check (close (1));
+ check (dup (p1 [1]));
+ check (close (p1 [0]));
+ check (close (p1 [1]));
+
+ check (pipe (p2));
+
+ check (f = fork ());
+
+ if (f > 0) {
+ check (close (p2 [1]));
+ check (close (0));
+ check (dup (p2 [0]));
+ check (close (p2 [0]));
+
+ if (argc == 1)
+ check (execl ("/bin/cat", "cat", NULL));
+ else
+ check (execvp (argv [1], argv + 1));
+ } else {
+ check (close (p2 [0]));
+ while (check (n = read (0, buf, 512)), n > 0)
+ check (write (p2 [1], buf, n));
+ check (close (p2 [1]));
+ exit (0);
+ }
+ }
+}
+@
+A small program shows the use of pipes through the [[popen]]-interface:
+
+<<x.c>>=
+# include <stdio.h>
+
+# include <assert.h>
+
+int main (int argc, char **argv)
+{
+ FILE *fp;
+ int c;
+
+ assert (argc == 2);
+ fp = popen (argv [1], "r");
+ assert (fp != NULL);
+ while ((c = getc (fp)) != EOF)
+ putchar (c);
+ pclose (fp);
+ return 0;
+}
+@
+A final test case makes sure, that [[read_prefix]] works correctly,
+even in the case, that the number of characters asked for is less than
+the length of the [[compress_prefix]].
+The program always reads only one character at a time.
+Try to use it with a plain file and remember, how [[read]] is implemented.
+
+<<y.c>>=
+# include <assert.h>
+
+int main (int argc, char **argv)
+{
+ char c;
+ int fd;
+
+ assert (argc == 2);
+ fd = open (argv [1], 0);
+ assert (fd >= 0);
+ while (read (fd, &c, 1) == 1)
+ write (1, &c, 1);
+ close (fd);
+ return 0;
+}
+@
+
+\section{Conclusions}
+
+The examples in the previous section show, that the new file system
+interface really hides the details of data compression, thereby
+providing this service in a fashion transparent to the programs that
+use it.
+However, everything works only as long as a single program has
+complete control over an open file.
+In a multi-tasking environment like UNIX, this is generally not true.
+This puts some severe constraints onto the usage of the new interface.
+The implementation presented in this paper assumes, that files opened
+for writing by [[open]] are not compressed.
+What, if the data in that file actually {\em are} compressed?
+
+Recently, there are some efforts made to integrate data compression with
+file system implementations themselves.
+Only here one has the opportunity to know about {\em every} access to a file,
+and things can be synchronized properly.
+
+Nevertheless, the given program text can be useful in many
+circumstances.
+I, for instance, tried to integrate it with [[VSCM]], which is my
+implementation of {\em Scheme}.
+Memory dumps written by [[VSCM]] are less than half as big as before,
+and everything still works fine.
+Probably, the fact that files containing symbolic expressions are
+written in compressed mode as well is a little bit surprising and annoying.
+(This leads to the demand for a switch to turn off compression, but
+this would expose details of the implementation, which is what I
+wanted to avoid in the first place.)
+
+\section{Indexes}
+
+\subsection{Code Chunks}
+\nowebchunks
+
+\subsection{Identifiers}
+\nowebindex
diff --git a/web/noweb/examples/dag.nw b/web/noweb/examples/dag.nw
new file mode 100644
index 0000000000..06ba17dbb8
--- /dev/null
+++ b/web/noweb/examples/dag.nw
@@ -0,0 +1,163 @@
+\section{Converting trees to dags}
+The problem with the trees generated in the previous section is that
+there's a different edge, and therefore a different child, for each
+possible interval of the field tested, even if those children both
+execute exactly the same ``original'' arm of the case statement.
+The code in this section converts the trees to dags, and as part of
+the process it combines edges pointing to the same node.
+This can reduce the size of the tree by huge factors.
+
+To make the transformation work, I have to represent a {\em set of
+intervals} on each edge, not just a single interval. Because no two intervals
+overlap, I can use a wonderful dirty trick, detailed below.
+I also {\em may} convert a node's name string to a [[namearray]] mapping
+field values to strings. The goal is for children of the same
+parent to share a single name array; that way the edges can be merged and
+the name operator can be implemented with an array reference.
+If I don't convert a node's name, the only penalty is that the tree
+might be bigger.
+(Code generation will be different for the two cases.)
+@
+Now, the dirty representation trick:
+I can represent a set of numbers $S$ (a union of intervals) as two
+sets, $lo$ and $hi$, such that
+\begin{itemize}
+% l2h substitution cap <b>intersect</b>#
+% l2h substitution cup <b>union</b>#
+% l2h substitution emptyset <b>empty#set</b>
+\item[] $lo \cap hi = \emptyset$
+\item[] if ${\tt sort}(lo \cup hi) = a, b, c, d, \ldots$, then
+ $S = [a,b-1] \cup [c,d-1] \cup \ldots$.
+\end{itemize}
+The procedure [[addinterval]] adds a new interval to such a set $S$,
+relying on the fact that no two intervals overlap.
+<<*>>=
+procedure addinterval(loset, hiset, lonum, hinum)
+ if member(loset, hinum) then delete(loset, hinum) else insert(hiset, hinum)
+ if member(hiset, lonum) then delete(hiset, lonum) else insert(loset, lonum)
+ return
+end
+@
+To convert trees to dags I need to be able to compare two nodes
+for structural identity, and the easiest way is to compute a canonical
+representation as a string:\par\noindent [[
+ node : [fname:patimage(list of edges)]
+ | <NOMATCH>
+ | (image(node.name):image(node.cs.arms[1].original))
+ edge : patimage(list of sort(loset ++ hiset)):node
+]]
+<<*>>=
+procedure nodetostring(n, depth)
+ static cache
+ initial cache := table()
+ /depth := 0
+ if /cache[n] then
+ if *n.children > 0 then {
+ result := "[" || n.field.name || ":"
+ every result ||:= edgetostring(!n.children, depth+2)
+ cache[n] := result || "]"
+ } else if *n.cs.arms = 0 then
+ cache[n] := "<NOMATCH>"
+ else
+ cache[n] := "(" || image(n.name) || ":" || image(n.cs.arms[1].original) ||")"
+ return \cache[n]
+end
+
+procedure edgetostring(e,depth)
+ return left("\n", depth) ||
+ "{" || patimage(sort(e.lo ++ e.hi)) || ":" || nodetostring(e.node,depth) || "}"
+end
+@
+Conversion to dag is the usual bottom-up hashing; here I compute the
+string and then use the string to index into a table.
+The real work of merging edges is done by [[combinechildren]].
+If edge merging results in a single each, the node is replaced by
+its child, provided the edge really covers all possible values
+of the field.
+<<*>>=
+procedure tree2dag(n, nodetable, depth)
+ /nodetable := table()
+ /depth := 0
+ if *n.children > 0 then
+ combinechildren(n, nodetable, depth+2) # converts edges to set form
+ if *n.children = 1 then {
+ e := n.children[1]
+ if covers(n.children[1], n.field.hi - n.field.lo) then
+ n := n.children[1].node # all roads to child: hoist it
+ else
+ warning("node with one child doesn't match all cases")
+ }
+ s := nodetostring(n, depth)
+ /nodetable[s] := n
+ return nodetable[s]
+end
+@
+Here's where I check coverage.
+Only success or failure of [[covers]] is meaningful, not
+the value returned.
+<<*>>=
+procedure covers(e, width)
+ l := sort(e.lo ++ e.hi)
+ return *l = 2 & l[1] = 0 & l[2] = 2^width
+end
+@
+The complicated stuff here is identifying a name array.
+At each node, either all edges go in an exiting name array
+or a new name array is used.
+If not, I create a new one.
+<<*>>=
+record namearray(field, tbl, hi, codename)
+ # field used as index, table[integer] of name, bound on table, name of this array
+global natable
+<<*>>=
+procedure arraycandidates(n)
+ initial MAXRANGE := 32
+ suspend e := !n.children & type(e.node.name) == "string" &
+ e.hi - e.lo <= MAXRANGE & e
+end
+
+procedure combinechildren(n, nodetable, depth)
+ initial natable := table()
+
+ if arraycandidates(n).node.name ~== arraycandidates(n).node.name then {
+ <<change names of children from strings to namearrays when possible>>
+ }
+
+ lotable := table()
+ hitable := table()
+ every e := !n.children & child := tree2dag(e.node, nodetable, depth) do {
+ /lotable[child] := set()
+ /hitable[child] := set()
+ addinterval(lotable[child], hitable[child], e.lo, e.hi)
+ }
+ n.children := []
+ every child := key(lotable) do
+ put(n.children, edge(child, lotable[child], hitable[child]))
+ return
+end
+<<change names of children from strings to namearrays when possible>>=
+mightuse := set() # name arrays we might use must have right field
+every na := !\natable[n.field] do
+ insert(mightuse, na)
+every e := arraycandidates(n) & na := !mightuse do
+ if \na.tbl[e.lo to e.hi - 1] ~== e.node.name then # slot used with wrong name
+ delete(mightuse, na)
+if *mightuse > 0 then
+ willuse := ?mightuse
+else {
+ /natable[n.field] := set()
+ insert(natable[n.field], willuse := namearray(n.field, table(), 0))
+}
+every e := arraycandidates(n) &
+ e.lo - willuse.hi <= MAXRANGE do {
+ every willuse.tbl[e.lo to e.hi - 1] := e.node.name;
+ e.node.name := willuse
+ willuse.hi <:= e.hi
+ }
+<<*>>=
+procedure namesused(n, result)
+ /result := set()
+ if type(n.name) == "namearray" then insert(result, n.name)
+ every namesused((!n.children).node, result)
+ return result
+end
diff --git a/web/noweb/examples/graphs.nw b/web/noweb/examples/graphs.nw
new file mode 100644
index 0000000000..a5f7b8cdc3
--- /dev/null
+++ b/web/noweb/examples/graphs.nw
@@ -0,0 +1,244 @@
+This is a noweb file for doing all the graphs in the paper. It sets
+up generic chunks for setting up the axis sizes, etc, and gets all of
+the graph's data from data.nw.
+
+@ This first chunk is to be used by all graphs. It sets up the axis
+sizes, as well as the font sizes for labels.
+<<Standard Defaults>>=
+ yaxis size 1.9 hash_labels fontsize 7 label fontsize 8 draw
+ xaxis size 2.14 hash_labels fontsize 7 label fontsize 8 draw
+ title fontsize 10
+@
+The following chunks define the curves for the four different
+types of checkpointing algorithms.
+<<Sequential Curve>>=
+ newcurve marktype circle fill 1 linetype solid
+<<Concurrent Curve>>=
+ newcurve marktype diamond fill 0 linetype solid
+<<Low Latency Curve>>=
+ newcurve marktype box fill 1 linetype solid
+<<Low Latency Large Curve>>=
+ newcurve marktype box fill 0 linetype solid
+@
+Finally, this chunk is for the split legends of graphs 1-4.
+<<Legend>>=
+newgraph
+ inherit_axes
+ xaxis min 0 max 10 nodraw
+ yaxis min 0 max 10 nodraw
+ <<Sequential Curve>> label fontsize 7 : Sequential
+ <<Concurrent Curve>> label fontsize 7 : Concurrent
+ legend x 0 y 11.5
+newgraph
+ inherit_axes
+ <<Low Latency Curve>> label fontsize 7 : Low Latency, Conc.
+ <<Low Latency Large Curve>> label fontsize 7 : Low Lat., Conc., Large
+ legend x 4.7 y 11.5
+@
+---- THE GRAPHS ----
+@
+GRAPHS 1 \& 2
+<<Graphs 1n2>>=
+Y 3
+newgraph x_translate -1.37
+ <<Graph 1>>
+newgraph inherit_axes x_translate 1.7
+ <<Graph 2>>
+@
+Graph \#1: Checkpoint time. This is the wall-clock time to take one
+checkpoint of a merge-sort program.
+<<Graph 1>>=
+ <<Standard Defaults>>
+ title : Graph 1: Checkpoint Time.
+ xaxis min 0 max 10 hash 2 mhash 1 label : Heap Size (MBytes)
+ yaxis min 0 max 70 hash 10 mhash 1 label : Time (sec)
+ <<Sequential Curve>>
+ pts shell : notangle -R"Ckp Time" data.nw | head -6 | awk '{print $1" "$2}'
+ <<Concurrent Curve>>
+ pts shell : notangle -R"Ckp Time" data.nw | head -6 | awk '{print $1" "$3}'
+ <<Low Latency Curve>>
+ pts shell : notangle -R"Ckp Time" data.nw | head -6 | awk '{print $1" "$4}'
+ <<Low Latency Large Curve>>
+ pts shell : notangle -R"Ckp Time" data.nw | head -6 | awk '{print $1" "$5}'
+ <<Legend>>
+
+@
+Graph \#2: Checkpoint overhead. This is the extra time that it took
+the program to complete after taking one checkpoint.
+<<Graph 2>>=
+ <<Standard Defaults>>
+ title : Graph 2: Checkpoint Overhead.
+ xaxis min 0 max 10 hash 2 mhash 1 label : Heap Size (MBytes)
+ yaxis min 0 max 35 hash 10 mhash 1 label : Time (sec)
+ <<Sequential Curve>>
+ pts shell : notangle -R"Overhead" data.nw | awk '{print $1" "$2}'
+ <<Concurrent Curve>>
+ pts shell : notangle -R"Overhead" data.nw | awk '{print $1" "$3}'
+ <<Low Latency Curve>>
+ pts shell : notangle -R"Overhead" data.nw | awk '{print $1" "$4}'
+ <<Low Latency Large Curve>>
+ pts shell : notangle -R"Overhead" data.nw | awk '{print $1" "$5}'
+ <<Legend>>
+@
+GRAPHS 3 \& 4
+<<Graphs 3n4>>=
+ Y 3
+ newgraph x_translate -1.37
+ <<Graph 3>>
+ newgraph inherit_axes x_translate 1.7
+ <<Graph 4>>
+@
+Graph \#3: Checkpoint Overhead Percentage. This is the percentage
+of the checkpointing time which is overhead incurred on the target
+program
+<<Graph 3>>=
+ <<Standard Defaults>>
+ title : Graph 3: Checkpoint Overhead Percentage
+ xaxis min 0 max 10 hash 2 mhash 1 label : Heap Size (MBytes)
+ yaxis min 0 max 100 hash 10 mhash 1 label : % Overhead
+ <<Sequential Curve>>
+ pts shell : notangle -R"Ckp %age" data.nw | awk '{print $1" "$2}'
+ <<Concurrent Curve>>
+ pts shell : notangle -R"Ckp %age" data.nw | awk '{print $1" "$3}'
+ <<Low Latency Curve>>
+ pts shell : notangle -R"Ckp %age" data.nw | awk '{print $1" "$4}'
+ <<Low Latency Large Curve>>
+ pts shell : notangle -R"Ckp %age" data.nw | awk '{print $1" "$5}'
+ <<Legend>>
+@
+Graph \#4: This displays what happens when the heaps get big
+<<Graph 4>>=
+ <<Standard Defaults>>
+ title : Graph 4: Checkpoint Time for Large Heaps.
+ xaxis min 0 max 13 hash 2 mhash 1 label : Heap Size (MBytes)
+ yaxis min 0 max 700 hash 100 mhash 1 label : Time (sec)
+ <<Sequential Curve>>
+ pts shell : notangle -R"Ckp Time" data.nw | awk '{print $1" "$2}'
+ <<Concurrent Curve>>
+ pts shell : notangle -R"Ckp Time" data.nw | awk '{print $1" "$3}'
+ <<Low Latency Curve>>
+ pts shell : notangle -R"Ckp Time" data.nw | awk '{print $1" "$4}'
+ <<Low Latency Large Curve>>
+ pts shell : notangle -R"Ckp Time" data.nw | awk '{print $1" "$5}'
+ <<Legend>>
+@
+Graph \#5: Latency Data
+<<Graph 5>>=
+ Y 3
+ newgraph
+ <<Standard Defaults>>
+ title : Graph 5: Latency Data.
+ xaxis min 0 max 13 hash 2 mhash 1 label : Heap Size (MBytes)
+ yaxis min 0 max .351 hash .1 mhash 1 label : Time(sec)
+ newcurve marktype circle fill 1 linetype solid
+ pts shell : notangle -R"Latency" data.nw | awk '{print $1" "$2}'
+ label : Initial Stop Time
+ newcurve marktype circle fill 0 linetype solid
+ pts shell : notangle -R"Latency" data.nw | awk '{print $1" "$3}'
+ label : Maximum Trap Time
+ legend right
+@
+GRAPHS 6 \& 7
+<<Graphs 6n7>>=
+ Y 3
+ newgraph x_translate -1.37
+ <<Graph 6>>
+ newgraph inherit_axes x_translate 1.7
+ <<Graph 7>>
+@
+Graph \#6: Number of traps vs Segment Size
+<<Graph 6>>=
+ <<Standard Defaults>>
+ title : Graph 6: Number of Traps vs. Segment Size.
+ xaxis min 0 max 128 hash 32 mhash 1 label : Segment Size (KBytes)
+ yaxis min 0 max 1000 hash 200 mhash 1 label : Number of Traps
+ newcurve marktype circle fill 1 linetype solid
+ pts shell : notangle -R"Num Traps" data.nw
+@
+Graph \#7: Number of traps vs Segment Size
+<<Graph 7>>=
+ <<Standard Defaults>>
+ title : Graph 7: Maximum Trap Time vs. Segment Size.
+ xaxis min 0 max 128 hash 32 mhash 1 label : Segment Size (KBytes)
+ yaxis min 0 max 1.4 hash .2 mhash 1 label : Maximum Trap Time (Sec)
+ newcurve marktype circle fill 1 linetype solid
+ pts shell : notangle -R"Trap Time" data.nw
+@
+Graph \#8: Frequency of Traps
+<<Graph 8>>=
+ Y 3
+ newgraph
+ <<Standard Defaults>>
+ title : Graph \#8: Frequency of Traps.
+ xaxis min 0 max 2.6001 hash .5 mhash 4
+ label : Starting Time of 0.1 second interval (sec)
+ yaxis min 0 max 10 hash 1 mhash 0
+ label : Traps per 0.1 second Interval
+ newcurve marktype circle fill 0 pts
+ shell : notangle -R"Freq" data.nw
+ newstring hjr vjc fontsize 7 x 2.6 y 10 : Average Trap Time = 0.015 seconds
+@
+GRAPHS 9 \& 10
+<<Graphs 9n10>>=
+ Y 3
+ newgraph x_translate -1.37
+ <<Graph 9>>
+ newgraph inherit_axes x_translate 1.7
+ <<Graph 10>>
+@
+Graph 9 \& 10 have bizarre legends as well:
+<<Merge>>=
+ newcurve marktype circle fill 0 linetype solid
+<<Trs>>=
+ newcurve marktype triangle fill 0 linetype none
+<<Pattern>>=
+ newcurve marktype diamond fill 1 linetype none
+<<Bubble>>=
+ newcurve marktype cross fill 1 linetype none
+<<Matrix>>=
+ newcurve marktype box fill 1 linetype none
+<<9n10 Legend>>=
+ newgraph inherit_axes
+ xaxis min 0 max 10 nodraw
+ yaxis min 0 max 10 nodraw
+ <<Merge>>
+ label fontsize 7 : Merge Sort
+ <<Trs>>
+ label fontsize 7 : Travelling Salesman
+ <<Pattern>>
+ label fontsize 7 : Pattern Match
+ legend x 0 y 12
+ newgraph inherit_axes
+ <<Bubble>>
+ label fontsize 7 : Bubble Sort
+ <<Matrix>>
+ label fontsize 7 : Matrix Multiplication
+ legend x 5.6 y 12
+@
+Graph \#9:
+<<Graph 9>>=
+ <<Standard Defaults>>
+ title : Graph 9: Checkpoint Time of Other Benchmarks.
+ xaxis min 0 max 10 hash 2 mhash 1 label : Heap Size (MBytes)
+ yaxis min 0 max 40 hash 10 mhash 1 label : Time (sec)
+ <<Merge>>
+ pts shell : notangle -R"Ckp Time" data.nw | head -6 | awk '{print $1" "$4}'
+ <<Trs>> pts .064 2.359
+ <<Pattern>> pts 1.233 6.374
+ <<Bubble>> pts .513 3.91
+ <<Matrix>> pts 3.000 14.71
+ <<9n10 Legend>>
+@
+Graph \#10:
+<<Graph 10>>=
+ <<Standard Defaults>>
+ title : Graph 10: Checkpoint Overhead of Other Benchmarks.
+ xaxis min 0 max 10 hash 2 mhash 1 label : Heap Size (MBytes)
+ yaxis min 0 max 5 hash 1 mhash 1 label : Time (sec)
+ <<Merge>>
+ pts shell : notangle -R"Overhead" data.nw | awk '{print $1" "$4}'
+ <<Trs>> pts .064 0.17
+ <<Pattern>> pts 1.233 0.07
+ <<Bubble>> pts .513 0.07
+ <<Matrix>> pts 3.000 0.75
+ <<9n10 Legend>>
diff --git a/web/noweb/examples/mipscoder.nw b/web/noweb/examples/mipscoder.nw
new file mode 100644
index 0000000000..a97f30774e
--- /dev/null
+++ b/web/noweb/examples/mipscoder.nw
@@ -0,0 +1,1118 @@
+\section{A small assembler for the MIPS}
+This is part of the code generator for Standard ML of New Jersey.
+We generate code in several stages.
+This is nearly the lowest stage; it is like an assembler.
+The user can call any function in the [[MIPSCODER]] signature.
+Each one corresponds to an assembler pseudo-instruction.
+Most correspond to single MIPS instructions.
+The assembler remembers all the instructions that have been
+requested, and when [[codegen]] is called it generates MIPS
+code for them.
+
+Some other structure will be able to use the MIPS structure to implement
+a [[CMACHINE]], which is the abstract machine that ML thinks it is running
+on.
+(What really happens is a functor maps some structure
+implementing [[MIPSCODER]] to a different structure implementing
+[[CMACHINE]].)
+
+{\em Any function using a structure of this signature must avoid
+touching registers 1~and~31.
+Those registers are reserved for use by the assembler.}
+
+@ Here is the signature of the assembler, [[MIPSCODER]].
+It can be extracted from this file by
+$$\hbox{\tt notangle mipsinstr.nw -Rsignature}.$$
+<<signature>>=
+signature MIPSCODER = sig
+
+(* Assembler for the MIPS chip *)
+
+eqtype Label
+datatype Register = Reg of int
+ (* Registers 1 and 31 are reserved for use by this assembler *)
+datatype EA = Direct of Register | Immed of int | Immedlab of Label
+ (* effective address *)
+
+structure M : sig
+
+ (* Emit various constants into the code *)
+
+ val emitstring : string -> unit (* put a literal string into the
+ code (null-terminated?) and
+ extend with nulls to 4-byte
+ boundary. Just chars, no
+ descriptor or length *)
+ exception BadReal of string
+ val low_order_offset : int (* does the low-order word of a
+ floating point literal come
+ first (0) or second (1) *)
+ val realconst : string -> unit (* emit a floating pt literal *)
+ val emitlong : int -> unit (* emit a 4-byte integer literal *)
+
+
+ (* Label bindings and emissions *)
+
+ val newlabel : unit -> Label (* new, unbound label *)
+ val define : Label -> unit (* cause the label to be bound to
+ the code about to be generated *)
+ val emitlab : int * Label -> unit (* L3: emitlab(k,L2) is equivalent to
+ L3: emitlong(k+L2-L3) *)
+
+ (* Control flow instructions *)
+
+ val slt : Register * EA * Register -> unit
+ (* (operand1, operand2, result) *)
+ (* set less than family *)
+ val beq : bool * Register * Register * Label -> unit
+ (* (beq or bne, operand1, operand2, branch address) *)
+ (* branch equal/not equal family *)
+
+ val jump : Register -> unit (* jump register instruction *)
+
+ val slt_double : Register * Register -> unit
+ (* floating pt set less than *)
+ val seq_double : Register * Register -> unit
+ (* floating pt set equal *)
+ val bcop1 : bool * Label -> unit (* floating pt conditional branch *)
+
+
+ (* Arithmetic instructions *)
+ (* arguments are (operand1, operand2, result) *)
+
+ val add : Register * EA * Register -> unit
+ val and' : Register * EA * Register -> unit
+ val or : Register * EA * Register -> unit
+ val xor : Register * EA * Register -> unit
+ val sub : Register * Register * Register -> unit
+ val div : Register * Register * Register -> unit
+ (* first arg is some register
+ guaranteed to overflow when
+ added to itself. Used to
+ detect divide by zero. *)
+ val mult : Register * Register * Register -> unit
+ val mfhi : Register -> unit (* high word of 64-bit multiply *)
+
+ (* Floating point arithmetic *)
+
+ val neg_double : Register * Register -> unit
+ val mul_double : Register * Register * Register -> unit
+ val div_double : Register * Register * Register -> unit
+ val add_double : Register * Register * Register -> unit
+ val sub_double : Register * Register * Register -> unit
+
+ (* Move pseudo-instruction : move(src,dest) *)
+
+ val move : EA * Register -> unit
+
+ (* Load and store instructions *)
+ (* arguments are (destination, source address, offset) *)
+
+ val lbu : Register * EA * int -> unit (* bytes *)
+ val sb : Register * EA * int -> unit
+ val lw : Register * EA * int -> unit (* words *)
+ val sw : Register * EA * int -> unit
+ val lwc1: Register * EA * int -> unit (* floating point coprocessor *)
+ val swc1: Register * EA * int -> unit
+ val lui : Register * int -> unit
+
+ (* Shift instructions *)
+ (* arguments are (shamt, operand, result) *)
+ (* shamt as Immedlab _ is senseless *)
+
+ val sll : EA * Register * Register -> unit
+ val sra : EA * Register * Register -> unit
+
+
+ (* Miscellany *)
+
+ val align : unit -> unit (* cause next data to be emitted on
+ a 4-byte boundary *)
+ val mark : unit -> unit (* emit a back pointer,
+ also called mark *)
+
+ val comment : string -> unit
+
+ end (* signature of structure M *)
+
+ val codegen : unit->unit
+
+ val codestats : outstream -> unit (* write statistics on stream *)
+
+end (* signature MIPSCODER *)
+@ The basic strategy of the implementation is to hold on, via the [[kept]]
+pointer, to the list of instructions generated so far.
+We use [[instr]] for the type of an instruction, so
+[[kept]] has type [[instr list ref]].
+
+The instructions will be executed in the following order: the
+instruction at the head of the [[!kept]] is executed last.
+This enables us to accept calls in the order of execution but
+add the new instruction(s) to the list in constant time.
+
+
+@
+We structure the instruction stream a little bit by factoring
+out the different load and store instructions that can
+occur: we have load byte, load word, and load to coprocessor (floating point).
+<<types auxiliary to [[instr]]>>=
+datatype size = Byte | Word | Floating
+@
+Here are the instructions that exist.
+We list them in more or less the order of the MIPSCODER signature.
+<<definition of [[instr]]>>=
+<<types auxiliary to [[instr]]>>
+
+datatype instr =
+ STRINGCONST of string (* constants *)
+ | EMITLONG of int
+
+ | DEFINE of Label (* labels *)
+ | EMITLAB of int * Label
+
+ | SLT of Register * EA * Register (* control flow *)
+ | BEQ of bool * Register * Register * Label
+ | JUMP of Register
+ | SLT_D of Register * Register
+ | SEQ_D of Register * Register
+ | BCOP1 of bool * Label
+
+ | NOP (* no-op for delay slot *)
+
+ | ADD of Register * EA * Register (* arithmetic *)
+ | AND of Register * EA * Register
+ | OR of Register * EA * Register
+ | XOR of Register * EA * Register
+ | SUB of Register * Register * Register
+ | MULT of Register * Register
+ | DIV of Register * Register
+ | MFLO of Register (* mflo instruction used with
+ 64-bit multiply and divide *)
+ | MFHI of Register
+
+ | NEG_D of Register * Register
+ | MUL_D of Register * Register * Register
+ | DIV_D of Register * Register * Register
+ | ADD_D of Register * Register * Register
+ | SUB_D of Register * Register * Register
+
+ | MOVE of EA * Register (* put something into a register *)
+ | LDI_32 of int * Register (* load in a big immediate constant (>16 bits) *)
+ | LUI of Register * int (* Mips lui instruction *)
+
+ | LOAD of size * Register * EA * int (* load and store *)
+ | STORE of size * Register * EA * int
+
+ | SLL of EA * Register * Register (* shift *)
+ | SRA of EA * Register * Register
+
+ | COMMENT of string (* generates nothing *)
+ | MARK (* a backpointer *)
+
+ | BREAK of int (* break instruction *)
+@
+Here is the code that handles the generated stream, [[kept]].
+It begins life as [[nil]] and returns to [[nil]] every time code is
+generated.
+The function [[keep]] is a convenient way of adding a single [[instr]] to
+the list; it's very terse.
+Sometimes we have to add multiple [[instr]]s; then we use [[keeplist]].
+We also define a function [[delay]] that is just like a [[keep]] but
+it adds a NOP in the delay slot.
+<<instruction stream and its functions>>=
+ val kept = ref nil : instr list ref
+ fun keep f a = kept := f a :: !kept
+ fun delay f a = kept := NOP :: f a :: !kept
+ fun keeplist l = kept := l @ !kept
+<<reinitialize [[kept]]>>=
+ kept := nil
+@
+\subsection{Exporting functions for {\tt MIPSCODER}}
+We now know enough to implement most of the functions called for in
+[[MIPSCODER]].
+We still haven't decided on an implementation of labels,
+and there is one subtlety in multiplication and division,
+but the rest is set.
+<<[[MIPSCODER]] functions>>=
+ val emitstring = keep STRINGCONST (* literals *)
+ exception BadReal = IEEEReal.BadReal
+ val low_order_offset = Emitter.low_order_offset
+ val realconst = keep (STRINGCONST o order_real o IEEEReal.realconst)
+ val emitlong = keep EMITLONG
+
+ <<label functions>> (* labels *)
+
+ val slt = keep SLT (* control flow *)
+ val beq = delay BEQ
+ val jump = delay JUMP
+ val slt_double = delay SLT_D
+ val seq_double = delay SEQ_D
+ val bcop1 = delay BCOP1
+
+ val add = keep ADD (* arithmetic *)
+ val and' = keep AND
+ val or = keep OR
+ val xor = keep XOR
+ val op sub = keep SUB
+ <<multiplication and division functions>>
+
+ val neg_double = keep NEG_D
+ val mul_double = keep MUL_D
+ val div_double = keep DIV_D
+ val add_double = keep ADD_D
+ val sub_double = keep SUB_D
+
+ val move = keep MOVE
+
+ fun lbu (a,b,c) = delay LOAD (Byte,a,b,c) (* load and store *)
+ fun lw (a,b,c) = delay LOAD (Word,a,b,c)
+ fun lwc1 (a,b,c) = delay LOAD (Floating,a,b,c)
+ fun sb (a,b,c) = keep STORE (Byte,a,b,c)
+ fun sw (a,b,c) = keep STORE (Word,a,b,c)
+ fun swc1 (a,b,c) = delay STORE (Floating,a,b,c)
+ val lui = keep LUI
+
+ val sll = keep SLL (* shift *)
+ val sra = keep SRA
+
+ fun align() = () (* never need to align on MIPS *)
+ val mark = keep (fn () => MARK)
+ val comment = keep COMMENT
+@
+Multiplication has a minor complication; the
+result has to be fetched from the LO register.
+<<multiplication and division functions>>=
+fun mult (op1, op2, result) = keeplist [MFLO result, MULT (op1, op2)]
+val mfhi = keep MFHI
+@
+Division has a major complication; I must test for divide by zero since
+the hardware does not.
+If the divisor is zero, I cause an overflow exception by
+adding [[limitreg]] to itself.
+<<multiplication and division functions>>=
+fun op div (op1, op2, result) =
+ let val next = newlabel()
+ in keeplist [
+ MFLO result, (* get the result *)
+ DEFINE next, (* skip to here if nonzero *)
+ BREAK 7, (* signals zerodivide *)
+ DIV (op1, op2), (* divide in delay slot *)
+ BEQ (false, Reg 0, op2, next) (* skip if divisor nonzero *)
+ ]
+ end
+@
+For now, labels are just pointers to integers.
+During code generation, those integers will be set to positions
+in the instruction stream, and then they'll be useful as addresses
+relative to the program counter pointer (to be held in [[Reg pcreg]]).
+<<definition of [[Label]]>>=
+ type Label = int ref
+<<label functions>>=
+ fun newlabel () = ref 0
+ val define = keep DEFINE
+ val emitlab = keep EMITLAB
+@
+Here's the overall plan of this structure:
+<<*>>=
+functor MipsCoder(Emitter: EMITTER) : MIPSCODER = struct
+
+ open Emitter
+ <<definition of [[Label]]>>
+
+ datatype Register = Reg of int
+
+ datatype EA = Direct of Register
+ | Immed of int
+ | Immedlab of Label
+
+ <<definition of [[instr]]>>
+
+ <<instruction stream and its functions>>
+
+ structure M = struct
+ <<[[MIPSCODER]] functions>>
+ end
+
+ open M
+
+ <<functions that assemble [[instr]]s into code>>
+
+ <<statistics>>
+
+end (* MipsInstr *)
+@ \subsection{Sizes of {\tt instr}s}
+Now let's consider the correspondence between our [[instr]] type and the
+actual MIPS instructions we intend to emit.
+One important problem to solve is figuring out how big things are,
+so that we know what addresses to generate for the various labels.
+We will also want to know what address is currently stored in the program
+counter regsiter ([[pcreg]]),
+because we'll need to know when something is close
+enough that we can use a sixteen-bit address relative to that register.
+The kind of address we can use will determine how big things are.
+
+We'll rearrange the code so that we have a list of [[ref int * instr]] pairs,
+where the [[ref int]] stores the position in the list.
+(Positions start at zero.)
+Since in the MIPS all instructions are the same size, we measure
+position as number of instructions.
+While we're at it, we reverse the list so that the head will execute first,
+then the rest of the list.
+
+We begin with each position set to zero, and make a pass over the list
+trying to set the value of each position.
+We do this by estimating the size of (number of MIPS instructions
+generated for) each [[instr]].
+Since there are forward references, we may not have all the distances right
+the first time, so we have to make a second pass.
+But during this second pass we could find that something is further
+away than we thought, and we have to switch from using a pc-relative mode to
+something else (or maybe grab the new pc?), which changes the size again,
+and moves things even further away.
+Because we can't control this process, we just keep making passes over the
+list until the process quiesces (we get the same size twice).
+
+In order to guarantee termination, we have to make sure later passes only
+increase the sizes of things.
+This is sufficient since there is a maximum number of MIPS instructions
+we can generate for each [[instr]].
+
+
+While we're at it, we might want to complicate things by making the function
+that does the passes also emit code.
+For a single pass we hand an optional triple of emitters, the initial position,
+an [[int option]] for the program counter pointer (if known), and the
+instructions.
+
+
+
+I'm not sure what explains the use of the [[ref int]] to track the position,
+instead of just an [[int]]---it might be a desire to avoid the
+overhead of creating a bunch of new objects, or it might be really hard
+to do the passes cheaply.
+It should think a variation on [[map]] would do the job, but maybe I'm
+missing something.
+
+@
+[[emit : int * int -> unit]] emits one instruction,
+and [[emit_string : int -> string -> unit]] emits a string constant.
+[[emit_string]] could be specified as a function of [[emit]],
+but the nature of the function would depend on whether the target
+machine was little-endian or big-endian, and we don't want to have
+that dependency built in.
+
+ [[instrs]] is the
+list of instructions (in execute-head-last order).
+
+The second argument to [[pass]] indicates for what instructions code
+is to be generated.
+It is a record (position of next instruction, program counter pointer if any,
+remaining instructions to generate [with positions]).
+
+\indent [[prepare]] produces two results: the instruction stream with
+size pointers added, and the total size of code to be generated.
+We add the total size because that is the only way to find the number
+of [[bltzal]]s, which are implicit in the instruction stream.
+
+<<assembler>>=
+fun prepare instrs =
+ let fun add_positions(done, inst::rest) =
+ add_positions( (ref 0, inst) :: done, rest)
+ | add_positions(done, nil) = done
+
+ val instrs' = add_positions(nil, instrs) (* reverse and add [[ref int]]s*)
+
+ fun passes(oldsize) =
+ (* make passes with no emission until size is stable*)
+ let val size = pass false (0,NONE,instrs')
+ in if size=oldsize then size
+ else passes size
+ end
+ in {size = passes 0, stream = instrs'}
+ end
+
+fun assemble instrs =
+ pass true (0,NONE,#stream (prepare instrs))
+
+<<functions that assemble [[instr]]s into code>>=
+fun get (SOME x) = x
+ | get NONE = ErrorMsg.impossible "missing pcptr in mipscoder"
+
+<<[[pcptr]] functions>>
+<<single pass>>
+<<assembler>>
+
+fun codegen () = (
+ assemble (!kept);
+ <<reinitialize [[kept]]>>
+ )
+@
+The program counter pointer is a device that enables us to to addressing
+relative to the pcp register, register 31.
+The need for it arises when we want to access a data element which we know
+only by its label.
+The labels give us addresses relative to the beginning of the function,
+but we can only use addresses relative to some register.
+The answer is to set register~31 with a [[bltzal]] instruction,
+then use that for addressing.
+
+The function [[needs_a_pcptr]] determines when it is necessary
+to have a known value in register~31.
+That is, we need the program counter pointer
+\begin{itemize}
+\item
+at [[NOP]] for a reason to be named later?
+\item
+at any operation that uses an effective address that refers to a label
+(since all labels have to be relative to the program counter).
+\item
+BEQ's and BCOP1's to very far away,
+since we have to compute the address for a JUMP
+knowing the value of the program counter pointer.
+\end{itemize}
+<<[[pcptr]] functions>>=
+fun needs_a_pcptr(_,SLT(_,Immedlab _,_)) = true
+ | needs_a_pcptr(_,ADD(_,Immedlab _,_)) = true
+ | needs_a_pcptr(_,AND(_,Immedlab _,_)) = true
+ | needs_a_pcptr(_,OR(_,Immedlab _,_)) = true
+ | needs_a_pcptr(_,XOR(_,Immedlab _,_)) = true
+ | needs_a_pcptr(_,MOVE(Immedlab _,_)) = true
+ | needs_a_pcptr(_,LOAD(_,_,Immedlab _,_)) = true
+ | needs_a_pcptr(_,STORE(_,_,Immedlab _,_)) = true
+ | needs_a_pcptr(_,SLL(Immedlab _,_,_)) = true
+ | needs_a_pcptr(_,SRA(Immedlab _,_,_)) = true
+ | needs_a_pcptr(1, BEQ _) = false (* small BEQ's dont need pcptr *)
+ | needs_a_pcptr(_, BEQ _) = true (* but large ones do *)
+ | needs_a_pcptr(1, BCOP1 _) = false (* small BCOP1's dont need pcptr *)
+ | needs_a_pcptr(_, BCOP1 _) = true (* but large ones do *)
+ | needs_a_pcptr _ = false
+@
+Creating the program counter pointer once, with a [[bltzal]], is not
+enough; we have to invalidate the program counter pointer at every
+label, since control could arrive at the label from God knows where, and
+therefore we don't know what the program counter pointer is.
+
+We use the function [[makepcptr]] to create a new program counter pointer
+``on the fly'' while generating code for other [[instrs]].
+(I chose not to create a special [[instr]] for [[bltzal]], which I
+could have inserted at appropriate points in the instruction stream.)
+To try and find an odd bug, I'm adding no-ops after each [[bltzal]].
+I don't really believe they're necessary.
+
+The function [[gen]], which generates the instructions (or computes
+their size), takes three arguments.
+Third: the list of instructions to be generated (paired with pointers
+to their sizes); first: the position (in words) at which to generate
+those instructions; second: the current value of the program counter
+pointer (register~31), if known.
+
+The mutual recursion between [[gen]] and [[makepcptr]] maintains
+the program counter pointer.
+[[gen]] invalidates it at labels, and calls [[makepcptr]] to create a valid
+one when necessary (as determined by [[needs_a_pcptr]]).
+<<single pass>>=
+fun pass emit_now =
+let fun makepcptr(i,x) =
+ (* may need to emit NOP for delay slot if next instr is branch *)
+ let val size = case x of ((_,BEQ _)::rest) => 2
+ | ((_,BCOP1 _)::rest) => 2
+ | _ => 1
+ in if emit_now then (emit(Opcodes.bltzal(0,0));
+ if size=2 then emit(Opcodes.add(0,0,0)) else ())
+ else ();
+ gen(i+size, SOME (i+2), x)
+ end
+and gen(i,_,nil) = i
+ | gen(i, _, (_,DEFINE lab) :: rest) = (lab := i; gen(i,NONE, rest))
+ (* invalidate the pc pointer at labels *)
+ (* may want to do special fiddling with NOPs *)
+ | gen(pos, pcptr, x as ((sizeref as ref size, inst) :: rest)) =
+ if (pcptr=NONE andalso needs_a_pcptr(size, inst)) then makepcptr(pos,x)
+ else if emit_now
+ then
+ <<emit MIPS instructions>>
+ else
+ <<compute positions>>
+in gen
+end
+
+@ \subsection{Generating the instructions}
+Now we need to consider the nitty-gritty details of just what instructions
+are generated for each [[instr]].
+In early passes, we'll just need to know how many instructions are
+required (and that number may change from pass to pass, so it must be
+recomputed).
+In the last pass, the sizes are stable (by definition), so we can look
+at the sizes to see what instructions to generate.
+
+We'll consider the [[instrs]] in groups, but first, here's the
+way we will structure things:
+<<compute positions>>=
+let <<functions for computing sizes>>
+ val newsize = case inst of
+ <<cases for sizes to be computed>>
+in if newsize > size then sizeref := newsize else ();
+ gen(pos+(!sizeref) (* BUGS -- was pos+size*),pcptr,rest)
+end
+<<emit MIPS instructions>>=
+let fun gen1() = gen(pos+size,pcptr,rest)
+ (* generate the rest of the [[instr]]s *)
+ open Bits
+ open Opcodes
+ <<declare reserved registers [[tempreg]] and [[pcreg]]>>
+ <<functions for emitting instructions>>
+in case inst of
+ <<cases of instructions to be emitted>>
+end
+@ When we get around to generating code, we may need to use a temporary
+register.
+For example, if we want to load into a register
+an immediate constant that won't fit
+into 16~bits, we will have to load the high-order part of the constant
+with [[lui]], then use [[addi]] to add then the low-order part.
+The MIPS assembler has a similar problem, and on page D-2 of
+the MIPS book we notice that register~1 is reserved for the use of the
+assembler.
+So we do the same.
+
+We need to reserve a second register for use in pointing to the program
+counter.
+We will use register 31 because the [[bltzal]] instruction automatically
+sets register 31 to the PC.
+<<declare reserved registers [[tempreg]] and [[pcreg]]>>=
+val tempreg = 1
+val pcreg = 31
+@
+Before showing the code for the actual instructions, we should
+point out that
+we have two different ways of emitting a long word.
+[[emitlong]] just splits the bits into two pieces for those cases
+when it's desirable to put a word into the memory image.
+[[split]] gives something that will load correctly
+when the high-order piece is loaded into a high-order halfword
+(using [[lui]]),
+and the low-order piece is sign-extended and then added to the
+high-order piece.
+This is the way we load immediate constants of more than sixteen bits.
+It is also useful for generating load or store instructions with
+offsets of more than sixteen bits: we [[lui]] the [[hi]] part and
+add it to the base regsiter, then use the [[lo]] part as an offset.
+<<functions for emitting instructions>>=
+fun emitlong i = emit(rshift(i,16), andb(i,65535))
+ (* emit one long word (no sign fiddling) *)
+fun split i = let val hi = rshift(i,16) and lo = andb(i,65535)
+ in if lo<32768 then (hi,lo) else (hi+1, lo-65536)
+ end
+
+@ We begin implementing [[instrs]] by considering those that emit constants.
+String constants are padded with nulls out to a word boundary.
+Integer constants are just emitted with [[emitlong]].
+<<cases for sizes to be computed>>=
+ STRINGCONST s => Integer.div(String.length(s)+3,4)
+| EMITLONG _ => 1
+<<cases of instructions to be emitted>>=
+ STRINGCONST s =>
+ let val s' = s ^ "\000\000\000\000"
+ in gen1(emit_string (4*size) s')
+ (* doesn't know Big vs Little-Endian *)
+ end
+| EMITLONG i => gen1(emitlong i)
+@
+Next consider the labels.
+A [[DEFINE]] should never reach this far, and [[EMITLAB]] is almost like
+an [[EMITLONG]].
+<<cases for sizes to be computed>>=
+| DEFINE _ => ErrorMsg.impossible "generate code for DEFINE in mipscoder"
+| EMITLAB _ => 1
+<<cases of instructions to be emitted>>=
+| DEFINE _ => gen1(ErrorMsg.impossible "generate code for DEFINE in mipscoder")
+| EMITLAB(i, ref d) => gen1(emitlong((d-pos)*4+i))
+@
+Now we have to start worrying about instructions with [[EA]] in them.
+The real difficulty these things present is that they may have an
+immediate operand that won't fit in 16~bits.
+So we'll need to get this large immediate operand into a register,
+sixteen bits at a time, and then do the operation on the register.
+
+Since all of the arithmetic instructions have this difficulty, and since
+we can use them to implement the others, we'll start with those and
+catch up with the control-flow instructions later.
+@ [[SUB]], [[MULT]], [[DIV]], and [[MFLO]] all use registers only,
+so they are easy.
+The other arithmetic operations get treated exactly the same, so we'll
+use a function to compute the size.
+{\bf move this to follow the definition of [[arith]]?}
+<<cases for sizes to be computed>>=
+| ADD(_, ea, _) => easize ea
+| AND(_, ea, _) => easize ea
+| OR (_, ea, _) => easize ea
+| XOR(_, ea, _) => easize ea
+| SUB _ => 1
+| DIV (_,_) => 1
+| MULT (_,_) => 1
+| MFLO _ => 1
+| MFHI _ => 1
+@ Register operations take one instruction.
+Immediate operations take one instruction for 16~bit constants,
+and 3 for larger constants (since it costs two instructions to load
+a big immediate constant into a register).
+An immediate instruction with [[Immedlab l]] means that the operand
+is intended to be the machine address associated with that label.
+To compute that address, we need to add
+[[4*(l-pcptr)]] to the contents of
+register~[[pcreg]] (which holds [[4*pcptr]]),
+put the results in a register, and operate on that register.
+
+This tells us enough to compute the sizes.
+<<functions for computing sizes>>=
+fun easize (Direct _) = 1
+ | easize (Immed i) = if abs(i)<32768 then 1 else 3
+ | easize (Immedlab(ref lab)) = 1 + easize(Immed (4*(lab-(get pcptr))))
+@
+As we have seen,
+to implement any arithmetic operation, we need to know the register
+form and the sixteen-bit immediate form.
+We will also want the operator from [[instr]], since we do the
+large immediate via a recursive call.
+We'll set up a function, [[arith]], that does the job.
+<<functions for emitting instructions>>=
+fun arith (opr, rform, iform) =
+ let fun ar (Reg op1, Direct (Reg op2), Reg result) =
+ gen1(emit(rform(result,op1,op2)))
+ | ar (Reg op1, Immed op2, Reg result) =
+ (case size of
+ 1 (* 16 bits *) => gen1(emit(iform(result,op1,op2)))
+ | 3 (* 32 bits *) =>
+ gen(pos,pcptr,
+ (ref 2, LDI_32(op2, Reg tempreg))::
+ (ref 1, opr(Reg op1, Direct(Reg tempreg), Reg result))::
+ rest)
+ | _ => gen(ErrorMsg.impossible
+ "bad size in arith Immed in mipscoder")
+ )
+ | ar (Reg op1, Immedlab (ref op2), Reg result) =
+ gen(pos, pcptr,
+ (ref (size-1),
+ ADD(Reg pcreg,Immed(4*(op2-(get pcptr))), Reg tempreg))::
+ (ref 1, opr(Reg op1, Direct(Reg tempreg), Reg result))::
+ rest)
+ in ar
+ end
+@
+The generation itself may be a bit anticlimactic.
+The MIPS has no ``subtract immediate'' instruction, and [[SUB]] has
+a different type than the others, so we emit it directly.
+<<cases of instructions to be emitted>>=
+| ADD stuff => arith (ADD,add,addi) stuff
+| AND stuff => arith (AND,and',andi) stuff
+| OR stuff => arith (OR,or,ori) stuff
+| XOR stuff => arith (XOR,xor,xori) stuff
+| SUB (Reg op1, Reg op2, Reg result) => gen1(emit(sub(result,op1,op2)))
+| DIV (Reg op1, Reg op2) => gen1(emit(div(op1,op2)))
+| MULT(Reg op1, Reg op2) => gen1(emit(mult(op1,op2)))
+| MFLO(Reg result) => gen1(emit(mflo(result)))
+| MFHI(Reg result) => gen1(emit(mfhi(result)))
+@ Floating point arithmetic is pretty easy because we always do it in
+registers.
+We also support only one format, double precision.
+<<cases for sizes to be computed>>=
+| NEG_D _ => 1
+| MUL_D _ => 1
+| DIV_D _ => 1
+| ADD_D _ => 1
+| SUB_D _ => 1
+@ When emitting instructions we have to remember the Mips instructions
+use result on the left, but the [[MIPSCODER]] signature requires result
+on the right.
+<<cases of instructions to be emitted>>=
+| NEG_D (Reg op1,Reg result) => gen1(emit(neg_fmt(D_fmt,result,op1)))
+<<functions for emitting instructions>>=
+fun float3double instruction (Reg op1,Reg op2,Reg result) =
+ gen1(emit(instruction(D_fmt,result,op1,op2)))
+<<cases of instructions to be emitted>>=
+| MUL_D x => float3double mul_fmt x
+| DIV_D x => float3double div_fmt x
+| ADD_D x => float3double add_fmt x
+| SUB_D x => float3double sub_fmt x
+
+
+@ We offer a separate [[MOVE]] instruction because of large immediate
+constants.
+It is always possible to do [[move(src,dest)]] by doing
+[[add(Reg 0,src,dest)]], but the general form [[add(Reg i, Immed c, dest)]]
+takes three instructions when [[c]] is a large constant (more than 16 bits).
+Rather than clutter up the code for [[add]] (and [[or]] and [[xor]]) by
+trying to recognize register~0, we provide [[move]] explicitly.
+
+\indent [[LDI_32]] takes care of the particular case in which we are
+loading a 32-bit immediate constant into a register.
+It dates from the bad old days before [[MOVE]], and it might be a good idea
+to remove it sometime.
+<<functions for emitting instructions>>=
+fun domove (Direct (Reg src), Reg dest) = gen1(emit(add(dest,src,0)))
+ | domove (Immed src, Reg dest) =
+ (case size of
+ 1 (* 16 bits *) => gen1(emit(addi(dest,0,src)))
+ | 2 (* 32 bits *) =>
+ gen(pos,pcptr,(ref 2, LDI_32(src, Reg dest))::rest)
+ | _ => gen(ErrorMsg.impossible "bad size in domove Immed in mipscoder")
+ )
+ | domove (Immedlab (ref src), Reg dest) =
+ gen(pos, pcptr,
+ (ref size,
+ ADD(Reg pcreg,Immed(4*(src-(get pcptr))), Reg dest))::rest)
+@ Notice we use [[easize]] and not [[movesize]] in the third clause
+because when we reach this point the treatment of a [[MOVE]] is the same
+as that of an [[ADD]].
+<<functions for computing sizes>>=
+fun movesize (Direct _) = 1
+ | movesize (Immed i) = if abs(i)<32768 then 1 else 2
+ | movesize (Immedlab(ref lab)) = easize(Immed (4*(lab-(get pcptr))))
+
+<<cases for sizes to be computed>>=
+| MOVE (src,_) => movesize src
+| LDI_32 _ => 2
+| LUI _ => 1
+<<cases of instructions to be emitted>>=
+| MOVE stuff => domove stuff
+| LDI_32 (immedconst, Reg dest) =>
+ let val (hi,lo) = split immedconst
+ in gen1(emit(lui(dest,hi));emit(addi(dest,dest,lo)))
+ end
+| LUI (Reg dest,immed16) => gen1(emit(lui(dest,immed16)))
+
+@
+Now that we've done arithmetic, we can see how to do control flow without
+too much trouble.
+[[SLT]] can be treated just like an arithmetic operator.
+[[BEQ]] is simple if the address to which we branch is close enough.
+Otherwise we use the following sequence for [[BEQ(Reg op1, Reg op2, ref dest)]]:
+\begin{verbatim}
+ bne op1,op2,L
+ ADD (Reg pcreg, Immed (4*(dest-pcptr)), Reg tempreg)
+ jr tempreg
+ L: ...
+\end{verbatim}
+Notice we don't have to put a [[NOP]] in the delay slot of the [[bne]].
+We don't need one after the jump unless we needed one after the
+original [[BEQ]], in which case one will be there.
+If the branch is taken, we're doing as well as we can.
+If the branch is not taken, we will have executed an [[add]] or [[lui]] in the
+delay slot of the [[bne]], but the results just get thrown away.
+<<cases for sizes to be computed>>=
+| SLT(_, ea, _) => easize ea
+| BEQ(_,_,_,ref dest) =>
+ if abs((pos+1)-dest) < 32768 then 1 (* single instruction *)
+ else 2+easize (Immed (4*(dest-(get pcptr))))
+| JUMP _ => 1
+| SLT_D _ => 1
+| SEQ_D _ => 1
+| BCOP1(_,ref dest) =>
+ if abs((pos+1)-dest) < 32768 then 1 (* single instruction *)
+ else 2+easize (Immed (4*(dest-(get pcptr))))
+| NOP => 1
+@ The implementation is as described, except we use a
+non-standard [[nop]].
+There are many Mips instructions that have no effect, and the standard
+one is the word with all zeroes ([[sll 0,0,0]]).
+We use [[add]], adding 0 to 0 and store the result in 0, because it
+will be easy to distinguish from a data word that happens to be zero.
+<<cases of instructions to be emitted>>=
+| SLT stuff => arith (SLT,slt,slti) stuff
+| BEQ(b, Reg op1, Reg op2, ref dest) =>
+ if size = 1 then
+ gen1(emit((if b then beq else bne)(op1,op2,dest-(pos+1))))
+ else gen(pos,pcptr,
+ (ref 1, BEQ(not b, Reg op1, Reg op2, ref(pos+size)))
+ ::(ref (size-2),
+ ADD(Reg pcreg, Immed(4*(dest-(get pcptr))), Reg tempreg))
+ ::(ref 1, JUMP(Reg tempreg))
+ ::rest)
+| JUMP(Reg dest) => gen1(emit(jr(dest)))
+| SLT_D (Reg op1, Reg op2) =>
+ gen1(emit(c_lt(D_fmt,op1,op2)))
+| SEQ_D (Reg op1, Reg op2) =>
+ gen1(emit(c_seq(D_fmt,op1,op2)))
+| BCOP1(b, ref dest) =>
+ let fun bc1f offset = cop1(8,0,offset)
+ fun bc1t offset = cop1(8,1,offset)
+ in if size = 1 then
+ gen1(emit((if b then bc1t else bc1f)(dest-(pos+1))))
+ else gen(pos,pcptr,
+ (ref 1, BCOP1(not b, ref(pos+size)))
+ ::(ref (size-2),
+ ADD(Reg pcreg, Immed(4*(dest-(get pcptr))), Reg tempreg))
+ ::(ref 1, JUMP(Reg tempreg))
+ ::rest)
+ end
+| NOP => gen1(emit(add(0,0,0))) (* one of the many MIPS no-ops *)
+@
+Our next problem is to tackle load and store.
+The major difficulty is if the offset is too large to fit in
+sixteen bits; if so, we have to create a new base register.
+If we have [[Immedlab]], we do it as an offset from [[pcreg]].
+<<functions for emitting instructions>>=
+fun memop(rform,Reg dest, Direct (Reg base), offset) =
+ (case size
+ of 1 => gen1(emit(rform(dest,offset,base)))
+ | 3 => let val (hi,lo) = split offset
+ in gen1(emit(lui(tempreg,hi)); (* tempreg = hi @<< 16 *)
+ emit(add(tempreg,base,tempreg));(* tempreg += base *)
+ emit(rform(dest,lo,tempreg)) (* load dest,lo(tempreg) *)
+ )
+ end
+ | _ => gen1(ErrorMsg.impossible "bad size in memop Direct in mipscoder")
+ )
+ | memop(rform,Reg dest, Immed address, offset) =
+ (case size
+ of 1 => gen1(emit(rform(dest,offset+address,0)))
+ | 2 => let val (hi,lo) = split (offset+address)
+ in gen1(emit(lui(tempreg,hi));
+ emit(rform(dest,lo,tempreg))
+ )
+ end
+ | _ => gen1(ErrorMsg.impossible "bad size in memop Immed in mipscoder")
+ )
+ | memop(rform,Reg dest, Immedlab (ref lab), offset) =
+ memop(rform, Reg dest, Direct (Reg pcreg), offset+4*(lab - get pcptr))
+@ The actual registers don't matter for computing sizes, and in fact
+the value of [[pcreg]] is not visible here, so we use an arbitrary
+register ([[Reg 0]]) to compute the size.
+<<functions for computing sizes>>=
+fun adrsize(_, Reg _, Direct _, offset) =
+ if abs(offset)<32768 then 1 else 3
+ | adrsize(_, Reg _, Immed address, offset) =
+ if abs(address+offset) < 32768 then 1 else 2
+ | adrsize(x, Reg dest, Immedlab (ref lab), offset) =
+ adrsize(x, Reg dest, Direct (Reg 0 (* pcreg in code *) ),
+ offset+4*(lab-(get pcptr)))
+<<cases for sizes to be computed>>=
+| LOAD x => adrsize x
+| STORE x => adrsize x
+<<cases of instructions to be emitted>>=
+| LOAD (Byte,dest,address,offset) => memop(lbu,dest,address,offset)
+| LOAD (Word,dest,address,offset) => memop(lw,dest,address,offset)
+| LOAD (Floating,dest,address,offset) => memop(lwc1,dest,address,offset)
+| STORE (Byte,dest,address,offset) => memop(sb,dest,address,offset)
+| STORE (Word,dest,address,offset) => memop(sw,dest,address,offset)
+| STORE (Floating,dest,address,offset) => memop(swc1,dest,address,offset)
+@
+For the shift instructions, only register and immediate operands
+make sense.
+Immediate operands make sense if and only if they are representable
+in five bits.
+If everything is right, these are single instructions.
+<<cases for sizes to be computed>>=
+| SLL _ => 1
+| SRA _ => 1
+<<cases of instructions to be emitted>>=
+| SLL (Immed shamt, Reg op1, Reg result) => gen1(
+ if (shamt >= 0 andalso shamt < 32) then emit(sll(result,op1,shamt))
+ else ErrorMsg.impossible ("bad sll shamt "
+ ^ (Integer.makestring shamt) ^ " in mipscoder"))
+| SLL (Direct(Reg shamt), Reg op1, Reg result) =>
+ gen1(emit(sllv(result,op1,shamt)))
+| SLL (Immedlab _,_,_) => ErrorMsg.impossible "sll shamt is Immedlab in mipscoder"
+| SRA (Immed shamt, Reg op1, Reg result) => gen1(
+ if (shamt >= 0 andalso shamt < 32) then emit(sra(result,op1,shamt))
+ else ErrorMsg.impossible ("bad sra shamt "
+ ^ (Integer.makestring shamt) ^ " in mipscoder"))
+| SRA (Direct(Reg shamt), Reg op1, Reg result) =>
+ gen1(emit(srav(result,op1,shamt)))
+| SRA (Immedlab _,_,_) => ErrorMsg.impossible "sra shamt is Immedlab in mipscoder"
+@
+Finally, comments are ignored, and marks (backpointers) are written into the
+instruction stream.
+
+Comments are used by the front end to give diagnostics.
+In the bad old days we would have had two different [[MIPSCODER]]s, one
+which generated machine code (and ignored comments), and one which
+wrote out assembly code (and copied comments).
+Today we have just one, which means the rerouting of comments takes place
+at a much higher level. Look in [[cps/mipsglue.nw]].
+<<cases for sizes to be computed>>=
+| COMMENT _ => 0
+| MARK => 1 (* backpointer takes one word *)
+| BREAK _ => 1 (* break instruction *)
+@ Just for the record, here's the description of what a mark (backpointer)
+is.
+``Take the byte address at which the mark resides and add 4, giving
+the byte address of the object following the mark.
+(That object is the marked object.)
+Subtract the byte address of the initial word that marks the
+start of this instruction stream.
+Now divide by 4, giving the distance in words between the
+beginning of the block and the marked object.
+Take that quantity and shift it left by multiplying by [[power_tags]],
+and indicate the result is a mark by adding the tag bits [[tag_backptr]]
+into the low order part.''
+ [[pos+1]] is exactly the required distance in words.
+<<cases of instructions to be emitted>>=
+| COMMENT _ => gen1()
+| MARK => gen1(
+ let open System.Tags
+ in emitlong((pos+1) * power_tags + tag_backptr)
+ end)
+| BREAK n => gen1(
+ if n < 0 orelse n > 32 then ErrorMsg.impossible "bad break code"
+ else emit(break n))
+@
+\subsection{Optimization}
+The first step towards optimization is to take statistics.
+We will count: [[instrs]], Mips words, [[NOP]]s in load and branch delays,
+and [[bltzal]]s.
+In the current implementation the [[bltzal]]s are implicit, so there
+is no way to count them or optimize them.
+<<statistics>>=
+fun printstats stream
+ {inst : int, code : int, data : int,
+ load : int, branch : int, compare : int, size : int} =
+ let val print = output stream
+ val nop = load+branch+compare
+ val bltzal = size - (code + data)
+ val code = code + bltzal
+ <<definition of [[sprintf]]>>
+ fun P x = substring(makestring(100.0 * x),0,4) (* percent *)
+ fun printf f d = print (sprintf f d)
+ in printf ["Counted "," instrs in "," words (",
+ " code, "," data)\n" ^
+ "Used "," NOPs ("," load, "," branch,"," compare) and "," bltzals\n" ^
+ "","% of code words were NOPs; ","% were bltzals\n" ^
+ "","% of all words were code; ","% of all words were NOPs\n"]
+ [I inst, I size, I code, I data,
+ I nop, I load, I branch, I compare, I bltzal,
+ P (real nop / real code), P (real bltzal / real code),
+ P (real code / real size), P (real nop / real size)]
+ handle Overflow => print "[Overflow in computing Mips stats]\n"
+ end
+
+<<statistics>>=
+<<definition of [[iscode]]>>
+fun addstats (counts as {inst,code,data,load,branch,compare}) =
+ fn nil => counts
+ | (sizeref,first)::(_,NOP)::rest => addstats
+ {inst=inst+2, code=code+(!sizeref)+1, data=data,
+ load=load+ (case first of LOAD _ => 1 | _ => 0),
+ branch=branch +(case first of BEQ _ => 1 | JUMP _ => 1
+ | BCOP1 _ => 1 | _ => 0),
+ compare=compare+(case first of SLT_D _ => 1 | SEQ_D _ => 1
+ | _ => 0)
+ } rest
+ | (sizeref,first)::rest => addstats
+ {inst=inst+1,
+ code = code + if iscode(first) then !sizeref else 0,
+ data = data + if not (iscode first) then !sizeref else 0,
+ load=load,
+ branch=branch,
+ compare=compare
+ } rest
+
+
+fun codestats outfile =
+ let val {size,stream=instrs} = prepare (!kept)
+ val zero = {inst=0, code=0, data=0, load=0, branch=0, compare=0}
+ val counts as {inst,code,data,load,branch,compare} =
+ addstats zero instrs
+ in printstats outfile
+ {inst=inst,code=code,data=data,
+ load=load,branch=branch,compare=compare,size=size}
+ end
+
+<<definition of [[iscode]]>>=
+val iscode = fn
+ STRINGCONST _ => false
+ | EMITLONG _ => false
+ | DEFINE _ => false
+ | EMITLAB _ => false
+
+ | SLT _ => true
+ | BEQ _ => true
+ | JUMP _ => true
+ | NOP => true
+ | SLT_D _ => true
+ | SEQ_D _ => true
+ | BCOP1 _ => true
+
+ | ADD _ => true
+ | AND _ => true
+ | OR _ => true
+ | XOR _ => true
+ | SUB _ => true
+ | MULT _ => true
+ | DIV _ => true
+ | MFLO _ => true
+ | MFHI _ => true
+
+ | NEG_D _ => true
+ | MUL_D _ => true
+ | DIV_D _ => true
+ | ADD_D _ => true
+ | SUB_D _ => true
+
+ | MOVE _ => true
+ | LDI_32 _ => true
+ | LUI _ => true
+
+ | LOAD _ => true
+ | STORE _ => true
+
+ | SLL _ => true
+ | SRA _ => true
+
+ | COMMENT _ => false
+ | MARK => false
+ | BREAK _ => true
+
+<<definition of [[sprintf]]>>=
+val I = Integer.makestring
+val R = Real.makestring
+exception Printf
+fun sprintf format values =
+ let fun merge([x],nil) = [x]
+ | merge(nil,nil) = nil
+ | merge(x::y,z::w) = x::z:: merge(y,w)
+ | merge _ = raise Printf
+ in implode(merge(format,values))
+ end
+
+@
+At the moment these functions are meaningless junk.
+<<functions that remove pipeline bubbles>>=
+val rec squeeze =
+
+ fn (x as LOAD(_,Reg d, m, i))::NOP::instr::rest =>
+ if use(instr,d) then ??
+ else squeeze(x::instr::rest)
+ | (x as STORE _)::(y as LOAD _)::rest =>
+ x :: squeeze(y::rest)
+ | instr::(x as LOAD(_,Reg d, Direct(Reg s), i))::NOP::rest =>
+ if use(instr, d) orelse gen(instr, s) then ??
+ else squeeze(x::instr::rest)
+ | instr::(x as LOAD(_,Reg d, _, i))::NOP::rest =>
+ if use(instr,d) then ??
+ else squeeze(x::instr::rest)
+ | (x as MFLO _):: (y as MULDIV _) :: rest =>
+ x :: squeeze (y::rest)
+ | (x as MFLO(Reg d))::instr::rest =>
+ if (use(instr,d) orelse gen(instr,d) then ??
+ else squeeze(instr::x::rest)
+ | instr :: (x as MULDIV(Reg a, Reg b)) :: rest =>
+ if gen(instr,a) orelse gen(instr,b) then ??
+ else squeeze(x::instr::rest)
+
+val rec final =
+ fn
+ | instr::(x as LOAD(_,Reg d, Direct(Reg s), i))::NOP::rest =>
+ if gen(instr, s) then instr::final(x::NOP::rest)
+ else x::instr::(final rest)
+ | instr :: (x as JUMP _) :: NOP :: rest =>
+ x :: instr :: final rest
+ | instr :: (x as BEQ(_,Reg a, Reg b, _)) :: NOP :: rest =>
+ if gen(instr,a) orelse gen(instr,b) then instr::x::NOP::(final rest)
+ else x::instr::(final rest)
+@
+\section{Indices}
+\subsection{Chunks}
+\nowebchunks
+\subsection{Identifiers}
+\nowebindex
diff --git a/web/noweb/examples/multicol.sty b/web/noweb/examples/multicol.sty
new file mode 100644
index 0000000000..bc1b703031
--- /dev/null
+++ b/web/noweb/examples/multicol.sty
@@ -0,0 +1,525 @@
+%%
+%% This is file `multicol.sty', generated
+%% on <1993/10/28> with the docstrip utility (2.1e).
+%%
+%% The original source files were:
+%%
+%% multicol.doc (with options: `style,check,marktrace')
+%%
+%% Copyright (C) 1989-1992 by Frank Mittelbach. All rights reserved.
+%%
+%% This file is part of the multicol package.
+%%
+%% IMPORTANT NOTICE:
+%%
+%% You are not allowed to change this file. You may however copy
+%% this file to a file with a different name and then change the copy
+%% if you obey the restrictions on file changes described in
+%% readme.mz.
+%%
+%% You are NOT ALLOWED to distribute this file alone. You are NOT
+%% ALLOWED to take money for the distribution or use of this file (or
+%% a changed version) except for a nominal charge for copying etc.
+%%
+%% You are allowed to distribute this file under the condition that
+%% it is distributed together with all files mentioned in readme.mz1.
+%%
+%% If you receive only some of these files from someone, complain!
+%%
+%% However, if these files are distributed by established suppliers
+%% as part of a complete TeX distribution, and the structure of the
+%% distribution would make it difficult to distribute the whole set
+%% of files, *those parties* are allowed to distribute only some of
+%% the files provided that it is made clear that the user will get a
+%% complete distribution-set upon request to that supplier (not me).
+%% Notice that this permission is not granted to the end user.
+%%
+%%
+%% For error reports in case of UNCHANGED versions see readme.mz
+%%
+%%
+\def\fileversion{v1.4m}
+\def\filedate{92/09/04}
+\def\docdate {92/09/04}
+
+%% \CheckSum{1101}
+%% \CharacterTable
+%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+%%
+%% Style-option `multicol' to use with LaTeX v2.09
+%% Copyright (C) 1989-1992 Frank Mittelbach, all rights reserved.
+\@ifundefined{mult@cols}{}{\endinput}
+\typeout{Style option: `multicol'
+ \fileversion\space <\filedate> (FMi)}
+\typeout{English documentation
+ \@spaces\@spaces\space<\docdate> (FMi)}
+\def\multicols#1{\col@number#1\relax
+ \ifnum\col@number<\tw@
+ \@warning{Using `\number\col@number'
+ columns doesn't seem a good idea.^^J
+ I therefore use two columns instead}%
+ \col@number\tw@ \fi
+ \ifnum\col@number>5
+ \@warning{Current implementation doesn't
+ support more than five columns.^^J
+ I therefore use five columns instead}%
+ \col@number5 \fi
+ \@ifnextchar[\mult@cols{\mult@cols[]}}
+\def\mult@cols[#1]{\@ifnextchar[%
+ {\mult@@cols{#1}}%
+ {\mult@@cols{#1}[\premulticols]}}
+\def\mult@@cols#1[#2]{%
+ \par
+ \ifinner \@boxedmulticolstrue
+ \else
+ \ifnum \doublecol@number>\z@
+ \@boxedmulticolstrue
+ \fi
+ \fi
+ \ifnum\c@tracingmulticols>\z@
+ \typeout{^^J^^JStarting multicolumn
+ output with \the\col@number
+ \space columns%
+ \if@boxedmulticols\space
+ (boxed mode)\fi
+ \on@line:^^J}\fi
+ \enough@room{#2}%
+ {#1\par}\addvspace\multicolsep
+ \begingroup
+ \prepare@multicols
+ \if@boxedmulticols
+ \setbox\mult@box\vbox\bgroup
+ \penalty-\@M
+ \fi
+ \ignorespaces}
+\newif\if@boxedmulticols \@boxedmulticolsfalse
+\newbox\mult@box
+\def\enough@room#1{%
+ \if@boxedmulticols\else
+ \par
+ \bgroup\@nobreakfalse\addpenalty\z@\egroup
+ \page@free \pagegoal
+ \advance \page@free -\pagetotal
+ \ifnum \c@tracingmulticols>\z@
+ \typeout{Current page:}%
+ \message{\@spaces goal height=%
+ \the\pagegoal: used \the\pagetotal
+ \space -> free=\the\page@free}%
+ \typeout{\@spaces needed \the#1
+ (for \string#1)}\fi
+ \ifdim \page@free <#1\newpage \fi
+ \fi}
+\def\prepare@multicols{%
+ \multicol@leftmargin\@totalleftmargin
+ \@totalleftmargin\z@
+ \parshape\z@
+ \doublecol@number\col@number
+ \multiply\doublecol@number\tw@
+ \if@boxedmulticols
+ \let\l@kept@firstmark\kept@firstmark
+ \let\l@kept@botmark\kept@botmark
+ \global\let\kept@firstmark\@empty
+ \global\let\kept@botmark\@empty
+ \else
+ \nointerlineskip \null
+ \output{%
+ \global\setbox\partial@page\vbox
+ {%
+ \ifvoid\partial@page\else
+ \@latexerr{Error saving partial
+ page\on@line}%
+ {The part of the page before
+ the multicols environment was
+ nearly full with the result
+ that starting the environment
+ will produce an overfull
+ page. Some text may be lost!
+ Please increase \premulticols
+ either generally or for this
+ environment by specifying a
+ suitable value in the second
+ optional argument to the
+ multicols environment.}
+ \unvbox\partial@page
+ \box\last@line
+ \fi
+ \unvbox\@cclv
+ \global\setbox\last@line\lastbox
+ }%
+ \prep@keptmarks
+ \global\let\kept@topmark\firstmark
+ }\eject
+ \advance\@colroom-\ht\partial@page
+ \vsize\col@number\@colroom
+ \advance\vsize\c@collectmore\baselineskip
+ \output{\multi@column@out}%
+ \multiply\count\footins\col@number
+ \multiply\skip \footins\col@number
+ \reinsert@footnotes
+ \fi
+ \vbadness10001 \hbadness5000
+ \tolerance\multicoltolerance
+ \pretolerance\multicolpretolerance
+ \setemergencystretch\col@number\hsize
+ \set@floatcmds
+ \advance\baselineskip\multicolbaselineskip
+ \hsize\linewidth \advance\hsize\columnsep
+ \advance\hsize-\col@number\columnsep
+ \divide\hsize\col@number
+ \full@width\linewidth
+ \linewidth\hsize
+}
+\newdimen\multicol@leftmargin
+\def\endmulticols{\par
+ \if@boxedmulticols
+ \egroup
+ \setbox\@tempboxa\vsplit\mult@box to\z@
+ \balance@columns
+ \return@nonemptymark{first}\kept@firstmark
+ \return@nonemptymark{bot}\kept@botmark
+ \page@sofar
+ \global\let\kept@firstmark\l@kept@firstmark
+ \global\let\kept@botmark\l@kept@botmark
+ \ifnum\c@tracingmulticols>\tw@
+ \typeout{Restore kept marks to%
+ ^^J first: \meaning\kept@firstmark%
+ ^^J bot\space\space:
+ \meaning\kept@botmark }%
+ \fi
+ \else
+ \bgroup\@nobreakfalse\addpenalty\z@\egroup
+ \output{\balance@columns@out}\eject
+ \ifvbox\partial@page\unvbox\partial@page\fi
+ \global\let\kept@firstmark\@empty
+ \global\let\kept@botmark\@empty
+ \ifnum\c@tracingmulticols>\tw@
+ \typeout{Make kept marks empty}%
+ \fi
+ \fi
+ \@checkend{multicols}%
+ \endgroup
+ \if@boxedmulticols\else
+ \reinsert@footnotes
+ \fi
+ \global\c@unbalance\z@
+ \enough@room\postmulticols
+ \addvspace\multicolsep
+ \ifnum\c@tracingmulticols>\z@
+ \typeout{^^JEnding multicolumn
+ output%
+ \if@boxedmulticols
+ \space(boxed mode)\fi
+ .^^J^^J}\fi}
+\newcount\c@unbalance
+\newcount\c@collectmore
+\newcount\c@tracingmulticols
+\newcount\col@number
+\newcount\doublecol@number
+\newcount\multicoltolerance
+\newcount\multicolpretolerance
+\newdimen\full@width
+\newdimen\page@free
+\newdimen\premulticols
+\newdimen\postmulticols
+\newskip\multicolsep
+\newskip\multicolbaselineskip
+\newbox\partial@page
+\newbox\last@line
+\c@unbalance = 0
+\c@collectmore = 0
+\c@tracingmulticols = 0
+\col@number = 1
+\multicoltolerance = 9999
+\multicolpretolerance = -1
+\premulticols = 50pt
+\postmulticols= 20pt
+\multicolsep = 12pt plus 4pt minus 3pt
+\multicolbaselineskip=0pt
+\def\process@cols#1#2{\count@#1\relax
+ \loop #2%
+ \advance\count@\tw@
+ \ifnum\count@<\doublecol@number
+ \repeat}
+\def\page@sofar{%
+ \process@cols\z@{\wd\count@\hsize}%
+ \ifnum\c@tracingmulticols>\z@
+ \typeout{Column spec:
+ (\the\multicol@leftmargin\space -->
+ \the\full@width\space = \the\hsize
+ \space x \the\col@number)^^J}%
+ \fi
+\ifvmode\else\errmessage{Multicol Error}\fi
+ \moveright\multicol@leftmargin
+ \hbox to\full@width{%
+ \process@cols\tw@{\box\count@
+ \hss\vrule\@width\columnseprule\hss}%
+ \box\z@
+ \rlap{\phantom p}%
+}%
+}
+\def\reinsert@footnotes{\ifvoid\footins\else
+ \insert\footins{}\fi}
+\def\multi@column@out{%
+ \ifnum\outputpenalty <-\@Mi
+ \speci@ls \else
+ \splittopskip\topskip
+ \splitmaxdepth\maxdepth
+ \dimen@\@colroom
+ \divide\skip\footins\col@number
+ \ifvoid\footins \else
+ \advance\dimen@-\skip\footins
+ \advance\dimen@-\ht\footins \fi
+ \process@cols\tw@{\setbox\count@
+ \vsplit\@cclv to\dimen@
+ \set@keptmarks
+ \ifshr@nking
+ \setbox\count@\vbox to\dimen@
+ {\unvbox\count@\vfill}%
+ \fi
+ }%
+ \setbox\z@\vsplit\@cclv to\dimen@
+ \set@keptmarks
+ \ifshr@nking
+ \setbox\z@\vbox to\dimen@
+ {\unvbox\z@\vfill}%
+ \fi
+ \ifvoid\@cclv \else
+ \unvbox\@cclv
+ \penalty\outputpenalty
+ \ifvoid\footins\else
+ \@warning{I moved some lines to
+ the next page.^^J
+ \@spaces Footnotes on page
+ \thepage\space might be wrong}%
+ \fi
+ \ifnum \c@tracingmulticols>\thr@@
+ \hrule\allowbreak \fi
+ \fi
+ \ifx\@empty\kept@firstmark
+ \let\firstmark\kept@topmark
+ \let\botmark\kept@topmark
+ \else
+ \let\firstmark\kept@firstmark
+ \let\botmark\kept@botmark
+ \fi
+ \ifnum\c@tracingmulticols>\tw@
+ \typeout{Use kept top
+ \space\space mark:
+ `\meaning\kept@topmark'%
+ ^^JUse kept first mark:
+ `\meaning\kept@firstmark'%
+ ^^JUse kept bot
+ \space\space mark:
+ `\meaning\kept@botmark'%
+ ^^JProduce first mark:
+ `\meaning\firstmark'%
+ ^^JProduce bot
+ \space\space mark:
+ `\meaning\botmark'}%
+ \fi
+ \setbox\@cclv\vbox{\unvbox\partial@page
+ \page@sofar}%
+ \@makecol\@outputpage
+ \global\let\kept@topmark\botmark
+ \global\let\kept@firstmark\@empty
+ \global\let\kept@botmark\@empty
+ \ifnum\c@tracingmulticols>\tw@
+ \typeout{(Re)Init top
+ \space\space mark:
+ `\meaning\kept@topmark'}%
+ \fi
+ \global\@colroom\@colht
+ \process@deferreds
+ \@whilesw\if@fcolmade\fi{\@outputpage
+ \global\@colroom\@colht
+ \process@deferreds}%
+ \ifnum\c@tracingmulticols>\@ne
+ \typeout{Colroom: \the\@colht\space
+ after float space removed
+ = \the\@colroom }\fi
+ \global\vsize\col@number\@colroom
+ \global\advance\vsize
+ \c@collectmore\baselineskip
+ \fi}
+\def\speci@ls{%
+ \typeout{Floats and marginpars not
+ allowed inside `multicols'
+ environment!}%
+ \unvbox\@cclv\reinsert@footnotes
+ \xdef\@freelist{\@freelist\@currlist}%
+ \gdef\@currlist{}}
+\def\process@deferreds{%
+ \@floatplacement
+ \@tryfcolumn\@deferlist
+ \if@fcolmade\else
+ \begingroup
+ \let\@tempb\@deferlist
+ \gdef\@deferlist{}%
+ \let\@elt\@scolelt
+ \@tempb \endgroup
+ \fi}
+\newif\ifshr@nking
+\def\raggedcolumns{%
+ \@bsphack\shr@nkingtrue\@esphack}
+\def\flushcolumns{%
+ \@bsphack\shr@nkingfalse\@esphack}
+\def\balance@columns@out{%
+ \setbox\mult@box\vbox{\unvbox\@cclv}%
+ \balance@columns
+ \global\vsize\@colroom
+ \global\advance\vsize\ht\partial@page
+ \unvbox\partial@page
+ \return@nonemptymark{first}\kept@firstmark
+ \return@nonemptymark{bot}\kept@botmark
+ \page@sofar}
+\def\balance@columns{%
+ \setbox\mult@box\vbox to\ht\mult@box{%
+ \unvbox\mult@box
+ \remove@discardable@items
+ }%
+ \get@keptmarks\mult@box
+ \splittopskip\topskip
+ \splitmaxdepth\maxdepth
+ \@tempdima\ht\mult@box
+ \advance\@tempdima\dp\mult@box
+ \divide\@tempdima\col@number
+ \count@\@tempdima
+ \divide\count@\baselineskip
+ \dimen@\count@\baselineskip
+ \advance\dimen@\topskip
+ \ifdim \dimen@ >\@tempdima
+ \advance\dimen@-\baselineskip
+ \fi
+ \advance\dimen@\c@unbalance\baselineskip
+ \ifnum\c@tracingmulticols>\@ne
+ \typeout{Balance columns\on@line:
+ \ifnum\c@unbalance=\z@\else
+ (off balance=\number\c@unbalance)\fi}%
+ \fi
+ \ifnum\dimen@<\topskip
+ \ifnum\c@tracingmulticols>\@ne
+ \typeout{Start value
+ \the\dimen@ \space ->
+ \the\topskip \space (corrected)}%
+ \fi
+ \dimen@\topskip
+ \fi
+ \vbadness\@M \loop
+ {\process@cols\@ne{\global\setbox\count@
+ \box\voidb@x}}%
+ \global\setbox\@ne\copy\mult@box
+ {\process@cols\thr@@{%
+ \global\setbox\count@
+ \vsplit\@ne to\dimen@
+ }}%
+ \boxmaxdepth\maxdepth
+ \global\setbox\@ne\vbox{\unvbox\@ne}%
+ \ifnum\c@tracingmulticols>\@ne
+ \message{\@spaces First column
+ = \the\ht\thr@@}\fi
+ \ifshr@nking \global\setbox\thr@@
+ \vbox{\unvbox\thr@@}%
+ \ifnum\c@tracingmulticols>\@ne
+ \message{ after shrinking
+ \the\ht\thr@@}\fi\fi
+ \ifnum\c@tracingmulticols>\@ne
+ \message{<> last column =
+ \the\ht\@ne^^J}%
+ \fi
+ \ifdim\ht\@ne >\ht\thr@@
+ \advance\dimen@\p@
+ \repeat
+ \dimen@\ht\thr@@
+ \ifdim\dimen@>\@colroom
+ \dimen@\@colroom
+ \fi
+ \process@cols\z@{\@tempcnta\count@
+ \advance\@tempcnta\@ne
+ \setbox\count@\vbox to\dimen@
+ {\unvbox\@tempcnta
+ \ifshr@nking\vfill\fi}}%
+}
+\@ifundefined{emergencystretch}
+ {\newdimen\emergencystretch}{}
+\def\setemergencystretch#1#2{%
+ \emergencystretch 4pt
+ \multiply\emergencystretch#1}
+
+\def\set@floatcmds{%
+ \let\@dblfloat\@dbflt
+ \def\end@dblfloat{\par
+ \vskip\z@\egroup
+ \ifnum\@floatpenalty<\z@
+ \@cons\@deferlist\@currbox
+ \fi
+ \ifnum\@floatpenalty=-\@Mii
+ \@esphack
+ \fi}}
+\def\kept@topmark{{}{}}
+\let\kept@firstmark\@empty
+\let\kept@botmark\@empty
+\def\return@nonemptymark#1#2{%
+ \ifx#2\@empty
+ \else
+ \ifnum\c@tracingmulticols>\tw@
+ \typeout{Returned #1 mark: \meaning#2}%
+ \nobreak
+ \fi
+ \mark{#2}%
+ \nobreak
+ \fi}
+\def\get@keptmarks#1{%
+ \begingroup
+ \vbadness\@M
+ \setbox#1\copy#1%
+ \setbox#1\vsplit#1to\maxdimen
+ \set@keptmarks
+ \endgroup
+}
+\def\set@keptmarks{%
+ \ifx\kept@firstmark\@empty
+ \expandafter\gdef\expandafter
+ \kept@firstmark
+ \expandafter{\splitfirstmark}%
+ \ifnum\c@tracingmulticols>\tw@
+ \ifx\kept@firstmark\@empty\else
+ \typeout{Set kept first mark:
+ `\meaning\kept@firstmark'}%
+ \fi
+ \fi
+ \fi
+ \expandafter\def\expandafter\@tempa
+ \expandafter{\splitbotmark}%
+ \ifx\@tempa\@empty\else
+ \global\let\kept@botmark\@tempa
+ \ifnum\c@tracingmulticols>\tw@
+ \typeout{Set kept bot mark:
+ `\meaning\kept@botmark'}%
+ \fi
+ \fi}%
+\def\prep@keptmarks{%
+ \if@boxedmulticols \else
+ \get@keptmarks\partial@page
+ \fi}
+\def\remove@discardable@items{%
+ \unskip\unpenalty\unkern
+ \unskip\unpenalty\unkern
+ \unskip\unpenalty\unkern
+ \unskip\unpenalty\unkern
+}
+\endinput
+%%
+%% End of file `multicol.sty'.
diff --git a/web/noweb/examples/primes.bbl b/web/noweb/examples/primes.bbl
new file mode 100644
index 0000000000..6fbb9884a5
--- /dev/null
+++ b/web/noweb/examples/primes.bbl
@@ -0,0 +1,13 @@
+\begin{thebibliography}{1}
+
+\bibitem{knuth:literate}
+Donald~E. Knuth.
+\newblock Literate programming.
+\newblock {\em The Computer Journal}, 27(2):97--111, 1984.
+
+\bibitem{dahl:structured}
+Ole-Johan Dahl, Edsger~W. Dijkstra, and C.~A.~R. Hoare.
+\newblock {\em Structured Programming}.
+\newblock Academic Press, London and New York, 1972.
+
+\end{thebibliography}
diff --git a/web/noweb/examples/primes.nw b/web/noweb/examples/primes.nw
new file mode 100644
index 0000000000..d265b81b91
--- /dev/null
+++ b/web/noweb/examples/primes.nw
@@ -0,0 +1,186 @@
+% Copyright 1991 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+
+% l2h substitution nw <tt>noweb</tt>
+% some insanity is needed to avoid getting a double square bracket
+% l2h substitution [ <b>[</b><b>[</b>
+% l2h substitution ] <b>]</b><b>]</b>
+\def\nw{{\tt noweb}}
+\def\[{\ifhmode\ \fi$[\mkern-2mu[$}
+\def\]{$]\mkern-2mu]$}
+
+\title{Printing Primes: An example of \nw}
+
+\section{Printing Primes: An example of \nw}
+The following program is essentially the program that appears in
+Reference~\cite{knuth:literate}, the first article on literate programming,
+but rendered using \nw.
+An important differents is the {\tt WEB} has macros, but \nw\ does not.
+Knuth's program is itself essentially the same as Edsger Dijkstra's
+``first example of step-wise program composition.''~\cite[pages
+26--39]{dahl:structured}.
+
+Dijkstra's program prints a table of the first thousand prime numbers.
+We shall begin as he did, by reducing the entire program to its
+top-level description.
+
+<<*>>=
+<<program to print the first thousand prime numbers>>
+@
+\[Double brackets will be used in what follows to enclose comments
+relating to \nw\ itself.
+This definition of the root module could have been eliminated by
+choosing to use
+\begin{quote}
+\tt notangle -R'program to print the first thousand prime numbers'
+\end{quote}
+to extract the program.\]
+@ This program has no input, because we want to keep it simple.
+The result of the program will be to produce a list of the first
+thousand prime numbers, and this list will appear on the [[output]]
+file.
+
+Since there is no input, we declare the value [[m = 1000]] as a
+compile-time constant.
+The program itself is capable of generating the first [[m]] prime
+numbers for any positive [[m]], as long as the computer's finite
+limitations are not exceeded.
+<<program to print the first thousand prime numbers>>=
+program `print_primes(output);
+ const m = 1000;
+ <<other constants of the program>>
+ var <<variables of the program>>
+ begin <<print the first [[m]] prime numbers>>
+ end.
+@
+
+\section{Plan of the program}
+We shall proceed to fill out the rest of the program by making
+whatever decisions seem easiest at each step; the idea will be to
+strive for simplicity first and efficiency later, in order to see
+where this leads us.
+The final program may not be optimum, but we want it to be reliable,
+well motivated, and reasonably fast.
+
+Let us decide at this point to maintain a table that includes all of
+the prime numebrs that will be generated, and to sepaerate the
+genreation problem from the printing problem.
+<<print the first [[m]] prime numbers>>=
+<<fill table [[p]] with the first [[m]] prime numbers>>;
+<<print table [[p]]>>
+@
+How should table [[p]] be represented?
+Two possibilities suggest themselves: We could construct a
+sifficiently large aray of boolean values in whith the $k$th entry is
+[[true]] if and only if the number $k$ is prime; or we could build an
+array of integers in which the $k$th entry is the $k$th prime number.
+Let us choose the latter alternatice, by introducing an intereger
+array called [[p[1..m]]].
+In the documentation below, the notation [[p[k]]] will refer to the
+[[k]]th element of the array [[p]], while $p_k$ will refer to the
+$k$th prime number.
+If the program is correct [[p[k]]] will equal $p_k$ or it will not yet
+have nbeen asigned any value.
+<<variables of the program>>=
+p: array [1..m] of integer;
+ { the first m prime numbers, in increasing order }
+@
+\section{The output phase}
+<<other constants of the program>>=
+rr = 50;
+cc = 4;
+ww = 10;
+<<variables of the program>>=
+`page_number: integer;
+`page_offset: integer;
+`row_offset: integer;
+c: 0..cc;
+@
+<<print table [[p]]>>=
+begin page_number := 1; page_offset := 1;
+while page_offset <= m do
+ begin <<output a page of answers>>;
+ page_number := page_number + 1;
+ page_offset := page_poffset + rr * cc;
+ end;
+end
+<<output a page of answers>>=
+begin write('The First ');
+write(m:1);
+write(' Prime Numbers --- Page ');
+write(page_number:1); write_ln; write_ln;
+ { there's a blank line after the heading }
+for row_offset := pages_offset to page_offset + rr - 1
+ do <<output a line of answers>>;
+page;
+end
+<<output a line of answers>>=
+begin for c := 0 to cc - 1 do
+ if for_offset + c * rr <= m then
+ write(p[row_offset + c * rr]);
+writeln;
+end
+@
+\section{Generating the primes}
+<<fill table [[p]] with the first [[m]] prime numbers>>=
+<<initialize the data structures>>
+while k < m do
+ begin <<increase [[j]] until it is the next prime number>>
+ k := k + 1; p[k] := j;
+ end
+<<variables of the program>>=
+j: integer; { all primes <= j are in table p }
+k: 0..m; { this many primes are in table p }
+<<increase [[j]] until it is the next prime number>>=
+repeat j := j + 2;
+ <<update variables that depend on [[j]]>>;
+ <<give to [[j_prime]] the meaning: [[j]] is a prime number>>
+until j_prime
+<<variables of the program>>=
+`j_prime: boolean;
+<<initialize the data structures>>=
+j := 1; k := 1; p[1] := 2;
+<<variables of the program>>=
+`ord: 2..ord_max;
+ { the smallest index >= 2 such that p_ord squared > j }
+`square: integer;
+ { square = p_ord squared }
+<<initialize the data structures>>=
+ord := 2; square := 9;
+<<other constants of the program>>=
+ord_max = 30; { p_ord_max squared must exceed p_m }
+<<update variables that depend on [[j]]>>=
+if j = square then
+ begin ord := ord + 1;
+ <<update variables that depend on [[ord]]>>
+ end
+<<update variables that depend on [[ord]]>>=
+square := p[ord] * p[ord]; { at this point ord <= k }
+@
+\section{The inner loop}
+<<give to [[j_prime]] the meaning: [[j]] is a prime number>>=
+n := 2; j_prime := true;
+while (n < ord) and j_prime do
+ begin <<if [[p[n]]] is a factor of [[j]], set [[j_prime := false]]>>;
+ n := n + 1;
+ end
+<<variables of the program>>=
+n: 2..ord_max; { runs from 2 to ord when testing divisibility }
+<<variables of the program>>=
+`mult: array [2..ord_max] of integer;
+ { runs through multiples of primes }
+<<update variables that depend on [[ord]]>>=
+mult[ord-1] := j;
+<<if [[p[n]]] is a factor of [[j]], set [[j_prime := false]]>>=
+while mult[n] < j do
+ mult[n] := mult[n] + p[n] + p[n];
+if mult[n] = j then j_prime := false;
+@
+\section{Index}
+\subsection{Chunks}
+\nowebchunks
+\subsection{Identifiers}
+\nowebindex
+
+\bibliographystyle{unsrt}
+\bibliography{web,cs,ramsey}
diff --git a/web/noweb/examples/scanner.nw b/web/noweb/examples/scanner.nw
new file mode 100644
index 0000000000..cb6372f8a4
--- /dev/null
+++ b/web/noweb/examples/scanner.nw
@@ -0,0 +1,444 @@
+% Norman Ramsey (nr@notecnirp) --- CS 320
+
+\def\sizedboxit#1#2{\vtop{\vbox{\hrule\hbox{\vrule\kern #2%
+ \vtop{\vbox{\kern #2\hbox{#1}}\kern #2}\kern #2\vrule}}\hrule}}
+\def\boxit#1{\sizedboxit{#1}{1pt}}
+\def\token#1{\boxit{\strut\tt #1}}
+
+\setcounter{secnumdepth}{0}
+
+% l2h ignore boxit
+% l2h argblock token tt
+@
+In this assignment I print intermediate code.
+<<grammatical C functions>>=
+void print6 (Exp e) {
+ extern int yylineno;
+ printf("line %d:\n",yylineno);
+ if (e.type==error_type)
+ printf("# ERROR\n");
+ else
+ printTree(e.tree,stdout);
+}
+<<grammatical C declarations>>=
+void print6(Exp e);
+@
+\section{The {\tt yacc} value stack}
+Here are all the objects I use as synthesized attributes:
+<<grammatical declarations>>=
+%union {
+ char *string;
+ Type type;
+ Product product;
+ Symbol symbol;
+ Exp exp;
+ Explist explist;
+ int bit;
+}
+@
+\section{3. Vocabulary and representation}
+\subsection{Representation of terminal symbols}
+{\tt yacc} and {\tt lex} use integers to represent terminal
+symbols (tokens).
+Single-character tokens are represented by their ASCII codes.
+Longer tokens are declared using {\tt yacc}'s [[%token]] declaration;
+{\tt yacc} chooses an integer representation of each such token.
+These representations are made available to the lexer via [[y.tab.h]].
+I use the standard trick from Kernighan and Pike ([[x.tab.h]] instead of
+[[y.tab.h]]) to avoid remaking the lexer unecessarily.
+<<lexical include files>>=
+#include "x.tab.h"
+@
+\subsection{1. Identifiers}
+Since {\tt lex} is notoriously slow at using patterns to recognize
+ reserved words, I look up every identifier in a table of reserved words.
+[[idcategory(id)]] returns the category of the reserved word [[id]]
+when [[id]] is in fact a reserved word.
+When [[id]] is not a reserved word, [[idcategory(id)]] returns [[IDENT]].
+<<lexical definitions>>=
+letter [A-Za-z]
+digit [0-9]
+@
+The offensive [[<INITIAL>]] below has to do with handling comments (q.v.).
+Both identifiers and reserved words
+are saved in the string table and put on the {\tt yacc} value stack.
+<<lexical rules>>=
+<INITIAL>{letter}({letter}|{digit})* { yylval.string = strsave(yytext);
+ return idcategory(yytext); }
+<<lexical C declarations>>=
+extern char *strsave(char *s);
+<<grammatical declarations>>=
+%token IDENT
+%type <string> IDENT
+<<grammatical rules>>=
+ident : IDENT
+ ;
+<<grammatical declarations>>=
+%type <string> ident
+<<grammatical C declarations>>=
+extern char yytext[];
+@
+\subsection{2. Numbers}
+I have to use two different [[ScaleFactor]] definitions
+so I can tell the difference between long and short reals.
+Notice that the scale factor is {\em not} optional for the long real.
+<<lexical rules>>=
+<INITIAL>{digit}+|{digit}({hexDigit}*)[Hh] { yylval.string = strsave(yytext);
+ return INTEGER; }
+<INITIAL>{digit}+"."{digit}*{EScaleFactor}? { yylval.string = strsave(yytext);
+ return REAL; }
+<INITIAL>{digit}+"."{digit}*{DScaleFactor} { yylval.string = strsave(yytext);
+ return LONGREAL; }
+<<grammatical declarations>>=
+%token <string> INTEGER REAL LONGREAL
+@
+I permit lower case where Wirth insists on upper case.
+This will be convenient later on.
+Besides, Hanson does it.
+
+I need parentheses around things like [[EScaleFactor]] because I'n not
+really defining a regular expression---I'm using a macro facility.
+<<lexical definitions>>=
+hexDigit [0-9A-Fa-f]
+EScaleFactor ([eE][+\-]?{digit}+)
+DScaleFactor ([dD][+\-]?{digit}+)
+@
+\subsection{3,4. Strings and character constants}
+Single character strings [["x"]] become character constants,
+not strings, thanks to the {\tt lex} disambiguation rules.
+<<lexical rules>>=
+<INITIAL>"\'"{nonquote}"\'" { yylval.string=strsave(yytext); return CHARCONST; }
+<INITIAL>{digit}{hexDigit}*[Xx] { yylval.string=strsave(yytext); return CHARCONST; }
+<INITIAL>"\""{nondoublequote}*"\"" { yylval.string=strsave(yytext); return STRING; }
+<<grammatical declarations>>=
+%token <string> CHARCONST STRING
+@
+The character set for string literals is awkward,
+because I want to include backslash escapes.
+I use the ANSI standard backslash escapes from section A2.5.2 of
+the second edition of Kernighan and Ritchie.
+Because the lexical analyzer is probably not the right place to
+handle illegal backslash escapes, I allow any reasonable
+character to follow the backslash.
+I define [[nonoctalx]] to be those characters
+that can't start an octal or hexadecimal constant (when following
+a backslash).
+Then I can recognize octal and hexdecimal character constants like [["\012"]].
+I {\em don't} insist that at least one [[hexDigit]] follow [[\x]],
+because again that should be handled downstream of the lexical analyzer.
+<<lexical definitions>>=
+plainnonquote [ \t\]\"!#$%&()*+,\-./0-9:;<=>?@A-Z[^_`a-z{|}~]
+plainnondoublequote [ \t\]\'!#$%&()*+,\-./0-9:;<=>?@A-Z[^_`a-z{|}~]
+escapedchar (\\({nonoctalx}|{octal}{octal}?{octal}?|x{hexDigit}*))
+nonoctalx [ \]\'\"!#$%&()*+,\-./89:;<=>?@A-Z[\\^_`a-wyz{|}~]
+nonquote ({plainnonquote}|{escapedchar})
+nondoublequote ({plainnondoublequote}|{escapedchar})
+octal [0-7]
+@
+I also need to handle strings that don't terminate.
+When I see one, I gobble up the whole line on which it sits---that should
+make it easier for the parser to recover.
+(The alternative is trying to tokenize the characters following the open
+quote.)
+<<lexical rules>>=
+<INITIAL>("\""{nondoublequote}*|"\'"{nonquote}*) <<complain; return bad string>>
+@
+I print the first few characters of a nonterminated string,
+followed by an ellipsis.
+I return the string anyway because that way there's a chance that the parser
+can just ignore the error.
+<<complain; return bad string>>=
+{ yyerror("Unterminated string %.8s%s",yytext,yyleng>8?"...":"");
+ yylval.string=strsave("");
+ return STRING;
+}
+@
+I include prototypes for the string functions, to keep {\tt lcc -A}
+from complaining about missing prototypes.
+<<common include files>>=
+#include <string.h>
+@
+\subsection{5. Operators and delimiters}
+Here are [[%token]] declarations for all the multicharacter tokens,
+including the reserved words.
+I use [[yyBEGIN]] because [[BEGIN]] means something special to {\tt lex}.
+<<grammatical declarations>>=
+%token ARROW INC DEC LSHIFT RSHIFT LEQ GEQ EQ NEQ AND OR
+ /* -> ++ -- @<< @>> <= >= == != && || */
+@
+I make sure the lexer always returns strings for identifiers
+and reserved words.
+@
+Recognizing the operators and delimiters is straightforward:
+<<lexical rules>>=
+<INITIAL>"->" return ARROW;
+<INITIAL>"++" return INC;
+<INITIAL>"--" return DEC;
+<INITIAL>"<<" return LSHIFT;
+<INITIAL>">>" return RSHIFT;
+<INITIAL>"<=" return LEQ;
+<INITIAL>">=" return GEQ;
+<INITIAL>"==" return EQ;
+<INITIAL>"!=" return NEQ;
+<INITIAL>"&&" return AND;
+<INITIAL>"||" return OR;
+<INITIAL>[\]+!\-*/~&.,;|()[{}^=#<>:] return *yytext;
+@
+\paragraph{Reserved word search}
+Recall that, instead of having the {\tt lex}-generated automaton
+recognize reserved words, I wanted to look up each identifier to see
+if it is a reserved word.
+I put the reserved words into an array and use binary search to find their
+categories.
+A word that isn't in the list has category [[IDENT]].
+
+The list itself is excruciating to read.
+I use a trick I got from Dave Hanson---I put the list in a header
+file as calls to the [[kw]] (keyword) macro.
+Then I include the header with appropriate macros wherever I need it.
+<<list of reserved words>>=
+kw(INT, "int")
+@
+A binary search table of reserved words:
+<<reserved word data structures>>=
+static
+struct reserved {char *s; int category;}
+reservedwords[] = {
+#define kw(VAL,STRING) {STRING,VAL},
+<<list of reserved words>>
+#undef kw
+};
+static int numreservedwords = (sizeof(reservedwords)/sizeof(struct reserved));
+@
+[[idcategory]] is just binary search.
+<<lexical C functions>>=
+<<reserved word data structures>>
+static int idcategory (char *id) {
+ int low=0, high=numreservedwords-1, mid;
+ int compare;
+ while (low <= high) {
+ /* Invariant: if id is in the initial range low...high,
+ it is in the current range low...high */
+ mid = (low+high)/2; /* note low <= mid <= high */
+ compare = strcmp(id,reservedwords[mid].s);
+ if (compare>0) low = mid + 1;
+ else if (compare<0) high = mid - 1;
+ else return reservedwords[mid].category;
+ }
+ return IDENT; /* id is not a reserved word */
+}
+<<lexical C declarations>>=
+static int idcategory(char *);
+@
+\subsection{Comments}
+I use the standard trick of defining a special state just for comments.
+A begin comment sends the lexer into state [[<COMMENT>]], and an
+end comment returns it to state [[<INITIAL>]].
+All tokens that aren't comments are recognized only in state [[<INITIAL>]],
+which explains the offensive [[<INITIAL>]] prepended to every rule.
+
+<<lexical definitions>>=
+%S COMMENT
+<<lexical rules>>=
+<INITIAL>"/*" BEGIN COMMENT;
+<COMMENT>"*/" BEGIN INITIAL;
+<COMMENT>"\n" ;
+<COMMENT>. ;
+@
+\subsection{Whitespace and bad characters}
+<<lexical rules>>=
+<INITIAL>[ \t\n]+ ; /* ignore whitespace */
+<INITIAL>. <<complain about a bad character>>
+@
+The error message we print is different for printable and nonprintable
+characters.
+<<complain about a bad character>>=
+{ if (*yytext >= ' ' && *yytext < 0177)
+ yyerror("bad character `%c'", *yytext);
+ else yyerror("bad character `\\%03o'", *yytext);
+}
+@
+\section{8. Expressions}
+\subsection{8.1 Operands (designators and constants)}
+There are no qualified identifiers, so this simplifies the parsing
+of designators.
+It is a bit awkward to distinguish variables and parameters from
+constant identifiers.
+There is also an awkwardness with rvalues---boolean expressions
+have to be converted from ``test'' to values using [[BOOL]].
+Following a suggestion of Hanson's, I use
+three nonterminals: [[exp]] is an expression (possibly a test);
+[[rvalue]] is an rvalue (never a test), and
+[[lvalue]] is an lvalue.
+I introduce [[complex_lvalue]] because I need to distinguish identifiers from
+all other lvalues (otherwise I get a reduce-reduce conflict when converting
+lvalues to expressions).
+@
+<<grammatical declarations>>=
+%type <exp> arraydes lvalue complex_lvalue rvalue exp
+@
+Here are productions for all the C literals.
+I use [[make_constval(type,string)]] to convert a string to a value of
+the type desired.
+
+I issue warnings for long reals, since they aren't supported in Oberon/320.
+<<grammatical rules>>=
+exp : INTEGER { $$ = make_constval(integer_type,$1); }
+ | REAL { $$ = make_constval(real_type,$1); }
+ | LONGREAL { warning("Long reals not supported (replaced with zero)");
+ $$ = make_constval(real_type,strsave("0.0")); }
+ | CHARCONST { $$ = make_constval(char_type,$1); }
+ | STRING { $$ = make_constval(build_array(0,stringchar_type),$1); }
+ ;
+@
+\subsection{8.2 Operators}
+I use {\tt yacc} precedence declarations.
+
+These declarations define precedence.
+My task is much simplified because unary and binary [[-]] have
+exactly the same precedence.
+<<grammatical declarations>>=
+%left OR
+%left AND
+%left '|'
+%left '^'
+%left '&'
+%left EQ NEQ
+%left '<' '>' LEQ GEQ
+%left LSHIFT RSHIFT
+%left '+' '-'
+%left '*' '/' '%'
+%right '!' '~' INC DEC /* unary operators */
+%left ARROW '.'
+@
+[[binop]] checks types and generates intermediate code.
+Consult the chapter on typechecking for the description of the
+correct operation of [[binop]] and the meanings of
+various permissions [[p_xxx]].
+<<grammatical rules>>=
+complex_lvalue : lvalue '.' ident { $$ = find_field($1,$3); }
+ | exp ARROW ident { $$ = find_field(deref($1),$3) }
+ | '*' rvalue { $$ = deref($1); }
+ | arraydes ']' { $$ = $1; }
+ ;
+
+arraydes : rvalue '[' exp { $$ = subscript($1,$3); }
+ ;
+
+lvalue : complex_lvalue { $$ = $1; }
+ | ident { $$ = lookup_lvalue($1); }
+ ;
+
+exp : complex_lvalue { $$.type=$1.type;
+ $$.tree=tMEM($1.type->size,$1.tree); }
+ | ident { $$ = lookup_exp($1); }
+ ;
+
+rvalue : exp { $$ = boolval($1); }
+ ;
+<<grammatical rules>>=
+exp : exp EQ exp { $$ = binop(OSeq, $1,$3,boolean_type,p_equality); }
+ | exp NEQ exp { $$ = binop(OSneq,$1,$3,boolean_type,p_equality); }
+ | exp '<' exp { $$ = binop(OSlt, $1,$3,boolean_type,p_relational); }
+ | exp LEQ exp { $$ = binop(OSleq,$1,$3,boolean_type,p_relational); }
+ | exp '>' exp { $$ = binop(OSgt, $1,$3,boolean_type,p_relational); }
+ | exp GEQ exp { $$ = binop(OSgeq,$1,$3,boolean_type,p_relational); }
+ ;
+exp : exp '+' exp { $$ = binop(OSplus, $1,$3,0,p_numeric); }
+ | exp '-' exp { $$ = binop(OSminus,$1,$3,0,p_numeric); }
+ | exp OR exp { $$ = binop(OSor, $1,$3,0,p_boolean); }
+ ;
+exp : exp '*' exp { $$ = binop(OSmul, $1,$3,0,p_numeric); }
+ | exp AND exp { $$ = binop(OSand,$1,$3,0,p_boolean); }
+ ;
+exp : '(' exp ')' { $$ = $2; }
+ ;
+@
+\subsection{Function calls}
+Calls to functions (procedures having a return type)
+may occur {\em only} as factors in the production given below.
+The
+bottom of p.~678 of the Oberon report makes it clear that the~[[()]] are
+required even if the function has no parameters.
+<<not yet grammatical rules>>=
+exp : ident ActualParameters { $$ = fcall($1,$2); }
+ ;
+
+ActualParameters: '(' ExpList ')' { $$ = $2; }
+ | '(' ')' { $$ = 0; }
+ ;
+
+ExpList : rvalue ',' ExpList { $$ = explist($1,$3); }
+ | rvalue { $$ = explist($1,0); }
+ ;
+<<not yet grammatical declarations>>=
+%type <explist> ActualParameters ExpList
+@
+\section{11. Compilation units}
+<<grammatical rules>>=
+module : exp { compile($1); }
+<<grammatical declarations>>=
+%start module
+@
+\section{Error recovery}
+Here are some simple error productions that might help the parser continue.
+The first four gobble up mangled declarations.
+The last two are stabs in the dark; I hope they give the parser a chance
+to recover from errors in statements and expressions.
+<<grammatical rules>>=
+exp : error { $$.type = error_type; }
+@
+\section{Putting it all together}
+Here are the necessary {\tt\#include} files:
+<<common include files>>=
+#include <assert.h>
+#include <stdio.h>
+#include "types.h"
+#include "predef.h"
+#include "tree.h"
+#include "typecheck.h"
+#include "codegen.h"
+#include "symbol.h"
+#include "declarations.h"
+#include "constants.h"
+#include "errors.h"
+@
+There are no include files used exclusively by the parser.
+This is because the lexer sees {\tt y.tab.h}, and so has to know everything
+the parser knows.
+<<grammatical include files>>=
+
+@
+This is boilerplate for every {\tt lex} specification ever written:
+<<lexer>>=
+%{
+<<common include files>>
+<<lexical include files>>
+<<lexical C declarations>>
+%}
+<<lexical definitions>>
+%%
+<<lexical rules>>
+%%
+<<lexical C functions>>
+@
+And this is boilerplate for every {\tt yacc} specification ever written:
+<<parser>>=
+%{
+<<common include files>>
+<<grammatical include files>>
+<<grammatical C declarations>>
+extern int yylex(void);
+%}
+<<grammatical declarations>>
+%%
+<<grammatical rules>>
+%%
+#define lint /* keep lcc from barking about no reference to yaccpar_sccsid */
+<<grammatical C functions>>
+@
+\section{Indices}
+\subsection{Chunks}
+\nowebchunks
+\subsection{Identifiers}
+\nowebindex
diff --git a/web/noweb/examples/sharpline b/web/noweb/examples/sharpline
new file mode 100755
index 0000000000..5682c942b8
--- /dev/null
+++ b/web/noweb/examples/sharpline
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# noweb filter to handle #line directives in noweb input
+#
+# sample usage:
+#
+# preprocessor files | notangle -L -filter sharpline - > result.c
+#
+
+nawk '
+BEGIN { linestart = 1 }
+/^(@nl|@index nl)$/ { linestart = 1; print; next }
+/^@text #line +[0-9]+$/ {
+ if (linestart)
+ printf "@line %d\n", $3
+ else
+ print
+ linestart = 0; next
+}
+/^@text #line +[0-9]+ +".*"$/ {
+ if (linestart) {
+ thisline = $3
+ sub(/^@text #line +[0-9]+ +/, "")
+ thisfile = substr($0, 2, length($0) - 2)
+ printf "@file %s\n@line %d\n", thisfile, thisline
+ } else
+ print
+ linestart = 0; next
+}
+/^@(text |quote )/ { linestart = 0 }
+{ print }' "$@"
diff --git a/web/noweb/examples/test.nw b/web/noweb/examples/test.nw
new file mode 100644
index 0000000000..c69da5a0ce
--- /dev/null
+++ b/web/noweb/examples/test.nw
@@ -0,0 +1,17 @@
+% Copyright 1991 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+<<*>>=
+one <<two>> <<three>> # uses two and three
+@ %def one
+<<two>>=
+first of two
+second of two
+third of two
+@ %def fish fowl duck
+@ %def two
+<<three>>=
+first of three
+ second of three
+ third of three
+@ %def three
+
diff --git a/web/noweb/examples/tree.nw b/web/noweb/examples/tree.nw
new file mode 100644
index 0000000000..43613fb431
--- /dev/null
+++ b/web/noweb/examples/tree.nw
@@ -0,0 +1,326 @@
+\section{Generating decision trees}
+
+The crux of the problem is to transform a {\em case statement} into a
+{\em decision tree}. A case statement has a {\em value}, a sequence
+of {\em arms}, and a {\em trailer}.
+Each arm has a pattern, and code to be executed.
+When the case statement is executed, it chooses the first arm whose
+pattern matches the value, then executes the corresponding code, then
+executes the trailer.
+I generate a {\em decision tree} to do the job.
+Each internal node of the decision tree tests a field of the value.
+It then chooses an edge (child) based on that value, and continues
+testing fields until it reaches a leaf, at which time it executes the
+code associated with that leaf.
+
+The goal of tree generation is not to generate just any tree, but the
+tree with the fewest nodes. This problem is NP-complete, so I apply
+a few heuristics. The results, at least for the machine descriptions
+I use, seem to be as good as what I would come up with by hand.
+@
+The arms of the case statement have some extra information.
+The file and line number help with error message and make it possible
+to generate [[#line]] statements that identify the source of the code.
+The original arm gives the arm from which the current arm is derived,
+and is useful for many of the heuristics.
+<<*>>=
+record caserec(arms,valcode,trailer)
+ # case arms, code to compute value, trailing code
+record arm(file, line, pattern, code, original)
+ # pattern and code are the content
+ # line, file, original(pattern) are used for error reporting
+@
+Each node of the decision tree is associated with a particular case
+statement.
+Internal nodes have children, and a [[field]] which says which field
+we decided to test on. The edges that point to the children record
+the interval of values for the particular child.
+Leaf nodes have a [[name]] that records the name of the pattern known
+to match at that leaf node.
+<<*>>=
+record node(cs, children, field, name)
+ # case statement, list of edges to children, field chosen, pattern name
+ # (name field used to support name operator, assigned only to leaves)
+record edge(node, lo, hi)
+ # node pointed to and lo and hi interval of field for this edge
+@
+To create a decision tree, I begin with a node containing the full,
+original case statement. I then use a ``work queue'' approach to check
+each node and see if it needs to be split.
+If no pattern matches the node, or if the first pattern always matches
+(with a unique name), no further splitting needs to be done, and I
+assign a name to the leaf.\footnote{If the name isn't used, I assign
+the name [["-unused-"]], because that will make it easier to combine
+nodes in the dagging phase.}
+Otherwise, I split the node.
+<<*>>=
+procedure needs_splitting(n)
+ if *n.cs.arms = 0 then fail
+ p := n.cs.arms[1].pattern
+ name := \p.disjuncts[1].name | p.name
+ every d := !p.disjuncts do {
+ n := \d.name | p.name
+ if n ~=== name then return # different names, needs splitting
+ else if *d.constraints = 0 then fail # always matches, needn't split
+ }
+ return # pattern doesn't always match -> split
+end
+
+procedure tree(cs)
+ static heuristics
+ initial heuristics := [leafarms, childarms, nomatch, childdisjuncts, branchfactor]
+
+ root := node(cs)
+ work := [edge(root)] # work queue of edges (nodes) to be expanded
+ while n := get(work).node do
+ if needs_splitting(n) then {
+ <<split node [[n]] and add children to work queue>>
+ } else {
+ if *n.cs.arms = 0 then
+ n.name := "-NOMATCH-"
+ else if n.cs.arms[1].code ? find_id("name") then {
+ p := n.cs.arms[1].pattern
+ n.name := \p.disjuncts[1].name | \p.name | "-unnamed-"
+ } else
+ n.name := &null
+ if \mapnames then n.name := map(\n.name)
+ }
+ return root
+end
+@
+Splitting a node involves choosing a field, finding out which intervals
+of values of that field are interesting, and creating a child node for
+each such interval of values. The patterns in the case statement of the
+child node reflect the knowledge of the value interval of the tested
+field.
+
+I make the decision by splitting the node on {\em each} field
+mentioned in the case statement. I then compute some heuristic
+functions of the children from each splitting and use the
+best-scoring field.
+
+Some debugging information may be written to [[hdebug]] or [[sdebug]].
+<<split node [[n]] and add children to work queue>>=
+fields := mentions(n.cs)
+*fields > 0 | impossible("internal node mentions no fields")
+candidates := table()
+every f := !fields do
+ candidates[f] := split(n, f)
+<<if debugging, split all and report>>
+*fields > 1 & write(\hdebug, "Choosing one of ", patimage(fields))
+every h := !heuristics do {
+ if *fields = 1 then break
+ fields := findmaxima(h, candidates, fields)
+write(\hdebug, image(h), " chose ", patimage(fields))
+}
+*fields > 0 | impossible("no fields")
+*fields = 1 | write(\hdebug, "tie among fields", patimage(fields), " near ",
+ image(n.cs.arms[1].original.file), ", line ",
+ n.cs.arms[1].original.line)
+work |||:= n.children := candidates[n.field := ?fields]
+<<if debugging, split all and report>>=
+if \tryall & \hdebug & *fields > 1 then {
+ write(\hdebug, repl("=",10), " Splitting ", repl("=", 10))
+ every findmaxima(!heuristics, candidates, fields) do write(\hdebug)
+ write(\hdebug, repl("=", 30), "\n")
+}
+@
+To split a node, I look at each interval of values that might be
+interesting. I apply that interval to the case statement, and if there
+can be any match, I create and add a new child node.
+<<*>>=
+procedure split(n, f)
+ local vals,v,d,val,c,p,j,i,newd,cst,child,newp
+
+ patterns := []
+ children := []
+ every put(patterns, (!n.cs.arms).pattern)
+ r := intervals(patterns, f)
+ <<if debugging, write about splitting this node>>
+
+ every i := 1 to *r - 1 do
+ put(children, edge(node(apply(n.cs, f, r[i], r[i+1]),[]), r[i], r[i+1]))
+
+ write(\sdebug, "Done splitting.\n")
+ return children
+end
+<<if debugging, write about splitting this node>>=
+writes(\sdebug, "Splitting ")
+outpattern(\sdebug, patterns[1])
+every i := 2 to *patterns do { writes(\sdebug, " | "); outpattern(\sdebug, patterns[i])}
+write(\sdebug, " on ", f.name)
+@
+So, what is the new case statement that results from applying
+$\tt lo \le f < hi$ to [[cs]]?
+For each arm, I match the pattern against the interval.
+If it succeeds, I create a new arm for the new case statement,
+containing the reduced pattern.
+<<*>>=
+procedure apply(cs, f, lo, hi)
+ result := copy(cs)
+ result.arms := []
+ write(\sdebug, " Applying ", stringininterval(f.name, lo, hi))
+ every a := !cs.arms do
+ put(result.arms,
+ arm(a.file, a.line, pmatch(a.pattern, f, lo, hi), a.code, a.original))
+ if alwaysmatches(result.arms[1].pattern) then
+ result.arms := [result.arms[1]]
+ return result
+end
+
+# if lo <= f < hi and p matches, return the new p
+
+procedure pmatch(p, f, lo, hi)
+ result := pattern([], p.name)
+ every d := !p.disjuncts do
+ if c := !d.constraints & c.field === f then # disjunct mentions f
+ if c.lo <= lo & hi <= c.hi then { # this constraint is matched
+ newd := disjunct([], d.name)
+ every c := !d.constraints & c.field ~=== f do
+ put(newd.constraints, c)
+ put(result.disjuncts, newd)
+ } else
+ c.hi <= lo | c.lo >= hi | impossible("bad intervals")
+ else # disjunct does not mention f
+ put(result.disjuncts, d)
+ <<if debugging, write about results of [[pmatch]]>>
+ if *result.disjuncts > 0 then return result
+end
+
+<<if debugging, write about results of [[pmatch]]>>=
+if *result.disjuncts > 0 then writes(\sdebug, " ===> ") & outpattern(\sdebug, p)
+# else writes(\sdebug, " ") & outpattern(\sdebug, p)
+
+if *result.disjuncts > 0 then write(\sdebug, " matches")
+# else write(\sdebug, " does not match")
+@
+\subsection{Tree-minimization heuristics}
+First, the boilerplate that takes a heuristic [[h]], candidate
+splittings, and a set of fields, and returns the set of fields with
+the largest score on [[h]].
+<<*>>=
+procedure findmaxima(h, candidates, fields)
+ local max
+ S := []
+ every f := !fields do {
+ score := h(candidates[f], f)
+ write(\hdebug,"Field ", f.name, " scores ", score, " on ", image(h))
+ /max := score - 1
+ if score > max then {
+ max := score
+ S := [f]
+ } else if score = max then
+ put(S, f)
+ }
+ return set(S)
+end
+@
+Here's a big pile of heuristics.
+I'm not sure I've ever needed more than the first two, but they're
+amusing and easy enough to write.
+<<*>>=
+# leafarms: prefer candidate with most arms that appear at leaf
+# nodes. Each original arm counted only once.
+# Not matching is also counted as an arm.
+
+procedure leafarms(children, f)
+ arms := set()
+ every n := (!children).node & *n.cs.arms > 0 do
+ if not needs_splitting(n) then
+ insert(arms, n.cs.arms[1].original)
+ return *arms + if *(!children).node.cs.arms = 0 then 1 else 0
+end
+
+# childarms: prefer the candidate with the fewest arms in children
+
+procedure childarms(children, f)
+ sum := 0
+ every sum -:= *(!children).node.cs.arms
+ return sum
+end
+
+# nomatch: if tied on leafarms and childarms, take candidate
+# with real leaf in preference to nomatch leaf
+
+procedure nomatch(children, f)
+ return if *(!children).node.cs.arms = 0 then -1 else 0
+end
+
+# childdisjuncts: prefer the candidate with the fewest disjuncts in children
+
+procedure childdisjuncts(children, f)
+ sum := 0
+ every sum -:= *(!(!children).node.cs.arms).pattern.disjuncts
+ return sum
+end
+
+# branchfactor: prefer the candidate with the fewest children
+
+procedure branchfactor(children, f)
+ return - *children
+end
+@
+\subsection{Utility functions}
+<<*>>=
+# If f is to be used to split patterns, what intervals need to be considered?
+
+procedure intervals(patterns, f)
+ cuts := set([0, 2^(f.hi - f.lo)])
+ every p := !patterns & d := !p.disjuncts & c := !d.constraints & c.field === f do
+ every insert(cuts, c.lo | c.hi)
+ return sort(cuts)
+end
+
+# what fields are mentioned in a case statement?
+
+procedure mentions(cs)
+ result := set()
+ every a := !cs.arms & d := !a.pattern.disjuncts & c := !d.constraints do
+ insert(result, c.field)
+ return result
+end
+
+# find_id: tab to and past identifier id, returning its position
+# ignores quotes, comment brackets
+
+procedure find_id(id)
+ static notlnum
+ initial notlnum := ~ (&letters ++ &digits ++ '_')
+ tab(p := find(id)) & p = 1 | (move(-1) & any(notlnum) & move(1)) &
+ =id & pos(0) | any(notlnum) & suspend p
+end
+@
+\subsection{Tree checking}
+Once the tree is generated, it's useful to check it for redundant arms
+and for arms that never match. These checks will help users catch
+mistakes in their specifications. Note that I must check the
+``original'' arms; that's why they're there.
+<<*>>=
+procedure checktree(n)
+ originals := set()
+ every insert(originals, (!n.cs.arms).original)
+ deletematching(n, originals)
+ every a := !originals do
+ warning("No word matches pattern at ", image(a.file), ", line ", a.line)
+ if hasnomatch(n) then
+ warning("Case statement at ", image(n.cs.arms[1].file), ", line ",
+ n.cs.arms[1].line - 1, " doesn't cover all cases")
+ return n
+end
+
+procedure deletematching(n, originals)
+ if *originals = 0 then return
+ else if *n.children > 0 then every deletematching((!n.children).node, originals)
+ else every delete(originals, (!n.cs.arms).original)
+end
+
+procedure hasnomatch(n)
+ if *n.children > 0 then return hasnomatch((!n.children).node)
+ else if *n.cs.arms = 0 then return # found it
+end
+@
+\section{Indices}
+\subsection{Chunks}
+\nowebchunks
+\subsection{Identifiers}
+\nowebindex
diff --git a/web/noweb/examples/wc.bbl b/web/noweb/examples/wc.bbl
new file mode 100644
index 0000000000..363d36fbe7
--- /dev/null
+++ b/web/noweb/examples/wc.bbl
@@ -0,0 +1,14 @@
+\begin{thebibliography}{1}
+
+\bibitem{guntermann:cweb}
+Klaus Guntermann and Joachim Schrod.
+\newblock {{\tt WEB}} adapted to {C}.
+\newblock {\em {TUG}boat}, 7(3):134--137, October 1986.
+
+\bibitem{knuth:literate:book}
+Donald~E. Knuth.
+\newblock {\em Literate Programming}, volume~27 of {\em Center for the Study of
+ Language and Information Lecture Notes}.
+\newblock Leland Stanford Junior University, Stanford, California, 1992.
+
+\end{thebibliography}
diff --git a/web/noweb/examples/wc.nw b/web/noweb/examples/wc.nw
new file mode 100644
index 0000000000..16ec82e7bf
--- /dev/null
+++ b/web/noweb/examples/wc.nw
@@ -0,0 +1,372 @@
+\makeatletter
+\def\idxexample#1{\nwix@id@uses#1}
+\makeatother
+
+\section{An example of {\tt noweb}}
+The following short program illustrates the use of {\tt noweb},
+a low-tech tool for literate programming.
+The purpose of the program is to provide a basis for
+comparing {\tt WEB} and {\tt noweb}, so I have used a program that has
+been published before;
+the text, code, and presentation are taken
+from~\cite[Chapter~12]{knuth:literate:book}.
+The notable differences are:
+\begin{itemize}
+\item
+When displaying source code,
+{\tt noweb} uses different typography.
+In particular, {\tt WEB} makes good use of multiple fonts
+and the ablity to typeset mathematics, and it may use
+ mathematical symbols in place of C~symbols (e.g.
+``$\land$'' for ``{\tt \&\&}'').
+{\tt noweb} uses a single fixed-width font for code.
+\item
+{\tt noweb} can work with {\LaTeX}, and I have used {\LaTeX} in this example.
+\item
+{\tt noweb} has no numbered ``sections.''
+\ifx\wbn\undefined
+When numbers are needed for cross-referencing, {\tt noweb} uses page
+numbers.
+\else
+When numbers are needed for cross-referencing, {\tt noweb} ordinarily uses page
+numbers.
+\fi
+If two or more chunks appear on a page, for example, page~24, they are
+distinguished by appending a letter to the page number, for example,
+24a or 24b.
+\ifx\wbn\undefined\else
+{\LaTeX} computes these page numbers, but since {\LaTeX} is not used
+in the production of {\it IEEE Software}, this example uses
+consecutive ``chunk numbers'' instead of page numbers.
+\fi
+\item
+{\tt noweb} has no special support for macros.
+In the sample program, I have used the chunk
+``\LA{}Definitions~{\nwtagstyle{}\subpageref{NWwc.5-DefB-1}}\RA{}'' to hold
+macro definitions.
+\item
+{\tt noweb} does not recognize C~identifier definitions automatically,
+so I had to add a list of defined identifiers to each code chunk.
+Because {\tt noweb} is language-independent, it must use a heuristic
+to find uses of identifiers.
+This heuristic can be fooled into finding false ``uses''
+in comments or string literals, such as the use of
+{\tt status} in chunk~\subpageref{NWwc.5-DefB-1}.
+\item
+The {\tt CWEB} version of this program has semicolons following most uses
+of \LA$\cdots$\RA{}.
+{\tt WEB} needs the semicolon or its equivalent to make
+its prettyprinting come out right.
+Because it does not attempt prettyprinting, {\tt noweb} needs no semicolons.
+\item
+Both {\tt WEB} and {\tt noweb} write chunk cross-reference information in
+{\footnotesize footnote} font below each code chunk, for example,
+``{\footnotesize\let\nwcodecomment=\relax\nwused{\\{NWwc.5-TheG-1}}}''
+Unlike {\tt WEB}, {\tt noweb} also includes cross-reference
+information for identifiers, for example,
+``{\footnotesize Defines
+{\let\nwcodecomment=\relax\idxexample{{file\_count}{file:uncount}}}}''
+This information is generated using the {\tt @~\%def} markings in the
+{\tt noweb} source.
+\end{itemize}
+
+\subsection{Counting words}
+This example, based on a program by Klaus Guntermann and
+Joachim Schrod~\cite{guntermann:cweb} and a program by Silvio Levy and
+D. E. Knuth~\cite[Chapter~12]{knuth:literate:book}, presents the ``word count''
+program from {\sc Unix}, rewritten in {\tt noweb} to demonstrate
+literate programming using {\tt noweb}.
+The level of detail in this document is intentionally high, for
+didactic purposes; many of the things spelled out here don't need to
+be explained in other programs.
+
+The purpose of {\tt wc} is to count lines, words, and/or characters in
+a list of files.
+The number of lines in a file is the number of newline characters it
+contains.
+The number of characters is the file length in bytes.
+A ``word'' is a maximal sequence of consecutive characters other than
+newline, space, or tab, containing at least one visible ASCII code.
+(We assume that the standard ASCII code is in use.)
+
+\bigskip
+@
+Most literate C programs share a common structure.
+It's probably a good idea to state the overall structure explicitly at
+the outset, even though the various parts could all be introduced in
+chunks named \LA{*}\RA{} if we wanted to add them piecemeal.
+
+Here, then, is an overview of the file {\tt wc.c} that is defined by
+the {\tt noweb} program {\tt wc.nw}:
+<<*>>=
+<<Header files to include>>
+<<Definitions>>
+<<Global variables>>
+<<Functions>>
+<<The main program>>
+@
+We must include the standard I/O definitions, since we want to send
+formatted output to [[stdout]] and [[stderr]].
+<<Header files to include>>=
+#include <stdio.h>
+@
+
+The [[status]] variable will tell the operating system if the run was
+successful or not, and [[prog_name]] is used in case there's an error
+message to be printed.
+<<Definitions>>=
+#define OK 0
+ /* status code for successful run */
+#define usage_error 1
+ /* status code for improper syntax */
+#define cannot_open_file 2
+ /* status code for file access error */
+<<Global variables>>=
+int status = OK;
+ /* exit status of command, initially OK */
+char *prog_name;
+ /* who we are */
+@
+
+Now we come to the general layout of the [[main]]
+function.
+<<The main program>>=
+main(`argc, `argv)
+ int argc;
+ /* number of arguments on UNIX command line */
+ char **argv;
+ /* the arguments, an array of strings */
+{
+ <<Variables local to [[main]]>>
+ prog_name = argv[0];
+ <<Set up option selection>>
+ <<Process all the files>>
+ <<Print the grand totals if there were multiple files>>
+ exit(status);
+}
+@
+
+If the first argument begins with a `{\tt-}', the
+user is choosing the desired counts and specifying
+the order in which they should be displayed.
+Each selection is given by the
+initial character (lines, words, or characters).
+For example, `{\tt-cl}' would cause just the
+number of characters and the number of lines to
+be printed, in that order.
+
+We do not process this string now; we simply remember where it is.
+It will be used to control the formatting at output time.
+<<Variables local to [[main]]>>=
+int file_count;
+ /* how many files there are */
+char *which;
+ /* which counts to print */
+<<Set up option selection>>=
+which = "lwc";
+ /* if no option is given, print 3 values */
+if (argc > 1 && *argv[1] == '-') {
+ which = argv[1] + 1;
+ argc--;
+ argv++;
+}
+file_count = argc - 1;
+@
+
+Now we scan the remaining arguments and try to open a file, if possible.
+The file is processed and its statistics are given.
+We use a [[do ... while]] loop because we should read from the standard
+input if no file name is given.
+<<Process all the files>>=
+argc--;
+do {
+ <<If a file is given, try to open [[*(++argv)]]; [[continue]] if unsuccessful>>
+ <<Initialize pointers and counters>>
+ <<Scan file>>
+ <<Write statistics for file>>
+ <<Close file>>
+ <<Update grand totals>>
+ /* even if there is only one file */
+} while (--argc > 0);
+@
+
+Here's the code to open the file. A special trick allows us to handle
+input from [[stdin]] when no name is given.
+Recall that the file descriptor to [[stdin]] is~0; that's what we use
+as the default initial value.
+<<Variables local to [[main]]>>=
+int `fd = 0;
+ /* file descriptor, initialized to stdin */
+<<Definitions>>=
+#define READ_ONLY 0
+ /* read access code for system open */
+<<If a file is given, try to open [[*(++argv)]]; [[continue]] if unsuccessful>>=
+if (file_count > 0
+&& (fd = open(*(++argv), READ_ONLY)) < 0) {
+ fprintf(stderr,
+ "%s: cannot open file %s\n",
+ prog_name, *argv);
+ status |= cannot_open_file;
+ file_count--;
+ continue;
+}
+<<Close file>>=
+close(fd);
+@
+We will do some homemade buffering in order to speed things up:
+Characters will be read into the [[buffer]] array before we process
+them.
+To do this we set up appropriate pointers and counters.
+<<Definitions>>=
+#define buf_size BUFSIZ
+ /* stdio.h BUFSIZ chosen for efficiency */
+<<Variables local to [[main]]>>=
+char buffer[buf_size];
+ /* we read the input into this array */
+register char *ptr;
+ /* first unprocessed character in buffer */
+register char *buf_end;
+ /* the first unused position in buffer */
+register int c;
+ /* current char, or # of chars just read */
+int in_word;
+ /* are we within a word? */
+long word_count, line_count, char_count;
+ /* # of words, lines, and chars so far */
+<<Initialize pointers and counters>>=
+ptr = buf_end = buffer;
+line_count = word_count = char_count = 0;
+in_word = 0;
+@
+
+The grand totals must be initialized to zero at the beginning of the
+program.
+If we made these variables local to [[main]], we would have to do this
+initialization explicitly; however, C's globals are automatically
+zeroed. (Or rather, ``statically zeroed.'') (Get it?)
+<<Global variables>>=
+long tot_word_count, tot_line_count,
+ tot_char_count;
+ /* total number of words, lines, chars */
+@
+
+\vskip0pt plus3in\penalty-500\vskip0pt plus-3in
+The present chunk, which does the counting that is {\tt wc}'s {\em
+raison d'\^etre}, was actually one of the simplest to write.
+We look at each character and change state if it begins or ends a word.
+<<Scan file>>=
+while (1) {
+ <<Fill [[buffer]] if it is empty; [[break]] at end of file>>
+ c = *ptr++;
+ if (c > ' ' && c < 0177) {
+ /* visible ASCII codes */
+ if (!in_word) {
+ word_count++;
+ in_word = 1;
+ }
+ continue;
+ }
+ if (c == '\n') line_count++;
+ else if (c != ' ' && c != '\t') continue;
+ in_word = 0;
+ /* c is newline, space, or tab */
+}
+@
+
+Buffered I/O allows us to count the number of characters almost for
+free.
+<<Fill [[buffer]] if it is empty; [[break]] at end of file>>=
+if (ptr >= buf_end) {
+ ptr = buffer;
+ c = read(fd, ptr, buf_size);
+ if (c <= 0) break;
+ char_count += c;
+ buf_end = buffer + c;
+}
+@
+
+It's convenient to output the statistics by defining a new function
+[[wc_print]]; then the same function can be used for the totals.
+Additionally we must decide here if we know the name of the file we have
+processed or if it was just [[stdin]].{\hfuzz=11.1pt\par}
+<<Write statistics for file>>=
+wc_print(which, char_count, word_count,
+ line_count);
+if (file_count)
+ printf(" %s\n", *argv); /* not stdin */
+else
+ printf("\n"); /* stdin */
+@
+<<Update grand totals>>=
+tot_line_count += line_count;
+tot_word_count += word_count;
+tot_char_count += char_count;
+@
+
+We might as well improve a bit on {\sc Unix}'s {\tt wc} by displaying
+the number of files too.
+<<Print the grand totals if there were multiple files>>=
+if (file_count > 1) {
+ wc_print(which, tot_char_count,
+ tot_word_count, tot_line_count);
+ printf(" total in %d files\n", file_count);
+}
+@
+
+Here now is the function that prints the values according to the
+specified options.
+The calling routine is supposed to supply a newline.
+If an invalid option character is found we inform the user about proper
+usage of the command.
+Counts are printed in 8-digit fields so that they will line up in
+columns.
+<<Definitions>>=
+#define print_count(n) printf("%8ld", n)
+<<Functions>>=
+wc_print(which, char_count, word_count, line_count)
+ char *which; /* which counts to print */
+ long char_count, word_count, line_count;
+ /* given totals */
+{
+ while (*which)
+ switch (*which++) {
+ case 'l': print_count(line_count);
+ break;
+ case 'w': print_count(word_count);
+ break;
+ case 'c': print_count(char_count);
+ break;
+ default:
+ if ((status & usage_error) == 0) {
+ fprintf(stderr,
+ "\nUsage: %s [-lwc] [filename ...]\n",
+ prog_name);
+ status |= usage_error;
+ }
+ }
+}
+@
+
+Incidentally, a test of this program against the system {\tt wc}
+command on a SPARCstation showed that the ``official'' {\tt wc} was
+slightly slower.
+Furthermore, although that {\tt wc} gave an appropriate error message
+for the options `{\tt-abc}', it made no complaints about the options
+`{\tt-labc}'!
+Dare we suggest that the system routine might have been better if its
+programmer had used a more literate approach?
+@
+
+\section*{List of code chunks}
+This list is generated automatically.
+The numeral is that of the first definition of the chunk.
+\nowebchunks
+%\begin{multicols}{2}[
+\section*{Index}
+Here is a list of the identifiers used, and where they appear.
+Underlined entries indicate the place of definition.
+This index is generated automatically.
+%]
+\nowebindex
+%\end{multicols}
+
diff --git a/web/noweb/examples/wc.nw2html b/web/noweb/examples/wc.nw2html
new file mode 100644
index 0000000000..6067d7768c
--- /dev/null
+++ b/web/noweb/examples/wc.nw2html
@@ -0,0 +1,370 @@
+<html>
+<HEAD>
+<title>An Example of noweb</title></HEAD>
+<BODY>
+
+<H1>An Example of noweb</H1>
+<address>Norman Ramsey<br>
+Dept. of Computer Science, Princeton University<br>
+Princeton, NJ 08544
+</address>
+
+<h2><a name="contents">Contents</a></h2>
+<ul>
+<li><a href="#intro">Introduction</a>
+<li><a href="#counting">Counting words</a>
+<li><a href="#index">Index</a>
+</ul>
+
+<h2><a name="intro">Introduction</a></h2>
+
+The following short program illustrates the use of <tt>noweb</tt>,
+a low-tech tool for literate programming.
+The purpose of the program is to provide a basis for
+comparing <tt>WEB</tt> and <tt>noweb</tt>, so I have used a program that has
+been published before;
+the text, code, and presentation are taken
+from Chapter 12 of D. E. Knuth,
+<cite>Literate Programming</cite>
+(volume 27 of <cite>Center for the Study of
+Language and Information Lecture Notes</cite>,
+Stanford Univ., 1992).<p>
+
+The notable differences are:
+<ul>
+<li>
+When displaying source code,
+<tt>noweb</tt> uses different typography.
+In particular, <tt>WEB</tt> makes good use of multiple fonts
+and the ablity to typeset mathematics, and it may use
+ mathematical symbols in place of C symbols (e.g.
+a logical ``and'' symbol for ``[[&&]]'').
+<tt>noweb</tt> uses a single fixed-width font for code.
+<li>
+<tt>noweb</tt> can work with HTML, and I have used HTML in this example.
+<li>
+<tt>noweb</tt> has no numbered ``sections.''
+When cross-referencing is needed, <tt>noweb</tt> uses hypertext links or page
+numbers.
+<li>
+<tt>noweb</tt> has no special support for macros.
+In the sample program, I have used
+a ``Definitions'' chunk to hold
+macro definitions.
+<li>
+<tt>noweb</tt>'s index of identifiers is less accurate than <tt>WEB</tt>'s,
+because it uses a language-independent heuristic to find identifiers.
+This heuristic may erroneously find ``uses'' of identifiers
+in string literals or comments.
+Although <tt>noweb</tt> does have a language-dependent algorithm for finding
+definitions of identifiers, that algorithm is less reliable than <tt>CWEB</tt>'s,
+because <tt>noweb</tt> does not really parse C code.
+<li>
+The <tt>CWEB</tt> version of this program has semicolons following most uses
+of &lt;...&gt.
+<tt>WEB</tt> needs the semicolon or its equivalent to make
+its prettyprinting come out right.
+Because it does not attempt prettyprinting, <tt>noweb</tt> needs no semicolons.
+</ul>
+
+<h2><a name="counting">Counting words</a></h2>
+
+This example, based on a program by Klaus Guntermann and
+Joachim Schrod (`<tt>WEB</tt> adapted to C.'
+<cite>TUGboat</cite> <b>7</b>(3):134-7, Oct. 1986)
+and a program by Silvio Levy and
+D. E. Knuth (Ch. 12 of <cite>Literate Programming</cite>),
+presents the ``word count''
+program from Unix, rewritten in <tt>noweb</tt> to demonstrate
+literate programming using <tt>noweb</tt>.
+The level of detail in this document is intentionally high, for
+didactic purposes; many of the things spelled out here don't need to
+be explained in other programs.<p>
+
+The purpose of <tt>wc</tt> is to count lines, words, and/or characters in
+a list of files.
+The number of lines in a file is the number of newline characters it
+contains.
+The number of characters is the file length in bytes.
+A ``word'' is a maximal sequence of consecutive characters other than
+newline, space, or tab, containing at least one visible ASCII code.
+(We assume that the standard ASCII code is in use.)<p>
+
+Most literate C programs share a common structure.
+It's probably a good idea to state the overall structure explicitly at
+the outset, even though the various parts could all be introduced in
+chunks named &lt;*&gt; if we wanted to add them piecemeal.<p>
+
+Here, then, is an overview of the file <tt>wc.c</tt> that is defined by
+the <tt>noweb</tt> program <tt>wc.nw</tt>:
+<<*>>=
+<<Header files to include>>
+<<Definitions>>
+<<Global variables>>
+<<Functions>>
+<<The main program>>
+@
+We must include the standard I/O definitions, since we want to send
+formatted output to [[stdout]] and [[stderr]].
+<<Header files to include>>=
+#include <stdio.h>
+@
+
+The [[status]] variable will tell the operating system if the run was
+successful or not, and [[prog_name]] is used in case there's an error
+message to be printed.
+<<Definitions>>=
+#define OK 0
+ /* status code for successful run */
+#define usage_error 1
+ /* status code for improper syntax */
+#define cannot_open_file 2
+ /* status code for file access error */
+@ %def OK usage_error cannot_open_file
+<<Global variables>>=
+int status = OK;
+ /* exit status of command, initially OK */
+char *prog_name;
+ /* who we are */
+@ %def status prog_name
+
+Now we come to the general layout of the [[main]]
+function.
+<<The main program>>=
+main(argc, argv)
+ int argc;
+ /* number of arguments on UNIX command line */
+ char **argv;
+ /* the arguments, an array of strings */
+{
+ <<Variables local to [[main]]>>
+ prog_name = argv[0];
+ <<Set up option selection>>
+ <<Process all the files>>
+ <<Print the grand totals if there were multiple files>>
+ exit(status);
+}
+@ %def main argc argv
+
+If the first argument begins with a `[[-]]', the
+user is choosing the desired counts and specifying
+the order in which they should be displayed.
+Each selection is given by the
+initial character (lines, words, or characters).
+For example, `[[-cl]]' would cause just the
+number of characters and the number of lines to
+be printed, in that order.<p>
+
+We do not process this string now; we simply remember where it is.
+It will be used to control the formatting at output time.
+<<Variables local to [[main]]>>=
+int file_count;
+ /* how many files there are */
+char *which;
+ /* which counts to print */
+@ %def file_count which
+<<Set up option selection>>=
+which = "lwc";
+ /* if no option is given, print 3 values */
+if (argc > 1 && *argv[1] == '-') {
+ which = argv[1] + 1;
+ argc--;
+ argv++;
+}
+file_count = argc - 1;
+@
+
+Now we scan the remaining arguments and try to open a file, if possible.
+The file is processed and its statistics are given.
+We use a [[do ... while]] loop because we should read from the standard
+input if no file name is given.
+<<Process all the files>>=
+argc--;
+do {
+ <<If a file is given, try to open [[*(++argv)]]; [[continue]] if unsuccessful>>
+ <<Initialize pointers and counters>>
+ <<Scan file>>
+ <<Write statistics for file>>
+ <<Close file>>
+ <<Update grand totals>>
+ /* even if there is only one file */
+} while (--argc > 0);
+@
+
+Here's the code to open the file. A special trick allows us to handle
+input from [[stdin]] when no name is given.
+Recall that the file descriptor to [[stdin]] is 0; that's what we use
+as the default initial value.
+<<Variables local to [[main]]>>=
+int fd = 0;
+ /* file descriptor, initialized to stdin */
+@ %def fd
+<<Definitions>>=
+#define READ_ONLY 0
+ /* read access code for system open */
+@ %def READ_ONLY
+<<If a file is given, try to open [[*(++argv)]]; [[continue]] if unsuccessful>>=
+if (file_count > 0
+&& (fd = open(*(++argv), READ_ONLY)) < 0) {
+ fprintf(stderr,
+ "%s: cannot open file %s\n",
+ prog_name, *argv);
+ status |= cannot_open_file;
+ file_count--;
+ continue;
+}
+<<Close file>>=
+close(fd);
+@
+We will do some homemade buffering in order to speed things up:
+Characters will be read into the [[buffer]] array before we process
+them.
+To do this we set up appropriate pointers and counters.
+<<Definitions>>=
+#define buf_size BUFSIZ
+ /* stdio.h BUFSIZ chosen for efficiency */
+@ %def buf_size
+<<Variables local to [[main]]>>=
+char buffer[buf_size];
+ /* we read the input into this array */
+register char *ptr;
+ /* first unprocessed character in buffer */
+register char *buf_end;
+ /* the first unused position in buffer */
+register int c;
+ /* current char, or # of chars just read */
+int in_word;
+ /* are we within a word? */
+long word_count, line_count, char_count;
+ /* # of words, lines, and chars so far */
+@ %def buffer ptr buf_end in_word word_count line_count char_count
+<<Initialize pointers and counters>>=
+ptr = buf_end = buffer;
+line_count = word_count = char_count = 0;
+in_word = 0;
+@
+
+The grand totals must be initialized to zero at the beginning of the
+program.
+If we made these variables local to [[main]], we would have to do this
+initialization explicitly; however, C's globals are automatically
+zeroed. (Or rather, ``statically zeroed.'') (Get it?)
+<<Global variables>>=
+long tot_word_count, tot_line_count,
+ tot_char_count;
+ /* total number of words, lines, chars */
+@
+
+The present chunk, which does the counting that is <tt>wc</tt>'s
+<i>raison d'etre</i>, was actually one of the simplest to write.
+We look at each character and change state if it begins or ends a word.
+<<Scan file>>=
+while (1) {
+ <<Fill [[buffer]] if it is empty; [[break]] at end of file>>
+ c = *ptr++;
+ if (c > ' ' && c < 0177) {
+ /* visible ASCII codes */
+ if (!in_word) {
+ word_count++;
+ in_word = 1;
+ }
+ continue;
+ }
+ if (c == '\n') line_count++;
+ else if (c != ' ' && c != '\t') continue;
+ in_word = 0;
+ /* c is newline, space, or tab */
+}
+@
+
+Buffered I/O allows us to count the number of characters almost for
+free.
+<<Fill [[buffer]] if it is empty; [[break]] at end of file>>=
+if (ptr >= buf_end) {
+ ptr = buffer;
+ c = read(fd, ptr, buf_size);
+ if (c <= 0) break;
+ char_count += c;
+ buf_end = buffer + c;
+}
+@
+
+It's convenient to output the statistics by defining a new function
+[[wc_print]]; then the same function can be used for the totals.
+Additionally we must decide here if we know the name of the file we have
+processed or if it was just [[stdin]].
+<<Write statistics for file>>=
+wc_print(which, char_count, word_count,
+ line_count);
+if (file_count)
+ printf(" %s\n", *argv); /* not stdin */
+else
+ printf("\n"); /* stdin */
+@
+<<Update grand totals>>=
+tot_line_count += line_count;
+tot_word_count += word_count;
+tot_char_count += char_count;
+@
+
+We might as well improve a bit on Unix's <tt>wc</tt> by displaying
+the number of files too.
+<<Print the grand totals if there were multiple files>>=
+if (file_count > 1) {
+ wc_print(which, tot_char_count,
+ tot_word_count, tot_line_count);
+ printf(" total in %d files\n", file_count);
+}
+@
+
+Here now is the function that prints the values according to the
+specified options.
+The calling routine is supposed to supply a newline.
+If an invalid option character is found we inform the user about proper
+usage of the command.
+Counts are printed in 8-digit fields so that they will line up in
+columns.
+<<Definitions>>=
+#define print_count(n) printf("%8ld", n)
+@ %def print_count
+<<Functions>>=
+wc_print(which, char_count, word_count, line_count)
+ char *which; /* which counts to print */
+ long char_count, word_count, line_count;
+ /* given totals */
+{
+ while (*which)
+ switch (*which++) {
+ case 'l': print_count(line_count);
+ break;
+ case 'w': print_count(word_count);
+ break;
+ case 'c': print_count(char_count);
+ break;
+ default:
+ if ((status & usage_error) == 0) {
+ fprintf(stderr,
+ "\nUsage: %s [-lwc] [filename ...]\n",
+ prog_name);
+ status |= usage_error;
+ }
+ }
+}
+@ %def wc_print
+
+Incidentally, a test of this program against the system <tt>wc</tt>
+command on a SPARCstation showed that the ``official'' <tt>wc</tt> was
+slightly slower.
+Furthermore, although that <tt>wc</tt> gave an appropriate error message
+for the options `[[-abc]]', it made no complaints about the options
+`[[-labc]]'!
+Dare we suggest that the system routine might have been better if its
+programmer had used a more literate approach?
+
+<h2><a name=index>Index</a></h2>
+<h3>Chunks
+<nowebchunks>
+<h3>Indifiers
+<nowebindex>
+</body>
+</html>
diff --git a/web/noweb/examples/whitespace b/web/noweb/examples/whitespace
new file mode 100644
index 0000000000..5ac6c1d0f9
--- /dev/null
+++ b/web/noweb/examples/whitespace
@@ -0,0 +1,10 @@
+
+# whitespace -- noweb filter to make multiple whitespace
+# characters equivalent to a single space, so that
+# << Hello World>>, <<Hello World>>,
+# and <<Hello World >> all refer to the chunk
+# <<Hello World>>
+
+sed -e '/^@use /s/[ \t][ \t]*/ /g' -e '/^@defn /s/[ \t][ \t]*/ /g' \
+ -e '/^@use /s/[ \t]*$//g' -e '/^@defn /s/[ \t]*$//g'
+
diff --git a/web/noweb/nwsrcfilter.icn b/web/noweb/nwsrcfilter.icn
new file mode 100644
index 0000000000..b1b1c0491b
--- /dev/null
+++ b/web/noweb/nwsrcfilter.icn
@@ -0,0 +1,60 @@
+# nwsrcfilter -- filter out irrelevant files, put .nw files first
+
+procedure main(args)
+ while line := read() do
+ if not (line[-1] == "~" | line == "." | find("/RCS", line) |
+ (line ? (tab(find("./binaries/")), move(1))) |
+ line[3] == line[-1] == "#" | line == "./nwsrcfilter") then
+ line ? (="./" & save_file(tab(0)))
+ dump_files()
+end
+
+global root
+
+global files_in_input
+
+procedure save_file(name)
+ initial {root := table(); files_in_input := set()}
+ insert(files_in_input, name)
+ name ? do_save(root)
+ return
+end
+
+procedure do_save(root)
+ if key := tab(upto('/')) & tab(many('/')) then {
+ /root[key] := table()
+ do_save(root[key])
+ } else
+ /root[tab(0)] := table()
+end
+
+procedure dump_files(prefix, r)
+ /prefix := ""
+ /r := root
+ if *r = 0 then return
+ l := sort(r)
+ bubblenw(l)
+ every p := !l do
+ if *p[2] > 0 then {
+ dump_files(prefix || p[1] || "/", p[2])
+ if member(files_in_input, prefix || p[1]) then write(prefix, p[1])
+ # only dump directories if they were given explicitly
+ } else {
+ write(prefix, p[1])
+ }
+end
+
+procedure bubblenw(l)
+ lo := 1 # first non-nw
+ while l[lo][1][-3:0] == ".nw" do lo +:= 1
+ hi := lo +1 # first succeeding nw
+ while l[hi][1][-3:0] ~== ".nw" do hi +:= 1
+ while hi <= *l do {
+ i := hi
+ while i > lo do {l[i] :=: l[i-1]; i -:= 1}
+ lo +:= 1
+ hi +:= 1
+ while l[hi][1][-3:0] ~== ".nw" do hi +:= 1
+ }
+ return l
+end
diff --git a/web/noweb/src/COPYRIGHT b/web/noweb/src/COPYRIGHT
new file mode 100644
index 0000000000..48c98d1f17
--- /dev/null
+++ b/web/noweb/src/COPYRIGHT
@@ -0,0 +1,21 @@
+Noweb is copyright 1989-2000 by Norman Ramsey. All rights reserved.
+
+Noweb is protected by copyright. It is not public-domain
+software or shareware, and it is not protected by a ``copyleft''
+agreement like the one used by the Free Software Foundation.
+
+You may use and distribute noweb for any purpose, for free. You may
+redistribute noweb in whole or in part provided you acknowledge its
+source and include this COPYRIGHT file. You may modify noweb and
+create derived works, provided you retain this copyright notice, but
+the result may not be called noweb without my written consent.
+
+You may sell noweb if you wish. For example, you may sell a CD-ROM
+including noweb.
+
+You may use noweb in products as long as you charge for only those
+components that are entirely your own and you acknowledge the use of
+noweb clearly in all product documentation and distribution media. You
+must state clearly that your product uses or is based on noweb and
+that noweb is available free of change. You must also request that
+bug reports on your product be reported to you.
diff --git a/web/noweb/src/FAQ b/web/noweb/src/FAQ
new file mode 100644
index 0000000000..33304a1503
--- /dev/null
+++ b/web/noweb/src/FAQ
@@ -0,0 +1,501 @@
+Noweb Frequently Asked Questions
+
+ • Problems Building Noweb
+ • Indentation of code, especially FORTRAN
+ • Formatting the printed documentation
+ • Microsoft Madness
+ • Noweb and Emacs
+ • Other Questions
+
+Problems Building Noweb
+
+Q. The build fails because it can't find notangle. What am I doing wrong?
+
+ A. Your source files have the wrong timestamps. The noweb files are
+ carefully distributed so that the C code is more recent than the literate
+ source code. Retrieving that noweb distribution as a compressed tar file
+ preserves these stamps. The CTAN sites will create a compressed tar file on
+ the fly for any directory. Your best bet is to get the tar file, unpack it,
+ and try again, because your abortive attempt will probably have stomped on
+ a C file that you need.
+
+ I have reports that the former CTAN site ftp.shsu.edu fouled the
+ timestamps. Don't use the site! If you get bad timestamps, you can try
+ `make touch' as soon as you unpack the distribution, which should touch all
+ of the derived files. This trick won't work on NeXT systems, which have a
+ strange idea of 'touch'.
+
+Q. The system builds OK, but when I try to run noweave, I get an error in /usr/
+public/pkg/noweb/lib/totex (or some similar place) complaining about being out
+of environment space or something equally unpleasant.
+
+ A. The awk versions of the noweb scripts pass the awk programs as arguments
+ on the command line. Some shells or systems are too broken to handle a real
+ awk program on the command line. This problem is one of many reasons that
+ the awk versions are officially deprecated. The Icon versions will make you
+ happy, but if you prefer, you can edit the offending scripts so that the
+ awk programs reside in separate files and the scripts call awk -f.
+
+Q. I'm unable to run noweb on Windows NT 4.0. The problem is that the Icon
+programs use a DOS extender which doesn't work in an NT console.
+
+ A. Clint Jeffery, the Icon Master for Windows, says to use the NT console
+ binaries (nticont.exe and nticonx.exe) rather than wiconx.exe with its faux
+ console. Only applications that use the graphics facilities require
+ wiconx.exe and its kin. The nticonx* binaries should run fine on Win95
+ also.
+
+Q. I'm having trouble getting noweb to work on Windows XP.
+
+ A. Bad news. There used to be a distribution from literateprogramming.org,
+ but as of January 2010, that domain is no longer registered, and I don't
+ know where the distribution went.
+
+Indentation of code, especially FORTRAN
+
+Q. Has anyone devised a clean way of handling FORTRAN 77 using a litprog tool
+such as noweb? If I have the following:
+
+<<Block>>=
+ <<Nicely Indented Chunk Title>>
+@
+<<Nicely Indented Chunk Title>>=
+C A comment in a chunk!
+ Z = X *
+ + Y
+@
+
+I'll get the "C" in column 7, and the continuation character "+" in column 12,
+neither of which is desirable.
+
+ A. As noted on the man page, notangle's -L option suppresses the usual
+ behavior with respect to indentation. Thus, a command like
+
+ notangle -L'%N' pgm.nw > pgm.f
+
+ should do the job.
+
+Q. I noticed the -L option to notangle turns off the usual indentation. Is
+there an easy way to get both -L and indentation?
+
+ A. No. It was my design decision that -L should preserve the column numbers
+ in the original source code. This behavior is extremely useful in cases
+ where a compiler reports an error in the source by line and column number.
+ Of course, this decision precludes changing the indentation of the input.
+
+Formatting the printed documentation
+
+Q. There's too much white space at the bottom of the pages, especially if a
+code chunk is followed by a section. How do I fix it?
+
+ A. Noweb is set up never to break chunks across pages. You can get better
+ results by relaxing this constraint, e.g., by
+
+ \def\nwendcode{\endtrivlist \endgroup \vfil\penalty10\vfilneg}
+ \let\nwdocspar=\smallbreak
+
+ or the even less liberal
+
+ \def\nwendcode{\endtrivlist \endgroup}
+ \let\nwdocspar=\par
+
+Q. In a noweb source file, what is the difference between a line beginning with
+"@" followed by a space and some text versus a line with nothing but "@"?
+
+ A. A line with nothing but @ begins the `documentation chunk' with a blank
+ line. TeX thinks blank lines are new paragraphs and good places to put page
+ breaks. By default, TeX thinks that if a new documentation chunk starts
+ with a new paragraph, this is an especially good place for a page break.
+
+Q. I know how to switch between code and documentation via <<*>>= and @, but
+sometimes, after a <<*>>= section, automatically a new page is started, even if
+I do not want this but prefer to go on with commenting directly after the
+inserted programm code. How can I avoid this?
+
+ A. The @ sign you use to switch back to documentation should not appear on
+ a line by itself, but should be followed by a blank space and some text.
+ You should then put a bare @ sign on a line by itself at the next place
+ that is suitable for a page break.
+
+Q. I don't quite understand noweb's default page breaking.
+
+Here is some text
+that leads up to a chunk
+<<chunk>>=
+ a = b;
+ c = d;
+@ and here is some more text.
+Sometimes this appears on a new page even though
+there is plenty of room on this page. Can I fix it by adding
+the following line (which I haven't been doing) ?
+@
+New paragraph here.
+
+ A. Sad but true. Perhaps a future version of noweb will provide better
+ facilities for controlling page breaking.
+
+Q. I ran into a problem when trying to use several files in a single noweb
+project. In my project, I have a LaTeX master file (say, doc.tex) that \
+include's three others: say, a.tex, b.tex, and copyright.tex. These later files
+are generated from a.nw, b.nw, and copyright.nw, respectively, using the
+command "noweave -n -index" I really want to keep these noweb files separated.
+In the code chunks appearing in both a.nw and b.nw a copyright notice chunk
+(defined in copyright.nw) is included.
+
+Tangling works fine, provided that copyright.nw appears in the notangle
+command. Problems arise with noweave. Copyright chunks appear as "(never
+defined)" in a.tex and b.tex, what is obvious, because I cannot use
+copyright.nw for weaving a.nw or b.nw (otherwise the copyright notice chunk
+would appear several times in my printed document).
+
+Does someone know how to solve this problem?
+
+ A. This is a form of question that arises repeatedly, which is to say,
+ ``what is the scope of chunk names?'' In Noweb, chunk names are in the same
+ scope if the files in which the chunks appear are used on the same command
+ line. Thus, the normal rule is one Noweb file per command line, and
+ therefore each file is its own scope.
+
+ You want to have chunks in the same scope for purposes of tangling, but not
+ to weave files together. If you want files a.nw and b.nw in separate
+ scopes, the situation is hopeless, because ``being in the same scope'' has
+ to be a transitive property, and if a.nw and b.nw are both in the same
+ scope as copyright.nw, they must be in the same scope as each other.
+
+ However, if you want all files to be in the same scope, there is a
+ solution, although it is a bit ugly. The solution is to weave all the files
+ together, then use a special back end to split them into separate .tex
+ files. This back end, called scopehack, could be used as follows:
+
+ noweave -n -index -backend scopehack *.nw
+
+ and this results in multiple *.tex files as required.
+
+Q. I have problems using LaTeX \ifthenelse with noweb--- code chunks inside an
+\ifthenelse are not typeset correctly and a %def directive causes (La)TeX
+groups to be unbalanced.
+
+ A. Noweb code chunks are ``moving arguments'' (like \verb) and can't be
+ arguments to macros. I suggest you combine \ifthenelse with the noweb
+ 'elide' filter to remove the offending code chunks.
+
+Q. I embed the build instructions for a noweb-based project in a code chunk
+called build-script that I don't wish to have show up in the printed
+documentation. So, I surround the section with LaTeX \iffalse ... \fi. If I do
+this at the same time as using noweb's index, the \fi shows up in the generated
+TeX file at the end of the index information, resulting in an empty index.
+
+ A. Make sure that the \fi appears before the last documentation chunk, by
+ creating an empty documentation chunk (with @) if necessary. Then use
+ noweave -delay to insert the index information.
+
+ Incidentally, it is recommended that, in addition to using \iffalse ... \
+ fi, you remove unwanted code chunks by using the elide filter provided with
+ noweb. Latex can get confused if chunk cross-reference anchors are hidden
+ away inside \iffalse ... \fi.
+
+Q. When I write C code and use the decrement operator --, it appears in the
+resulting document as a single -. This unpleasantness seems to be a side effect
+of \usepackage[T1]{fontenc}.
+
+ A. Indeed. We don't understand this behavior, but as an ill-understood
+ workaround, you can add
+
+ \catcode`\-=\active
+
+ to \def\setupcode, and things may work better.
+
+Microsoft Madness
+
+Q. Using the precompiled MS-DOS and Windows binaries for noweb, many of the
+programs throw their output to the screen and not to whatever receiving program
+/file they ought to go to. A typical example: I go to /noweb/examples and type
+
+ notangle wc.nw > wc.c
+
+I see the tangled program scroll by on the screen, but it isn't piped to the
+file wc.c as requested. Any solutions?
+
+ A. This is a known COMMAND.COM problem. Try:
+
+ command /c notangle wc.nw > wc.c
+
+ or get a COMMAND.COM replacement such as 4DOS. Better yet, help with the
+ noweb 3 port.
+
+Q. For Windows 95/NT systems: Why do I get the error message "This program
+cannot be run in DOS mode." when I run some of the programs (including
+noweave.bat)?
+
+ A. [Thanks to Chris Harris.] The problem is that some of the files used in
+ the noweb system (including totex.exe and tohtml.exe used by noweave.bat)
+ are written using an old version of icon that uses a DOS extender which is
+ incompatible with 95/NT. The solution is to rebuild all of these files that
+ were built using icon source:
+ 1. Go get the console ICON executables for use on 95/NT. They are the
+ files nticont.exe, nticonx.exe, noop.bat. Put them in your noweb/bin
+ directory.
+ 1. The other two were available on the noweb ftp site, from the FAQ,
+ but noop.bat wasn't... it's availbe via FTP with the icon
+ distribution, but it's pretty easy to build yourself, it's contents
+ are the single line:
+
+ @rem this file prevents further batch processing after launching nticonx
+
+ 2. So to build noop.bat, just type at the prompt "copy con noop.bat"
+ and then paste in the above line (starting with the @) hit enter
+ and ^Z and you're good to go. Note: This file could really be
+ empty, the above line is a dos batch file comment, but you may want
+ to put this in there just so you remember in 2 years why you
+ haven't deleted this file! :)
+ 2. Get the noweb source distribution and extract just the icon files (i.e.
+ those located in the icon/ directory with a .icn extention)
+ 3. Build a batch file for each one using "nticont .icn"
+ 4. Copy all of the .bat files built in step #2 into your noweb/bin/
+ directory
+ 5. For each new .bat file you have in the bin directory, delete the
+ corresponding .exe file
+ Additionally, do NOT rename nticont to icont or nticonx to iconx. The batch
+ files created with nticont REQUIRE nticonx to exist. So if you rename it,
+ it'll get very confused.
+
+Noweb and Emacs
+
+Q. Emacs noweb-mode is driving me crazy. For example, I want 4-space tabs
+instead of the usual 8. I put this line in my file:
+
+% -*- mode: Noweb; noweb-code-mode: c-mode; tab-width: 4 -*-
+
+Or equivalently I do M-x set-variable tab-width 4. Everything is fine until the
+cursor moves from one chunk to another---then whammo! Tabs are 8 spaces again.
+What can I do??
+
+ A. If you have GNU emacs 20.4, or perhaps some other version, an
+ undocumented internal function of files.el will do what you want. Try
+ adding this to your ~/.emacs file:
+
+ (add-hook 'noweb-select-mode-hook
+ '(lambda () (hack-local-variables-prop-line)))
+
+ Thanks to Glenn Holloway for this discovery.
+
+Q. Emacs noweb-mode is driving me crazy. I want to use Tab or Ctl-J to handle
+indentation, but when I'm in the middle of a code chunk, the indentation is
+wrong, and the cursor jumps to a strange place. How can I make emacs behave?
+
+ A. These symptoms indicate that perhaps emacs has lost track of the
+ boundaries between noweb chunks, perhaps material in documentation chunks
+ is confusing the auto-indenter, or perhaps both. As of Emacs 21 in 2008,
+ you can now easily afford to fix these problems using scary Emacs macros:
+
+ (defun my-newline-and-indent ()
+ "Newline and indent that works better with noweb mode"
+ (interactive "*")
+ (if (and (boundp 'noweb-mode) noweb-mode)
+ (save-restriction
+ (noweb-update-chunk-vector)
+ (noweb-narrow-to-chunk)
+ (newline-and-indent))
+ (newline-and-indent)))
+
+ (defun my-tab-key ()
+ "Tab that always tabs in Fundamental mode" (interactive)
+ (if (string= "Fundamental" mode-name)
+ (insert "\t")
+ (if (and (boundp 'noweb-mode) noweb-mode)
+ (save-restriction
+ (noweb-update-chunk-vector)
+ (noweb-narrow-to-chunk)
+ (indent-for-tab-command))
+ (indent-for-tab-command))))
+
+ (defun use-my-indent-keys ()
+ "Locally bind tab and ^J to keys that indent better" (interactive)
+ (local-set-key "\t" 'my-tab-key)
+ (local-set-key "\C-j" 'my-newline-and-indent))
+
+ (add-hook 'noweb-select-code-mode-hook 'use-my-indent-keys)
+
+ Add these to your .emacs file and perhaps the problem will go away. Isn't
+ Moore's law grand?
+
+Other Questions
+
+Q. What about noweb 3?
+
+ A. I use the alpha version, which is alpha only because the new Hackers'
+ Guide is not finished. But don't look for a release before I retire.
+ Noweb 3 is definitely an improvement over noweb 2, but for most people,
+ it's not enough of an improvement for me to go to the trouble of making a
+ real release. Noweb 3 was started in 1996(!) in response to situations that
+ no longer obtain, and by 2000 it was substantially complete—the last
+ significant revisions being done when I was first drafting my textbook.
+
+ Today performance is no longer an issue, and with Darwin and mingw/cygwin,
+ portability is less of a concern as well. And with Lua 5.1 available, no
+ sane person wants to use Lua 2.5. I believe that noweb 3 no longer fills a
+ need.
+
+Q. I compiled and installed, and everything looks OK, but when I ran the
+examples, two things do not work.
+
+ • Noweave can not find definitions for 'C':
+
+ noweave -index -autodefs c compress.nw > compress.tex
+ noweave: don't know how to find definitions for 'c'
+
+ • Noweave can't find l2h for the -filter.
+
+ A. The awk library doesn't include all the filters that the Icon library
+ includes. To get these extra features, you'll have to get Icon from the
+ University of Arizona and re-install noweb using the Icon library.
+
+Q. I've been playing with LP, using noweb. I put related header, source and
+test files into a single .nw file. But that means that if I make a change in
+the source component, the header file is re-extracted, with the result that
+many files which haven't actually changed are recompiled. Any suggestions on
+simplifying the process?
+
+ A.
+
+ notangle -Rheader foo.nw | cpif foo.h
+
+ To understand why this works, see the cpif man page.
+
+Q. What are these weird Makefile targets like install-preformat-man? Why is
+Makefile built from a .nw file? Why is the Makefile so ugly?
+
+ A. Pay no attention to the man behind the curtain. That's all trickery I
+ use to build a Slackware-style package for Linux.
+
+Q. We often get an error from TeX asking us to have a wizard enlarge it, due to
+a line buffer overflow (the buffer is at 3000 bytes now). This is truly
+annoying, since our wizard refuses to enlarge TeX, insisting there is a problem
+in our LaTeX macros or the Icon programs that generate them. Unfortunately,
+that all comes straight from noweave.
+
+ A. Starting with web2c version 7, you can increase the size up to 30000 in
+ texmf.cnf. teTeX changed to a 30,000-byte line buffer starting in November,
+ 1997, so if you encounter this problem you should upgrade your TeX. teTeX
+ and web2c are both available from the TeX User's Group.
+
+ Noweave emits very long lines on purpose, to preserve the desirable
+ property that the source and TeX files have identical line numbers. This
+ property guarantees that the line numbers in error messages from TeX refer
+ to the lines of the source file, so that, for example, if TeX complains of
+ an unknown control sequence on line 632, you can just refer to line 632 of
+ your noweb file.
+
+ Most very long lines are caused by long code chunks containing lots of
+ identifier definitions, so if you cannot get a new TeX, you can fix the
+ problem by adding more <<...>>= lines, which breaks up the big chunk into
+ smaller chunks. For example, instead of using a single chunk definition to
+ define a large header file, use several:
+
+ <<alinfo.h>>=
+ #define ...
+ #define ...
+ ...
+ <<alinfo.h>>=
+ #define ...
+ #define ...
+ ...
+
+Q. I am trying to process multiple *.nw files independently of each other with
+noweb, only merging the *.tex files for the final documentation (using noindex
+and nodefs to produce cross references). It seems that noweb uses the same
+labels (for TeX references) in different files. (The file names and the
+identifiers defined in these files are quite similar).
+
+ A. Noweb uses the heuristic made famous by FORTH: names are reduced to the
+ first three characters plus the length. Changing your file names should be
+ sufficient. If you don't like that, you could use -filter with a sed script
+ that adds a unique prefix to all the relevant labels (see the Hacker's
+ Guide for info about where labels appear).
+
+Q. I have a problem with noweave's -delay option. It does not seem to prevent
+the program from inserting its information before the first chunk and after the
+last one.
+
+ A. Put your first @ sign after the \begin{document} instead of at the
+ beginning of the file, and your last @ sign just before the \end{document}.
+
+Q. How do I get an output file (root chunk) with an underscore in its name?
+LaTeX complains about the underscore.
+
+ A. All chunk names are set in ordinary TeX mode. This means that underscore
+ is a subscript character. Rather than use special hacks, I just avoid
+ underscores in file names, since I prefer to use hyphens anyway. However,
+ you can write a simple sed script to filter the underscores for use by
+ noweave:
+
+ noweave -filter 'sed "/^@use /s/_/\\\\_/g;/^@defn /s/_/\\\\_/g"'
+
+ and the filter will change _ to \_ before TeX sees it.
+
+Q. Having used nuweb2noweb on a nuweb file which uses @i to include other files
+I find that the resulting noweb file is enormous because the included files are
+written directly into the noweb file. How do I emulate nuweb's @i with noweb?
+
+ A. The short answer is it can't be done. (Some would say that it doesn't
+ need to be done, because notangle and noweave can accept multiple files on
+ the command line.) The long answer is that you can usually use LaTeX's \
+ include or \input commands and keep the noweb files separate. If you
+ actually need to tangle all those files together (as opposed to just
+ weaving them), you can usually mention all the names on the command line:
+
+ notangle foo.nw bar.nw quux.nw > big.out
+
+Q. I have a problem with typesetting Mathematica's double-bracketed
+subscripting command using [[...]] in my documentation chunks. noweb considers
+[[a[[#]]&]] to mean the symbols a[[# in typewriter and then latex gets stuck on
+the offending & character. How can I get around this problem?
+
+ A. Split the quoted code into two pieces, which you write consecutively,
+ thus:
+
+ [[a[[#]]]][[&]]
+
+Q. Why is the noweb command so slow?
+
+ A. It's expensive to create a TeX file, so
+
+ noweb foo
+
+ is probably at least 5 times slower than
+
+ noweb -t foo
+
+ and in an edit/compile/debug cycle you may not need the docs and can use
+ the faster form.
+
+Q. What is the origin of the ``no'' prefix in noweb ?
+
+ A. I wrote noweb at a time when language-dependent webs were proliferating,
+ e.g., adaweb, cweb, mweb, etc. So the "no" in noweb is a triple pun:
+ â–¡ A language-independent web, not limited to one programming language,
+ hence web for no particular language or `noweb'.
+ â–¡ A contraction of `Norman's web'
+ â–¡ The third part of the pun is not suitable for publication.
+
+Q. Norman, what made you choose Lua as the implementation language for Noweb 3,
+rather than, say, Python?
+
+ A. Lua is small and simple. I wanted not to be vulnerable to future changes
+ in language definitions or implementations, which meant I would have to
+ clone and maintain the implementation forever. When I was making this
+ decision in 1997, Lua 2.5 was small enough that I could feel comfortable
+ doing this.
+
+Q. Are there noweb comments? It would be very useful to comment parts of a
+noweb file that wouldn't be parsed as either TeX or code.
+
+ A. I recommend that you put comments in specially named chunks and use the
+ elide filter that comes with the distribution. For example, if the name of
+ each comment chunk begins with comment:, you could run
+
+ noweave -filter elide comment:* ...
+
+ (Because chunks that are not used are ignored, there would be no need to
+ elide when tangling.)
+
diff --git a/web/noweb/src/FAQ.html b/web/noweb/src/FAQ.html
new file mode 100644
index 0000000000..f492e5c5ca
--- /dev/null
+++ b/web/noweb/src/FAQ.html
@@ -0,0 +1,676 @@
+<html><head><title>
+Noweb Frequently Asked Questions</title></head><body>
+
+<h2><a name=toc1>Noweb Frequently Asked Questions</a></h2>
+
+<tableofcontents>
+<ul compact>
+<li><a href="#toc2">Problems Building Noweb</a></li>
+<li><a href="#toc3">Indentation of code, especially FORTRAN</a></li>
+<li><a href="#toc4">Formatting the printed documentation</a></li>
+<li><a href="#toc5">Microsoft Madness</a></li>
+<li><a href="#toc6">Noweb and Emacs</a></li>
+<li><a href="#toc7">Other Questions</a></li>
+</ul>
+</tableofcontents>
+
+<h3><a name=toc2>Problems Building Noweb</a></h3>
+
+<b>Q.</b> The build fails because it can't find notangle. What am I doing wrong?
+
+<p><blockquote><b>A.</b> Your source files have the wrong timestamps. The noweb files are
+ carefully distributed so that the C code is more recent than the
+ literate source code. Retrieving that noweb distribution as a
+ compressed tar file preserves these stamps. The CTAN sites will
+ create a compressed tar file on the fly for any directory. Your
+ best bet is to get the tar file, unpack it, and try again, because
+ your abortive attempt will probably have stomped on a C file that
+ you need.
+<p>
+ I have reports that the former CTAN site <tt>ftp.shsu.edu</tt>
+fouled the timestamps. Don't use the site!
+If you get bad timestamps,
+ you can try
+ `make touch' as soon as you unpack the distribution, which should
+ touch all of the derived files. This trick won't work on NeXT
+ systems, which have a strange idea of 'touch'.
+
+</blockquote><p><b>Q.</b> The system builds OK, but when I try to run noweave, I get an
+ error in /usr/public/pkg/noweb/lib/totex (or some similar place)
+ complaining about being out of environment space or something
+ equally unpleasant.
+
+<p><blockquote><b>A.</b> The awk versions of the noweb scripts pass the awk programs as
+ arguments on the command line. Some shells or systems are too
+ broken to handle a real awk program on the command line. This
+ problem is one of many reasons that the awk versions are
+ officially deprecated. The Icon versions will make you happy, but
+ if you prefer, you can edit the offending scripts so that the awk
+ programs reside in separate files and the scripts call awk -f.
+</blockquote>
+
+<p><b>Q.</b>
+ I'm unable to run noweb on Windows NT 4.0. The problem is that the
+ Icon programs use a DOS extender which doesn't work in an NT console.
+<p><blockquote><b>A.</b>
+ Clint Jeffery, the Icon Master for Windows, says to
+ use the <a href=ftp://ringer.cs.utsa.edu/pub/icon/nt/console>NT
+console binaries</a>
+ (<tt>nticont.exe</tt> and
+<tt>nticonx.exe</tt>) rather than
+<tt>wiconx.exe</tt> with its faux console. Only applications that use
+the graphics
+facilities require <tt>wiconx.exe</tt> and its kin. The
+<tt>nticonx*</tt> binaries should run fine
+on Win95 also.
+</blockquote>
+
+
+<p><b>Q.</b>
+ I'm having trouble getting noweb to work on Windows&nbsp;XP.
+<p><blockquote><b>A.</b>
+Bad news. There used to be a distribution from
+<tt>literateprogramming.org</tt>, but as of January 2010, that domain
+ is no longer registered, and I don't know where the distribution
+ went.
+<!--
+Some users are very satisfied with a distribution from
+<a
+ href=http://www.literateprogramming.org><tt>http://www.literateprogramming.org</tt></a>.
+This distribution requires
+ Cygwin (in particular, Cygwin's bash shell) to get the pipes and so on
+working.
+ The installation instructions are at
+<A href=http://www.literateprogramming.com/noweb/nowebinstall.html><tt>http://www.literateprogramming.com/noweb/nowebinstall.html</tt></a>.
+-->
+</blockquote>
+
+<h3><a name=toc3>Indentation of code, especially FORTRAN</a></h3>
+
+<b>Q.</b>
+
+Has anyone devised a clean way of handling FORTRAN 77 using a litprog tool
+such as noweb? If I have the following:
+<pre>
+&lt;&lt;Block>>=
+ &lt;&lt;Nicely Indented Chunk Title>>
+@
+&lt;&lt;Nicely Indented Chunk Title>>=
+C A comment in a chunk!
+ Z = X *
+ + Y
+@
+</pre>
+I'll get the "C" in column 7, and the continuation character "+" in column
+12, neither of which is desirable.
+<p><blockquote><b>A.</b>
+As noted on the man page, notangle's <tt>-L</tt> option suppresses the
+usual behavior with respect to indentation.
+Thus, a command like
+<blockquote><tt>notangle -L'%N' pgm.nw > pgm.f</tt></blockquote>
+should do the job.
+</blockquote>
+
+
+<p><b>Q.</b>
+I noticed the <tt>-L</tt> option to notangle turns off the usual indentation.
+Is there an easy way to get both <tt>-L</tt> and indentation?
+<p><blockquote><b>A.</b>
+No. It was my design decision that <tt>-L</tt> should preserve the column numbers
+in the original source code. This behavior is extremely useful in
+cases where a compiler reports an error in the source by line and
+<em>column</em> number. Of course, this decision precludes changing the
+indentation of the input.
+</blockquote>
+
+
+
+
+<h3><a name=toc4>Formatting the printed documentation</a></h3>
+
+<b>Q.</b> There's too much white space at the bottom of the pages,
+especially if a code chunk is followed by a section. How do I fix it?
+
+<p><blockquote><b>A.</b>
+Noweb is set up never to break chunks across pages.
+You can get better results by relaxing this constraint, e.g., by
+<pre>
+\def\nwendcode{\endtrivlist \endgroup \vfil\penalty10\vfilneg}
+\let\nwdocspar=\smallbreak
+</pre>
+or the even less liberal
+<pre>
+\def\nwendcode{\endtrivlist \endgroup}
+\let\nwdocspar=\par
+</pre>
+</blockquote>
+
+<p>
+<b>Q.</b>
+In a noweb source file, what is the difference between a
+line beginning with "@" followed by a space and some text
+versus a line with nothing but "@"?
+<p><blockquote><b>A.</b>
+A line with nothing but @ begins the `documentation chunk' with a
+blank line. TeX thinks blank lines are new paragraphs and good places
+to put page breaks. By default, TeX thinks that if a new
+documentation chunk starts with a new paragraph, this is an especially
+good place for a page break.
+</blockquote>
+<p>
+<b>Q.</b>
+I know how to switch between code and documentation via
+<tt>&lt;&lt;*&gt;&gt;=</tt> and <tt>@</tt>,
+but sometimes, after a <tt>&lt;&lt;*&gt;&gt;=</tt> section, automatically a new page is
+started, even if I do not want this but prefer to go on with commenting
+directly after the inserted programm code. How can I avoid this?
+<p><blockquote><b>A.</b>
+The <tt>@</tt> sign you use to switch back to documentation should not
+appear on a line by itself, but should be followed by a blank space
+and some text.
+You should then put a bare <tt>@</tt> sign on a line by itself at the
+next place that is suitable for a page break.
+</blockquote>
+<p>
+<b>Q.</b>
+I don't quite understand noweb's default page breaking.
+<pre>
+Here is some text
+that leads up to a chunk
+&lt;&lt;chunk>>=
+ a = b;
+ c = d;
+@ and here is some more text.
+Sometimes this appears on a new page even though
+there is plenty of room on this page. Can I fix it by adding
+the following line (which I haven't been doing) ?
+@
+New paragraph here.
+</pre>
+<p>
+<blockquote>
+<b>A.</b>
+Sad but true.
+Perhaps a future version of noweb will provide better facilities for
+controlling page breaking.
+</blockquote>
+
+
+
+
+<p>
+<b>Q.</b> I ran into a problem when trying to use several files in a single noweb
+project. In my project, I have a LaTeX master file (say, doc.tex) that
+\include's three others: say, a.tex, b.tex, and copyright.tex. These
+later files are generated from a.nw, b.nw, and copyright.nw,
+respectively, using the command "noweave -n -index" I <em>really</em> want to
+keep these noweb files separated. In the code chunks appearing in both
+a.nw and b.nw a copyright notice chunk (defined in copyright.nw) is
+included.
+<p>
+Tangling works fine, provided that copyright.nw appears in the notangle
+command. Problems arise with noweave. Copyright chunks appear as
+"(never defined)" in a.tex and b.tex, what is obvious, because I cannot
+use copyright.nw for weaving a.nw or b.nw (otherwise the copyright
+notice chunk would appear several times in my printed document).
+<p>
+Does someone know how to solve this problem?
+
+<p><blockquote><b>A.</b>
+This is a form of question that arises repeatedly, which is to say,
+``what is the scope of chunk names?''
+In Noweb, chunk names are in the same scope if the files in which the
+chunks appear are used on the same command line.
+Thus, the normal rule is one Noweb file per command line, and
+therefore each file is its own scope.
+<p>
+You want to have chunks in the same scope for purposes of tangling,
+but not to weave files together.
+If you want files a.nw and b.nw in separate scopes, the situation is
+hopeless, because ``being in the same scope'' has to be a transitive
+property, and if a.nw and b.nw are both in the same scope as
+copyright.nw, they must be in the same scope as each other.
+<p>
+However, if you want all files to be in the same scope, there is a
+solution, although it is a bit ugly. The solution is to weave all the
+files together, then use a special back end to split them into
+separate .tex files.
+This back end, called <a href=scopehack.icn><tt>scopehack</tt></a>, could
+be used as follows:
+<blockquote>
+<pre>
+noweave -n -index -backend scopehack *.nw
+</pre>
+</blockquote>
+and this results in multiple *.tex files as required.
+</blockquote>
+
+<p>
+<b>Q.</b>
+I have problems using LaTeX <code>\ifthenelse</code> with noweb---
+code chunks inside an <code>\ifthenelse</code> are not typeset correctly and
+a <code>%def</code> directive causes (La)TeX groups to be unbalanced.
+
+<p><blockquote><b>A.</b>
+Noweb code chunks are ``moving arguments'' (like <code>\verb</code>) and can't be
+arguments to macros. I suggest you combine <code>\ifthenelse</code> with the noweb
+'elide' filter to remove the offending code chunks.
+</blockquote>
+
+<p>
+<b>Q.</b>
+I embed the build instructions for a noweb-based project in a code chunk
+called <tt>build-script</tt> that I don't
+wish to have show up in the printed documentation. So, I surround the
+section with LaTeX <code>\iffalse ... \fi</code>.
+If I do this at the same time as using noweb's index, the <code>\fi</code> shows up in
+the generated TeX file
+at the end of the index information, resulting in an empty index.
+<p>
+<blockquote><b>A.</b>
+Make sure that the <code>\fi</code> appears <em>before</em> the last
+documentation chunk, by creating an empty documentation chunk
+(with&nbsp;@) if necessary.
+Then use <code>noweave -delay</code> to insert the index information.
+<p>
+Incidentally, it is recommended that, in addition to using
+<code>\iffalse ... \fi</code>, you remove unwanted code chunks by
+using the <tt>elide</tt> filter provided with noweb.
+Latex can get confused if chunk cross-reference anchors are hidden
+away inside <code>\iffalse ... \fi</code>.
+</blockquote>
+
+<b>Q.</b> When I write C&nbsp;code and use the decrement
+operator <tt>--</tt>, it appears in the resulting document as a single
+<tt>-</tt>.
+This unpleasantness seems to be a side effect of
+<tt>\usepackage[T1]{fontenc}</tt>.
+<p><blockquote><b>A.</b>
+Indeed. We don't understand this behavior, but as an ill-understood
+workaround, you can add
+<pre>
+\catcode`\-=\active
+</pre>
+to <tt>\def\setupcode</tt>, and things may work better.
+</blockquote>
+
+
+
+
+
+<h3><a name=toc5>Microsoft Madness</a></h3>
+<b>Q.</b> Using the precompiled MS-DOS and Windows
+binaries for noweb, many of the programs throw their
+output to the screen and not to whatever receiving program/file they
+ought to go to. A typical example: I go to /noweb/examples and type
+<pre>
+ notangle wc.nw > wc.c
+</pre>
+I see the tangled program scroll by on the screen, but it isn't piped to
+the file wc.c as requested.
+Any solutions?
+
+<p><blockquote><b>A.</b>
+This is a known COMMAND.COM problem. Try:
+<pre>
+ command /c notangle wc.nw > wc.c
+</pre>
+or get a COMMAND.COM replacement such as 4DOS.
+Better yet, help with the <a href=todo3.html>noweb 3 port</a>.
+</blockquote>
+
+<p><b>Q.</b>
+For Windows 95/NT systems:
+Why do I get the error message "This program cannot be run in DOS mode."
+when I run some of the programs (including noweave.bat)?
+<p><blockquote><b>A.</b>
+[Thanks to Chris Harris.]
+The problem is that some of the files used in the noweb system (including
+totex.exe and tohtml.exe used by noweave.bat) are written using an old
+version of icon that uses a DOS extender which is incompatible with 95/NT.
+The solution is to rebuild all of these files that were built using icon
+source:
+<ol>
+<li>
+Go get the console ICON executables for use on 95/NT. They are the files
+nticont.exe, nticonx.exe, noop.bat. Put them in your noweb/bin directory.
+<ol>
+<li>The other two were available on the noweb ftp site, from the
+FAQ, but noop.bat wasn't... it's availbe via FTP with the icon distribution,
+but it's pretty easy to build yourself, it's contents are the single line:
+<pre>
+@rem this file prevents further batch processing after launching nticonx
+</pre>
+<li>So to build noop.bat, just type at the prompt "copy con
+noop.bat<enter>" and then paste in the above line (starting with the @) hit
+enter and ^Z and you're good to go. Note: This file could really be empty,
+the above line is a dos batch file comment, but you may want to put this in
+there just so you remember in 2 years why you haven't deleted this file! :)
+</ol>
+<li>Get the noweb source distribution and extract just the icon files (i.e.
+those located in the icon/ directory with a .icn extention)
+<li>Build a batch file for each one using "nticont <filename>.icn"
+
+<li>Copy all of the .bat files built in step #2 into your noweb/bin/
+directory
+
+<li>For each new .bat file you have in the bin directory, delete the
+corresponding .exe file
+</ol>
+Additionally, do NOT rename nticont to icont or nticonx to iconx. The batch
+files created with nticont REQUIRE nticonx to exist. So if you rename it,
+it'll get very confused.
+</blockquote>
+
+
+
+<h3><a name="toc6">Noweb and Emacs</a></h3>
+
+<p><b>Q.</b>
+Emacs noweb-mode is driving me crazy. For example, I want 4-space tabs instead
+of the usual 8. I put this line in my file:
+<pre>
+% -*- mode: Noweb; noweb-code-mode: c-mode; tab-width: 4 -*-
+</pre>
+Or equivalently I do M-x set-variable tab-width 4.
+Everything is fine until the cursor moves from one chunk to
+another---then whammo! Tabs are 8 spaces again.
+What can I do??
+
+<p><blockquote><b>A.</b>
+If you have GNU emacs 20.4, or perhaps some other version, an
+undocumented internal function of files.el will do what you want.
+Try adding this to your ~/.emacs file:
+<pre>
+ (add-hook 'noweb-select-mode-hook
+ '(lambda () (hack-local-variables-prop-line)))
+</pre>
+Thanks to Glenn Holloway for this discovery.
+</blockquote>
+
+
+<p><b>Q.</b>
+Emacs noweb-mode is driving me crazy.
+I&nbsp;want to use Tab or Ctl-J to handle indentation, but when I'm in the
+middle of a code chunk, the indentation is wrong, and the cursor jumps
+to a strange place.
+How can I make emacs behave?
+<p><blockquote><b>A.</b>
+These symptoms indicate that perhaps emacs has lost track of the boundaries
+between noweb chunks, perhaps material in documentation chunks is
+confusing the auto-indenter, or perhaps both.
+As of Emacs&nbsp;21 in 2008, you can now easily afford to fix these
+problems using scary Emacs macros:
+<pre>
+ (defun my-newline-and-indent ()
+ "Newline and indent that works better with noweb mode"
+ (interactive "*")
+ (if (and (boundp 'noweb-mode) noweb-mode)
+ (save-restriction
+ (noweb-update-chunk-vector)
+ (noweb-narrow-to-chunk)
+ (newline-and-indent))
+ (newline-and-indent)))
+
+ (defun my-tab-key ()
+ "Tab that always tabs in Fundamental mode" (interactive)
+ (if (string= "Fundamental" mode-name)
+ (insert "\t")
+ (if (and (boundp 'noweb-mode) noweb-mode)
+ (save-restriction
+ (noweb-update-chunk-vector)
+ (noweb-narrow-to-chunk)
+ (indent-for-tab-command))
+ (indent-for-tab-command))))
+
+ (defun use-my-indent-keys ()
+ "Locally bind tab and ^J to keys that indent better" (interactive)
+ (local-set-key "\t" 'my-tab-key)
+ (local-set-key "\C-j" 'my-newline-and-indent))
+
+ (add-hook 'noweb-select-code-mode-hook 'use-my-indent-keys)
+</pre>
+Add these to your <tt>.emacs</tt> file and perhaps the problem will go away.
+Isn't Moore's law grand?
+</blockquote>
+
+
+
+
+<h3><a name=toc7>Other Questions</a></h3>
+
+<b>Q.</b>
+What about noweb 3?
+
+<p><blockquote><b>A.</b>
+ I use the <a href=nwalphacur.zip>alpha version</a>, which is alpha
+ only because the new Hackers' Guide is not finished.
+ But <strong>don't look for a release before I retire</strong>.
+ Noweb&nbsp;3 is definitely an improvement over noweb&nbsp;2, but
+ for most people, it's not <em>enough</em> of an improvement for me
+ to go to the trouble of making a real release.
+ Noweb&nbsp;3
+ was started in 1996(!) in response to situations that no longer
+ obtain, and by 2000 it was substantially complete&mdash;the last
+ significant revisions being done when I was first drafting my
+ textbook.
+ <p>
+ Today performance is no longer an issue, and with Darwin and
+ mingw/cygwin, portability is less of a concern as well.
+ And with Lua 5.1 available, no sane person wants to use Lua 2.5.
+ I&nbsp;believe that noweb&nbsp;3 no longer fills a need.
+</blockquote><p>
+
+
+
+<b>Q.</b>
+I compiled
+and installed, and everything looks
+OK, but when I ran the examples, two things do not work.
+<ul>
+<li>Noweave can not find definitions for 'C':
+<pre>
+noweave -index -autodefs c compress.nw > compress.tex
+noweave: don't know how to find definitions for 'c'
+</pre>
+<li>Noweave can't find <tt>l2h</tt> for the <tt>-filter</tt>.
+</ul>
+
+<p><blockquote><b>A.</b>
+The awk library doesn't include all the filters that the Icon library
+includes. To get these extra features, you'll have to get <a
+href=http://www.cs.arizona.edu/icon/>Icon</a> from
+the University of Arizona and re-install noweb using the Icon library.
+</blockquote><p>
+
+<b>Q.</b>
+
+I've been playing with LP, using noweb. I put related header, source and
+test files into a single .nw file. But that means that if I make a change
+in the source component, the header file is re-extracted, with the result
+that many files which haven't actually changed are recompiled.
+Any suggestions on simplifying the process?
+
+<p><blockquote><b>A.</b>
+<pre>
+notangle -Rheader foo.nw | cpif foo.h
+</pre>
+To understand why this works, see the <tt>cpif</tt> man page.
+</blockquote><p>
+
+<b>Q.</b> What are these weird Makefile targets like install-preformat-man?
+ Why is Makefile built from a .nw file? Why is the Makefile so ugly?
+
+<p><blockquote><b>A.</b> Pay no attention to the man behind the curtain. That's all
+ trickery I use to build a Slackware-style package for Linux.
+
+</blockquote><p><b>Q.</b> We often get an error from TeX asking us to have a wizard enlarge
+ it, due to a line buffer overflow (the buffer is at 3000 bytes
+ now). This is truly annoying, since our wizard refuses to enlarge
+ TeX, insisting there is a problem in our LaTeX macros or the Icon
+ programs that generate them. Unfortunately, that all comes straight
+ from noweave.
+
+<p><blockquote><b>A.</b>
+Starting with web2c version 7, you can increase the size up to 30000
+in <tt>texmf.cnf</tt>.
+teTeX changed to a 30,000-byte line buffer starting in November, 1997,
+so if you encounter this problem you should upgrade your TeX.
+teTeX and web2c are both available from the <a
+href=http://www.tug.org/>TeX User's Group</a>.
+<p>
+
+ Noweave emits very long lines on purpose, to preserve the desirable
+ property that the source and TeX files have identical line numbers.
+ This property guarantees that the line numbers in error messages
+ from TeX refer to the lines of the source file, so that, for
+ example, if TeX complains of an unknown control sequence on line 632,
+ you can just refer to line 632 of your noweb file.
+<p>
+ Most very long lines are caused by long
+ code chunks
+ containing lots of identifier definitions, so
+ if you cannot get a new TeX, you can
+ fix the problem by adding more <<...>>= lines, which breaks up
+ the big chunk into smaller chunks.
+ For example, instead of using a
+ single chunk definition to define a large header file, use several:
+<pre>
+ &lt;&lt;alinfo.h>>=
+ #define ...
+ #define ...
+ ...
+ &lt;&lt;alinfo.h>>=
+ #define ...
+ #define ...
+ ...
+</pre>
+
+</blockquote><p><b>Q.</b> I am trying to process multiple *.nw files independently of each
+ other with noweb, only merging the *.tex files for the final
+ documentation (using noindex and nodefs to produce cross
+ references). It seems that noweb uses the same labels (for TeX
+ references) in different files. (The file names and the identifiers
+ defined in these files are quite similar).
+
+<p><blockquote><b>A.</b> Noweb uses the heuristic made famous by FORTH: names are reduced to
+ the first three characters plus the length. Changing your file names
+ should be sufficient. If you don't like that, you could use -filter
+ with a sed script that adds a unique prefix to all the relevant labels
+ (see the <a href=guide.html>Hacker's Guide</a> for info about where labels appear).
+
+</blockquote><p><b>Q.</b>
+I have a problem with noweave's <code>-delay</code> option. It does not seem to prevent
+ the program from inserting its information before the first chunk and after
+ the last one.
+
+<p><blockquote><b>A.</b>
+Put your first @ sign after the <code>\begin{document}</code> instead of at the
+beginning of the file, and your last @ sign just before the
+<code>\end{document}</code>.
+
+
+</blockquote><p><b>Q.</b> How do I get an output file (root chunk) with an underscore in its name?
+ LaTeX complains about the underscore.
+
+<p><blockquote><b>A.</b> All chunk names are set in ordinary TeX mode. This means that
+ underscore is a subscript character. Rather than use special
+ hacks, I just avoid underscores in file names, since I prefer to
+ use hyphens anyway. However, you can write a simple sed script to
+ filter the underscores for use by noweave:
+<pre>
+ noweave -filter 'sed "/^@use /s/_/\\\\_/g;/^@defn /s/_/\\\\_/g"'
+</pre>
+ and the filter will change _ to \_ before TeX sees it.
+
+
+</blockquote><p><b>Q.</b> Having used nuweb2noweb on a nuweb file which uses @i to include
+ other files I find that the resulting noweb file is enormous
+ because the included files are written directly into the noweb
+ file. How do I emulate nuweb's @i with noweb?
+
+<p><blockquote><b>A.</b> The short answer is it can't be done. (Some would say that it
+ doesn't <em>need</em> to be done, because notangle and noweave can accept
+ multiple files on the command line.) The long answer is that you
+ can usually use LaTeX's \include or \input commands and keep the
+ noweb files separate. If you actually need to tangle all those
+ files together (as opposed to just weaving them), you can usually
+ mention all the names on the command line:
+<pre>
+ notangle foo.nw bar.nw quux.nw > big.out
+</pre>
+
+</blockquote><p><b>Q.</b> I have a problem with typesetting Mathematica's double-bracketed
+ subscripting command using <code>[[</code>...<code>]]</code>
+ in my documentation chunks.
+noweb considers <code>[[a[[#]]&amp;]]</code> to mean the symbols <code>a[[#</code> in
+typewriter and then latex gets stuck on the offending <code>&amp;</code> character.
+How can I get around this problem?
+
+<p><blockquote><b>A.</b>
+Split the quoted code into two
+pieces, which you write consecutively, thus:
+<blockquote>
+ <code>[[a[[#]]]][[&amp;]]</code>
+</blockquote>
+
+
+
+
+</blockquote><p><b>Q.</b> Why is the <tt>noweb</tt> command so slow?
+
+
+<p><blockquote><b>A.</b> It's expensive to create a TeX file, so
+<pre>noweb foo</pre>
+is probably at least 5 times slower than
+<pre>noweb -t foo</pre>
+and in an edit/compile/debug cycle you may not need the docs and can
+ use the faster form.
+</blockquote>
+
+<p><b>Q.</b> What is the origin of the ``no'' prefix in <tt>noweb</tt> ?
+
+<p><blockquote><b>A.</b>
+I wrote <tt>noweb</tt> at a time when language-dependent webs were
+proliferating, e.g., adaweb, cweb, mweb, etc. So the "no" in <tt>noweb</tt> is
+a triple pun:
+<ul>
+<li>A language-independent web, not limited to one programming
+ language, hence web for no particular language or `<tt>noweb</tt>'.
+<li>A contraction of `Norman's web'
+<li>The third part of the pun is not suitable for publication.
+</ul>
+</blockquote>
+
+<p><b>Q.</b>
+Norman, what made you choose <a href=http://www.lua.org/>Lua</a> as the
+implementation language for Noweb&nbsp;3, rather
+than, say, Python?
+<p><blockquote><b>A.</b>
+Lua is small and simple. I wanted not to be vulnerable to future
+changes in language definitions or implementations, which meant I
+would have to clone and maintain the implementation forever. When I
+was making this decision in 1997, Lua&nbsp;2.5 was small enough that I
+could feel comfortable doing this.
+</blockquote>
+
+
+<p><b>Q.</b>
+ Are there noweb comments?
+ It would be very useful to comment parts of a noweb file that wouldn't
+ be parsed as either TeX or code.
+<p><blockquote><b>A.</b>
+I recommend that you put comments in specially named chunks and use
+ the <tt>elide</tt> filter that comes with the distribution.
+For example, if the name of each comment chunk begins with
+<tt>comment:</tt>, you could run
+<blockquote>
+<pre>
+noweave -filter elide comment:* ...
+</pre>
+</blockquote>
+(Because chunks that are not used are ignored, there would be no need
+ to <tt>elide</tt> when tangling.)
+</blockquote>
+
+</body></html>
diff --git a/web/noweb/src/HPUX b/web/noweb/src/HPUX
new file mode 100644
index 0000000000..ee65c1462b
--- /dev/null
+++ b/web/noweb/src/HPUX
@@ -0,0 +1,29 @@
+HPUX awk has bugs. I recommend that you use Brian Kernighan's
+implementation of awk, which is available for free from AT&T.
+Try http://cm.bell-labs.com/who/bwk/.
+
+If you must use HPUX awk, Steven Ooms kindly provided the following
+changes to the awk script "totex". The problem lines are all situated
+in the function "indexlabel( ident, l )":
+
+---------------start included text---------------
+totex: gsub(/{/, ":lb", l) # left brace
+...
+totex: gsub(/{/, "{\\char123}", arg)
+...
+totex: gsub(/{\\char92>/, "{\\char92}", arg)
+---------------end included text---------------
+
+The corresponding new lines look as follows:
+
+---------------start included text---------------
+totex: gsub(/\{/, ":lb", l) # left brace
+...
+totex: gsub(/\{/, "{\\char123}", arg)
+...
+totex: gsub(/\{\\char92>/, "{\\char92}", arg)
+---------------end included text---------------
+
+Also, I'm told that in src/Makefile the strip command in an HPUX8
+machine causes the make to fail. Commenting out the 'strip' fixes the
+problem.
diff --git a/web/noweb/src/INSTALL b/web/noweb/src/INSTALL
new file mode 100644
index 0000000000..a56b88aedc
--- /dev/null
+++ b/web/noweb/src/INSTALL
@@ -0,0 +1,92 @@
+These installation instructions are for Unix systems.
+For Plan 9 systems, Russ Cox has kindly provided scripts in the contrib
+directory, but for installation instructions, you are on your own.
+If you use Microsoft Windows, Jim Pettigrew has written installation
+instructions for Windows 7 at http://www.jim-pettigrew.com/noweb/install/.
+
+Crucial parts of noweb are written in both Icon and Awk. You can use
+either Icon or Awk, but Icon is better:
+
+ - If you have Icon, use the Icon version of the noweb library; this
+ code speeds up noweave by a factor of 3. The Icon versions have
+ fewer bugs and provide more filters (e.g., convert LaTeX to HTML
+ in documentation chunks). Not all of the examples will work with
+ the awk library. If you have an Icon compiler and believe it
+ works, set `ICONC=iconc -f l' in the Makefile. (Icon is freely
+ available from the University of Arizona, but the compiler is no
+ longer maintained.)
+
+ - As of version 2.12, the Awk code for noweb's indexing and
+ cross-reference relies on the bit-manipulation primitives found
+ in GNU Awk. If you have neither Icon nor GNU Awk, you will not
+ be able to index or cross-reference literate programs.
+ (This breaking change was put in to enable the Awk and Icon codes
+ to generate *identical* outputs, for regression testing.)
+
+
+To build noweb:
+
+ 1) First point to compilers to be used to built the tools and
+ library by setting these variables in the Makefile:
+ CC the name of an ANSI C compiler
+ LIBSRC 'awk' or 'icon', depending on which library you want
+
+ Now choose locations for the noweb files, and set the appropriate
+ variables in the Makefile:
+ BIN on $PATH, will hold notangle, noweave, noroots, ...
+ LIB a directory to store markup, nt, noxref, ...
+ MAN man pages will go in $MAN/man1
+ TEXINPUTS a directory TeX will look for nwmac.tex and noweb.sty
+ ELISP a directory for noweb-mode.el, for emacs 19 and up
+ All of these files are *output* files, where noweb will place
+ binaries and man pages that are customized for your installation.
+ Therefore you should:
+ - make sure you have permission to write to these directories
+ - refrain from making them point into the noweb source distribution
+ - arrange for BIN to be on your $PATH and MAN to be on your $MANPATH
+ If you don't use emacs, just leave ELISP set to /dev/null.
+
+ 2) If your modern awk is called something other than `nawk', run the
+ `awkname' script to change all references to nawk. For example,
+ `awkname gawk'. You need to do this even if you have chosen
+ LIBSRC=icon, because there are a few scripts here and there that
+ are only written in awk. If you have an HPUX system and you're
+ using the vendor-supplied awk, you have a problem---see file HPUX
+ for details.
+
+ Note: the `awkname' script relies on mktemp(1) to create
+ temporary files. If your system lacks this program, you'll need
+ to substitute tempfile(1) or some other means of creating a
+ temporary file.
+
+ 3) Type `make boot'. This command updates timestamps so that noweb
+ does not try to build itself using noweb.
+
+ 4) Fasten your seat belt and type `make all install'. If you want a
+ nonstandard noweave, you can use the WEAVE variable in the
+ Makefile; for example, `make WEAVE=noweave.simple'. In contrast
+ with previous versions, the standard noweave should work with
+ HPUX and SGI Irix.
+
+ 5) If you want to install contributed software, you need the
+ `contrib' hierarchy. Get it, set the LIB variable in the
+ Makefile, and type 'make all install'. If you just want the
+ nuweb parser, try
+ (cd ../contrib/norman; make LIB=$LIB all install)
+ where $LIB is the noweb LIB directory.
+
+ 6) On some installations, (e.g., Unix teTeX), you may have to run
+ texhash(1) before TeX or latex will see files added to TEXINPUTS.
+
+ 7) You can clean up by typing `make clean'. If you wish, you can
+ remove the pre-built sources by typing `make clobber', but then
+ you will be unable to build noweb unless you already have noweb.
+
+Instead of editing the Makefile, you can create a shell script that
+invokes make with the proper variables. `nwmake' is an example of
+such a script; I use it to install noweb at Princeton using the Icon
+cross-referencer and our local C compiler. If you make your own
+script, call it something else so it won't get overwritten by the
+default nwmake when you unbundle a new distribution.
+
+If you encounter a problem building noweb, try the FAQ file.
diff --git a/web/noweb/src/INSTALL.DOS b/web/noweb/src/INSTALL.DOS
new file mode 100644
index 0000000000..4428acc559
--- /dev/null
+++ b/web/noweb/src/INSTALL.DOS
@@ -0,0 +1,43 @@
+Lee Wittenburg kindly provided this account of his efforts in getting
+noweb working on a DOS machine using the MKS toolkit.
+
+ 1. All the shell scripts without an extension required a .KSH. The
+ makefile, of course needed to be changed accordingly. Also, the
+ normal .o to .obj and <no extension> to .exe was necessary in the
+ makefile. No other changes were necessary, except minor ones due to
+ bugs in MKS make.
+
+ 2. Rename INSTALL to INSTALL.NIX to keep make from getting confused.
+
+ 3. I changed all references to "nawk" to "awk".
+
+ 4. There is a bug in MKS Awk that requires a couple of changes in
+ NOWEAVE. There's a problem with backslashes in the 2nd argument to
+ gsub() that requires a couple of changes to NOWEAVE. The lines
+
+ gsub("\\\\", "\\\\", line)
+ gsub("{", "\\{", line); gsub("}", "\\}", line)
+
+ need to be
+
+ gsub("\\\\", "\\\\\\", line)
+ gsub("{", "\\\{", line); gsub("}", "\\\}", line)
+
+ I've reported this bug to MKS (when I first found it in version
+ 3.2), but it still hasn't been fixed. It's not a NOWEB bug, but
+ MKS Awk NOWEB users need to know about it.
+
+ 5. MKS Awk is POSIX compiliant with regard to regular expression
+ syntax; Unix Awk isn't; GNU Awk swings both ways (I believe); other
+ Awks I couldn't say about. This causes a problem ONLY in NOXREF.
+ I had to change the line
+
+ gsub(/[\[\]\\{} -]/, "*", key)
+
+ to
+
+ gsub(/[[\{} -]|\]/, "*", key)
+
+ which probably won't work on a Unix Awk. There's likely to be
+ a Unix/POSIX discrepency in Awks for quite a while.
+
diff --git a/web/noweb/src/Makefile b/web/noweb/src/Makefile
new file mode 100644
index 0000000000..339df3b9b4
--- /dev/null
+++ b/web/noweb/src/Makefile
@@ -0,0 +1,222 @@
+# Copyright 1995-2018 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+#
+# Adjust these two lines for your ANSI C compiler
+CC=gcc -ansi -pedantic -O -Wall -Werror
+CFLAGS=
+# If you have Icon, you should use the Icon versions of the noweb pipeline.
+# Set LIBSRC=icon
+LIBSRC=awk
+# If you have no Icon compiler, but do have icont, make ICONC=icont
+ICONC=iconc
+ICONT=icont
+
+# BIN is where the commands (notangle, noweave, nountangle, noroots) land
+# LIB is where the pieces of the pipes (nt, markup, unmarkup) are stored
+# MAN is the root of your local man pages directory
+# MANEXT is the extension for your commands' man pages (usually 1 or l)
+# MAN7EXT is the extension for the nowebstyle man page (usually 7)
+# TEXINPUTS is the directory for TeX macro files
+# ELISP is the directory for emacs lisp files, or /dev/null not to install
+BIN=/usr/local/noweb
+LIB=/usr/local/noweb/lib
+MAN=/usr/local/noweb/man
+MANEXT=1
+MAN7EXT=7
+TEXINPUTS=/usr/local/tex/inputs
+ELISP=/dev/null
+
+# change WEAVE if you want a different version of noweave to be installed
+WEAVE=noweave
+
+# Stop editing. No user-serviceable parts below.
+SHELL=/bin/sh
+CINAME=
+CIMSG=
+MANDIR=$(MAN)/man$(MANEXT)
+MAN7DIR=$(MAN)/man$(MAN7EXT)
+CATDIR=$(MAN)/cat$(MANEXT)
+CAT7DIR=$(MAN)/cat$(MAN7EXT)
+LIBNAME=$(LIB)
+TEXNAME=$(TEXINPUTS)
+
+all:
+ cd c; make "CC=$(CC)" "CFLAGS=$(CFLAGS)" all
+ for i in shell lib xdoc tex; do (cd $$i; make all); done
+ cd $(LIBSRC); make "ICONT=$(ICONT)" "ICONC=$(ICONC)" all
+
+FAQ: FAQ.html
+ sleep 1; html2ascii FAQ.html > FAQ
+
+FAQ.html: $(HOME)/www/noweb/FAQ.html
+ rm -f FAQ.html
+ /bin/cp $(HOME)/www/noweb/FAQ.html FAQ.html
+ chmod -w FAQ.html
+
+install: install-code install-man install-tex install-elisp
+uninstall: uninstall-code uninstall-man uninstall-tex uninstall-elisp
+ -rmdir $(BIN) $(LIB) 2>/dev/null || true
+
+install-shell:
+ mkdir -p $(BIN) $(LIB)
+ sed "s@|LIBDIR|@$(LIBNAME)@" shell/noweb > $(BIN)/noweb
+ chmod +x $(BIN)/noweb
+ sed "s@|LIBDIR|@$(LIBNAME)@" shell/notangle > $(BIN)/notangle
+ chmod +x $(BIN)/notangle
+ sed "s@|LIBDIR|@$(LIBNAME)@" shell/$(WEAVE) > $(BIN)/$(WEAVE)
+ chmod +x $(BIN)/$(WEAVE)
+ sed "s@|LIBDIR|@$(LIBNAME)@" shell/nountangle > $(BIN)/nountangle
+ chmod +x $(BIN)/nountangle
+ sed "s@|LIBDIR|@$(LIBNAME)@" shell/nodefs > $(BIN)/nodefs
+ chmod +x $(BIN)/nodefs
+ sed "s@|LIBDIR|@$(LIBNAME)@" shell/noroots > $(BIN)/noroots
+ chmod +x $(BIN)/noroots
+ sed "s@|LIBDIR|@$(LIBNAME)@" shell/nuweb2noweb > $(BIN)/nuweb2noweb
+ chmod +x $(BIN)/nuweb2noweb
+ sed "s@|LIBDIR|@$(LIBNAME)@" shell/cpif > $(BIN)/cpif
+ chmod +x $(BIN)/cpif
+ sed "s@|LIBDIR|@$(LIBNAME)@" shell/htmltoc > $(BIN)/htmltoc
+ chmod +x $(BIN)/htmltoc
+ sed "s@|LIBDIR|@$(LIBNAME)@" shell/noroff > $(BIN)/noroff
+ chmod +x $(BIN)/noroff
+ sed "s@|LIBDIR|@$(LIBNAME)@" shell/toroff > $(LIB)/toroff
+ chmod +x $(LIB)/toroff
+ cp shell/tmac.w $(LIB)
+
+uninstall-shell:
+ rm -f $(BIN)/noweb
+ rm -f $(BIN)/notangle
+ rm -f $(BIN)/$(WEAVE)
+ rm -f $(BIN)/nountangle
+ rm -f $(BIN)/nodefs
+ rm -f $(BIN)/noroots
+ rm -f $(BIN)/nuweb2noweb
+ rm -f $(BIN)/cpif
+ rm -f $(BIN)/htmltoc
+ rm -f $(BIN)/noroff
+ rm -f $(LIB)/toroff
+ rm -f $(LIB)/tmac.w
+
+install-code: install-shell
+ mkdir -p $(BIN) $(LIB)
+ strip c/nt c/markup c/mnt c/finduses c/nwmktemp
+ cp c/nt c/markup c/mnt c/finduses c/nwmktemp $(LIB)
+ cd $(LIBSRC); make ICONT=$(ICONT) ICONC=$(ICONC) LIB=$(LIB) BIN=$(BIN) install
+ cd lib; make LIB=$(LIB) install
+
+uninstall-code: uninstall-shell
+ rm -f $(LIB)/nt $(LIB)/markup $(LIB)/mnt $(LIB)/finduses
+ cd $(LIBSRC); make ICONT=$(ICONT) ICONC=$(ICONC) LIB=$(LIB) BIN=$(BIN) uninstall
+ cd lib; make LIB=$(LIB) uninstall
+install-man:
+ mkdir -p $(MAN) $(MANDIR) $(MAN7DIR)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/cpif.1 > $(MANDIR)/cpif.$(MANEXT)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/nodefs.1 > $(MANDIR)/nodefs.$(MANEXT)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/noroots.1 > $(MANDIR)/noroots.$(MANEXT)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/noweb.1 > $(MANDIR)/noweb.$(MANEXT)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/noindex.1 > $(MANDIR)/noindex.$(MANEXT)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/nuweb2noweb.1 > $(MANDIR)/nuweb2noweb.$(MANEXT)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/notangle.1 > $(MANDIR)/notangle.$(MANEXT)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/noroff.1 > $(MANDIR)/noroff.$(MANEXT)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/sl2h.1 > $(MANDIR)/sl2h.$(MANEXT)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/htmltoc.1 > $(MANDIR)/htmltoc.$(MANEXT)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/nowebstyle.7 > $(MAN7DIR)/nowebstyle.$(MAN7EXT)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/nowebfilters.7 > $(MAN7DIR)/nowebfilters.$(MAN7EXT)
+ rm -f $(MANDIR)/noweave.$(MANEXT)
+ (cd $(MANDIR); ln notangle.$(MANEXT) noweave.$(MANEXT))
+ rm -f $(MANDIR)/nountangle.$(MANEXT)
+ (cd $(MANDIR); ln notangle.$(MANEXT) nountangle.$(MANEXT))
+uninstall-man:
+ rm -f $(MANDIR)/cpif.$(MANEXT)
+ rm -f $(MANDIR)/nodefs.$(MANEXT)
+ rm -f $(MANDIR)/noroots.$(MANEXT)
+ rm -f $(MANDIR)/noweb.$(MANEXT)
+ rm -f $(MANDIR)/noindex.$(MANEXT)
+ rm -f $(MANDIR)/nuweb2noweb.$(MANEXT)
+ rm -f $(MANDIR)/notangle.$(MANEXT)
+ rm -f $(MANDIR)/noroff.$(MANEXT)
+ rm -f $(MANDIR)/sl2h.$(MANEXT)
+ rm -f $(MANDIR)/htmltoc.$(MANEXT)
+ rm -f $(MAN7DIR)/nowebstyle.$(MAN7EXT)
+ rm -f $(MAN7DIR)/nowebfilters.$(MAN7EXT)
+ rm -f $(MANDIR)/noweave.$(MANEXT)
+ rm -f $(MANDIR)/nountangle.$(MANEXT)
+ -rmdir $(MANDIR) $(MAN7DIR) $(MAN) 2>/dev/null || true
+install-gzipped-man:
+ mkdir -p $(MAN) $(MANDIR) $(MAN7DIR)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/cpif.1 | gzip -9 > $(MANDIR)/cpif.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/nodefs.1 | gzip -9 > $(MANDIR)/nodefs.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/noroots.1 | gzip -9 > $(MANDIR)/noroots.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/noweb.1 | gzip -9 > $(MANDIR)/noweb.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/noindex.1 | gzip -9 > $(MANDIR)/noindex.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/nuweb2noweb.1 | gzip -9 > $(MANDIR)/nuweb2noweb.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/notangle.1 | gzip -9 > $(MANDIR)/notangle.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/noroff.1 | gzip -9 > $(MANDIR)/noroff.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/sl2h.1 | gzip -9 > $(MANDIR)/sl2h.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/htmltoc.1 | gzip -9 > $(MANDIR)/htmltoc.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/nowebstyle.7 | gzip -9 > $(MAN7DIR)/nowebstyle.$(MAN7EXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/nowebfilters.7 | gzip -9 > $(MAN7DIR)/nowebfilters.$(MAN7EXT).gz
+ rm -f $(MANDIR)/noweave.$(MANEXT).gz
+ (cd $(MANDIR); ln notangle.$(MANEXT).gz noweave.$(MANEXT).gz)
+ rm -f $(MANDIR)/nountangle.$(MANEXT).gz
+ (cd $(MANDIR); ln notangle.$(MANEXT).gz nountangle.$(MANEXT).gz)
+install-preformat-man:
+ -echo "Warning: install-preformat-man is obsolete, even on Slackware systems" 1>&2
+ mkdir -p $(MAN) $(CATDIR) $(CAT7DIR)
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/cpif.txt | gzip > $(CATDIR)/cpif.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/nodefs.txt | gzip > $(CATDIR)/nodefs.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/noroots.txt | gzip > $(CATDIR)/noroots.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/noweb.txt | gzip > $(CATDIR)/noweb.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/noindex.txt | gzip > $(CATDIR)/noindex.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/nuweb2noweb.txt | gzip > $(CATDIR)/nuweb2noweb.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/notangle.txt | gzip > $(CATDIR)/notangle.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/noroff.txt | gzip > $(CATDIR)/noroff.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/sl2h.txt | gzip > $(CATDIR)/sl2h.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/htmltoc.txt | gzip > $(CATDIR)/htmltoc.$(MANEXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/nowebstyle.txt | gzip > $(CAT7DIR)/nowebstyle.$(MAN7EXT).gz
+ sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@" xdoc/nowebfilters.txt | gzip > $(CAT7DIR)/nowebfilters.$(MAN7EXT).gz
+ rm -f $(CATDIR)/noweave.$(MANEXT).gz
+ (cd $(CATDIR); ln notangle.$(MANEXT).gz noweave.$(MANEXT).gz)
+ rm -f $(CATDIR)/nountangle.$(MANEXT).gz
+ (cd $(CATDIR); ln notangle.$(MANEXT).gz nountangle.$(MANEXT).gz)
+install-tex:
+ mkdir -p $(TEXINPUTS)
+ cp tex/nwmac.tex tex/noweb.sty $(TEXINPUTS)
+ -texhash || echo "Program texhash not found or failed"
+
+uninstall-tex:
+ rm -f $(TEXINPUTS)/nwmac.tex $(TEXINPUTS)/noweb.sty || true
+
+install-elisp:
+ if [ "/dev/null" != "$(ELISP)" ]; then mkdir -p $(ELISP); fi
+ cp elisp/noweb-mode.el $(ELISP)
+
+uninstall-elisp:
+ rm -f $(ELISP)/noweb-mode.el || true
+checkin:
+ for i in lib tex xdoc; do (cd $$i; make "CINAME=$(CINAME)" "CIMSG=$(CIMSG)" checkin); done
+ for i in c icon awk; do (cd $$i; ci -l $(CINAME) $(CIMSG) *.nw Makefile); done
+ (cd elisp; ci -l $(CINAME) $(CIMSG) *.el)
+ ci -l $(CINAME) $(CIMSG) Makefile.nw INSTALL INSTALL.DOS README FAQ COPYRIGHT nwmake *.nw
+
+source: FAQ
+ for i in c shell lib xdoc icon awk tex; do (cd $$i; make CPIF=">" source); done
+ sleep 1
+ for i in c shell lib xdoc icon awk tex; do (cd $$i; make touch); done
+touch:
+ touch FAQ
+ for i in c shell lib xdoc icon awk tex; do (cd $$i; make touch); done
+boot:
+ for i in c shell lib xdoc icon awk tex; do (cd $$i; make boot); done
+clean:
+ for i in c shell lib xdoc icon awk tex; do (cd $$i; make clean); done
+ rm -f nwsrcfilter *~ */*~
+
+clobber: clean
+ for i in c shell lib xdoc icon awk tex; do (cd $$i; make clobber); done
+
+Makefile: Makefile.nw
+ chmod +w Makefile
+ notangle -R'script' Makefile.nw | sh > Makefile
+ chmod -w Makefile
+
diff --git a/web/noweb/src/Makefile.nw b/web/noweb/src/Makefile.nw
new file mode 100644
index 0000000000..079a844b09
--- /dev/null
+++ b/web/noweb/src/Makefile.nw
@@ -0,0 +1,228 @@
+I got sick and tired of copying goo for multiple files.
+This nonsense is the result. (Too bad mk isn't everywhere.)
+<<script>>=
+(cat Makefile.nw; echo ""; notangle -t8 -R'generate chunks' Makefile.nw | sh) | notangle -t8 -
+<<*>>=
+# Copyright 1995-2018 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+#
+# Adjust these two lines for your ANSI C compiler
+CC=gcc -ansi -pedantic -O -Wall -Werror
+CFLAGS=
+# If you have Icon, you should use the Icon versions of the noweb pipeline.
+# Set LIBSRC=icon
+LIBSRC=awk
+# If you have no Icon compiler, but do have icont, make ICONC=icont
+ICONC=iconc
+ICONT=icont
+
+# BIN is where the commands (notangle, noweave, nountangle, noroots) land
+# LIB is where the pieces of the pipes (nt, markup, unmarkup) are stored
+# MAN is the root of your local man pages directory
+# MANEXT is the extension for your commands' man pages (usually 1 or l)
+# MAN7EXT is the extension for the nowebstyle man page (usually 7)
+# TEXINPUTS is the directory for TeX macro files
+# ELISP is the directory for emacs lisp files, or /dev/null not to install
+BIN=/usr/local/noweb
+LIB=/usr/local/noweb/lib
+MAN=/usr/local/noweb/man
+MANEXT=1
+MAN7EXT=7
+TEXINPUTS=/usr/local/tex/inputs
+ELISP=/dev/null
+
+# change WEAVE if you want a different version of noweave to be installed
+WEAVE=noweave
+
+# Stop editing. No user-serviceable parts below.
+SHELL=/bin/sh
+CINAME=
+CIMSG=
+MANDIR=$(MAN)/man$(MANEXT)
+MAN7DIR=$(MAN)/man$(MAN7EXT)
+CATDIR=$(MAN)/cat$(MANEXT)
+CAT7DIR=$(MAN)/cat$(MAN7EXT)
+LIBNAME=$(LIB)
+TEXNAME=$(TEXINPUTS)
+
+all:
+ cd c; make "CC=$(CC)" "CFLAGS=$(CFLAGS)" all
+ for i in shell lib xdoc tex; do (cd $$i; make all); done
+ cd $(LIBSRC); make "ICONT=$(ICONT)" "ICONC=$(ICONC)" all
+
+FAQ: FAQ.html
+ sleep 1; html2ascii FAQ.html > FAQ
+
+FAQ.html: $(HOME)/www/noweb/FAQ.html
+ rm -f FAQ.html
+ /bin/cp $(HOME)/www/noweb/FAQ.html FAQ.html
+ chmod -w FAQ.html
+
+install: install-code install-man install-tex install-elisp
+uninstall: uninstall-code uninstall-man uninstall-tex uninstall-elisp
+ -rmdir $(BIN) $(LIB) 2>/dev/null || true
+
+install-shell:
+ mkdir -p $(BIN) $(LIB)
+ <<shell binaries>>
+ cp shell/tmac.w $(LIB)
+
+uninstall-shell:
+ <<uninstall shell binaries>>
+ rm -f $(LIB)/tmac.w
+
+install-code: install-shell
+ mkdir -p $(BIN) $(LIB)
+ strip c/nt c/markup c/mnt c/finduses c/nwmktemp
+ cp c/nt c/markup c/mnt c/finduses c/nwmktemp $(LIB)
+ cd $(LIBSRC); make ICONT=$(ICONT) ICONC=$(ICONC) LIB=$(LIB) BIN=$(BIN) install
+ cd lib; make LIB=$(LIB) install
+
+uninstall-code: uninstall-shell
+ rm -f $(LIB)/nt $(LIB)/markup $(LIB)/mnt $(LIB)/finduses
+ cd $(LIBSRC); make ICONT=$(ICONT) ICONC=$(ICONC) LIB=$(LIB) BIN=$(BIN) uninstall
+ cd lib; make LIB=$(LIB) uninstall
+@ I do the [[<<shell binaries>>]] before [[$(LIBSRC)]] so that the
+Icon version of [[htmltoc]], if present, will overwrite the Perl
+version.
+@
+<<generate chunks>>=
+for i in noweb notangle '$(WEAVE)' nountangle nodefs noroots nuweb2noweb cpif htmltoc \
+ noroff
+do
+ echo '@<<shell binaries@>>='
+ echo 'sed "s@|LIBDIR|@$(LIBNAME)@"' "shell/$i" '> $(BIN)/'"$i"
+ echo 'chmod +x $(BIN)/'"$i"
+ echo '@<<uninstall shell binaries@>>='
+ echo 'rm -f $(BIN)/'"$i"
+done
+for i in toroff
+do
+ echo '@<<shell binaries@>>='
+ echo 'sed "s@|LIBDIR|@$(LIBNAME)@"' "shell/$i" '> $(LIB)/'"$i"
+ echo 'chmod +x $(LIB)/'"$i"
+ echo '@<<uninstall shell binaries@>>='
+ echo 'rm -f $(LIB)/'"$i"
+done
+<<*>>=
+install-man:
+ mkdir -p $(MAN) $(MANDIR) $(MAN7DIR)
+ <<ordinary pages>>
+uninstall-man:
+ <<uninstall ordinary pages>>
+ -rmdir $(MANDIR) $(MAN7DIR) $(MAN) 2>/dev/null || true
+@
+Slackware no longer uses preformatted compressed pages, just
+compressed pages.
+<<*>>=
+install-gzipped-man:
+ mkdir -p $(MAN) $(MANDIR) $(MAN7DIR)
+ <<compressed pages>>
+<<*>>=
+install-preformat-man:
+ -echo "Warning: install-preformat-man is obsolete, even on Slackware systems" 1>&2
+ mkdir -p $(MAN) $(CATDIR) $(CAT7DIR)
+ <<preformatted compressed pages>>
+<<generate chunks>>=
+NORMALPAGES="cpif nodefs noroots noweb noindex nuweb2noweb notangle noroff sl2h htmltoc"
+NORMAL7PAGES="nowebstyle nowebfilters"
+LINKPAGES="noweave nountangle"
+
+
+for i in $NORMALPAGES; do
+ echo '@<<ordinary pages@>>='
+ echo 'sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@"' \
+ "xdoc/$i.1" '> $(MANDIR)/'"$i"'.$(MANEXT)'
+ echo '@<<uninstall ordinary pages@>>='
+ echo 'rm -f $(MANDIR)/'"$i"'.$(MANEXT)'
+done
+for i in $NORMAL7PAGES; do
+ echo '@<<ordinary pages@>>='
+ echo 'sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@"' \
+ "xdoc/$i.7" '> $(MAN7DIR)/'"$i"'.$(MAN7EXT)'
+ echo '@<<uninstall ordinary pages@>>='
+ echo 'rm -f $(MAN7DIR)/'"$i"'.$(MAN7EXT)'
+done
+
+for i in $LINKPAGES; do
+ echo '@<<ordinary pages@>>='
+ echo 'rm -f $(MANDIR)/'"$i"'.$(MANEXT)'
+ echo '(cd $(MANDIR); ln notangle.$(MANEXT)' "$i"'.$(MANEXT))'
+ echo '@<<uninstall ordinary pages@>>='
+ echo 'rm -f $(MANDIR)/'"$i"'.$(MANEXT)'
+done
+
+echo '@<<compressed pages@>>='
+
+for i in $NORMALPAGES; do
+ echo 'sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@"' \
+ "xdoc/$i.1" ' | gzip -9 > $(MANDIR)/'"$i"'.$(MANEXT).gz'
+done
+for i in $NORMAL7PAGES; do
+ echo 'sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@"' \
+ "xdoc/$i.7" ' | gzip -9 > $(MAN7DIR)/'"$i"'.$(MAN7EXT).gz'
+done
+
+for i in $LINKPAGES; do
+ echo 'rm -f $(MANDIR)/'"$i"'.$(MANEXT).gz'
+ echo '(cd $(MANDIR); ln notangle.$(MANEXT).gz' "$i"'.$(MANEXT).gz)'
+done
+
+echo '@<<preformatted compressed pages@>>='
+
+for i in $NORMALPAGES; do
+ echo 'sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@"' \
+ "xdoc/$i.txt" ' | gzip > $(CATDIR)/'"$i"'.$(MANEXT).gz'
+done
+for i in $NORMAL7PAGES; do
+ echo 'sed -e "s@|LIBDIR|@$(LIBNAME)@" -e "s@|TEXINPUTS|@$(TEXNAME)@"' \
+ "xdoc/$i.txt" ' | gzip > $(CAT7DIR)/'"$i"'.$(MAN7EXT).gz'
+done
+
+for i in $LINKPAGES; do
+ echo 'rm -f $(CATDIR)/'"$i"'.$(MANEXT).gz'
+ echo '(cd $(CATDIR); ln notangle.$(MANEXT).gz' "$i"'.$(MANEXT).gz)'
+done
+<<*>>=
+install-tex:
+ mkdir -p $(TEXINPUTS)
+ cp tex/nwmac.tex tex/noweb.sty $(TEXINPUTS)
+ -texhash || echo "Program texhash not found or failed"
+
+uninstall-tex:
+ rm -f $(TEXINPUTS)/nwmac.tex $(TEXINPUTS)/noweb.sty || true
+
+install-elisp:
+ if [ "/dev/null" != "$(ELISP)" ]; then mkdir -p $(ELISP); fi
+ cp elisp/noweb-mode.el $(ELISP)
+
+uninstall-elisp:
+ rm -f $(ELISP)/noweb-mode.el || true
+@
+<<*>>=
+checkin:
+ for i in lib tex xdoc; do (cd $$i; make "CINAME=$(CINAME)" "CIMSG=$(CIMSG)" checkin); done
+ for i in c icon awk; do (cd $$i; ci -l $(CINAME) $(CIMSG) *.nw Makefile); done
+ (cd elisp; ci -l $(CINAME) $(CIMSG) *.el)
+ ci -l $(CINAME) $(CIMSG) Makefile.nw INSTALL INSTALL.DOS README FAQ COPYRIGHT nwmake *.nw
+
+source: FAQ
+ for i in c shell lib xdoc icon awk tex; do (cd $$i; make CPIF=">" source); done
+ sleep 1
+ for i in c shell lib xdoc icon awk tex; do (cd $$i; make touch); done
+touch:
+ touch FAQ
+ for i in c shell lib xdoc icon awk tex; do (cd $$i; make touch); done
+boot:
+ for i in c shell lib xdoc icon awk tex; do (cd $$i; make boot); done
+clean:
+ for i in c shell lib xdoc icon awk tex; do (cd $$i; make clean); done
+ rm -f nwsrcfilter *~ */*~
+
+clobber: clean
+ for i in c shell lib xdoc icon awk tex; do (cd $$i; make clobber); done
+
+Makefile: Makefile.nw
+ chmod +w Makefile
+ notangle -R'script' Makefile.nw | sh > Makefile
+ chmod -w Makefile
diff --git a/web/noweb/src/README b/web/noweb/src/README
new file mode 100644
index 0000000000..5e25dc05e0
--- /dev/null
+++ b/web/noweb/src/README
@@ -0,0 +1,20 @@
+These are the base sources and documents for version 2.12 of
+``noweb'', a simple, extensible literate-programming tool. noweb is
+available from https://github.com/nrnrnr/noweb. The file INSTALL
+tells how to build noweb. The file FAQ answers some frequently asked
+questions about building and using noweb.
+
+
+STRUCTURE OF THE BASE SOURCES
+
+This part of the distribution contains the following directories:
+
+ awk pipeline stages and back ends in awk and sh
+ src C source code for nt, markup, and finduses
+ icon pipeline stages and back ends in Icon
+ lib other pipeline stages and back ends, not available in Icon
+ rc replacements for shell scripts; useful on Plan 9
+ shell the shell scripts that make up the actual commands
+ tex supporting tex code for /usr/local/lib/tex/macros
+ xdoc man pages, hacker's guide (named to be unpacked last)
+
diff --git a/web/noweb/src/VERSIONS b/web/noweb/src/VERSIONS
new file mode 100644
index 0000000000..273eec39d4
--- /dev/null
+++ b/web/noweb/src/VERSIONS
@@ -0,0 +1,11 @@
+2.11: Bug fix in parsing; a dozen small repairs
+2.10: nountangle becomes a filter; multilanguage support; ...
+2.9: Support for hyperref; many small repairs
+2.8: LaTeX2e, support for HTML tables
+2.7: Reads nuweb files, converts latex to HTML
+2.6: HTML support, necessitating a rewrite of cross-referencer
+2.5: Index of identifiers and identifier cross-reference
+2.4: Icon versions of the major pipeline stages
+2.0: Fully detailed pipeline representation
+1: Pipelined architecture
+0: Monolithic notangle; noweave as unholy awk script
diff --git a/web/noweb/src/awk/Makefile b/web/noweb/src/awk/Makefile
new file mode 100644
index 0000000000..f090674347
--- /dev/null
+++ b/web/noweb/src/awk/Makefile
@@ -0,0 +1,47 @@
+# Copyright 1993 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+
+LIB=/dev/null # must be overridden
+BIN=/dev/null # must be overridden
+SHELL=/bin/sh
+
+LIBEXECSBARE=noidx tohtml
+LIBEXECSDEP=totex
+LIBEXECS=$(LIBEXECSBARE) $(LIBEXECSDEP)
+BINEXECS=noindex
+EXECS=$(BINEXECS) $(LIBEXECS)
+
+all: $(EXECS)
+ chmod +x $(EXECS)
+sources: $(EXECS)
+touch: $(EXECS)
+ touch $(EXECS)
+boot:
+ touch $(EXECS)
+
+install: all
+ cp $(LIBEXECSBARE) $(LIB)
+ for i in $(LIBEXECSDEP); do sed "s@|LIBDIR|@$(LIB)@" "$$i" > $(LIB)/"$$i"; chmod +x $(LIB)/$$i; done
+ cp $(BINEXECS) $(BIN)
+
+uninstall:
+ for i in $(LIBEXECS); do rm -f $(LIB)/$$i; done
+ for i in $(BINEXECS); do rm -f $(BIN)/$$i; done
+
+source: $(EXECS)
+
+totex: totex.nw
+ notangle -Rtotex totex.nw > totex
+
+noidx: noidx.nw
+ notangle noidx.nw > noidx
+
+tohtml: tohtml.nw
+ notangle tohtml.nw > tohtml
+
+noindex: noindex.nw
+ notangle -Rnoindex noindex.nw > noindex
+
+clean: ; rm -f *.log *.blg *.dvi *.toc *.aux *.tex *~ *.html
+clobber: clean
+ rm -f totex noidx tohtml noindex
diff --git a/web/noweb/src/awk/noidx b/web/noweb/src/awk/noidx
new file mode 100755
index 0000000000..59f35046af
--- /dev/null
+++ b/web/noweb/src/awk/noidx
@@ -0,0 +1,362 @@
+#!/bin/sh
+delay=0 anchordist=0
+while [ $# -gt 0 ]; do
+ case $1 in
+ -delay) delay=1 ;;
+ -docanchor) anchordist="$2"; shift ;;
+ *) echo "This can't happen -- $1 passed to noidx" 1>&2 ; exit 1 ;;
+ esac
+ shift
+done
+nawk 'function insertafter(i, s, n) {
+ for(n = nextline++; n - 1 > i; n--) lines[n] = lines[n-1]
+ lines[n] = s
+ }
+ function slipin(s) {
+ lines[nextline++] = s
+ }
+ function fill_charcode_table(i) {
+ if (charcode_table[64])
+ return
+ for (i = 0; i < 256; i++) {
+ charcode_table[sprintf("%c", i)] = i
+ }
+ }
+
+ function charcode(s, i) {
+ fill_charcode_table()
+ return charcode_table[substr(s, i, 1)]
+ }
+ function fill_crc_table(POLY, sum, i, j) {
+ POLY = 245 * 4096 * 4096
+ if (crc_table[0]) {
+ return
+ }
+ for (i = 0; i < 256; i ++) {
+ sum = 0
+ for (j = 7; j >= 0; j -= 1) {
+ if (and(i, lshift(1, j)) != 0) {
+ sum = xor(sum, rshift(POLY, j))
+ }
+ }
+ crc_table[i] = sum
+ }
+ }
+
+ function crc(s, sum, i) {
+ fill_crc_table()
+ sum = 0
+ for (i = 1; i <= length(s); i++) {
+ sum = xor(rshift(sum, 8), crc_table[and(xor(sum, charcode(s, i)), 255)])
+ }
+ return sum
+ }
+ function newdefnlabel(arg, label) {
+ defcount[arg] = defcount[arg] + 1
+ label = "NW" curfile "-" uniqueid(arg) "-" alphacode(defcount[arg])
+ return label
+ }
+ function newdocslabel() {
+ newdocslabelcount++
+ return "NWD" alphacode(newdocslabelcount)
+ }
+ function addlabel(tbl, arg, label, marker) {
+ marker = " " label
+ if (!tailmatch(tbl[arg], marker))
+ tbl[arg] = tbl[arg] marker
+ return label
+ }
+ function tailmatch(string, tail, pos) {
+ pos = length(string) - length(tail) + 1
+ if (pos > 0 && substr(string, pos) == tail)
+ return 1
+ else
+ return 0
+ }
+ function addud(udlist, name, arg, label, s) {
+ s = " " name "{" label "}"
+ if (!tailmatch(udlist[arg], s))
+ udlist[arg] = udlist[arg] s
+ }
+ function listget(l, i, n, a) {
+ n = split(l, a)
+ return a[i]
+ }
+ function uniqueid(name, key) {
+ if (uidtable[name] == "") {
+ key = make_key(name)
+ # gsub(/[\]\[ \\{}`#%&~_^<>"-]/, "*", key) # old
+ gsub(/[^a-zA-Z0-9!$()*+,.\/:;=?@|]/, "*", key)
+ keycounts[key] = keycounts[key] + 1
+ uidtable[name] = key
+ if (keycounts[key] > 1)
+ uidtable[name] = uidtable[name] "." alphacode(keycounts[key])
+ }
+ return uidtable[name]
+ }
+ function old_make_key(name, key, l) {
+ l = length(name)
+ sub(/^.*\//, "", name)
+ key = substr(name, 1, 3)
+ if (l >= 3) key = key alphacode(l)
+ return key
+ }
+ function make_key(name) {
+ return alphacode(crc(name))
+ }
+ function lognowebchunks(l, j, n, x) {
+ if (loggednowebchunks > 0) return
+ loggednowebchunks = 1
+ delete allchunks[0]
+ n = alphasort(allchunks)
+ print "@xref beginchunks"
+ for (j = 0; j < n; j++) {
+ name = sorted[j]; delete sorted[j]
+ printf "@xref chunkbegin %s %s\n",
+ (anchorlabel[name] != "" ? anchorlabel[name] : "nw@notdef"), name
+ m = split(chunkud[name], a)
+ for (k = 1; k <= m; k++)
+ if (a[k] ~ /^use/)
+ printf "@xref chunkuse %s\n", substr(a[k], 5, length(a[k])-5)
+ else if (a[k] ~ /^defn/)
+ printf "@xref chunkdefn %s\n", substr(a[k], 6, length(a[k])-6)
+ print "@xref chunkend"
+ }
+ print "@xref endchunks"
+ }
+ function lognowebindex(l, j, n, x) {
+ if (loggednowebindex > 0) return
+ loggednowebindex = 1
+ delete allidents[0]
+ n = alphasort(allidents)
+ print "@index beginindex"
+ for (j = 0; j < n; j++) {
+ name = sorted[j]; delete sorted[j]
+ printf "@index entrybegin %s %s\n",
+ (indexanchorlabel[name] != "" ? indexanchorlabel[name] : "nw@notdef"), name
+ m = split(indexud[name], a)
+ for (k = 1; k <= m; k++)
+ if (a[k] ~ /^use/)
+ printf "@index entryuse %s\n", substr(a[k], 5, length(a[k])-5)
+ else if (a[k] ~ /^defn/)
+ printf "@index entrydefn %s\n", substr(a[k], 6, length(a[k])-6)
+ print "@index entryend"
+ }
+ print "@index endindex"
+ }
+ function alphasort(a, x, n) {
+ n = 0
+ for (x in a)
+ n = insertitem(x, n)
+ return n
+ }
+ function insertitem(x, n, i, tmp) {
+ sorted[n] = x
+ sortkeys[n] = sortkey(x)
+ i = n
+ while (i > 0 && (sortkeys[i] < sortkeys[i-1] ||
+ sortkeys[i] == sortkeys[i-1] && sorted[i] < sorted[i-1])) {
+ tmp = sortkeys [i]; sortkeys [i] = sortkeys [i-1]; sortkeys [i-1] = tmp
+ tmp = sorted[i]; sorted[i] = sorted[i-1]; sorted[i-1] = tmp
+ i = i - 1
+ }
+ return n + 1
+ }
+ function sortkey(s) {
+ return tolower(s) "\n" s # relies on \n sorting lower than other characters
+ }
+ function alphacode(n) {
+ if (n < 0)
+ return "-" alphacode(-n)
+ else if (n >= alphacodelen)
+ return alphacode(n / alphacodelen) alphacode(n % alphacodelen)
+ else
+ return substr(alphacodes, n+1, 1)
+ }
+ BEGIN { curfile = "standard input?"
+ lastchunkbegin = "never any chunks?" ;
+ allchunks[0] = 0 ; allidents[0] = 0 ; indexlabels[0] = 0
+ defanchors[0] = 0 ; uses[0] = 0 ; anchorlabel[0] = 0 ; indexanchorlabel[0] = 0
+ thesedefns[0] = 0; theseuses[0] = 0 ;
+ defcount[0] = 0 ;
+ udlist[0] = 0 ;
+ uidtable[0] = 0
+ keycounts[0] = 0 ;
+ sorted[0] = 0; sortkeys[0] = 0;
+ alphacodes = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ alphacodelen = length(alphacodes) ; nextline = 0 }
+ /^@file / { curfile = uniqueid(substr($0, 7)) }
+ /^@begin / { lastchunkbegin = $0 }
+ /^@end docs / { if (anchordist > 0) { n = anchordist
+ lastanchorlabel = newdocslabel()
+ for(i = nextline - 1; i >= 0; i--) {
+ if (n == 0 || lines[i] ~ /^@begin docs /) {
+ insertafter(i, "@xref label " lastanchorlabel)
+ i = -1 # cause loop to terminate
+ } else if (lines[i] == "@nl") {
+ n--
+ }
+ }
+ } }
+ /^@end code / { lastanchorlabel = "" }
+ /^@defn / { arg = substr($0, 7)
+ allchunks[arg] = 1
+ lastdefnlabel = newdefnlabel(arg)
+ slipin("@xref label " lastdefnlabel)
+ if (lastanchorlabel == "") lastanchorlabel = lastdefnlabel
+ if (anchorlabel[arg] == "") anchorlabel[arg] = lastanchorlabel
+ addlabel(defanchors, arg, lastanchorlabel)
+ addud(chunkud, "defn", arg, lastanchorlabel)
+ thisusecount = 0
+ }
+ /^@use / { if (lastchunkbegin ~ /^@begin code /) {
+ arg = substr($0, 6)
+ allchunks[arg] = 1
+ slipin("@xref label " lastdefnlabel "-u" (++thisusecount))
+ addlabel(uses, arg, lastanchorlabel)
+ addud(chunkud, "use", arg, lastanchorlabel)
+ }
+ }
+ /^@index use / { arg = substr($0, 12)
+ allidents[arg] = 1
+ if (lastanchorlabel != "") addud(indexud, "use", arg, lastanchorlabel)
+ }
+ /^@index defn / { arg = substr($0, 13)
+ allidents[arg] = 1
+ if (lastanchorlabel != "") {
+ l = lastanchorlabel
+ } else {
+ l = newdocslabel()
+ slipin("@xref label " l)
+ }
+ addud(indexud, "defn", arg, l)
+ if (indexanchorlabel[arg] == "") indexanchorlabel[arg] = l
+ slipin("@xref ref " l) # bug fix
+ }
+ /^@index localdefn / { arg = substr($0, 18)
+ allidents[arg] = 1
+ if (lastanchorlabel != "") {
+ l = lastanchorlabel
+ } else {
+ l = newdocslabel()
+ slipin("@xref label " l)
+ }
+ addud(indexud, "defn", arg, l)
+ if (indexanchorlabel[arg] == "") indexanchorlabel[arg] = l
+ slipin("@xref ref " l) # bug fix
+ }
+ { lines[nextline] = $0; nextline++ }
+ END {
+ for (i = 0; i < nextline; i ++) {
+ line = lines[i]
+ if (line ~ /^@begin /) {
+ if (delay && lastchunkbegin == line) { print "@nl"
+ print "@nl"
+ lognowebchunks()
+ lognowebindex()
+ }
+ print line
+ for (x in thesedefns) delete thesedefns[x]
+ for (x in theseuses) delete theseuses[x]
+ thischunk = ""
+ } else if (line ~ /^@defn /) {
+ thischunk = substr(line, 7)
+ printf "@xref ref %s\n", anchorlabel[thischunk]
+ print line
+ defout[thischunk]++
+ if (defout[thischunk] > 1)
+ printf "@xref prevdef %s\n", listget(defanchors[thischunk], defout[thischunk]-1)
+ if (defout[thischunk] < defcount[thischunk])
+ printf "@xref nextdef %s\n", listget(defanchors[thischunk], defout[thischunk]+1)
+ if (defout[thischunk] == 1) {if (defcount[thischunk] > 1) {
+ print "@xref begindefs"
+ n = split(defanchors[thischunk], a)
+ for (j = 2; j <= n; j++) printf "@xref defitem %s\n", a[j]
+ print "@xref enddefs"
+
+ }
+ if (uses[thischunk] != "") {
+ print "@xref beginuses"
+ n = split(uses[thischunk], a)
+ for (j = 1; j <= n; j++) printf "@xref useitem %s\n", a[j]
+ print "@xref enduses"
+ } else {
+ printf "@xref notused %s\n", thischunk
+ }}
+ } else if (line ~ /^@use /) {
+ arg = substr(line, 6)
+ printf "@xref ref %s\n", (anchorlabel[arg] == "" ? "nw@notdef" : anchorlabel[arg])
+ print line
+ } else if (line ~ /^@index defn /) {
+ arg = substr(line, 13)
+ thesedefns[arg] = 1
+ # no xref ref because of bug fix
+ # if (indexanchorlabel[arg] != "")
+ # printf "@xref ref %s\n", indexanchorlabel[arg]
+ print line
+ } else if (line ~ /^@index localdefn /) {
+ arg = substr(line, 18)
+ thesedefns[arg] = 1
+ # no xref ref because of bug fix
+ # if (indexanchorlabel[arg] != "")
+ # printf "@xref ref %s\n", indexanchorlabel[arg]
+ print line
+ } else if (line ~ /^@index use /) {
+ arg = substr(line, 12)
+ theseuses[arg] = 1
+ if (indexanchorlabel[arg] != "")
+ printf "@xref ref %s\n", indexanchorlabel[arg]
+ print line
+ } else if (line ~ /^@end code/) {
+ for (x in thesedefns)
+ delete theseuses[x]
+ delete thesedefns[0]
+ n = alphasort(thesedefns)
+ if (n > 0) {
+ print "@index begindefs"
+ for (j = 0; j < n; j++) {
+ m = split(indexud[sorted[j]], a)
+ for (k = 1; k <= m; k++)
+ if (a[k] ~ /^use/)
+ printf "@index isused %s\n", substr(a[k], 5, length(a[k])-5)
+ printf "@index defitem %s\n", sorted[j]
+ delete sorted[j]
+ }
+ print "@index enddefs"
+ }
+ delete theseuses[0]
+ n = alphasort(theseuses)
+ if (n > 0) {
+ print "@index beginuses"
+ for (j = 0; j < n; j++) {
+ m = split(indexud[sorted[j]], a)
+ for (k = 1; k <= m; k++)
+ if (a[k] ~ /^defn/)
+ printf "@index isdefined %s\n", substr(a[k], 6, length(a[k])-6)
+ printf "@index useitem %s\n", sorted[j]
+ delete sorted[j]
+ }
+ print "@index enduses"
+ }
+ print line
+ } else if (line ~ /^@text /) {
+ # grotesque hack to get indexes in HTML
+ if (thischunk == "") { # docs mode
+ arg = substr(line, 7)
+ if (arg == "<nowebchunks>") lognowebchunks()
+ else if (arg == "<nowebindex>") lognowebindex()
+ else print line
+ } else {
+ print line
+ }
+ } else {
+ print line
+ }
+ delete lines[i]
+ }
+ if (!delay) { print "@nl"
+ print "@nl"
+ lognowebchunks()
+ lognowebindex()
+ }
+ }' delay=$delay anchordist=$anchordist
diff --git a/web/noweb/src/awk/noidx.nw b/web/noweb/src/awk/noidx.nw
new file mode 100644
index 0000000000..77b4430027
--- /dev/null
+++ b/web/noweb/src/awk/noidx.nw
@@ -0,0 +1,477 @@
+\documentstyle[noweb]{article}
+\pagestyle{noweb}
+\begin{document}
+@
+\section{Cross-reference and index support}
+Here is is.
+<<*>>=
+#!/bin/sh
+delay=0 anchordist=0
+while [ $# -gt 0 ]; do
+ case $1 in
+ -delay) delay=1 ;;
+ -docanchor) anchordist="$2"; shift ;;
+ *) echo "This can't happen -- $1 passed to noidx" 1>&2 ; exit 1 ;;
+ esac
+ shift
+done
+nawk '<<awk program for indexing>>' delay=$delay anchordist=$anchordist
+@
+<<awk program for indexing>>=
+<<functions>>
+BEGIN { <<initialization>> nextline = 0 }
+<<first pass>>
+{ lines[nextline] = $0; nextline++ }
+END {
+ for (i = 0; i < nextline; i ++) {
+ <<second pass over [[lines[i]]]>>
+ delete lines[i]
+ }
+ if (!delay) <<write trailers>>
+}
+@ %def lines nextline
+<<initialization>>=
+curfile = "standard input?"
+lastchunkbegin = "never any chunks?" ;
+<<initialization>>=
+allchunks[0] = 0 ; allidents[0] = 0 ; indexlabels[0] = 0
+defanchors[0] = 0 ; uses[0] = 0 ; anchorlabel[0] = 0 ; indexanchorlabel[0] = 0
+@ %def allchunks allidents indexlabels defanchors uses anchorlabel indexanchorlabel
+<<first pass>>=
+/^@file / { curfile = uniqueid(substr($0, 7)) }
+/^@begin / { lastchunkbegin = $0 }
+/^@end docs / { if (anchordist > 0) <<insert and set [[lastanchorlabel]]>> }
+/^@end code / { lastanchorlabel = "" }
+@ %def curfile lastchunkbegin lastanchorlabel
+<<first pass>>=
+/^@defn / { arg = substr($0, 7)
+ allchunks[arg] = 1
+ lastdefnlabel = newdefnlabel(arg)
+ slipin("@xref label " lastdefnlabel)
+ if (lastanchorlabel == "") lastanchorlabel = lastdefnlabel
+ if (anchorlabel[arg] == "") anchorlabel[arg] = lastanchorlabel
+ addlabel(defanchors, arg, lastanchorlabel)
+ addud(chunkud, "defn", arg, lastanchorlabel)
+ thisusecount = 0
+ }
+/^@use / { if (lastchunkbegin ~ /^@begin code /) {
+ arg = substr($0, 6)
+ allchunks[arg] = 1
+ slipin("@xref label " lastdefnlabel "-u" (++thisusecount))
+ addlabel(uses, arg, lastanchorlabel)
+ addud(chunkud, "use", arg, lastanchorlabel)
+ }
+ }
+@ %def allchunks lastdefnlabel
+<<first pass>>=
+/^@index use / { arg = substr($0, 12)
+ allidents[arg] = 1
+ if (lastanchorlabel != "") addud(indexud, "use", arg, lastanchorlabel)
+ }
+/^@index defn / { arg = substr($0, 13)
+ <<handle index definition of [[arg]]>>
+ }
+/^@index localdefn / { arg = substr($0, 18)
+ <<handle index definition of [[arg]]>>
+ }
+<<handle index definition of [[arg]]>>=
+allidents[arg] = 1
+if (lastanchorlabel != "") {
+ l = lastanchorlabel
+} else {
+ l = newdocslabel()
+ slipin("@xref label " l)
+}
+addud(indexud, "defn", arg, l)
+if (indexanchorlabel[arg] == "") indexanchorlabel[arg] = l
+slipin("@xref ref " l) # bug fix
+@ %def allidents indexanchorlabel
+The bug fix\label{multi-def-bug}
+alluded to above occurs when there are multiple definitions of an identifier.
+In this case, we can't just use [[indexanchorlabel[id]]], because that refers only to
+the first definition. In the {\TeX} back end, that leads to bogus
+tags like \hbox{\it x \small\rm 7b 7b 7b} instead of \hbox{\it x
+\small\rm 7b 9 12a}; the first tag is repeated again and again.
+Because the tag for the current [[@defn]] is lost by the time pass~2
+rolls around, we have to slip it in on pass~1.
+@
+<<insert and set [[lastanchorlabel]]>>=
+{ n = anchordist
+ lastanchorlabel = newdocslabel()
+ for(i = nextline - 1; i >= 0; i--) {
+ if (n == 0 || lines[i] ~ /^@begin docs /) {
+ insertafter(i, "@xref label " lastanchorlabel)
+ i = -1 # cause loop to terminate
+ } else if (lines[i] == "@nl") {
+ n--
+ }
+ }
+}
+<<functions>>=
+function insertafter(i, s, n) {
+ for(n = nextline++; n - 1 > i; n--) lines[n] = lines[n-1]
+ lines[n] = s
+}
+@
+In the awk version, [[slipin]] is called {\em before} the current line is
+added to [[lines]].
+<<functions>>=
+function slipin(s) {
+ lines[nextline++] = s
+}
+<<initialization>>=
+thesedefns[0] = 0; theseuses[0] = 0 ;
+<<second pass over [[lines[i]]]>>=
+line = lines[i]
+if (line ~ /^@begin /) {
+ if (delay && lastchunkbegin == line) <<write trailers>>
+ print line
+ for (x in thesedefns) delete thesedefns[x]
+ for (x in theseuses) delete theseuses[x]
+ thischunk = ""
+} else if (line ~ /^@defn /) {
+ thischunk = substr(line, 7)
+ printf "@xref ref %s\n", anchorlabel[thischunk]
+ print line
+ <<write chunk cross-reference>>
+} else if (line ~ /^@use /) {
+ arg = substr(line, 6)
+ printf "@xref ref %s\n", (anchorlabel[arg] == "" ? "nw@notdef" : anchorlabel[arg])
+ print line
+} else if (line ~ /^@index defn /) {
+ arg = substr(line, 13)
+ thesedefns[arg] = 1
+ # no xref ref because of bug fix
+ # if (indexanchorlabel[arg] != "")
+ # printf "@xref ref %s\n", indexanchorlabel[arg]
+ print line
+} else if (line ~ /^@index localdefn /) {
+ arg = substr(line, 18)
+ thesedefns[arg] = 1
+ # no xref ref because of bug fix
+ # if (indexanchorlabel[arg] != "")
+ # printf "@xref ref %s\n", indexanchorlabel[arg]
+ print line
+} else if (line ~ /^@index use /) {
+ arg = substr(line, 12)
+ theseuses[arg] = 1
+ if (indexanchorlabel[arg] != "")
+ printf "@xref ref %s\n", indexanchorlabel[arg]
+ print line
+} else if (line ~ /^@end code/) {
+ <<write index cross-reference>>
+ print line
+} else if (line ~ /^@text /) {
+ # grotesque hack to get indexes in HTML
+ if (thischunk == "") { # docs mode
+ arg = substr(line, 7)
+ if (arg == "<nowebchunks>") lognowebchunks()
+ else if (arg == "<nowebindex>") lognowebindex()
+ else print line
+ } else {
+ print line
+ }
+} else {
+ print line
+}
+@ %def thesedefns theseuses
+The case of the [[@index defn]] is the one case where we don't emit a
+reference, because the reference has to go in earlier. See
+page~\pageref{multi-def-bug} for an explanation.
+<<write chunk cross-reference>>=
+defout[thischunk]++
+if (defout[thischunk] > 1)
+ printf "@xref prevdef %s\n", listget(defanchors[thischunk], defout[thischunk]-1)
+if (defout[thischunk] < defcount[thischunk])
+ printf "@xref nextdef %s\n", listget(defanchors[thischunk], defout[thischunk]+1)
+if (defout[thischunk] == 1) {<<write use and def summary for chunk cross-reference>>}
+<<write index cross-reference>>=
+for (x in thesedefns)
+ delete theseuses[x]
+delete thesedefns[0]
+n = alphasort(thesedefns)
+if (n > 0) {
+ print "@index begindefs"
+ for (j = 0; j < n; j++) {
+ m = split(indexud[sorted[j]], a)
+ for (k = 1; k <= m; k++)
+ if (a[k] ~ /^use/)
+ printf "@index isused %s\n", substr(a[k], 5, length(a[k])-5)
+ printf "@index defitem %s\n", sorted[j]
+ delete sorted[j]
+ }
+ print "@index enddefs"
+}
+<<write index cross-reference>>=
+delete theseuses[0]
+n = alphasort(theseuses)
+if (n > 0) {
+ print "@index beginuses"
+ for (j = 0; j < n; j++) {
+ m = split(indexud[sorted[j]], a)
+ for (k = 1; k <= m; k++)
+ if (a[k] ~ /^defn/)
+ printf "@index isdefined %s\n", substr(a[k], 6, length(a[k])-6)
+ printf "@index useitem %s\n", sorted[j]
+ delete sorted[j]
+ }
+ print "@index enduses"
+}
+<<write use and def summary for chunk cross-reference>>=
+if (defcount[thischunk] > 1) {
+ print "@xref begindefs"
+ n = split(defanchors[thischunk], a)
+ for (j = 2; j <= n; j++) printf "@xref defitem %s\n", a[j]
+ print "@xref enddefs"
+
+}
+if (uses[thischunk] != "") {
+ print "@xref beginuses"
+ n = split(uses[thischunk], a)
+ for (j = 1; j <= n; j++) printf "@xref useitem %s\n", a[j]
+ print "@xref enduses"
+} else {
+ printf "@xref notused %s\n", thischunk
+}
+<<functions>>=
+function fill_charcode_table(i) {
+ if (charcode_table[64])
+ return
+ for (i = 0; i < 256; i++) {
+ charcode_table[sprintf("%c", i)] = i
+ }
+}
+
+function charcode(s, i) {
+ fill_charcode_table()
+ return charcode_table[substr(s, i, 1)]
+}
+@
+32-bit Cyclic Redundancy Code implemented by A. Appel 1986
+
+This works only if [[POLY]] is a prime polynomial in the field
+of integers modulo~2, of order~32. Since the representation of this polynomial
+will not fit in a 32-bit word, the high-order bit is implicit.
+\textbf{It must also be the case} that the coefficients of orders~31 down to~25
+are zero. Fortunately, we have a candidate, from
+E. J. Watson, "Primitive Polynomials (Mod 2)", Math. Comp 16 (1962):
+It is: $x^{32} + x^7 + x^5 + x^3 + x^2 + x^1 + x^0$.
+
+Now we reverse the bits to get:
+\begin{verbatim}
+ 111101010000000000000000000000001 in binary (but drop the last 1)
+ f 5 0 0 0 0 0 0 in hex
+\end{verbatim}
+<<functions>>=
+function fill_crc_table(POLY, sum, i, j) {
+ POLY = 245 * 4096 * 4096
+ if (crc_table[0]) {
+ return
+ }
+ for (i = 0; i < 256; i ++) {
+ sum = 0
+ for (j = 7; j >= 0; j -= 1) {
+ if (and(i, lshift(1, j)) != 0) {
+ sum = xor(sum, rshift(POLY, j))
+ }
+ }
+ crc_table[i] = sum
+ }
+}
+
+function crc(s, sum, i) {
+ fill_crc_table()
+ sum = 0
+ for (i = 1; i <= length(s); i++) {
+ sum = xor(rshift(sum, 8), crc_table[and(xor(sum, charcode(s, i)), 255)])
+ }
+ return sum
+}
+<<functions>>=
+function newdefnlabel(arg, label) {
+ defcount[arg] = defcount[arg] + 1
+ label = "NW" curfile "-" uniqueid(arg) "-" alphacode(defcount[arg])
+ return label
+}
+@ %def newdefnlabel
+<<initialization>>=
+defcount[0] = 0 ;
+<<functions>>=
+function newdocslabel() {
+ newdocslabelcount++
+ return "NWD" alphacode(newdocslabelcount)
+}
+@ %def newdocslabel
+<<functions>>=
+function addlabel(tbl, arg, label, marker) {
+ marker = " " label
+ if (!tailmatch(tbl[arg], marker))
+ tbl[arg] = tbl[arg] marker
+ return label
+}
+@ %def addlabel
+<<functions>>=
+function tailmatch(string, tail, pos) {
+ pos = length(string) - length(tail) + 1
+ if (pos > 0 && substr(string, pos) == tail)
+ return 1
+ else
+ return 0
+}
+@ %def tailmatch
+<<functions>>=
+function addud(udlist, name, arg, label, s) {
+ s = " " name "{" label "}"
+ if (!tailmatch(udlist[arg], s))
+ udlist[arg] = udlist[arg] s
+}
+@ %def addud
+<<functions>>=
+function listget(l, i, n, a) {
+ n = split(l, a)
+ return a[i]
+}
+@ %def listget
+<<initialization>>=
+udlist[0] = 0 ;
+@
+[[uniqueid]] eliminates both {\TeX} and HTML specials.
+Escaping the [[/]] in the character class in the regexp pattern works
+around a bug in many awks.
+Unpalatable, but what can one do?
+<<functions>>=
+function uniqueid(name, key) {
+ if (uidtable[name] == "") {
+ key = make_key(name)
+ # gsub(/[\]\[ \\{}`#%&~_^<>"-]/, "*", key) # old
+ gsub(/[^a-zA-Z0-9!$()*+,.\/:;=?@|]/, "*", key)
+ keycounts[key] = keycounts[key] + 1
+ uidtable[name] = key
+ if (keycounts[key] > 1)
+ uidtable[name] = uidtable[name] "." alphacode(keycounts[key])
+ }
+ return uidtable[name]
+}
+@ %def uniqueid
+<<functions>>=
+function old_make_key(name, key, l) {
+ l = length(name)
+ sub(/^.*\//, "", name)
+ key = substr(name, 1, 3)
+ if (l >= 3) key = key alphacode(l)
+ return key
+}
+<<functions>>=
+function make_key(name) {
+ return alphacode(crc(name))
+}
+<<initialization>>=
+uidtable[0] = 0
+keycounts[0] = 0 ;
+<<write trailers>>=
+{ print "@nl"
+ print "@nl"
+ lognowebchunks()
+ lognowebindex()
+}
+@
+Now, a special hack, so we can write this stuff in the right place on pass 2.
+<<functions>>=
+function lognowebchunks(l, j, n, x) {
+ if (loggednowebchunks > 0) return
+ loggednowebchunks = 1
+ delete allchunks[0]
+ n = alphasort(allchunks)
+ print "@xref beginchunks"
+ for (j = 0; j < n; j++) {
+ name = sorted[j]; delete sorted[j]
+ printf "@xref chunkbegin %s %s\n",
+ (anchorlabel[name] != "" ? anchorlabel[name] : "nw@notdef"), name
+ m = split(chunkud[name], a)
+ for (k = 1; k <= m; k++)
+ if (a[k] ~ /^use/)
+ printf "@xref chunkuse %s\n", substr(a[k], 5, length(a[k])-5)
+ else if (a[k] ~ /^defn/)
+ printf "@xref chunkdefn %s\n", substr(a[k], 6, length(a[k])-6)
+ print "@xref chunkend"
+ }
+ print "@xref endchunks"
+}
+@ %def lognowebchunks
+<<functions>>=
+function lognowebindex(l, j, n, x) {
+ if (loggednowebindex > 0) return
+ loggednowebindex = 1
+ delete allidents[0]
+ n = alphasort(allidents)
+ print "@index beginindex"
+ for (j = 0; j < n; j++) {
+ name = sorted[j]; delete sorted[j]
+ printf "@index entrybegin %s %s\n",
+ (indexanchorlabel[name] != "" ? indexanchorlabel[name] : "nw@notdef"), name
+ m = split(indexud[name], a)
+ for (k = 1; k <= m; k++)
+ if (a[k] ~ /^use/)
+ printf "@index entryuse %s\n", substr(a[k], 5, length(a[k])-5)
+ else if (a[k] ~ /^defn/)
+ printf "@index entrydefn %s\n", substr(a[k], 6, length(a[k])-6)
+ print "@index entryend"
+ }
+ print "@index endindex"
+}
+@ %def lognowebindex
+<<functions>>=
+function alphasort(a, x, n) {
+ n = 0
+ for (x in a)
+ n = insertitem(x, n)
+ return n
+}
+function insertitem(x, n, i, tmp) {
+ sorted[n] = x
+ sortkeys[n] = sortkey(x)
+ i = n
+ while (i > 0 && (sortkeys[i] < sortkeys[i-1] ||
+ sortkeys[i] == sortkeys[i-1] && sorted[i] < sorted[i-1])) {
+ tmp = sortkeys [i]; sortkeys [i] = sortkeys [i-1]; sortkeys [i-1] = tmp
+ tmp = sorted[i]; sorted[i] = sorted[i-1]; sorted[i-1] = tmp
+ i = i - 1
+ }
+ return n + 1
+}
+@ %def alphasort insertitem
+<<initialization>>=
+sorted[0] = 0; sortkeys[0] = 0;
+<<old, evil code>>=
+function sortkey(name, s) {
+ s = name
+ gsub(/[^a-zA-Z ]/, "", s)
+ return s "\n" name # relies on \n sorting lower than other characters
+}
+<<functions>>=
+function sortkey(s) {
+ return tolower(s) "\n" s # relies on \n sorting lower than other characters
+}
+@ %def sortkey
+<<functions>>=
+function alphacode(n) {
+ if (n < 0)
+ return "-" alphacode(-n)
+ else if (n >= alphacodelen)
+ return alphacode(n / alphacodelen) alphacode(n % alphacodelen)
+ else
+ return substr(alphacodes, n+1, 1)
+}
+@ %def alphacode
+<<initialization>>=
+alphacodes = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+alphacodelen = length(alphacodes) ;
+@
+\section{List of chunks}
+\nowebchunks
+
+\twocolumn
+\section{Index}
+\nowebindex
+@
+\end{document}
diff --git a/web/noweb/src/awk/noindex b/web/noweb/src/awk/noindex
new file mode 100755
index 0000000000..ba530f5c5c
--- /dev/null
+++ b/web/noweb/src/awk/noindex
@@ -0,0 +1,155 @@
+#!/bin/sh
+
+if [ $# -ne 1 ]; then
+ echo "Usage: `basename $0` file[.tex]" 1>&2
+ exit 1
+fi
+
+nawk 'BEGIN { infile="'"$1"'"
+ if (infile ~ /\.tex$/) {
+ infile = substr(infile, 1, length(infile)-4) ".aux"
+ } else if (infile !~ /\.aux$/) {
+ infile = infile ".aux"
+ }
+ idx[0] = ""
+ delete idx[0]
+ gobble(infile)
+ alphasort(idx)
+ outname = substr(infile, 1, length(infile)-4) ".nwi"
+ last = ""
+ for (i = 0; i < count; i++) {
+ out = stripcount(sorted[i])
+ if (last != out) {
+ print out > outname
+ last = out
+ # <show sort key [[i]]>
+ }
+ }
+ exit
+ }
+function gobble(name, infile, rc, tag) {
+ for (rc = (getline line < name); rc > 0; rc = (getline line < name)) {
+ if (line ~ /^\\@input{[^}]*}$/)
+ gobble(substr(line, 9, length(line)-9))
+ else if (line ~ /^\\nwixadds{/) {
+ count++
+ tag = "000000" count
+ tag = substr(tag, length(tag)-6+1)
+ idx[count] = tag " " substr(line, 11)
+ }
+ }
+ if (rc < 0) print "No file " name "."
+ else close(name)
+ return
+}
+function stripcount(s) {
+ sub(/^[0-9]+/, "", s)
+ sub(/ +/, "", s)
+ return "\\nwixaddsx{" s
+}
+function alphasort(a, x, n) {
+ n = 0
+ for (x in a)
+ n = insertitem(a[x], n)
+ finish_sorting(n)
+ return n
+}
+function insertitem(x, n, i, tmp) {
+ sorted[n] = x
+ sortkeys[n] = sortkey(x)
+ return n+1
+}
+function finish_sorting(n) {
+ firstwork = nextwork = 0
+ addquick(0, n)
+ while(nextwork > firstwork)
+ qsort()
+}
+function addquick(l, r) {
+ workq[nextwork++] = l
+ workq[nextwork++] = r
+}
+function qsort(l, r, mid, i, last) {
+ l = workq[firstwork]
+ delete workq[firstwork]
+ firstwork++
+ r = workq[firstwork]
+ delete workq[firstwork]
+ firstwork++
+ if (r - l < 10)
+ isort(l, r)
+ else {
+ mid = l + int((r - l) * rand())
+ swap(l, mid)
+ last = l
+ for (i = l+1; i < r; i++)
+ if (sortkeys[i] < sortkeys[l] ||
+ sortkeys[i] == sortkeys[l] && sorted[i] < sorted[l])
+ swap(++last, i)
+ swap(l, last)
+ addquick(l, last)
+ addquick(last+1, r)
+ }
+}
+function isort(l, r, n) {
+ for (n = l + 1; n < r; n++)
+ for (i = n; i > l && (sortkeys[i] < sortkeys[i-1] ||
+ sortkeys[i] == sortkeys[i-1] && sorted[i] < sorted[i-1]); i--)
+ swap(i, i-1)
+}
+function swap(i, j, tmp) {
+ tmp = sortkeys [i]; sortkeys [i] = sortkeys [j]; sortkeys [j] = tmp
+ tmp = sorted[i]; sorted[i] = sorted[j]; sorted[j] = tmp
+}
+function sortkey(s, count) {
+ match(s, /^[0-9]+/)
+ count = substr(s, RSTART, RLENGTH)
+ sub(/^[0-9]+ */, "", s)
+ if (s ~ /c}/) {
+ return firstkey(substr(s, 3)) "\n" count
+ } else if (s ~ /i}/) {
+ return firstkey(substr(s, 3)) "\n" count
+ } else {
+ print "sortkey handed non-chunk and non-index: " s
+ exit 1
+ }
+}
+function firstkey(s, r, openbrace) {
+ if (s !~ /^{{/) {
+ print "key \"" substr(s, 1, 6) "...\" is ill-formatted"
+ exit 1
+ }
+ sub (/^{{/, "", s)
+ gsub(/\\([a-zA-Z]+|.) */, "", s) # kill control sequences
+ openbrace = 1
+ r = ""
+ while (openbrace > 0)
+ if (match(s, /^[^{}]*/) <= 0)
+ openbrace--
+ else {
+ r = r substr(s, RSTART, RLENGTH)
+ c = substr(s, RSTART+RLENGTH, 1)
+ s = substr(s, RSTART+RLENGTH+1)
+ if (c == "}") openbrace--
+ else openbrace++
+ if (openbrace > 0) r = r c
+ }
+ return alphabet(r) "\n" r
+}
+function alphabet(s, r) {
+ r = ""
+ while (match(s, /[a-zA-Z \t]/) > 0) {
+ s = substr(s, RSTART)
+ c = substr(s, 1, 1)
+ if (c == " " || c == "\t") {
+ r = r " "
+ sub(/^[ \t]+/, "", s)
+ } else {
+ match(s, /^[a-zA-Z]+/)
+ r = r substr(s, RSTART, RLENGTH)
+ s = substr(s, RSTART+RLENGTH)
+ }
+ }
+ sub(/^ +/, "", r)
+ return r
+}' 1>&2
diff --git a/web/noweb/src/awk/noindex.nw b/web/noweb/src/awk/noindex.nw
new file mode 100644
index 0000000000..ba57f6e234
--- /dev/null
+++ b/web/noweb/src/awk/noindex.nw
@@ -0,0 +1,187 @@
+This program is similar to [[makeindex]] in that it grovels through [[.aux]]
+files looking for index information, which it writes to a [[.nwi]] file.
+It's used when [[noweave -indexfrom]] is used on many files separately;
+it combines the separate indices into a single, correctly sorted index.
+That index file is read by [[\nowebindex*]].
+<<noindex>>=
+#!/bin/sh
+
+if [ $# -ne 1 ]; then
+ echo "Usage: `basename $0` file[.tex]" 1>&2
+ exit 1
+fi
+
+nawk 'BEGIN { infile="'"$1"'"
+ <<main code>>
+ exit
+ }
+<<functions>>' 1>&2
+<<main code>>=
+if (infile ~ /\.tex$/) {
+ infile = substr(infile, 1, length(infile)-4) ".aux"
+} else if (infile !~ /\.aux$/) {
+ infile = infile ".aux"
+}
+idx[0] = ""
+delete idx[0]
+gobble(infile)
+alphasort(idx)
+outname = substr(infile, 1, length(infile)-4) ".nwi"
+last = ""
+for (i = 0; i < count; i++) {
+ out = stripcount(sorted[i])
+ if (last != out) {
+ print out > outname
+ last = out
+# <show sort key [[i]]>
+ }
+}
+<<show sort key [[i]]>>=
+key = sortkeys[i]
+sub(/^\n+/, "", key)
+sub(/\n.*$/, "", key)
+print "% " key > outname
+<<functions>>=
+function gobble(name, infile, rc, tag) {
+ for (rc = (getline line < name); rc > 0; rc = (getline line < name)) {
+ if (line ~ /^\\@input{[^}]*}$/)
+ gobble(substr(line, 9, length(line)-9))
+ else if (line ~ /^\\nwixadds{/) {
+ count++
+ tag = "000000" count
+ tag = substr(tag, length(tag)-6+1)
+ idx[count] = tag " " substr(line, 11)
+ }
+ }
+ if (rc < 0) print "No file " name "."
+ else close(name)
+ return
+}
+<<functions>>=
+function stripcount(s) {
+ sub(/^[0-9]+/, "", s)
+ sub(/ +/, "", s)
+ return "\\nwixaddsx{" s
+}
+<<functions>>=
+function alphasort(a, x, n) {
+ n = 0
+ for (x in a)
+ n = insertitem(a[x], n)
+ finish_sorting(n)
+ return n
+}
+function insertitem(x, n, i, tmp) {
+ sorted[n] = x
+ sortkeys[n] = sortkey(x)
+ return n+1
+}
+<<functions>>=
+function finish_sorting(n) {
+ firstwork = nextwork = 0
+ addquick(0, n)
+ while(nextwork > firstwork)
+ qsort()
+}
+<<functions>>=
+function addquick(l, r) {
+ workq[nextwork++] = l
+ workq[nextwork++] = r
+}
+<<get [[l]] and [[r]] out of work queue>>=
+l = workq[firstwork]
+delete workq[firstwork]
+firstwork++
+r = workq[firstwork]
+delete workq[firstwork]
+firstwork++
+<<functions>>=
+function qsort(l, r, mid, i, last) {
+ <<get [[l]] and [[r]] out of work queue>>
+ if (r - l < 10)
+ isort(l, r)
+ else {
+ mid = l + int((r - l) * rand())
+ swap(l, mid)
+ last = l
+ for (i = l+1; i < r; i++)
+ if (sortkeys[i] < sortkeys[l] ||
+ sortkeys[i] == sortkeys[l] && sorted[i] < sorted[l])
+ swap(++last, i)
+ swap(l, last)
+ addquick(l, last)
+ addquick(last+1, r)
+ }
+}
+<<functions>>=
+function isort(l, r, n) {
+ for (n = l + 1; n < r; n++)
+ for (i = n; i > l && (sortkeys[i] < sortkeys[i-1] ||
+ sortkeys[i] == sortkeys[i-1] && sorted[i] < sorted[i-1]); i--)
+ swap(i, i-1)
+}
+<<functions>>=
+function swap(i, j, tmp) {
+ tmp = sortkeys [i]; sortkeys [i] = sortkeys [j]; sortkeys [j] = tmp
+ tmp = sorted[i]; sorted[i] = sorted[j]; sorted[j] = tmp
+}
+<<functions>>=
+function sortkey(s, count) {
+ match(s, /^[0-9]+/)
+ count = substr(s, RSTART, RLENGTH)
+ sub(/^[0-9]+ */, "", s)
+ if (s ~ /c}/) {
+ return firstkey(substr(s, 3)) "\n" count
+ } else if (s ~ /i}/) {
+ return firstkey(substr(s, 3)) "\n" count
+ } else {
+ print "sortkey handed non-chunk and non-index: " s
+ exit 1
+ }
+}
+<<functions>>=
+function firstkey(s, r, openbrace) {
+ if (s !~ /^{{/) {
+ <<complain about format and exit>>
+ }
+ sub (/^{{/, "", s)
+ gsub(/\\([a-zA-Z]+|.) */, "", s) # kill control sequences
+ openbrace = 1
+ r = ""
+ while (openbrace > 0)
+ if (match(s, /^[^{}]*/) <= 0)
+ openbrace--
+ else {
+ r = r substr(s, RSTART, RLENGTH)
+ c = substr(s, RSTART+RLENGTH, 1)
+ s = substr(s, RSTART+RLENGTH+1)
+ if (c == "}") openbrace--
+ else openbrace++
+ if (openbrace > 0) r = r c
+ }
+ return alphabet(r) "\n" r
+}
+<<complain about format and exit>>=
+print "key \"" substr(s, 1, 6) "...\" is ill-formatted"
+exit 1
+<<functions>>=
+function alphabet(s, r) {
+ r = ""
+ while (match(s, /[a-zA-Z \t]/) > 0) {
+ s = substr(s, RSTART)
+ c = substr(s, 1, 1)
+ if (c == " " || c == "\t") {
+ r = r " "
+ sub(/^[ \t]+/, "", s)
+ } else {
+ match(s, /^[a-zA-Z]+/)
+ r = r substr(s, RSTART, RLENGTH)
+ s = substr(s, RSTART+RLENGTH)
+ }
+ }
+ sub(/^ +/, "", r)
+ return r
+}
+@
+\section{Index}
+\nowebindex
diff --git a/web/noweb/src/awk/tohtml b/web/noweb/src/awk/tohtml
new file mode 100755
index 0000000000..f4a0439c41
--- /dev/null
+++ b/web/noweb/src/awk/tohtml
@@ -0,0 +1,237 @@
+#!/bin/sh
+# Copyright 1994-2018 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+# Do not try to understand this file! Look at lib/tohtml.nw in the noweb source!
+
+delay=0 raw=0 localindex=0 noindex=0 nocomment=0
+for i do
+ case $i in
+ -delay) delay=1 ;;
+ -raw) raw=1 ;;
+ -localindex) if [ $noindex -eq 0 ]; then localindex=1; fi;;
+ -noindex) localindex=0; noindex=1 ;;
+ -no-gen-comment) nocomment=1 ;;
+ esac
+done
+nawk 'function writechunk(label, ref, tag, name, suffix) {
+ printf "%s",
+ linklabelto(label, ref, sgmlwrap(tag, "&lt;" convquotes(name) "&gt;" suffix))
+ }
+ function linklabelto(label, ref, contents, s) {
+ s = label != "" || ref != "" ? "<a" : ""
+ if (label != "") s = s " name=" image(label)
+ if (ref != "") s = s " href=" image("#" ref)
+ s = s (label != "" || ref != "" ? ">" : "")
+ s = s contents
+ s = s (label != "" || ref != "" ? "</a>" : "")
+ return s
+ }
+
+ function linkto(ref, contents) {
+ return linklabelto("", ref, contents)
+ }
+
+ function linklabel(label, contents) {
+ return linklabelto(label, "", contents)
+ }
+ function sgmlwrap(tag, s) {
+ return "<" tag ">" s "</" tag ">"
+ }
+ function image(s) {
+ gsub(/"/, "\\\"", s)
+ return "\"" s "\""
+ }
+ function escapeSpecials (l) {
+ gsub(/&/, "\\&amp;", l)
+ gsub(/</, "\\&lt;", l)
+ gsub(/>/, "\\&gt;", l)
+ gsub(/"/, "\\&quot;", l)
+ return l
+ }
+ function convquotes(s, r, i, line) {
+ r = ""
+ while (i = index(s, "[[")) {
+ r = r substr(s, 1, i-1) "<code>"
+ s = substr(s, i+2)
+ if (i = match(s, "\\]\\]+")) {
+ line = substr(s, 1, i-1+RLENGTH-2)
+ # line = escapeSpecials(line) # destroys internal markup --- do not call
+ r = r line "</code>"
+ s = substr(s, i+RLENGTH)
+ } else {
+ r = r s "</code>"
+ s = ""
+ }
+ }
+ return r s
+ }
+ BEGIN {
+ defns[0] = 0
+ defns_above[0] = 0
+ useitemstab[0] = 0
+ }
+ !doneraw { # do not do in BEGIN because not all awks assign variables yet
+ if (raw) { braw = "\\begin{rawhtml}"; eraw = "\\end{rawhtml}" }
+ else braw = eraw = ""
+ doneraw = 1
+ if (!nocomment) {
+ print braw "<!-- this file was generated automatically by noweave;" " better not edit it-->" eraw
+ }
+ }
+ /^@begin code / { code = 1; printf "%s<pre>", braw; ecode = "</pre>" }
+ /^@end code / { code = 0; previscode = 1; useitemscount = split(useitemstab[thischunk], a)
+ if (pendingprev != "" || pendingnext != "" || useitemscount > 0) {
+ if (ecode == "</pre>") {
+ printf "</pre><blockquote>"
+ ecode = "</blockquote>"
+ }
+ useprefix = "Used "
+ for (j = 1; j <= useitemscount; j++) {
+ if (defns_above[a[j]] > 0)
+ usedir = "above"
+ else
+ usedir = "below"
+ printf "%s%s", useprefix, linkto(a[j], usedir (useitemscount > 1 ? " (" j ")" : ""))
+ useprefix = ", "
+ }
+ if (useitemscount > 0 && (pendingprev != "" || pendingnext != ""))
+ printf "; "
+ p = useitemscount > 0 ? "previous" : "Previous"
+ n = useitemscount > 0 ? "next" : "Next"
+ if (pendingprev != "")
+ if (pendingnext != "")
+ printf "%s and %s definitions", linkto(pendingprev, p), linkto(pendingnext, "next")
+ else
+ printf "%s definition", linkto(pendingprev, p)
+ else
+ if (pendingnext != "")
+ printf "%s definition", linkto(pendingnext, n)
+ pendingprev = pendingnext = ""
+ useitems = ""
+ print ".<p>"
+ }
+ printf "%s%s", ecode, eraw
+ }
+ /^@begin docs / { if (previscode) printf "%s", (raw ? "\\par" : "<p>")
+ previscode = text = 0
+ }
+ /^@end docs / { if (lastxreflabel != "")
+ printf "%s%s%s\n", braw, linklabel(lastxreflabel, "*"), eraw
+ lastxreflabel = ""
+ }
+ /^@text / { line = substr($0, 7); text += length(line)
+ if (code) {
+ if (lastindexref != "" && line ~ /[^ \t]/) {
+ printf "%s", linkto(lastindexref, line)
+ lastindexref = ""
+ } else {
+ printf "%s", escapeSpecials(line)
+ }
+ } else if (quoting) {
+ if (line ~ /[^ \t]/) {
+ printf "%s", linklabelto(lastxreflabel, lastindexref,
+ escapeSpecials(line))
+ lastindexref = lastxreflabel = ""
+ } else {
+ printf "%s", escapeSpecials(line)
+ }
+ } else {
+ if (lastxreflabel != "" && line ~ /[^ \t]/) {
+ match(line, /^[ \t]*/)
+ blanks = substr(line, RSTART, RLENGTH)
+ line = substr(line, RSTART+RLENGTH)
+ if (line ~ /^[{}\\<&]/) {
+ char = "*"
+ } else {
+ char = substr(line, 1, 1)
+ line = substr(line, 2)
+ }
+ printf "%s%s%s%s%s", braw, blanks, linklabel(lastxreflabel, char), eraw, line
+ if (lastxreflabel != "") defns_above[lastxreflabel] = 1
+ lastxreflabel = ""
+ } else {
+ printf "%s", line
+ }
+ }
+ }
+ /^@nl$/ { print "" }
+ /^@defn / { thischunk = name = substr($0, 7)
+ if (lastxreflabel != "") defns_above[lastxreflabel] = 1
+ writechunk(lastxreflabel, lastxrefref, "dfn", name, defns[name] "=")
+ lastxreflabel = lastxrefref = ""
+ defns[name] = "+"
+ }
+ /^@use / { writechunk(lastxreflabel, lastxrefref, "i", substr($0, 6), "") }
+ /^@quote$/ { quoting = 1 ; printf "%s<code>", braw }
+ /^@endquote$/ { quoting = 0 ; printf "</code>%s", eraw }
+ /^@file / { filename = substr($0, 7); lastxreflabel = lastxrefref = "" }
+ /^@literal / { printf "%s", substr($0, 10) }
+ /^@header html / { printf "<html><head><title>%s</title></head><body>", substr($0, 14)
+ }
+ /^@trailer html$/ { print "</body></html>" }
+ /^@xref label / { lastxreflabel = substr($0, 13) }
+ /^@xref ref / { lastxrefref = substr($0, 11) }
+ /^@xref prevdef/ { pendingprev = substr($0, 15) }
+ /^@xref nextdef/ { pendingnext = substr($0, 15) }
+ /^@xref beginuses/ { useitems = "" }
+ /^@xref useitem / { useitems = useitems " " substr($0, 15) }
+ /^@xref enduses/ { useitemstab[thischunk] = useitems }
+ /^@xref notused / { if (ecode == "</pre>") {
+ printf "</pre><blockquote>"
+ ecode = "</blockquote>"
+ }
+ printf "This code is written to a file (or else not used).<p>"
+ }
+ /^@xref (begindefs|defitem|enddefs)/ { }
+ /^@xref beginchunks$/ { printf "%s<ul>\n", braw }
+ /^@xref chunkbegin / { label = $3; name = substr($0, 19 + length(label))
+ printf "<li>"; comma = ": "; count = 0
+ writechunk("", label, "i", name, "")
+ }
+ /^@xref chunkuse / { printf "%s%s", comma, linkto(substr($0, 16), "U" ++count)
+ comma = ", "
+ }
+ /^@xref chunkdefn / { printf "%s%s", comma, linkto(substr($0, 17), "D" ++count)
+ comma = ", "
+ }
+ /^@xref chunkend$/ { print "" }
+ /^@xref endchunks$/ { printf "</ul>%s\n", eraw }
+ /^@index beginindex$/ { if (!noindex) { printf "%s<ul>\n", braw } }
+ /^@index entrybegin / { if (!noindex) {
+ label = $3; name = substr($0, 20 + length(label))
+ printf "<li>"; comma = ": "; count = 0
+ printf "%s",
+ linklabelto("NWI-" escapeSpecials(name), label, name)
+
+ } }
+ /^@index entryuse / { if (!noindex) {
+ printf "%s%s", comma, linkto(substr($0, 17), "U" ++count)
+ comma = ", "
+ } }
+ /^@index entrydefn / { if (!noindex) {
+ printf "%s%s", comma, linkto(substr($0, 18), "D" ++count)
+ comma = ", "
+ } }
+ /^@index entryend$/ { if (!noindex) { print "" } }
+ /^@index endindex$/ { if (!noindex) { printf "</ul>%s\n", eraw } }
+ /^@index use/ { lastindexref = lastxrefref; lastxrefref = "" }
+ /^@index defn/ { lastxreflabel = lastxrefref = "" }
+ /^@index localdefn/ { lastxreflabel = lastxrefref = "" }
+ /^@index nl/ { } # do nothing -- destroys line numbering
+ /^@index begindefs/ { if (localindex) {
+ if (ecode == "</pre>") {
+ printf "</pre><blockquote>"
+ ecode = "</blockquote>"
+ }; printf "Defines"; comma = " "
+ } }
+ /^@index isused / { }
+ /^@index defitem / { if (localindex) {
+ arg = substr($0, 16)
+ printf "%s%s", comma,
+ linkto("NWI-" escapeSpecials(arg), sgmlwrap("code", escapeSpecials(arg)))
+ comma = ", "
+ } }
+ /^@index enddefs/ { if (localindex) { printf " (links are to index).<p>\n" } }
+ /^@index (beginuses|isdefined|useitem|enduses)/ { } # use local links
+ END { print "" }' \
+ delay=$delay raw=$raw localindex=$localindex noindex=$noindex nocomment=$nocomment
diff --git a/web/noweb/src/awk/tohtml.nw b/web/noweb/src/awk/tohtml.nw
new file mode 100644
index 0000000000..807c59cf30
--- /dev/null
+++ b/web/noweb/src/awk/tohtml.nw
@@ -0,0 +1,331 @@
+\documentstyle[noweb]{article}
+\pagestyle{noweb}
+\begin{document}
+\section{Converting {\tt noweb} markup to {\tt HTML}}
+This copyright applies both to the {\tt noweb} source and to the
+generated shell script.
+Thanks to Bill Trost for getting me started with an early version.
+<<copyright notice>>=
+# Copyright 1994-2018 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+<<*>>=
+#!/bin/sh
+<<copyright notice>>
+# Do not try to understand this file! Look at lib/tohtml.nw in the noweb source!
+
+delay=0 raw=0 localindex=0 noindex=0 nocomment=0
+for i do
+ case $i in
+ -delay) delay=1 ;;
+ -raw) raw=1 ;;
+ -localindex) if [ $noindex -eq 0 ]; then localindex=1; fi;;
+ -noindex) localindex=0; noindex=1 ;;
+ -no-gen-comment) nocomment=1 ;;
+ esac
+done
+nawk '<<awk program for conversion to {\tt HTML}>>' \
+ delay=$delay raw=$raw localindex=$localindex noindex=$noindex nocomment=$nocomment
+@
+The [[-raw]] option brackets HTML with [[\begin{rawhtml}]] and
+[[\end{rawhtml}]]; the purpose is to embed HTML in a {\LaTeX}
+document before converting the document with {\tt latex2html}.
+[[braw]] and [[eraw]] hold those delimiters (or else empty strings).
+<<awk program for conversion to {\tt HTML}>>=
+<<functions>>
+BEGIN {
+ <<initialization>>
+}
+!doneraw { # do not do in BEGIN because not all awks assign variables yet
+ if (raw) { braw = "\\begin{rawhtml}"; eraw = "\\end{rawhtml}" }
+ else braw = eraw = ""
+ doneraw = 1
+ if (!nocomment) {
+ print braw "<!-- this file was generated automatically by noweave;" " better not edit it-->" eraw
+ }
+}
+<<patterns>>
+END { print "" }
+@
+[[ecode]] is the marker used at the end of the current code chunk.
+If there is no cross-reference stuff at the end, we just use [[</pre>]];
+otherwise we terminate whatever environment is used for the cross-reference stuff.
+<<patterns>>=
+/^@begin code / { code = 1; printf "%s<pre>", braw; ecode = "</pre>" }
+/^@end code / { code = 0; previscode = 1; <<dump pending cross-reference info>>
+ printf "%s%s", ecode, eraw
+ }
+@
+We want to try to avoid emitting paragraph elements when the
+preceding chunk is a code chunk, as tracked by [[previscode]].
+Also, if we do slip in a paragraph, we may use the {\LaTeX} style.
+<<patterns>>=
+/^@begin docs / { if (previscode) printf "%s", (raw ? "\\par" : "<p>")
+ previscode = text = 0
+ }
+@
+Sometimes it happens that a document-chunk anchor is put in a document chunk that
+contains no text. In that case, we put in a phony anchor at the end of the chunk so
+we won't lose the cross-reference.
+<<patterns>>=
+/^@end docs / { if (lastxreflabel != "")
+ printf "%s%s%s\n", braw, linklabel(lastxreflabel, "*"), eraw
+ lastxreflabel = ""
+ }
+@
+Normally, if there's a pending anchor, we put it on the first available text line.
+<<patterns>>=
+/^@text / { line = substr($0, 7); text += length(line)
+ if (code) {
+ if (lastindexref != "" && line ~ /[^ \t]/) {
+ printf "%s", linkto(lastindexref, line)
+ lastindexref = ""
+ } else {
+ printf "%s", escapeSpecials(line)
+ }
+ } else if (quoting) {
+ if (line ~ /[^ \t]/) {
+ printf "%s", linklabelto(lastxreflabel, lastindexref,
+ escapeSpecials(line))
+ lastindexref = lastxreflabel = ""
+ } else {
+ printf "%s", escapeSpecials(line)
+ }
+ } else {
+ if (lastxreflabel != "" && line ~ /[^ \t]/) {
+ <<print docs anchor>>
+ lastxreflabel = ""
+ } else {
+ printf "%s", line
+ }
+ }
+ }
+@
+We anchor on the first nonblank character of the line, unless that's
+a \TeX\ control sequence or an SGML tag.
+In that case we insert a {\tt*} to anchor to.
+None of this crap would be necessary if HTML could anchor to empty text.
+<<print docs anchor>>=
+match(line, /^[ \t]*/)
+blanks = substr(line, RSTART, RLENGTH)
+line = substr(line, RSTART+RLENGTH)
+if (line ~ /^[{}\\<&]/) {
+ char = "*"
+} else {
+ char = substr(line, 1, 1)
+ line = substr(line, 2)
+}
+printf "%s%s%s%s%s", braw, blanks, linklabel(lastxreflabel, char), eraw, line
+if (lastxreflabel != "") defns_above[lastxreflabel] = 1
+<<patterns>>=
+/^@nl$/ { print "" }
+/^@defn / { thischunk = name = substr($0, 7)
+ if (lastxreflabel != "") defns_above[lastxreflabel] = 1
+ writechunk(lastxreflabel, lastxrefref, "dfn", name, defns[name] "=")
+ <<clear [[lastxref*]]>>
+ defns[name] = "+"
+ }
+<<initialization>>=
+defns[0] = 0
+defns_above[0] = 0
+<<patterns>>=
+/^@use / { writechunk(lastxreflabel, lastxrefref, "i", substr($0, 6), "") }
+@
+Writing a chunk involves creating an anchor for it.
+<<functions>>=
+function writechunk(label, ref, tag, name, suffix) {
+ printf "%s",
+ linklabelto(label, ref, sgmlwrap(tag, "&lt;" convquotes(name) "&gt;" suffix))
+}
+@
+<<patterns>>=
+/^@quote$/ { quoting = 1 ; printf "%s<code>", braw }
+/^@endquote$/ { quoting = 0 ; printf "</code>%s", eraw }
+/^@file / { filename = substr($0, 7); <<clear [[lastxref*]]>> }
+/^@literal / { printf "%s", substr($0, 10) }
+/^@header html / { <<write HTML header>> }
+/^@trailer html$/ { <<write HTML trailer>> }
+@
+<<write HTML header>>=
+printf "<html><head><title>%s</title></head><body>", substr($0, 14)
+
+<<write HTML trailer>>=
+print "</body></html>"
+@
+<<patterns>>=
+/^@xref label / { lastxreflabel = substr($0, 13) }
+/^@xref ref / { lastxrefref = substr($0, 11) }
+/^@xref prevdef/ { pendingprev = substr($0, 15) }
+/^@xref nextdef/ { pendingnext = substr($0, 15) }
+/^@xref beginuses/ { useitems = "" }
+/^@xref useitem / { useitems = useitems " " substr($0, 15) }
+/^@xref enduses/ { useitemstab[thischunk] = useitems }
+/^@xref notused / { <<code-to-blockquote>>
+ printf "This code is written to a file (or else not used).<p>"
+ }
+<<initialization>>=
+useitemstab[0] = 0
+<<clear [[lastxref*]]>>=
+lastxreflabel = lastxrefref = ""
+<<dump pending cross-reference info>>=
+useitemscount = split(useitemstab[thischunk], a)
+if (pendingprev != "" || pendingnext != "" || useitemscount > 0) {
+ <<code-to-blockquote>>
+ <<write out uses with links>>
+ if (useitemscount > 0 && (pendingprev != "" || pendingnext != ""))
+ printf "; "
+ p = useitemscount > 0 ? "previous" : "Previous"
+ n = useitemscount > 0 ? "next" : "Next"
+ if (pendingprev != "")
+ if (pendingnext != "")
+ printf "%s and %s definitions", linkto(pendingprev, p), linkto(pendingnext, "next")
+ else
+ printf "%s definition", linkto(pendingprev, p)
+ else
+ if (pendingnext != "")
+ printf "%s definition", linkto(pendingnext, n)
+ pendingprev = pendingnext = ""
+ useitems = ""
+ print ".<p>"
+}
+<<write out uses with links>>=
+useprefix = "Used "
+for (j = 1; j <= useitemscount; j++) {
+ if (defns_above[a[j]] > 0)
+ usedir = "above"
+ else
+ usedir = "below"
+ printf "%s%s", useprefix, linkto(a[j], usedir (useitemscount > 1 ? " (" j ")" : ""))
+ useprefix = ", "
+}
+@
+The hack here is to put the supplementary information in a blockquote area
+after the code.
+<<code-to-blockquote>>=
+if (ecode == "</pre>") {
+ printf "</pre><blockquote>"
+ ecode = "</blockquote>"
+}
+@
+The HTML back end ignores [[@xref begindefs]], [[@xref defitem]], and
+[[@xref enddefs]]; it uses the [[nextdef]] and [[prevdef]] links instead.
+<<patterns>>=
+/^@xref (begindefs|defitem|enddefs)/ { }
+/^@xref beginchunks$/ { printf "%s<ul>\n", braw }
+/^@xref chunkbegin / { label = $3; name = substr($0, 19 + length(label))
+ printf "<li>"; comma = ": "; count = 0
+ writechunk("", label, "i", name, "")
+ }
+/^@xref chunkuse / { printf "%s%s", comma, linkto(substr($0, 16), "U" ++count)
+ comma = ", "
+ }
+/^@xref chunkdefn / { printf "%s%s", comma, linkto(substr($0, 17), "D" ++count)
+ comma = ", "
+ }
+/^@xref chunkend$/ { print "" }
+/^@xref endchunks$/ { printf "</ul>%s\n", eraw }
+<<patterns>>=
+/^@index beginindex$/ { if (!noindex) { printf "%s<ul>\n", braw } }
+/^@index entrybegin / { if (!noindex) {
+ label = $3; name = substr($0, 20 + length(label))
+ printf "<li>"; comma = ": "; count = 0
+ printf "%s",
+ linklabelto("NWI-" escapeSpecials(name), label, name)
+
+ } }
+/^@index entryuse / { if (!noindex) {
+ printf "%s%s", comma, linkto(substr($0, 17), "U" ++count)
+ comma = ", "
+ } }
+/^@index entrydefn / { if (!noindex) {
+ printf "%s%s", comma, linkto(substr($0, 18), "D" ++count)
+ comma = ", "
+ } }
+/^@index entryend$/ { if (!noindex) { print "" } }
+/^@index endindex$/ { if (!noindex) { printf "</ul>%s\n", eraw } }
+@
+The local identifier cross-reference doesn't show each use; it just shows
+the identifiers that are defined, with links to the full index.
+<<patterns>>=
+/^@index use/ { lastindexref = lastxrefref; lastxrefref = "" }
+/^@index defn/ { <<clear [[lastxref*]]>> }
+/^@index localdefn/ { <<clear [[lastxref*]]>> }
+/^@index nl/ { } # do nothing -- destroys line numbering
+/^@index begindefs/ { if (localindex) {
+ <<code-to-blockquote>>; printf "Defines"; comma = " "
+} }
+/^@index isused / { }
+/^@index defitem / { if (localindex) {
+ arg = substr($0, 16)
+ printf "%s%s", comma,
+ linkto("NWI-" escapeSpecials(arg), sgmlwrap("code", escapeSpecials(arg)))
+ comma = ", "
+} }
+/^@index enddefs/ { if (localindex) { printf " (links are to index).<p>\n" } }
+/^@index (beginuses|isdefined|useitem|enduses)/ { } # use local links
+@
+\subsection{Support functions}
+Here's all our anchor support goo.
+<<functions>>=
+function linklabelto(label, ref, contents, s) {
+ s = label != "" || ref != "" ? "<a" : ""
+ if (label != "") s = s " name=" image(label)
+ if (ref != "") s = s " href=" image("#" ref)
+ s = s (label != "" || ref != "" ? ">" : "")
+ s = s contents
+ s = s (label != "" || ref != "" ? "</a>" : "")
+ return s
+}
+
+function linkto(ref, contents) {
+ return linklabelto("", ref, contents)
+}
+
+function linklabel(label, contents) {
+ return linklabelto(label, "", contents)
+}
+@
+Another support function is used for wrapping tags around text:
+<<functions>>=
+function sgmlwrap(tag, s) {
+ return "<" tag ">" s "</" tag ">"
+}
+<<functions>>=
+function image(s) {
+ gsub(/"/, "\\\"", s)
+ return "\"" s "\""
+}
+@
+Lucky for us, {\tt HTML} has few special characters. Unlucky for us,
+we have to deal with each one seperately. Nothing much to whine
+about, really.
+<<functions>>=
+function escapeSpecials (l) {
+ gsub(/&/, "\\&amp;", l)
+ gsub(/</, "\\&lt;", l)
+ gsub(/>/, "\\&gt;", l)
+ gsub(/"/, "\\&quot;", l)
+ return l
+}
+@
+A special function is used to implement {\tt noweb}'s quoting
+convention within chunk names.
+<<functions>>=
+function convquotes(s, r, i, line) {
+ r = ""
+ while (i = index(s, "[[")) {
+ r = r substr(s, 1, i-1) "<code>"
+ s = substr(s, i+2)
+ if (i = match(s, "\\]\\]+")) {
+ line = substr(s, 1, i-1+RLENGTH-2)
+ # line = escapeSpecials(line) # destroys internal markup --- do not call
+ r = r line "</code>"
+ s = substr(s, i+RLENGTH)
+ } else {
+ r = r s "</code>"
+ s = ""
+ }
+ }
+ return r s
+}
+@
+\end{document}
diff --git a/web/noweb/src/awk/totex b/web/noweb/src/awk/totex
new file mode 100755
index 0000000000..ac74b82695
--- /dev/null
+++ b/web/noweb/src/awk/totex
@@ -0,0 +1,175 @@
+#!/bin/sh
+LIB=|LIBDIR|
+# Copyright 1991-2018 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+# Don't try to understand this file! Look at lib/totex.nw in the noweb source!
+delay=0 noindex=0
+for i do
+ case $i in
+ -delay) delay=1 ;;
+ -noindex) noindex=1 ;;
+ *) echo "This can't happen -- $i passed to totex" 1>&2 ; exit 1 ;;
+ esac
+done
+nawk 'BEGIN { code=0 ; quoting=0 ; text=1; defns[0] = 0
+ ulist[0] = 0 }
+ /^@begin code/ { code=1 ; printf "\\nwbegincode{%s}", substr($0, 13) }
+ /^@end code/ { code=0 ; printf "\\nwendcode{}"; lastdefnlabel = "" }
+ /^@begin docs 0$/ { if (delay) next }
+ /^@end docs 0$/ { if (delay) {
+ printf "\\nwfilename{%s}", filename; delay=0; next
+ } }
+ /^@begin docs/ { text=0 ; printf "\\nwbegindocs{%s}", substr($0, 13) }
+ /^@end docs/ { printf "\\nwenddocs{}" }
+ /^@text / { line = substr($0, 7) ; text += length - 6
+ if (code) printf "%s", escape_brace_bslash(line)
+ else if (quoting) printf "%s", TeXliteral(line)
+ else printf "%s", line
+ }
+ /^@nl$/ { if (!code) {if (text==0) printf "\\nwdocspar"
+ text=1}
+ if (quoting) printf "\\nwnewline"
+ printf "\n"
+ }
+ /^@defn / { name = substr($0, 7); if (lastxreflabel != "") {
+ printf "\\sublabel{%s}", lastxreflabel
+ printf "\\nwmargintag{%s}", label2tag(lastxreflabel)
+ }
+ printf "\\moddef{%s%s}\\%sendmoddef", convquotes(name), (lastxrefref != "" ? ("~" label2tag(lastxrefref)) : ""), defns[name]
+ lastdefnlabel = lastxreflabel
+ lastxreflabel = lastxrefref = ""
+ defns[name] = "plus" }
+ /^@use / { printf "\\LA{}%s%s\\RA{}",
+ convquotes(substr($0, 6)), (lastxrefref != "" ? ("~" label2tag(lastxrefref)) : "")
+ }
+ /^@quote$/ { quoting = 1 ; printf "{\\tt{}" }
+ /^@endquote$/ { quoting = 0 ; printf "}" }
+ /^@file / { filename = substr($0, 7); lastxreflabel = lastxrefref = ""
+ if (!delay) printf "\\nwfilename{%s}", filename
+ }
+ /^@literal / { printf "%s", substr($0, 10) }
+ /^@header latex / { printf "\\documentclass{article}\\usepackage{noweb}\\pagestyle{noweb}\\noweboptions{%s}%s",
+ substr($0, 15), "\\begin{document}" }
+ /^@header tex / { printf "\\input nwmac " }
+ /^@trailer latex$/ { print "\\end{document}" }
+ /^@trailer tex$/ { print "\\bye" }
+ /^@xref label / { lastxreflabel = substr($0, 13) }
+ /^@xref ref / { lastxrefref = substr($0, 11) }
+ /^@xref begindefs$/ { printf "\\nwalsodefined{" }
+ /^@xref defitem / { printf "\\\\{%s}", substr($0, 15) }
+ /^@xref enddefs$/ { printf "}" }
+ /^@xref beginuses$/ { printf "\\nwused{" }
+ /^@xref useitem / { printf "\\\\{%s}", substr($0, 15) }
+ /^@xref enduses$/ { printf "}" }
+ /^@xref notused / { printf "\\nwnotused{%s}", TeXliteral(substr($0, 15)) }
+ /^@xref nextdef / { }
+ /^@xref prevdef / { }
+ /^@xref beginchunks$/ { }
+ /^@xref chunkbegin / { label = $3; name = substr($0, 19 + length(label))
+ printf "\\nwixlogsorted{c}{{%s}{%s}{",
+ convquotes(name), label
+ }
+ /^@xref chunkuse / { printf "\\nwixu{%s}", substr($0, 16) }
+ /^@xref chunkdefn / { printf "\\nwixd{%s}", substr($0, 17) }
+ /^@xref chunkend$/ { print "}}%" }
+ /^@xref endchunks$/ { }
+ /^@index nl$/ { print (code ? "\\eatline" : "%") }
+ /^@index defn / {
+ if (!noindex) { arg = substr($0, 13); if (lastxreflabel != "") printf "\\nosublabel{%s}", lastxreflabel
+ if (lastxrefref != "")
+ printf "\\nwindexdefn{%s}{%s}{%s}", TeXliteral(arg), indexlabel(arg), lastxrefref
+ lastxreflabel = lastxrefref = "" } }
+ /^@index localdefn / {
+ if (!noindex) { arg = substr($0, 18); if (lastxreflabel != "") printf "\\nosublabel{%s}", lastxreflabel
+ if (lastxrefref != "")
+ printf "\\nwindexdefn{%s}{%s}{%s}", TeXliteral(arg), indexlabel(arg), lastxrefref
+ lastxreflabel = lastxrefref = "" } }
+ /^@index use / {
+ if (!noindex) { arg = substr($0, 12); if (!code) {
+ if (lastxreflabel != "") printf "\\protect\\nosublabel{%s}", lastxreflabel
+ if (lastxrefref != "")
+ printf "\\protect\\nwindexuse{%s}{%s}{%s}",
+ TeXliteral(arg), indexlabel(arg), lastxrefref
+ }
+ lastxreflabel = lastxrefref = "" } }
+ /^@index begindefs$/ { if (!noindex) { printf "\\nwidentdefs{" } }
+ /^@index isused / { if (!noindex) { } } # handled by latex
+ /^@index defitem / { if (!noindex) { i = substr($0,16); printf "\\\\{{%s}{%s}}", TeXliteral(i), indexlabel(i) } }
+ /^@index enddefs$/ { if (!noindex) { printf "}" } }
+ /^@index beginuses$/ { if (!noindex) { printf "\\nwidentuses{"; ucount = 0 } }
+ /^@index isdefined / { if (!noindex) { } } # latex finds the definitions
+ /^@index useitem / { if (!noindex) { i = substr($0, 16); printf "\\\\{{%s}{%s}}", TeXliteral(i), indexlabel(i)
+ ulist[ucount++] = i
+ } }
+ /^@index enduses$/ { if (!noindex) { printf "}"; if (lastdefnlabel != "") {
+ for (j = 0; j < ucount; j++)
+ printf "\\nwindexuse{%s}{%s}{%s}",
+ TeXliteral(ulist[j]), indexlabel(ulist[j]), lastdefnlabel
+ } } }
+ /^@index beginindex$/ { if (!noindex) { } }
+ /^@index entrybegin / { if (!noindex) { label = $3; name = substr($0, 20 + length(label))
+ printf "\\nwixlogsorted{i}{{%s}{%s}}%%\n",
+ TeXliteral(name), indexlabel(name)
+ } }
+ /^@index entryuse / { if (!noindex) { } } # handled by latex
+ /^@index entrydefn / { if (!noindex) { } } # handled by latex
+ /^@index entryend$/ { if (!noindex) { } }
+ /^@index endindex$/ { if (!noindex) { } }
+
+ END { printf "\n" }
+ function label2tag(label) {
+ return "{\\nwtagstyle{}\\subpageref{" label "}}"
+ }
+ function escape_brace_bslash(line) {
+ gsub(/[\\{}]/, "\n&", line)
+ gsub(/\n/, "\\", line)
+ return line
+ }
+ function convquotes(s, r, i) {
+ r = ""
+ while (i = index(s, "[[")) {
+ r = r substr(s, 1, i-1) "\\code{}"
+ s = substr(s, i+2)
+ if (i = match(s, "\\]\\]+")) {
+ r = r TeXliteral(substr(s, 1, i-1+RLENGTH-2)) "\\edoc{}"
+ s = substr(s, i+RLENGTH)
+ } else {
+ r = r s "\\edoc{}"
+ s = ""
+ }
+ }
+ return r s
+ }
+ function indexlabel(ident, l) {
+ l = ident
+ gsub(/:/, ":col", l) # must be first (colon)
+ gsub(/ /, ":sp", l) # space
+ gsub(/#/, ":has", l) # hash
+ gsub(/\$/, ":do", l) # dollar
+ gsub(/%/, ":pe", l) # percent
+ gsub(/&/, ":am", l) # ampersand
+ gsub(/,/, ":com", l) # commad
+ gsub(/\\/, ":bs", l) # backslash
+ gsub(/\^/, ":hat", l) # hat
+ gsub(/_/, ":un", l) # underscore
+ gsub(/{/, ":lb", l) # left brace
+ gsub(/}/, ":rb", l) # right brace
+ gsub(/~/, ":ti", l) # tilde
+ return l
+ }
+ function TeXliteral(arg) {
+ gsub(/\\/, "<\\char92>", arg)
+ gsub(/}/, "<\\char125}", arg)
+ gsub(/{/, "{\\char123}", arg)
+ gsub(/<\\char/, "{\\char", arg)
+ gsub(/{\\char92>/, "{\\char92}", arg)
+ gsub(/\$/, "{\\char36}", arg)
+ gsub(/&/, "{\\char38}", arg)
+ gsub(/#/, "{\\char35}", arg)
+ gsub(/\^/, "{\\char94}", arg)
+ gsub(/_/, "{\\char95}", arg)
+ gsub(/%/, "{\\char37}", arg)
+ gsub(/~/, "{\\char126}", arg)
+ gsub(/ /, "\\ ", arg)
+ return arg
+ }' delay=$delay noindex=$noindex
diff --git a/web/noweb/src/awk/totex.nw b/web/noweb/src/awk/totex.nw
new file mode 100644
index 0000000000..f0ccd3f23e
--- /dev/null
+++ b/web/noweb/src/awk/totex.nw
@@ -0,0 +1,287 @@
+\section{Converting {\tt noweb} markup to {\TeX} markup}
+The copyright applies both to the {\tt noweb} source and to the
+generated shell script.
+<<copyright notice>>=
+# Copyright 1991-2018 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+<<totex>>=
+#!/bin/sh
+LIB=|LIBDIR|
+<<copyright notice>>
+# Don't try to understand this file! Look at lib/totex.nw in the noweb source!
+delay=0 noindex=0
+for i do
+ case $i in
+ -delay) delay=1 ;;
+ -noindex) noindex=1 ;;
+ *) echo "This can't happen -- $i passed to totex" 1>&2 ; exit 1 ;;
+ esac
+done
+<<invoke awk program using parameter>>
+@
+On a forgiving system, we make the awk program an argument:
+<<invoke awk program using parameter>>=
+nawk '<<awk program for conversion to {\TeX}>>' delay=$delay noindex=$noindex
+@
+On an ugly system, we have to put it in a file.
+<<invoke awk program using file>>=
+awkfile=$($LIB/nwmktemp)
+trap 'rm -f $awkfile; exit 1' 0 1 2 15 # clean up files
+cat > $awkfile << 'EOF'
+<<awk program for conversion to {\TeX}>>
+EOF
+nawk -f $awkfile delay=$delay noindex=$noindex
+@
+The markup carefully adds no newlines not already present in the input,
+so that the line numbers of the {\TeX} file will be the same as the
+numbers of the corresponding {\tt noweb} file.
+The variables are:
+\begin{description}
+\item[\tt code] Nonzero if converting a code chunk.
+\item[\tt quoting] Nonzero if quoting code in documentation.
+\item[\tt text] Number of characters written since start of
+ documentation chunk.
+\end{description}
+[[text]] is used to write [[\par]] if a newline appears at the
+beginning of a documentation chunk without any intervening text.
+This subtle trick preserves new-paragraph semantics without requiring
+the insertion of a blank line that would throw off the line count.
+<<awk program for conversion to {\TeX}>>=
+BEGIN { code=0 ; quoting=0 ; text=1; <<initialization>> }
+/^@begin code/ { code=1 ; printf "\\nwbegincode{%s}", substr($0, 13) }
+/^@end code/ { code=0 ; printf "\\nwendcode{}"; lastdefnlabel = "" }
+<<special patterns for document chunk 0>>
+/^@begin docs/ { text=0 ; printf "\\nwbegindocs{%s}", substr($0, 13) }
+/^@end docs/ { printf "\\nwenddocs{}" }
+/^@text / { line = substr($0, 7) ; text += length - 6
+ if (code) printf "%s", escape_brace_bslash(line)
+ else if (quoting) printf "%s", TeXliteral(line)
+ else printf "%s", line
+ }
+/^@nl$/ { if (!code) {<<print [[\nwdocspar]] if no text>>}
+ if (quoting) printf "\\nwnewline"
+ printf "\n"
+ }
+/^@defn / { name = substr($0, 7); <<defn of [[name]], with cross-reference>> }
+/^@use / { printf "\\LA{}%s%s\\RA{}",
+ convquotes(substr($0, 6)), <<optional ref tag>>
+ }
+/^@quote$/ { quoting = 1 ; printf "{\\tt{}" }
+/^@endquote$/ { quoting = 0 ; printf "}" }
+/^@file / { filename = substr($0, 7); <<clear [[lastxref*]]>>
+ if (!delay) printf "\\nwfilename{%s}", filename
+ }
+/^@literal / { printf "%s", substr($0, 10) }
+/^@header latex / { <<write {\LaTeX} header>> }
+/^@header tex / { printf "\\input nwmac " }
+/^@trailer latex$/ { print "\\end{document}" }
+/^@trailer tex$/ { print "\\bye" }
+<<xref patterns>>
+<<index patterns>>
+END { printf "\n" }
+<<functions>>
+@
+<<print [[\nwdocspar]] if no text>>=
+if (text==0) printf "\\nwdocspar"
+text=1
+@
+Delaying markup is handled by special patterns for the first document chunk.
+Because several {\tt noweb} files can be marked up at once, there can be
+several document chunks numbered 0.
+The later ones are given no special treatment by the simple expedient of
+turning [[delay]] off after the first one.
+<<special patterns for document chunk 0>>=
+/^@begin docs 0$/ { if (delay) next }
+/^@end docs 0$/ { if (delay) {
+ printf "\\nwfilename{%s}", filename; delay=0; next
+ } }
+@
+<<defn of [[name]], with cross-reference>>=
+if (lastxreflabel != "") {
+ printf "\\sublabel{%s}", lastxreflabel
+ printf "\\nwmargintag{%s}", label2tag(lastxreflabel)
+}
+printf "\\moddef{%s%s}\\%sendmoddef", convquotes(name), <<optional ref tag>>, defns[name]
+lastdefnlabel = lastxreflabel
+<<clear [[lastxref*]]>>
+defns[name] = "plus"
+<<optional ref tag>>=
+(lastxrefref != "" ? ("~" label2tag(lastxrefref)) : "")
+<<functions>>=
+function label2tag(label) {
+ return "{\\nwtagstyle{}\\subpageref{" label "}}"
+}
+<<initialization>>=
+defns[0] = 0
+@
+<<write {\LaTeX} header>>=
+printf "\\documentclass{article}\\usepackage{noweb}\\pagestyle{noweb}\\noweboptions{%s}%s",
+ substr($0, 15), "\\begin{document}"
+@
+\subsection{Cross-reference and index support}
+<<xref patterns>>=
+/^@xref label / { lastxreflabel = substr($0, 13) }
+/^@xref ref / { lastxrefref = substr($0, 11) }
+/^@xref begindefs$/ { printf "\\nwalsodefined{" }
+/^@xref defitem / { printf "\\\\{%s}", substr($0, 15) }
+/^@xref enddefs$/ { printf "}" }
+/^@xref beginuses$/ { printf "\\nwused{" }
+/^@xref useitem / { printf "\\\\{%s}", substr($0, 15) }
+/^@xref enduses$/ { printf "}" }
+/^@xref notused / { printf "\\nwnotused{%s}", TeXliteral(substr($0, 15)) }
+/^@xref nextdef / { }
+/^@xref prevdef / { }
+<<clear [[lastxref*]]>>=
+lastxreflabel = lastxrefref = ""
+<<index patterns>>=
+/^@index nl$/ { print (code ? "\\eatline" : "%") }
+/^@index defn / {
+ if (!noindex) { arg = substr($0, 13); <<handle index defn of [[arg]]>> } }
+/^@index localdefn / {
+ if (!noindex) { arg = substr($0, 18); <<handle index defn of [[arg]]>> } }
+/^@index use / {
+ if (!noindex) { arg = substr($0, 12); <<handle index use of [[arg]]>> } }
+@
+Nothing is involved in handling definitions and uses unless there are cross-reference
+labels pending.
+An index definition or use has its own [[@xref label]] only if it's in documentation;
+if it's in code, we use the anchor label of the definition.
+(You don't have to know that to understand what happens here, but I thought you
+might like to.)
+<<handle index defn of [[arg]]>>=
+if (lastxreflabel != "") printf "\\nosublabel{%s}", lastxreflabel
+if (lastxrefref != "")
+ printf "\\nwindexdefn{%s}{%s}{%s}", TeXliteral(arg), indexlabel(arg), lastxrefref
+<<clear [[lastxref*]]>>
+@
+The {\LaTeX} back end ignores uses in code; they get bundled up by a previous filter
+(the cross-referencer) and handled elsewhere.
+<<handle index use of [[arg]]>>=
+if (!code) {
+ if (lastxreflabel != "") printf "\\protect\\nosublabel{%s}", lastxreflabel
+ if (lastxrefref != "")
+ printf "\\protect\\nwindexuse{%s}{%s}{%s}",
+ TeXliteral(arg), indexlabel(arg), lastxrefref
+}
+<<clear [[lastxref*]]>>
+@
+Here's the local identifier cross-reference that appears at the end of a code chunk.
+We guard everything with \LA{}SI\RA, as before.
+<<index patterns>>=
+/^@index begindefs$/ { if (!noindex) { printf "\\nwidentdefs{" } }
+/^@index isused / { if (!noindex) { } } # handled by latex
+/^@index defitem / { if (!noindex) { i = substr($0,16); <<write [[i]] with [[\\]]>> } }
+/^@index enddefs$/ { if (!noindex) { printf "}" } }
+/^@index beginuses$/ { if (!noindex) { printf "\\nwidentuses{"; ucount = 0 } }
+/^@index isdefined / { if (!noindex) { } } # latex finds the definitions
+/^@index useitem / { if (!noindex) { i = substr($0, 16); <<write [[i]] with [[\\]]>>
+ ulist[ucount++] = i
+ } }
+/^@index enduses$/ { if (!noindex) { printf "}"; <<write [[ulist]]>> } }
+<<initialization>>=
+ulist[0] = 0
+<<write [[i]] with [[\\]]>>=
+printf "\\\\{{%s}{%s}}", TeXliteral(i), indexlabel(i)
+<<write [[ulist]]>>=
+if (lastdefnlabel != "") {
+ for (j = 0; j < ucount; j++)
+ printf "\\nwindexuse{%s}{%s}{%s}",
+ TeXliteral(ulist[j]), indexlabel(ulist[j]), lastdefnlabel
+}
+@
+\subsubsection{The list of chunks and the index}
+The treatments of the list of chunks and the index are similar.
+Both use [[\nwixlogsorted]], which writes magic goo into the {\tt .aux} file.
+The real cross-referencing is done by the underlying {\LaTeX} code.
+<<xref patterns>>=
+/^@xref beginchunks$/ { }
+/^@xref chunkbegin / { label = $3; name = substr($0, 19 + length(label))
+ printf "\\nwixlogsorted{c}{{%s}{%s}{",
+ convquotes(name), label
+ }
+/^@xref chunkuse / { printf "\\nwixu{%s}", substr($0, 16) }
+/^@xref chunkdefn / { printf "\\nwixd{%s}", substr($0, 17) }
+/^@xref chunkend$/ { print "}}%" }
+/^@xref endchunks$/ { }
+<<index patterns>>=
+/^@index beginindex$/ { if (!noindex) { } }
+/^@index entrybegin / { if (!noindex) { label = $3; name = substr($0, 20 + length(label))
+ printf "\\nwixlogsorted{i}{{%s}{%s}}%%\n",
+ TeXliteral(name), indexlabel(name)
+ } }
+/^@index entryuse / { if (!noindex) { } } # handled by latex
+/^@index entrydefn / { if (!noindex) { } } # handled by latex
+/^@index entryend$/ { if (!noindex) { } }
+/^@index endindex$/ { if (!noindex) { } }
+
+@
+\subsection{Miscellany}
+I first insert a newline before the special characters, then change the
+newline to a backslash. I can't do the backslash directly because
+[[\&]] means a literal ampersand.
+<<functions>>=
+function escape_brace_bslash(line) {
+ gsub(/[\\{}]/, "\n&", line)
+ gsub(/\n/, "\\", line)
+ return line
+}
+@
+A special function is used to implement {\tt noweb}'s quoting
+convention within chunk names.
+<<functions>>=
+function convquotes(s, r, i) {
+ r = ""
+ while (i = index(s, "[[")) {
+ r = r substr(s, 1, i-1) "\\code{}"
+ s = substr(s, i+2)
+ if (i = match(s, "\\]\\]+")) {
+ r = r TeXliteral(substr(s, 1, i-1+RLENGTH-2)) "\\edoc{}"
+ s = substr(s, i+RLENGTH)
+ } else {
+ r = r s "\\edoc{}"
+ s = ""
+ }
+ }
+ return r s
+}
+<<functions>>=
+function indexlabel(ident, l) {
+ l = ident
+ gsub(/:/, ":col", l) # must be first (colon)
+ gsub(/ /, ":sp", l) # space
+ gsub(/#/, ":has", l) # hash
+ gsub(/\$/, ":do", l) # dollar
+ gsub(/%/, ":pe", l) # percent
+ gsub(/&/, ":am", l) # ampersand
+ gsub(/,/, ":com", l) # commad
+ gsub(/\\/, ":bs", l) # backslash
+ gsub(/\^/, ":hat", l) # hat
+ gsub(/_/, ":un", l) # underscore
+ gsub(/{/, ":lb", l) # left brace
+ gsub(/}/, ":rb", l) # right brace
+ gsub(/~/, ":ti", l) # tilde
+ return l
+}
+@ %def indexlabel
+@
+Because latex2e uses [[`]] as an active character, I have to use
+decimal character codes for the specials.
+<<functions>>=
+function TeXliteral(arg) {
+ gsub(/\\/, "<\\char92>", arg)
+ gsub(/}/, "<\\char125}", arg)
+ gsub(/{/, "{\\char123}", arg)
+ gsub(/<\\char/, "{\\char", arg)
+ gsub(/{\\char92>/, "{\\char92}", arg)
+ gsub(/\$/, "{\\char36}", arg)
+ gsub(/&/, "{\\char38}", arg)
+ gsub(/#/, "{\\char35}", arg)
+ gsub(/\^/, "{\\char94}", arg)
+ gsub(/_/, "{\\char95}", arg)
+ gsub(/%/, "{\\char37}", arg)
+ gsub(/~/, "{\\char126}", arg)
+ gsub(/ /, "\\ ", arg)
+ return arg
+}
+@ %def TeXliteral
+
diff --git a/web/noweb/src/awk/totex.nw.bad b/web/noweb/src/awk/totex.nw.bad
new file mode 100644
index 0000000000..aa99ff290c
--- /dev/null
+++ b/web/noweb/src/awk/totex.nw.bad
@@ -0,0 +1,292 @@
+\section{Converting {\tt noweb} markup to {\TeX} markup}
+The copyright applies both to the {\tt noweb} source and to the
+generated shell script.
+<<copyright notice>>=
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+<<totex>>=
+#!/bin/sh
+<<copyright notice>>
+# Don't try to understand this file! Look at lib/totex.nw in the noweb source!
+delay=0 noindex=0
+for i do
+ case $i in
+ -delay) delay=1 ;;
+ -noindex) noindex=1 ;;
+ *) echo "This can't happen -- $i passed to totex" 1>&2 ; exit 1 ;;
+ esac
+done
+<<invoke awk program using parameter>>
+@
+On a forgiving system, we make the awk program an argument:
+<<invoke awk program using parameter>>=
+nawk '<<awk program for conversion to {\TeX}>>' delay=$delay noindex=$noindex
+@
+On an ugly system, we have to put it in a file.
+<<invoke awk program using file>>=
+awkfile=/tmp/totex$$.awk
+trap 'rm -f $awkfile; exit 1' 0 1 2 15 # clean up files
+cat > $awkfile << 'EOF'
+<<awk program for conversion to {\TeX}>>
+EOF
+nawk -f $awkfile delay=$delay noindex=$noindex
+@
+The markup carefully adds no newlines not already present in the input,
+so that the line numbers of the {\TeX} file will be the same as the
+numbers of the corresponding {\tt noweb} file.
+The variables are:
+\begin{description}
+\item[\tt code] Nonzero if converting a code chunk.
+\item[\tt quoting] Nonzero if quoting code in documentation.
+\item[\tt text] Number of characters written since start of
+ documentation chunk.
+\end{description}
+[[text]] is used to write [[\par]] if a newline appears at the
+beginning of a documentation chunk without any intervening text.
+This subtle trick preserves new-paragraph semantics without requiring
+the insertion of a blank line that would throw off the line count.
+<<awk program for conversion to {\TeX}>>=
+BEGIN { code=0 ; quoting=0 ; text=1; <<initialization>> }
+/^@begin code/ { code=1 ; printf "\\nwbegincode{%s}", substr($0, 13) }
+/^@end code/ { code=0 ; printf "\\nwendcode{}"; lastdefnlabel = "" }
+<<special patterns for document chunk 0>>
+/^@begin docs/ { text=0 ; printf "\\nwbegindocs{%s}", substr($0, 13) }
+/^@end docs/ { printf "\\nwenddocs{}" }
+/^@text / { line = substr($0, 7) ; text += length - 6
+ if (code) printf "%s", escape_brace_bslash(line)
+ else if (quoting) printf "%s", TeXliteral(line)
+ else printf "%s", line
+ }
+/^@nl$/ { if (!code) {<<print [[\nwdocspar]] if no text>>}
+ if (quoting) printf "\\nwnewline"
+ printf "\n"
+ }
+/^@defn / { name = substr($0, 7); <<defn of [[name]], with cross-reference>> }
+/^@use / { <<set [[optreftag]]>>
+ printf "\\LA{}%s%s\\RA{}", \
+ convquotes(substr($0, 6)), optreftag
+ }
+/^@quote$/ { quoting = 1 ; printf "{\\tt{}" }
+/^@endquote$/ { quoting = 0 ; printf "}" }
+/^@file / { filename = substr($0, 7); <<clear [[lastxref*]]>>
+ if (!delay) printf "\\nwfilename{%s}", filename
+ }
+/^@literal / { printf "%s", substr($0, 10) }
+/^@header latex / { <<write {\LaTeX} header>> }
+/^@header tex / { printf "\\input nwmac " }
+/^@trailer latex$/ { print "\\end{document}" }
+/^@trailer tex$/ { print "\\bye" }
+<<xref patterns>>
+<<index patterns>>
+END { printf "\n" }
+<<functions>>
+@
+<<print [[\nwdocspar]] if no text>>=
+if (text==0) printf "\\nwdocspar"
+text=1
+@
+Delaying markup is handled by special patterns for the first document chunk.
+Because several {\tt noweb} files can be marked up at once, there can be
+several document chunks numbered 0.
+The later ones are given no special treatment by the simple expedient of
+turning [[delay]] off after the first one.
+<<special patterns for document chunk 0>>=
+/^@begin docs 0$/ { if (delay) next }
+/^@end docs 0$/ { if (delay) {
+ printf "\\nwfilename{%s}", filename; delay=0; next
+ } }
+@
+<<defn of [[name]], with cross-reference>>=
+if (lastxreflabel != "") {
+ printf "\\sublabel{%s}", lastxreflabel
+ printf "\\nwmargintag{%s}", label2tag(lastxreflabel)
+}
+
+<<set [[optreftag]]>>
+printf "\\moddef{%s%s}\\%sendmoddef", convquotes(name), optreftag, defns[name]
+lastdefnlabel = lastxreflabel
+<<clear [[lastxref*]]>>
+defns[name] = "plus"
+<<set [[optreftag]]>>=
+if (lastxrefref != "")
+ optreftag = "~" label2tag(lastxrefref)
+else
+ optreftag = ""
+<<functions>>=
+function label2tag(label) {
+ return "{\\nwtagstyle{}\\subpageref{" label "}}"
+}
+<<initialization>>=
+defns[0] = 0
+@
+<<write {\LaTeX} header>>=
+printf "\\documentclass{article}\\usepackage{noweb}\\pagestyle{noweb}\\noweboptions{%s}%s", substr($0, 15), "\\begin{document}"
+@
+\subsection{Cross-reference and index support}
+<<xref patterns>>=
+/^@xref label / { lastxreflabel = substr($0, 13) }
+/^@xref ref / { lastxrefref = substr($0, 11) }
+/^@xref begindefs$/ { printf "\\nwalsodefined{" }
+/^@xref defitem / { printf "\\\\{%s}", substr($0, 15) }
+/^@xref enddefs$/ { printf "}" }
+/^@xref beginuses$/ { printf "\\nwused{" }
+/^@xref useitem / { printf "\\\\{%s}", substr($0, 15) }
+/^@xref enduses$/ { printf "}" }
+/^@xref notused / { printf "\\nwnotused{%s}", TeXliteral(substr($0, 15)) }
+/^@xref nextdef / { }
+/^@xref prevdef / { }
+<<clear [[lastxref*]]>>=
+lastxreflabel = lastxrefref = ""
+<<index patterns>>=
+/^@index nl$/ { if (code) print "\\eatline"
+ else print "%" }
+/^@index defn / {
+ if (!noindex) { arg = substr($0, 13); <<handle index defn of [[arg]]>> } }
+/^@index localdefn / {
+ if (!noindex) { arg = substr($0, 18); <<handle index defn of [[arg]]>> } }
+/^@index use / {
+ if (!noindex) { arg = substr($0, 12); <<handle index use of [[arg]]>> } }
+@
+Nothing is involved in handling definitions and uses unless there are cross-reference
+labels pending.
+An index definition or use has its own [[@xref label]] only if it's in documentation;
+if it's in code, we use the anchor label of the definition.
+(You don't have to know that to understand what happens here, but I thought you
+might like to.)
+<<handle index defn of [[arg]]>>=
+if (lastxreflabel != "") printf "\\nosublabel{%s}", lastxreflabel
+if (lastxrefref != "")
+ printf "\\nwindexdefn{%s}{%s}{%s}", TeXliteral(arg), indexlabel(arg), lastxrefref
+<<clear [[lastxref*]]>>
+@
+The {\LaTeX} back end ignores uses in code; they get bundled up by a previous filter
+(the cross-referencer) and handled elsewhere.
+<<handle index use of [[arg]]>>=
+if (!code) {
+ if (lastxreflabel != "") printf "\\protect\\nosublabel{%s}", lastxreflabel
+ if (lastxrefref != "")
+ printf "\\protect\\nwindexuse{%s}{%s}{%s}", \
+ TeXliteral(arg), indexlabel(arg), lastxrefref
+}
+<<clear [[lastxref*]]>>
+@
+Here's the local identifier cross-reference that appears at the end of a code chunk.
+We guard everything with \LA{}SI\RA, as before.
+<<index patterns>>=
+/^@index begindefs$/ { if (!noindex) { printf "\\nwidentdefs{" } }
+/^@index isused / { if (!noindex) { } } # handled by latex
+/^@index defitem / { if (!noindex) { i = substr($0,16); <<write [[i]] with [[\\]]>> } }
+/^@index enddefs$/ { if (!noindex) { printf "}" } }
+/^@index beginuses$/ { if (!noindex) { printf "\\nwidentuses{"; ucount = 0 } }
+/^@index isdefined / { if (!noindex) { } } # latex finds the definitions
+/^@index useitem / { if (!noindex) { i = substr($0, 16); <<write [[i]] with [[\\]]>>
+ ulist[ucount++] = i
+ } }
+/^@index enduses$/ { if (!noindex) { printf "}"; <<write [[ulist]]>> } }
+<<initialization>>=
+ulist[0] = 0
+<<write [[i]] with [[\\]]>>=
+printf "\\\\{{%s}{%s}}", TeXliteral(i), indexlabel(i)
+<<write [[ulist]]>>=
+if (lastdefnlabel != "") {
+ for (j = 0; j < ucount; j++)
+ printf "\\nwindexuse{%s}{%s}{%s}", \
+ TeXliteral(ulist[j]), indexlabel(ulist[j]), lastdefnlabel
+}
+@
+\subsubsection{The list of chunks and the index}
+The treatments of the list of chunks and the index are similar.
+Both use [[\nwixlogsorted]], which writes magic goo into the {\tt .aux} file.
+The real cross-referencing is done by the underlying {\LaTeX} code.
+<<xref patterns>>=
+/^@xref beginchunks$/ { }
+/^@xref chunkbegin / { label = $3; name = substr($0, 19 + length(label))
+ printf "\\nwixlogsorted{c}{{%s}{%s}{", \
+ convquotes(name), label
+ }
+/^@xref chunkuse / { printf "\\nwixu{%s}", substr($0, 16) }
+/^@xref chunkdefn / { printf "\\nwixd{%s}", substr($0, 17) }
+/^@xref chunkend$/ { print "}}%" }
+/^@xref endchunks$/ { }
+<<index patterns>>=
+/^@index beginindex$/ { if (!noindex) { } }
+/^@index entrybegin / { if (!noindex) { label = $3; name = substr($0, 20 + length(label))
+ printf "\\nwixlogsorted{i}{{%s}{%s}}%%\n", \
+ TeXliteral(name), indexlabel(name)
+ } }
+/^@index entryuse / { if (!noindex) { } } # handled by latex
+/^@index entrydefn / { if (!noindex) { } } # handled by latex
+/^@index entryend$/ { if (!noindex) { } }
+/^@index endindex$/ { if (!noindex) { } }
+
+@
+\subsection{Miscellany}
+I first insert a newline before the special characters, then change the
+newline to a backslash. I can't do the backslash directly because
+[[\&]] means a literal ampersand.
+<<functions>>=
+function escape_brace_bslash(line) {
+ gsub(/[\\{}]/, "\n&", line)
+ gsub(/\n/, "\\", line)
+ return line
+}
+@
+A special function is used to implement {\tt noweb}'s quoting
+convention within chunk names.
+<<functions>>=
+function convquotes(s, r, i) {
+ r = ""
+ while (i = index(s, "[[")) {
+ r = r substr(s, 1, i-1) "\\code{}"
+ s = substr(s, i+2)
+ if (i = match(s, "\\]\\]+")) {
+ r = r TeXliteral(substr(s, 1, i-1+RLENGTH-2)) "\\edoc{}"
+ s = substr(s, i+RLENGTH)
+ } else {
+ r = r s "\\edoc{}"
+ s = ""
+ }
+ }
+ return r s
+}
+<<functions>>=
+function indexlabel(ident, l) {
+ l = ident
+ gsub(/:/, ":col", l) # must be first (colon)
+ gsub(/ /, ":sp", l) # space
+ gsub(/#/, ":has", l) # hash
+ gsub(/\$/, ":do", l) # dollar
+ gsub(/%/, ":pe", l) # percent
+ gsub(/&/, ":am", l) # ampersand
+ gsub(/,/, ":com", l) # commad
+ gsub(/\\/, ":bs", l) # backslash
+ gsub(/\^/, ":hat", l) # hat
+ gsub(/_/, ":un", l) # underscore
+ gsub(/{/, ":lb", l) # left brace
+ gsub(/}/, ":rb", l) # right brace
+ gsub(/~/, ":ti", l) # tilde
+ return l
+}
+@ %def indexlabel
+@
+Because latex2e uses [[`]] as an active character, I have to use
+decimal character codes for the specials.
+<<functions>>=
+function TeXliteral(arg) {
+ gsub(/\\/, "<\\char92>", arg)
+ gsub(/}/, "<\\char125}", arg)
+ gsub(/{/, "{\\char123}", arg)
+ gsub(/<\\char/, "{\\char", arg)
+ gsub(/{\\char92>/, "{\\char92}", arg)
+ gsub(/\$/, "{\\char36}", arg)
+ gsub(/&/, "{\\char38}", arg)
+ gsub(/#/, "{\\char35}", arg)
+ gsub(/\^/, "{\\char94}", arg)
+ gsub(/_/, "{\\char95}", arg)
+ gsub(/%/, "{\\char37}", arg)
+ gsub(/~/, "{\\char126}", arg)
+ gsub(/ /, "\\ ", arg)
+ return arg
+}
+@ %def TeXliteral
+
diff --git a/web/noweb/src/awkmake b/web/noweb/src/awkmake
new file mode 100755
index 0000000000..5c710ce0f8
--- /dev/null
+++ b/web/noweb/src/awkmake
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+WHICH=${LIBSRC:-awk}
+DIR=/usr/local/noweb-$WHICH
+
+mkdir -p $DIR
+
+
+if [ $# -eq 0 ]; then set all install; fi # "$@" breaks make for empty args
+/usr/bin/make ICONT=icont CC="gcc -ansi -pedantic -O -Wall -Werror" LIBSRC=$WHICH BIN=$DIR/bin LIB=$DIR/lib MAN=$DIR/man TEXINPUTS=/usr/local/share/texmf/tex/plain/misc ELISP=/dev/null "$@"
diff --git a/web/noweb/src/awkname b/web/noweb/src/awkname
new file mode 100755
index 0000000000..157843b903
--- /dev/null
+++ b/web/noweb/src/awkname
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+case $# in
+ 1) ;;
+ *) echo "Usage: `basename $0` [awk|nawk|gawk]" 1>&2; exit 1
+esac
+
+rc=0
+new=$(mktemp); old=$(mktemp)
+
+for file in lib/emptydefn lib/unmarkup lib/toascii lib/btdefn \
+ awk/noidx awk/totex awk/tohtml awk/noindex \
+ shell/noroff shell/toroff lib/pipedocs \
+ shell/nocount shell/nountangle shell/noweb shell/noroots
+do
+ trap 'rm -f $new $old; exit 1' 1 2 15 # clean up files
+ if sed -e "s/nawk '/$1 '/" -e "s/nawk -f/$1 -f/" -e "s/AWK=nawk/AWK=$1/" <$file >$new
+ then
+ cp $file $old # save original file
+ trap 'trap "" 1 2 15; cp $old $file # ignore signals
+ rm -f $new $old; exit 1' 1 2 15 # during restore
+ cp $new $file
+ else
+ echo "awkname: failed to change $file" 1>&2
+ rc=1
+ fi
+done
+rm -f $new $old
+exit $rc
+
diff --git a/web/noweb/src/c/Makefile b/web/noweb/src/c/Makefile
new file mode 100644
index 0000000000..52bf4e2c74
--- /dev/null
+++ b/web/noweb/src/c/Makefile
@@ -0,0 +1,112 @@
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+#
+# Adjust these two lines for your ANSI C compiler
+CC=gcc -ansi -pedantic -O -Wall -Werror
+CFLAGS=
+
+# after installation, make doc.dvi for literate version
+
+FINDUSESOBJS=columns.o errors.o finduses.o match.o getline.o recognize.o
+MNTOBJS=mnt.o getline.o match.o modules.o modtrees.o notangle.o \
+ strsave.o errors.o columns.o
+TANGLEOBJS=notangle.o getline.o match.o modules.o modtrees.o strsave.o \
+ main.o errors.o columns.o
+MARKUPOBJS=markmain.o strsave.o markup.o errors.o getline.o columns.o
+FILES=markmain.nw markup.nw \
+ main.nw notangle.nw match.nw mnt.nw modules.nw modtrees.nw \
+ finduses.nw recognize.nw \
+ getline.nw columns.nw errors.nw strsave.nw
+
+SRCS=columns.h errors.h getline.h markup.h match.h modtrees.h \
+ modules.h notangle.h recognize.h strsave.h \
+ columns.c errors.c getline.c finduses.c main.c markmain.c markup.c match.c \
+ mnt.c modtrees.c modules.c notangle.c nwmktemp.c recognize.c \
+ strsave.c markup.ps
+NAME='name of RCS version'
+
+NOTANGLE=notangle
+SHELL=/bin/sh
+# set this for CPIF and then distribute tools with bad timestamps...
+#CPIF=| cpif
+CPIF=>
+
+.SUFFIXES: .nw .tex .dvi .h
+.nw.tex: ; noweave $*.nw >$*.tex
+.nw.c: ; $(NOTANGLE) -L $*.nw >$*.c
+.nw.o: ; $(NOTANGLE) -L $*.nw >$*.c
+ $(CC) $(CFLAGS) -c $*.c
+.nw.h: ; $(NOTANGLE) -Rheader $*.nw $(CPIF) $*.h
+
+all: nt markup mnt finduses nwmktemp
+
+nt: $(TANGLEOBJS)
+ $(CC) $(CFLAGS) -o nt $(TANGLEOBJS)
+
+nwmktemp: nwmktemp.o
+ $(CC) $(CFLAGS) -o nwmktemp nwmktemp.o
+
+finduses: $(FINDUSESOBJS)
+ $(CC) $(CFLAGS) -o finduses $(FINDUSESOBJS)
+
+markup: $(MARKUPOBJS)
+ $(CC) $(CFLAGS) -o markup $(MARKUPOBJS)
+
+mnt: $(MNTOBJS)
+ $(CC) $(CFLAGS) -o mnt $(MNTOBJS)
+
+source: $(SRCS)
+touch: $(SRCS)
+ touch $(SRCS)
+
+boot: ; touch $(SRCS)
+
+clean: ; rm -f nt markup mnt finduses fakepretty
+ rm -f core *.makelog *.tex *.log *.blg *.dvi *.o *.toc *~
+ rm -f *.atac *.trace *.html
+
+clobber: clean
+ rm -f $(SRCS) fakepretty.c pretty.[ch]
+
+checkin: $(FILES) doc.nw
+ ci $(CINAME) $(CIMSG) -l $(FILES) doc.nw
+
+doc.tex: doc.nw
+ cp doc.nw doc.tex
+
+allcode.tex: $(FILES)
+ noweave -n -index $(FILES) > allcode.tex
+
+doc.dvi: doc.tex allcode.tex
+ latex doc; latex doc; latex doc
+
+doc.ps: doc.dvi
+ dvips doc
+
+markup.ps: markmain.nw
+ notangle -Rmarkup.dot markmain.nw | dot -Tps > markup.ps
+
+FPOBJS=fakepretty.o pretty.o errors.o getline.o match.o strsave.o columns.o
+
+fakepretty.o: pretty.h
+
+fakepretty: $(FPOBJS)
+ $(CC) $(CFLAGS) -o fakepretty $(FPOBJS)
+
+
+columns.o: columns.h
+errors.o: errors.h
+finduses.o: errors.h match.h getline.h recognize.h
+getline.o: columns.h errors.h getline.h
+main.o: notangle.h errors.h columns.h modules.h modtrees.h
+markmain.o: errors.h markup.h getline.h columns.h
+markup.o: markup.h strsave.h errors.h
+match.o: match.h
+mnt.o: modules.h modtrees.h notangle.h errors.h columns.h strsave.h
+modtrees.o: strsave.h modules.h modtrees.h errors.h
+modules.o: modules.h modtrees.h errors.h columns.h strsave.h
+notangle.o: strsave.h getline.h modules.h modtrees.h errors.h match.h notangle.h
+nwmktemp.o:
+pretty.o: getline.h match.h errors.h pretty.h strsave.h
+recognize.o:
+strsave.o: strsave.h errors.h
diff --git a/web/noweb/src/c/columns.c b/web/noweb/src/c/columns.c
new file mode 100644
index 0000000000..a34b2ebff6
--- /dev/null
+++ b/web/noweb/src/c/columns.c
@@ -0,0 +1,37 @@
+#line 18 "columns.nw"
+static char rcsid[] = "$Id: columns.nw,v 2.24 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include "columns.h"
+
+int tabsize = 8;
+#line 25 "columns.nw"
+int columnwidth (char *s) { /* width of a string in columns */
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return limitcolumn(s, 0);
+}
+#line 31 "columns.nw"
+int limitcolumn (char *s, int col) {
+ while (*s) {
+ col++;
+ if (*s=='\t' && tabsize > 0) while (col % tabsize != 0) col++;
+ s++;
+ }
+ return col;
+}
+#line 40 "columns.nw"
+void indent_for (int width, FILE *fp) {
+ /* write whitespace [[width]] columns wide */
+/*fprintf(fp,"<%2d>",width); if (width>4) {fprintf(fp," "); width -= 4;}*/
+ if (tabsize > 1)
+ while (width >= tabsize) {
+ putc('\t', fp);
+ width -= tabsize;
+ }
+ while (width > 0) {
+ putc(' ', fp);
+ width--;
+ }
+}
+
diff --git a/web/noweb/src/c/columns.h b/web/noweb/src/c/columns.h
new file mode 100644
index 0000000000..83762f5988
--- /dev/null
+++ b/web/noweb/src/c/columns.h
@@ -0,0 +1,6 @@
+extern int tabsize;
+extern int columnwidth (char *s); /* number of columns string occupies */
+extern int limitcolumn (char *s, int startcolumn);
+ /* width of startcolumn blanks plus s */
+extern void indent_for (int width, FILE *fp);
+ /* indent to width; next char -> width+1 */
diff --git a/web/noweb/src/c/columns.nw b/web/noweb/src/c/columns.nw
new file mode 100644
index 0000000000..ce35ed568b
--- /dev/null
+++ b/web/noweb/src/c/columns.nw
@@ -0,0 +1,53 @@
+% Copyright 1991 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+\subsection{Managing indentation and columns}
+These functions are used to help accumulate indentations across module
+boundaries by measuring the widths of various strings
+in columns.
+The size of things depends on [[tabsize]] as defined in columns.h.
+If [[tabsize == 0]], tabs shouldn't be touched on input and won't be
+generated on output.
+<<header>>=
+extern int tabsize;
+extern int columnwidth (char *s); /* number of columns string occupies */
+extern int limitcolumn (char *s, int startcolumn);
+ /* width of startcolumn blanks plus s */
+extern void indent_for (int width, FILE *fp);
+ /* indent to width; next char -> width+1 */
+<<*>>=
+static char rcsid[] = "$Id: columns.nw,v 2.24 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include "columns.h"
+
+int tabsize = 8;
+<<*>>=
+int columnwidth (char *s) { /* width of a string in columns */
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return limitcolumn(s, 0);
+}
+<<*>>=
+int limitcolumn (char *s, int col) {
+ while (*s) {
+ col++;
+ if (*s=='\t' && tabsize > 0) while (col % tabsize != 0) col++;
+ s++;
+ }
+ return col;
+}
+<<*>>=
+void indent_for (int width, FILE *fp) {
+ /* write whitespace [[width]] columns wide */
+/*fprintf(fp,"<%2d>",width); if (width>4) {fprintf(fp," "); width -= 4;}*/
+ if (tabsize > 1)
+ while (width >= tabsize) {
+ putc('\t', fp);
+ width -= tabsize;
+ }
+ while (width > 0) {
+ putc(' ', fp);
+ width--;
+ }
+}
+
diff --git a/web/noweb/src/c/doc.bbl b/web/noweb/src/c/doc.bbl
new file mode 100644
index 0000000000..e72476f0c4
--- /dev/null
+++ b/web/noweb/src/c/doc.bbl
@@ -0,0 +1,8 @@
+\begin{thebibliography}{1}
+
+\bibitem{aho:efficient}
+Alfred~V. Aho and Margaret~J. Corasick.
+\newblock Efficient string matching: An aid to bibliographic search.
+\newblock {\em Communications of the ACM}, 18(6):333--340, June 1975.
+
+\end{thebibliography}
diff --git a/web/noweb/src/c/doc.nw b/web/noweb/src/c/doc.nw
new file mode 100644
index 0000000000..d32e6cfc55
--- /dev/null
+++ b/web/noweb/src/c/doc.nw
@@ -0,0 +1,49 @@
+% $Id: doc.nw,v 1.21 2008/10/06 01:03:05 nr Exp nr $
+
+\documentclass[twoside]{article}
+\usepackage{noweb,multicol}
+\makeatletter
+\newenvironment{fields}{\@fields}{\crcr\egroup\par\end{quote}}
+\def\@fields{\@ifnextchar[{\@@fields}{\@@fields[4in]}}
+\def\@@fields[#1]{\begin{quote}\catcode`\_=\other
+ \tabskip=\leftmargin
+ \halign\bgroup\tt##\hfil\tabskip=2em&
+ {\hsize=#1\vtop{\noindent\raggedright\let\\=\cr
+ \strut##\strut\par}}\tabskip=0pt\cr}
+\makeatother
+\pagestyle{noweb}\raggedbottom\noweboptions{shift}
+
+\title{{\tt noweb} Source Code\thanks{{\tt noweb} is copyright 1989--2000 by Norman Ramsey.
+Although it is freely available, it is not in the public domain.}}
+\author{Norman Ramsey\thanks{Section~\ref{preston} is the
+generous contribution of Preston Briggs}\\{\tt nr@eecs.harvard.edu}}
+\begin{document}
+\maketitle
+\section*{Preface}
+This isn't a real literate program---there's just enough documentation
+here to get the job done.
+One of my observations is that the cost of creating a high-quality, well-documented
+literate program adds 1--3 times the amount of effort it took to create the program
+in the first place.
+Most programs I write aren't worth that kind of effort, and {\tt noweb} is
+no exception.
+Don't expect too much.
+
+\tableofcontents
+
+\input{allcode.tex}
+
+\bibliographystyle{plain}
+\bibliography{web}
+
+\section{List of all chunks from all files}
+
+\nowebchunks
+
+\begin{multicols}{2}[\section{Index}]
+\nowebindex
+\end{multicols}
+
+\end{document}
+
+
diff --git a/web/noweb/src/c/errors.c b/web/noweb/src/c/errors.c
new file mode 100644
index 0000000000..c47a092ab2
--- /dev/null
+++ b/web/noweb/src/c/errors.c
@@ -0,0 +1,53 @@
+#line 17 "errors.nw"
+static char rcsid[] = "$Id: errors.nw,v 2.26 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include "errors.h"
+
+#line 34 "errors.nw"
+enum errorlevel errorlevel = Normal;
+int finalstage = 0;
+char *progname = NULL;
+#line 44 "errors.nw"
+void nowebexit(char *msg) {
+ if (!finalstage && errorlevel > Normal)
+ printf("@fatal %s %s\n", progname != NULL ? progname : "a-noweb-filter",
+ msg != NULL ? msg : "an unspecified error occurred");
+ exit(errorlevel);
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+}
+#line 60 "errors.nw"
+void errormsg(enum errorlevel level, char *s,...) {
+ va_list args; /* see K&R, page 174 */
+ va_start(args,s);
+
+#line 81 "errors.nw"
+if (level > errorlevel)
+ errorlevel = level;
+vfprintf(stderr, s, args);
+fprintf(stderr,"\n");
+#line 64 "errors.nw"
+ va_end(args);
+ if (level >= Fatal)
+ nowebexit(s);
+}
+#line 71 "errors.nw"
+void errorat(char *filename, int lineno, enum errorlevel level, char *s, ...) {
+ va_list args; /* see K&R, page 174 */
+ va_start(args,s);
+ fprintf(stderr, "%s:%d: ", filename, lineno);
+
+#line 81 "errors.nw"
+if (level > errorlevel)
+ errorlevel = level;
+vfprintf(stderr, s, args);
+fprintf(stderr,"\n");
+#line 76 "errors.nw"
+ va_end(args);
+ if (level >= Fatal)
+ nowebexit(s);
+}
diff --git a/web/noweb/src/c/errors.h b/web/noweb/src/c/errors.h
new file mode 100644
index 0000000000..72cc81ec9e
--- /dev/null
+++ b/web/noweb/src/c/errors.h
@@ -0,0 +1,10 @@
+enum errorlevel { Normal=0, Warning, Error, Fatal, Impossible };
+extern enum errorlevel errorlevel;
+extern int finalstage; /* set nonzero if this main() is a final stage */
+extern char *progname; /* set to name of program if main() is a filter */
+extern void nowebexit(char *optional_msg);
+void errormsg(enum errorlevel level, char *s, ...);
+#define overflow(S) errormsg(Fatal,"Capacity exceeded: %s", S)
+#define impossible(S) errormsg(Impossible, "This can't happen: %s", S)
+#define checkptr(P) do { if (!(P)) overflow("memory"); } while (0)
+void errorat(char *filename, int lineno, enum errorlevel level, char *s, ...);
diff --git a/web/noweb/src/c/errors.nw b/web/noweb/src/c/errors.nw
new file mode 100644
index 0000000000..c3c59829d2
--- /dev/null
+++ b/web/noweb/src/c/errors.nw
@@ -0,0 +1,94 @@
+% -*- mode: Noweb; noweb-code-mode: c-mode; c-indent-level: 4 -*-
+% Copyright 1991 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+\subsection{Error messages}
+Here is a big set of functions that other places can call to issue
+error messages.
+
+It might be worth implementing these as macros so they could indicate
+the file name and line number in the source of where they were called.
+
+[[errorlevel]] is an integer that says how bad the worst error so far
+has been.
+[[newerrorlevel]] will update it conditionally.
+Some day we should hide it and give the world a function call that
+queries it.
+<<*>>=
+static char rcsid[] = "$Id: errors.nw,v 2.26 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include "errors.h"
+
+<<C functions>>
+@
+I track degrees of error as they occur.
+<<header>>=
+enum errorlevel { Normal=0, Warning, Error, Fatal, Impossible };
+extern enum errorlevel errorlevel;
+extern int finalstage; /* set nonzero if this main() is a final stage */
+extern char *progname; /* set to name of program if main() is a filter */
+<<C functions>>=
+enum errorlevel errorlevel = Normal;
+int finalstage = 0;
+char *progname = NULL;
+@
+If an error occurred, one can exit with the proper notice on the
+filter:
+<<header>>=
+extern void nowebexit(char *optional_msg);
+@
+<<C functions>>=
+void nowebexit(char *msg) {
+ if (!finalstage && errorlevel > Normal)
+ printf("@fatal %s %s\n", progname != NULL ? progname : "a-noweb-filter",
+ msg != NULL ? msg : "an unspecified error occurred");
+ exit(errorlevel);
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+}
+@
+The rest is just varying flavors of error messages.
+<<header>>=
+void errormsg(enum errorlevel level, char *s, ...);
+#define overflow(S) errormsg(Fatal,"Capacity exceeded: %s", S)
+#define impossible(S) errormsg(Impossible, "This can't happen: %s", S)
+#define checkptr(P) do { if (!(P)) overflow("memory"); } while (0)
+<<C functions>>=
+void errormsg(enum errorlevel level, char *s,...) {
+ va_list args; /* see K&R, page 174 */
+ va_start(args,s);
+ <<set [[errorlevel]] and print [[s]] with [[args]]>>
+ va_end(args);
+ if (level >= Fatal)
+ nowebexit(s);
+}
+<<header>>=
+void errorat(char *filename, int lineno, enum errorlevel level, char *s, ...);
+<<C functions>>=
+void errorat(char *filename, int lineno, enum errorlevel level, char *s, ...) {
+ va_list args; /* see K&R, page 174 */
+ va_start(args,s);
+ fprintf(stderr, "%s:%d: ", filename, lineno);
+ <<set [[errorlevel]] and print [[s]] with [[args]]>>
+ va_end(args);
+ if (level >= Fatal)
+ nowebexit(s);
+}
+<<set [[errorlevel]] and print [[s]] with [[args]]>>=
+if (level > errorlevel)
+ errorlevel = level;
+vfprintf(stderr, s, args);
+fprintf(stderr,"\n");
+@
+Some older machines don't do [[vfprintf]]; here's an implementation:
+<<crock for non-ANSI machines>>=
+extern int _doprnt(const char *format, va_list args, FILE *stream);
+
+int vfprintf(FILE *stream, const char *format, va_list arg) {
+ return _doprnt(format,arg,stream);
+}
+
+
diff --git a/web/noweb/src/c/fakepretty.nw b/web/noweb/src/c/fakepretty.nw
new file mode 100644
index 0000000000..0149413a1c
--- /dev/null
+++ b/web/noweb/src/c/fakepretty.nw
@@ -0,0 +1,85 @@
+\section{A fake prettyprinter}
+This ``prettyprinter'' builds a code brick.
+<<*>>=
+static char rcsid[] = "$Id: fakepretty.nw,v 1.19 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <stdlib.h>
+#include "pretty.h"
+
+struct prettyprinter {
+ int column;
+ int trailswhite;
+ PrettyPrinterCallback callback;
+ void *cb;
+};
+<<*>>=
+static void addwhite(PrettyPrinter pp) {
+ if (!pp->trailswhite) {
+ pp->callback(pp->cb, STRING, " ");
+ pp->column++;
+ pp->trailswhite = 1;
+ }
+}
+<<*>>=
+static void flushout(PrettyPrinter pp) {
+ if (pp->column > 0) {
+ pp->callback(pp->cb, NEWLINE, (char *)0);
+ pp->column = 0;
+ pp->trailswhite = 1;
+ }
+}
+<<*>>=
+static void addthing(PrettyPrinter pp, Parttype type, char *contents) {
+ addwhite(pp);
+ if (pp->column + strlen(contents) > 70) flushout(pp);
+ pp->callback(pp->cb, type, contents);
+ pp->column += strlen(contents);
+ pp->trailswhite = 0;
+}
+#define addtoken(PP,T) addthing(pp, STRING, T)
+#define adduse(PP,C) addthing(pp, USE_CHUNK, C)
+@
+<<*>>=
+void prettyprint(PrettyPrinter pp, Parttype type, char *contents) {
+ switch(type) {
+ case START_OF_CHUNK: break;
+ case END_OF_CHUNK: if (pp->column > 0) flushout(pp); break;
+ case STRING: <<write tokens>> break;
+ case USE_CHUNK: adduse(pp, contents); break;
+ case NEWLINE: addwhite(pp); break;
+ case WHATSIT: pp->callback(pp->cb, type, contents); break;
+ default: assert(0);
+ }
+}
+
+PrettyPrinter new_prettyprinter(PrettyPrinterCallback callback, void *closure) {
+ PrettyPrinter pp = (PrettyPrinter) malloc(sizeof *pp);
+ pp->callback = callback;
+ pp->cb = closure;
+ pp->column = 0;
+ pp->trailswhite = 0;
+ return pp;
+}
+@
+<<write tokens>>=
+{ char *p = contents;
+ char *q;
+
+ while (*p && isspace(*p)) p++;
+ while (*p) {
+ for (q = p; *q && !isspace(*q); q++);
+ { char c = *q;
+ *q = 0;
+ addtoken(pp, p);
+ *q = c;
+ }
+ p = q;
+ while (*p && isspace(*p)) p++;
+ }
+}
+@
+
+
diff --git a/web/noweb/src/c/finduses.c b/web/noweb/src/c/finduses.c
new file mode 100644
index 0000000000..096f18f211
--- /dev/null
+++ b/web/noweb/src/c/finduses.c
@@ -0,0 +1,137 @@
+#line 5 "finduses.nw"
+static char rcsid[] = "$Id: finduses.nw,v 1.22 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+static struct keepalive { char *s; struct keepalive *p; } keepalive[] =
+ { {rcsid, keepalive}, {rcsname, keepalive} }; /* avoid warnings */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "errors.h"
+#include "match.h"
+#include "getline.h"
+#include "recognize.h"
+#line 23 "finduses.nw"
+static Recognizer nwindex;
+#define ALPHANUM "_'@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#"
+#define SYMBOLS "!%^&*-+:=|~<>./?`"
+/* note $ and \ both delimiters */
+#line 31 "finduses.nw"
+static int showquotes = 1;
+#line 97 "finduses.nw"
+typedef struct line_and_outfile {
+ char *line;
+ FILE *out;
+} LineOut;
+#line 66 "finduses.nw"
+static void read_ids(FILE *in);
+#line 102 "finduses.nw"
+static void add_use_markers(FILE *in, FILE *out);
+#line 154 "finduses.nw"
+static void write_index_use(void *closure, char *id, char *instance);
+static char *emit_up_to(FILE *f, char *s, char *limit);
+#line 35 "finduses.nw"
+int main(int argc, char **argv) {
+ FILE *fp;
+ int i;
+
+ progname = argv[0];
+ for (i = 1; i < argc && argv[i][0] == '-' && argv[i][1] != 0; i++)
+ if (!strcmp(argv[i], "-noquote"))
+ showquotes = 0;
+ else
+ errormsg(Error, "%s: unknown option %s\n", progname, argv[i]);
+ nwindex = new_recognizer(ALPHANUM, SYMBOLS);
+ if (i == argc) {
+
+#line 77 "finduses.nw"
+{ FILE *tmp = tmpfile();
+ char *line;
+ if (tmp == NULL)
+#line 157 "finduses.nw"
+errormsg(Fatal, "%s: couldn't open temporary file\n", progname);
+#line 80 "finduses.nw"
+ while ((line = getline_nw(stdin)) != NULL) {
+ if (fputs(line, tmp) == EOF)
+#line 159 "finduses.nw"
+errormsg(Fatal, "%s: error writing temporary file\n", progname);
+#line 82 "finduses.nw"
+ if (is_index(line, "defn")) {
+ if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0;
+ add_ident(nwindex, line+1+5+1+4+1);
+ } else if (is_index(line, "localdefn")) {
+ if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0;
+ add_ident(nwindex, line+1+5+1+9+1);
+ } else if (is_keyword(line, "fatal")) {
+ exit(1);
+ }
+ }
+ rewind(tmp);
+ stop_adding(nwindex);
+ add_use_markers(tmp, stdout);
+}
+#line 48 "finduses.nw"
+ } else {
+
+#line 58 "finduses.nw"
+for (; i < argc; i++)
+ if ((fp=fopen(argv[i],"r"))==NULL)
+ errormsg(Error, "%s: couldn't open file %s\n", progname, argv[i]);
+ else {
+ read_ids(fp);
+ fclose(fp);
+ }
+#line 50 "finduses.nw"
+ stop_adding(nwindex);
+ add_use_markers(stdin, stdout);
+ }
+ nowebexit(NULL);
+ return errorlevel; /* slay warning */
+}
+#line 68 "finduses.nw"
+static void read_ids(FILE *in) {
+ char *line;
+ while ((line = getline_nw(in)) != NULL) {
+ if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0;
+ add_ident(nwindex, line);
+ }
+}
+#line 104 "finduses.nw"
+static void add_use_markers(FILE *in, FILE *out) {
+ char *line;
+ int incode = 0;
+ LineOut info; info.line = (char *)0; info.out = out;
+
+ while ((line = getline_nw(in)) != NULL) {
+ if (is_begin(line, "code") || (showquotes && is_keyword(line, "quote")))
+ incode = 1;
+ else if (is_end(line, "code") || is_keyword(line, "endquote"))
+ incode = 0;
+ if (is_keyword(line, "text") && incode) {
+ info.line = line + 6; /* skip "@text " */
+ search_for_ident(nwindex, line, write_index_use, &info);
+ if (*info.line && *info.line != '\n')
+ fprintf(out, "@text %s", info.line); /* has newline */
+ } else
+ fprintf(out, "%s", line);
+ }
+}
+#line 135 "finduses.nw"
+static void write_index_use(void *closure, char *id, char *instance) {
+ LineOut *info = (LineOut *) closure;
+ info->line = emit_up_to(info->out, info->line, instance);
+ fprintf(info->out, "@index use %s\n", id);
+ info->line = emit_up_to(info->out, info->line, instance + strlen(id));
+}
+#line 142 "finduses.nw"
+static char *emit_up_to(FILE *f, char *s, char *limit) {
+ if (s < limit) {
+ char saved = *limit;
+ *limit = 0;
+ fprintf(f, "@text %s\n", s);
+ *limit = saved;
+ return limit;
+ } else {
+ return s;
+ }
+}
diff --git a/web/noweb/src/c/finduses.nw b/web/noweb/src/c/finduses.nw
new file mode 100644
index 0000000000..ba070a6501
--- /dev/null
+++ b/web/noweb/src/c/finduses.nw
@@ -0,0 +1,159 @@
+% -*- mode: Noweb; noweb-code-mode: c-mode; c-indent-level: 4 -*-
+\section{Scanning for uses of identifiers}
+\subsection{Main program}
+<<*>>=
+static char rcsid[] = "$Id: finduses.nw,v 1.22 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+static struct keepalive { char *s; struct keepalive *p; } keepalive[] =
+ { {rcsid, keepalive}, {rcsname, keepalive} }; /* avoid warnings */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "errors.h"
+#include "match.h"
+#include "getline.h"
+#include "recognize.h"
+@
+These choices of alphanumerics and symbols seem to work for most languages.
+Making [[@]] alphanumeric helps {\LaTeX}, and making [[#]]
+alphanumeric helps avoid false hits on C preprocessor directives like
+[[#define]] and [[#include]].
+<<*>>=
+static Recognizer nwindex;
+#define ALPHANUM "_'@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#"
+#define SYMBOLS "!%^&*-+:=|~<>./?`"
+/* note $ and \ both delimiters */
+@
+
+By default, find uses within quoted code ([[[[...]]]]).
+<<*>>=
+static int showquotes = 1;
+<<typedefs>>
+<<local prototypes>>
+<<*>>=
+int main(int argc, char **argv) {
+ FILE *fp;
+ int i;
+
+ progname = argv[0];
+ for (i = 1; i < argc && argv[i][0] == '-' && argv[i][1] != 0; i++)
+ if (!strcmp(argv[i], "-noquote"))
+ showquotes = 0;
+ else
+ errormsg(Error, "%s: unknown option %s\n", progname, argv[i]);
+ nwindex = new_recognizer(ALPHANUM, SYMBOLS);
+ if (i == argc) {
+ <<add uses to stdin, grabbing defns from stdin>>
+ } else {
+ <<read identifiers to be defined from files named in [[argv]]>>
+ stop_adding(nwindex);
+ add_use_markers(stdin, stdout);
+ }
+ nowebexit(NULL);
+ return errorlevel; /* slay warning */
+}
+@
+<<read identifiers to be defined from files named in [[argv]]>>=
+for (; i < argc; i++)
+ if ((fp=fopen(argv[i],"r"))==NULL)
+ errormsg(Error, "%s: couldn't open file %s\n", progname, argv[i]);
+ else {
+ read_ids(fp);
+ fclose(fp);
+ }
+<<local prototypes>>=
+static void read_ids(FILE *in);
+<<*>>=
+static void read_ids(FILE *in) {
+ char *line;
+ while ((line = getline_nw(in)) != NULL) {
+ if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0;
+ add_ident(nwindex, line);
+ }
+}
+@
+<<add uses to stdin, grabbing defns from stdin>>=
+{ FILE *tmp = tmpfile();
+ char *line;
+ if (tmp == NULL) <<complain about opening temp file and exit>>
+ while ((line = getline_nw(stdin)) != NULL) {
+ if (fputs(line, tmp) == EOF) <<complain about writing temp file and exit>>
+ if (is_index(line, "defn")) {
+ if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0;
+ add_ident(nwindex, line+1+5+1+4+1);
+ } else if (is_index(line, "localdefn")) {
+ if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0;
+ add_ident(nwindex, line+1+5+1+9+1);
+ } else if (is_keyword(line, "fatal")) {
+ exit(1);
+ }
+ }
+ rewind(tmp);
+ stop_adding(nwindex);
+ add_use_markers(tmp, stdout);
+}
+<<typedefs>>=
+typedef struct line_and_outfile {
+ char *line;
+ FILE *out;
+} LineOut;
+<<local prototypes>>=
+static void add_use_markers(FILE *in, FILE *out);
+<<*>>=
+static void add_use_markers(FILE *in, FILE *out) {
+ char *line;
+ int incode = 0;
+ LineOut info; info.line = (char *)0; info.out = out;
+
+ while ((line = getline_nw(in)) != NULL) {
+ if (is_begin(line, "code") || (showquotes && is_keyword(line, "quote")))
+ incode = 1;
+ else if (is_end(line, "code") || is_keyword(line, "endquote"))
+ incode = 0;
+ if (is_keyword(line, "text") && incode) {
+ info.line = line + 6; /* skip "@text " */
+ search_for_ident(nwindex, line, write_index_use, &info);
+ if (*info.line && *info.line != '\n')
+ fprintf(out, "@text %s", info.line); /* has newline */
+ } else
+ fprintf(out, "%s", line);
+ }
+}
+@
+
+We gradually cut out the uses, and the tail of the line is left in [[info.line]],
+to be printed by the code above.
+There's a tricky bug lurking here---if one identifier is a prefix of another,
+but both are recognized (as with the C$++$ [[::]] separator), we have to avoid
+writing them both out in full, because that would duplicate text unnecessarily.
+As a result, we always emit the line in pieces.
+The function [[emit_up_to(f, s, limit)]] emits the piece of the string [[s]] up to
+but not including [[limit]], if any.
+It returns [[limit]] or [[s]], whichever is greater.
+<<*>>=
+static void write_index_use(void *closure, char *id, char *instance) {
+ LineOut *info = (LineOut *) closure;
+ info->line = emit_up_to(info->out, info->line, instance);
+ fprintf(info->out, "@index use %s\n", id);
+ info->line = emit_up_to(info->out, info->line, instance + strlen(id));
+}
+<<*>>=
+static char *emit_up_to(FILE *f, char *s, char *limit) {
+ if (s < limit) {
+ char saved = *limit;
+ *limit = 0;
+ fprintf(f, "@text %s\n", s);
+ *limit = saved;
+ return limit;
+ } else {
+ return s;
+ }
+}
+<<local prototypes>>=
+static void write_index_use(void *closure, char *id, char *instance);
+static char *emit_up_to(FILE *f, char *s, char *limit);
+<<complain about opening temp file and exit>>=
+errormsg(Fatal, "%s: couldn't open temporary file\n", progname);
+<<complain about writing temp file and exit>>=
+errormsg(Fatal, "%s: error writing temporary file\n", progname);
diff --git a/web/noweb/src/c/getline.c b/web/noweb/src/c/getline.c
new file mode 100644
index 0000000000..5d14367c9e
--- /dev/null
+++ b/web/noweb/src/c/getline.c
@@ -0,0 +1,69 @@
+#line 17 "getline.nw"
+static char rcsid[] = "$Id: getline.nw,v 2.24 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#define START_SIZE 128 /* initial buffer size */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "columns.h"
+#include "errors.h"
+#include "getline.h"
+
+static char *buf1 = NULL, *buf2 = NULL; /* lines without, with tabs expanded */
+static int buf_size = START_SIZE; /* size of both buffers if non-NULL */
+
+#line 44 "getline.nw"
+void new_buffers(void) {
+ checkptr(buf1 = (char *) realloc(buf1, buf_size));
+ checkptr(buf2 = (char *) realloc(buf2, buf_size));
+}
+#line 49 "getline.nw"
+char *getline_nw (FILE *fp) {
+
+
+#line 86 "getline.nw"
+if (buf1==NULL) {
+ checkptr(buf1 = (char *) malloc (buf_size));
+ checkptr(buf2 = (char *) malloc (buf_size));
+}
+#line 52 "getline.nw"
+
+ buf1=fgets(buf1, buf_size, fp);
+ if (buf1==NULL) return buf1; /* end of file */
+ while (buf1[strlen(buf1)-1] != '\n') { /* failed to get whole line */
+ buf_size *= 2;
+ new_buffers();
+ if (fgets(buf1+strlen(buf1),buf_size-strlen(buf1),fp)==NULL)
+ return buf1; /* end of file */
+ }
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return buf1;
+}
+#line 66 "getline.nw"
+char *getline_expand (FILE *fp) {
+ char *s, *t;
+ int width;
+
+ if (getline_nw(fp)==NULL) return NULL;
+
+#line 91 "getline.nw"
+if (columnwidth(buf1) > buf_size - 1) {
+ while (columnwidth(buf1) > buf_size - 1) buf_size *= 2;
+ new_buffers();
+}
+#line 72 "getline.nw"
+ s = buf1; t = buf2; width=0;
+ while (*s)
+ if (*s=='\t' && tabsize > 0) {
+ do {
+ *t++ = ' '; width++;
+ } while (width % tabsize != 0);
+ s++;
+ } else {
+ *t++ = *s++; width++;
+ }
+ *t='\0';
+ return buf2;
+}
diff --git a/web/noweb/src/c/getline.h b/web/noweb/src/c/getline.h
new file mode 100644
index 0000000000..e560dfaf49
--- /dev/null
+++ b/web/noweb/src/c/getline.h
@@ -0,0 +1,6 @@
+char *getline_expand (FILE *fp);
+ /* grab a line in buffer, return new buffer or NULL for eof
+ tabs in line are expanded according to tabsize */
+char *getline_nw (FILE *fp);
+ /* grab a line in the buffer, return a new buffer or NULL for eof
+ no expansion of tabs */
diff --git a/web/noweb/src/c/getline.nw b/web/noweb/src/c/getline.nw
new file mode 100644
index 0000000000..9ba4c6160d
--- /dev/null
+++ b/web/noweb/src/c/getline.nw
@@ -0,0 +1,94 @@
+% Copyright 1991 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+@
+\section{Utility functions}
+
+\subsection{Line-oriented input}
+[[getline_nw]] is reads in the next line, no matter
+how long it is, expanding tabs.
+I allocate more and more space for the line, until I've
+read a whole line or until I run out of space, whichever comes first.
+The buffer grows in size exponentially, so the cost in overhead is roughly the logarithm
+of the length of the longest line.
+@
+[[getline_nw]] reuses the same internal buffers over and over, so subsequent
+calls destroy the results of previous calls.
+<<*>>=
+static char rcsid[] = "$Id: getline.nw,v 2.24 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#define START_SIZE 128 /* initial buffer size */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "columns.h"
+#include "errors.h"
+#include "getline.h"
+
+static char *buf1 = NULL, *buf2 = NULL; /* lines without, with tabs expanded */
+static int buf_size = START_SIZE; /* size of both buffers if non-NULL */
+
+<<C functions>>
+@
+<<header>>=
+char *getline_expand (FILE *fp);
+ /* grab a line in buffer, return new buffer or NULL for eof
+ tabs in line are expanded according to tabsize */
+char *getline_nw (FILE *fp);
+ /* grab a line in the buffer, return a new buffer or NULL for eof
+ no expansion of tabs */
+@ N.B. In 2008, [[getline]] became part of a POSIX standard,
+so Noweb's version (which is 20 years old) is now [[getline_nw]].
+@
+<<C functions>>=
+void new_buffers(void) {
+ checkptr(buf1 = (char *) realloc(buf1, buf_size));
+ checkptr(buf2 = (char *) realloc(buf2, buf_size));
+}
+<<C functions>>=
+char *getline_nw (FILE *fp) {
+
+ <<if [[buf1==NULL]], allocate initial buffers>>
+
+ buf1=fgets(buf1, buf_size, fp);
+ if (buf1==NULL) return buf1; /* end of file */
+ while (buf1[strlen(buf1)-1] != '\n') { /* failed to get whole line */
+ buf_size *= 2;
+ new_buffers();
+ if (fgets(buf1+strlen(buf1),buf_size-strlen(buf1),fp)==NULL)
+ return buf1; /* end of file */
+ }
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return buf1;
+}
+<<C functions>>=
+char *getline_expand (FILE *fp) {
+ char *s, *t;
+ int width;
+
+ if (getline_nw(fp)==NULL) return NULL;
+ <<if [[columnwidth(buf1) > buf_size - 1]], allocate new buffers>>
+ s = buf1; t = buf2; width=0;
+ while (*s)
+ if (*s=='\t' && tabsize > 0) {
+ do {
+ *t++ = ' '; width++;
+ } while (width % tabsize != 0);
+ s++;
+ } else {
+ *t++ = *s++; width++;
+ }
+ *t='\0';
+ return buf2;
+}
+<<if [[buf1==NULL]], allocate initial buffers>>=
+if (buf1==NULL) {
+ checkptr(buf1 = (char *) malloc (buf_size));
+ checkptr(buf2 = (char *) malloc (buf_size));
+}
+<<if [[columnwidth(buf1) > buf_size - 1]], allocate new buffers>>=
+if (columnwidth(buf1) > buf_size - 1) {
+ while (columnwidth(buf1) > buf_size - 1) buf_size *= 2;
+ new_buffers();
+}
diff --git a/web/noweb/src/c/main.c b/web/noweb/src/c/main.c
new file mode 100644
index 0000000000..f120c207fe
--- /dev/null
+++ b/web/noweb/src/c/main.c
@@ -0,0 +1,75 @@
+#line 7 "main.nw"
+static char rcsid[] = "$Id: main.nw,v 2.25 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "notangle.h"
+#include "errors.h"
+#include "columns.h"
+#include "modules.h"
+#include "modtrees.h"
+
+#line 25 "main.nw"
+int main(int argc, char **argv) {
+ int i;
+ char *locformat = "";
+ char *Clocformat = "#line %L \"%F\"%N";
+ int root_options_seen = 0;
+
+ tabsize = 0; /* default for nt is not to use tabs */
+ progname = argv[0];
+ finalstage = 1;
+
+ for (i=1; i<argc; i++) {
+
+#line 55 "main.nw"
+if (*argv[i]=='-') {
+
+#line 71 "main.nw"
+ switch (argv[i][1]) {
+ case 't': /* set tab size or turn off */
+ if (isdigit(argv[i][2]))
+ tabsize = atoi(argv[i]+2);
+ else if (argv[i][2]==0)
+ tabsize = 0; /* no tabs */
+ else
+ errormsg(Error, "%s: ill-formed option %s\n", argv[0], argv[i]);
+ break;
+ case 'R': /* change name of root module */
+ root_options_seen++;
+ break;
+ case 'L': /* have a #line number format */
+ locformat = argv[i]+2;
+ if (!*locformat) locformat = Clocformat;
+ break;
+ default:
+ errormsg(Warning, "Ignoring unknown option -%s", argv[i]);
+ }
+#line 57 "main.nw"
+} else {
+
+#line 92 "main.nw"
+errormsg(Warning,
+ "I can't handle arguments yet, so I'll just ignore `%s'",argv[i]);
+
+#line 59 "main.nw"
+}
+#line 37 "main.nw"
+ }
+
+ read_defs(stdin); /* read all the definitions */
+ apply_each_module(remove_final_newline); /* pretty up the module texts */
+ if (root_options_seen == 0)
+ emit_module_named(stdout, "*", locformat);
+ else
+ for (i=1; i<argc; i++)
+ if (argv[i][0] == '-' && argv[i][1] == 'R')
+ emit_module_named(stdout, argv[i]+2, locformat);
+
+ nowebexit(NULL);
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return errorlevel; /* slay warning */
+}
diff --git a/web/noweb/src/c/main.nw b/web/noweb/src/c/main.nw
new file mode 100644
index 0000000000..bebe9092eb
--- /dev/null
+++ b/web/noweb/src/c/main.nw
@@ -0,0 +1,94 @@
+% -*- mode: Noweb; noweb-code-mode: c-mode -*-
+% Copyright 1991 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+\section{Tangling}
+\subsection{Main program}
+<<*>>=
+static char rcsid[] = "$Id: main.nw,v 2.25 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "notangle.h"
+#include "errors.h"
+#include "columns.h"
+#include "modules.h"
+#include "modtrees.h"
+
+@
+The main program makes one pass through the arguments, using options
+to set global state, and counting any roots it sees.
+It then makes a second pass to emit all the roots, or if there are no
+roots on the command line, it emits the module (chunk) named [[<<*>>]].
+<<*>>=
+int main(int argc, char **argv) {
+ int i;
+ char *locformat = "";
+ char *Clocformat = "#line %L \"%F\"%N";
+ int root_options_seen = 0;
+
+ tabsize = 0; /* default for nt is not to use tabs */
+ progname = argv[0];
+ finalstage = 1;
+
+ for (i=1; i<argc; i++) {
+ <<process argument [[i]]---first pass>>
+ }
+
+ read_defs(stdin); /* read all the definitions */
+ apply_each_module(remove_final_newline); /* pretty up the module texts */
+ if (root_options_seen == 0)
+ emit_module_named(stdout, "*", locformat);
+ else
+ for (i=1; i<argc; i++)
+ if (argv[i][0] == '-' && argv[i][1] == 'R')
+ emit_module_named(stdout, argv[i]+2, locformat);
+
+ nowebexit(NULL);
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return errorlevel; /* slay warning */
+}
+@
+<<process argument [[i]]---first pass>>=
+if (*argv[i]=='-') {
+ <<handle option in argument [[i]]>>
+} else {
+ <<handle argument in argument [[i]]>>
+}
+@
+The following options are good on the command line:
+\begin{fields}
+-Rname& make name the name of the root module.
+ Default is [[@<<*@>>]].\\
+-L[format]& Use the given format to write {\tt\#line} numbers.
+ If -L is given alone, use ANSI C format.
+ If not given, write no {\tt\#line} numbers.\\
+-t[tabsize]& Fiddle with tabs
+\end{fields}
+<<handle option in argument [[i]]>>=
+ switch (argv[i][1]) {
+ case 't': /* set tab size or turn off */
+ if (isdigit(argv[i][2]))
+ tabsize = atoi(argv[i]+2);
+ else if (argv[i][2]==0)
+ tabsize = 0; /* no tabs */
+ else
+ errormsg(Error, "%s: ill-formed option %s\n", argv[0], argv[i]);
+ break;
+ case 'R': /* change name of root module */
+ root_options_seen++;
+ break;
+ case 'L': /* have a #line number format */
+ locformat = argv[i]+2;
+ if (!*locformat) locformat = Clocformat;
+ break;
+ default:
+ errormsg(Warning, "Ignoring unknown option -%s", argv[i]);
+ }
+@
+<<handle argument in argument [[i]]>>=
+errormsg(Warning,
+ "I can't handle arguments yet, so I'll just ignore `%s'",argv[i]);
+
diff --git a/web/noweb/src/c/markmain.c b/web/noweb/src/c/markmain.c
new file mode 100644
index 0000000000..5e63bba06e
--- /dev/null
+++ b/web/noweb/src/c/markmain.c
@@ -0,0 +1,406 @@
+#line 66 "markmain.nw"
+static char rcsid[] = "$Id: markmain.nw,v 2.29 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include "errors.h"
+#include "markup.h"
+#include "getline.h"
+#include "columns.h"
+
+#line 35 "markmain.nw"
+typedef enum state {Code=1, Docs=2, CodeIndex=3} State;
+typedef enum mark {Begin=1, End=2} Mark;
+typedef enum index {Defn=1, Use=2, Newline=3} Index;
+
+static char *states[] = { "bad state", "code", "docs", "code" };
+static char *marks[] = { "bad mark", "begin", "end" };
+static char *indices[] = { "bad index", "defn", "use", "nl" };
+static char low_at_sign = '@';
+
+static void print_state(FILE *out, Mark be, State state, int count) {
+ fprintf(out, "%c%s %s %d\n", low_at_sign, marks[be], states[state], count);
+}
+
+static void print_index(FILE *out, Index idx, char *arg) {
+ if (arg)
+ fprintf(out, "%cindex %s %s\n", low_at_sign, indices[idx], arg);
+ else
+ fprintf(out, "%cindex %s\n", low_at_sign, indices[idx]);
+}
+
+static void print_pair(FILE *out, char *name, char *value) {
+ if (value) {
+ int last=strlen(value)-1;
+ if (last>=0 && value[last]=='\n')
+ fprintf(out, "%c%s %s%cnl\n", low_at_sign, name, value, low_at_sign);
+ else
+ fprintf(out, "%c%s %s\n", low_at_sign, name, value);
+ } else
+ fprintf(out, "%c%s\n", low_at_sign, name);
+}
+
+#line 80 "markmain.nw"
+void markup (FILE* in, FILE *out, char *filename) {
+ State state = Docs; /* what we are reading */
+ int quoting = 0; /* currently quoting code? */
+ int count = 0; /* number of current chunk, from 0 */
+ int missing_newline = 0; /* was last line missing a trailing \n? */
+ int lineno = 0; /* number of lines read */
+ int last_open_quote = -1; /* line number of last unmatched open quote */
+
+ char *line; /* part of line up to mark (or end) */
+#define MAX_MODNAME 255
+ char modname[MAX_MODNAME+1] = ""; /* name of module currently being read,
+ [[""]] if no module is being read */
+
+
+#line 120 "markmain.nw"
+print_pair(out, "file", filename);
+print_state(out, Begin, state, count);
+while ((line = getline_expand(in)) != NULL) {
+ lineno++;
+
+#line 171 "markmain.nw"
+missing_newline = line[strlen(line)-1] != '\n';
+#line 125 "markmain.nw"
+ if (starts_code(line, filename, lineno)) {
+
+#line 541 "markmain.nw"
+if (quoting) {
+ errorat(filename, last_open_quote, Warning, "open quote `[[' never closed");
+ quoting = 0;
+}
+#line 127 "markmain.nw"
+ print_state(out, End, state, count);
+ count++;
+ state = Code;
+ print_state(out, Begin, state, count);
+ getmodname(modname,MAX_MODNAME,line);
+ print_pair(out,"defn",modname);
+ print_pair(out,"nl",0); /* could be implicit but this is better */
+ } else if (is_def(line)) {
+
+#line 527 "markmain.nw"
+line = remove_def_marker(line);
+while (*line && isspace(*line)) line++;
+while (*line) {
+ char tmp;
+ char *s = line+1;
+ while (*s && !isspace(*s)) s++;
+ tmp = *s; *s = 0;
+ print_index(out, Defn, line);
+ *s = tmp;
+ while (isspace(*s)) s++;
+ line = s;
+}
+print_index(out, Newline, 0);
+#line 136 "markmain.nw"
+ if (state == Code)
+ state = CodeIndex;
+ } else {
+ if (starts_doc(line) || state == CodeIndex) {
+
+#line 541 "markmain.nw"
+if (quoting) {
+ errorat(filename, last_open_quote, Warning, "open quote `[[' never closed");
+ quoting = 0;
+}
+#line 141 "markmain.nw"
+ print_state(out, End, state, count);
+ count++;
+ state = Docs; /* always reading docs after a stop */
+ print_state(out, Begin, state, count);
+ if (starts_doc(line))
+ line = first_doc_line(line);
+ }
+ {
+#line 180 "markmain.nw"
+char *p, *s, *t, c;
+static char *buf;
+static int buflen = 0;
+#line 149 "markmain.nw"
+
+#line 258 "markmain.nw"
+#define LA1 '<'
+#define LA2 '<'
+#define RA1 '>'
+#define RA2 '>'
+#define LS1 '['
+#define LS2 '['
+#define RS1 ']'
+#define RS2 ']'
+#define ESC '@'
+#line 271 "markmain.nw"
+#define next(L) do { c = *t++; goto L; } while (0)
+#define copy(L) do { *s++ = c; c = *t++; goto L; } while (0)
+#line 277 "markmain.nw"
+#define lexassert(E) ((void)0)
+#line 150 "markmain.nw"
+
+#line 504 "markmain.nw"
+if (buf == NULL)
+ checkptr(buf = (char *) malloc(buflen = 128));
+if (buflen < strlen(line) + 1 + 2) {
+ while (buflen < strlen(line) + 1 + 2)
+ buflen *= 2;
+ checkptr(buf = (char *) realloc(buf, buflen));
+}
+#line 185 "markmain.nw"
+p = s = buf+2;
+t = line;
+c = *t++;
+#line 151 "markmain.nw"
+
+#line 205 "markmain.nw"
+if (c == ESC && *t == ESC) { *s++ = ESC; c = *++t; ++t; }
+#line 152 "markmain.nw"
+ if (state == Code || quoting)
+ goto convert_code;
+ else
+ goto convert_docs;
+
+#line 295 "markmain.nw"
+convert_docs:
+t: lexassert(state == Docs && !quoting);
+ if (c == ESC) next(at);
+ if (c == LA1) next(la);
+ if (c == LS1) next(ls);
+
+#line 241 "markmain.nw"
+if (c == '\0') {
+
+#line 512 "markmain.nw"
+if (s > p) {
+ *s = 0;
+ print_pair(out, "text", p);
+}
+s = p = buf + 2;
+#line 243 "markmain.nw"
+ goto done_converting;
+}
+#line 301 "markmain.nw"
+ copy(t);
+#line 309 "markmain.nw"
+at: if (c == LA1) next(atla);
+ if (c == LS1) next(atls);
+ if (c == RA1) next(atra);
+ if (c == RS1) next(atrs);
+ *s++ = ESC; goto t;
+#line 318 "markmain.nw"
+atls: if (c == LS2) { *s++ = LS1; *s++ = LS2; next(t); }
+ *s++ = ESC; *s++ = LS1; goto t;
+#line 324 "markmain.nw"
+atla: if (c == LA2) { *s++ = LA1; *s++ = LA2; next(t); }
+ *s++ = ESC; *s++ = LA1; goto t;
+#line 330 "markmain.nw"
+atrs: if (c == RS2) { *s++ = RS1; *s++ = RS2; next(t); }
+ *s++ = ESC; *s++ = RS1; goto t;
+#line 336 "markmain.nw"
+atra: if (c == RA2) { *s++ = RA1; *s++ = RA2; next(t); }
+ *s++ = ESC; *s++ = RA1; goto t;
+#line 342 "markmain.nw"
+la: if (c == LA2) {
+
+#line 524 "markmain.nw"
+errorat(filename, lineno, Error, "unescaped << in documentation chunk");
+#line 344 "markmain.nw"
+ *s++ = LA1; *s++ = LA2; next(t);
+ }
+ *s++ = LA1; goto t;
+#line 354 "markmain.nw"
+ls: lexassert(state == Docs);
+ if (c == LS2) {
+
+#line 512 "markmain.nw"
+if (s > p) {
+ *s = 0;
+ print_pair(out, "text", p);
+}
+s = p = buf + 2;
+#line 357 "markmain.nw"
+ quoting = 1; last_open_quote = lineno; print_pair(out, "quote", 0);
+ next(c);
+ }
+ *s++ = LS1;
+ goto t;
+#line 371 "markmain.nw"
+convert_code:
+c: lexassert(state == Code || quoting);
+ if (c == RS1 && quoting) next(crs);
+ if (c == LA1) next(cla);
+ if (c == ESC) next(cat);
+
+#line 241 "markmain.nw"
+if (c == '\0') {
+
+#line 512 "markmain.nw"
+if (s > p) {
+ *s = 0;
+ print_pair(out, "text", p);
+}
+s = p = buf + 2;
+#line 243 "markmain.nw"
+ goto done_converting;
+}
+#line 377 "markmain.nw"
+ copy(c);
+#line 385 "markmain.nw"
+cat: if (c == LA1) next(catla);
+ if (c == RA1) next(catra);
+ *s++ = ESC; goto c;
+#line 392 "markmain.nw"
+catla: if (c == LA2) { *s++ = LA1; *s++ = LA2; next(c); }
+ *s++ = ESC; *s++ = LA1; goto c;
+#line 398 "markmain.nw"
+catra: if (c == RA2) { *s++ = RA1; *s++ = RA2; next(c); }
+ *s++ = ESC; *s++ = RA1; goto c;
+#line 406 "markmain.nw"
+crs: if (c == RS2) next(ce);
+ *s++ = RS1; goto c;
+#line 412 "markmain.nw"
+ce: lexassert(quoting);
+ if (c == RS2) copy(ce);
+ quoting = 0;
+#line 512 "markmain.nw"
+if (s > p) {
+ *s = 0;
+ print_pair(out, "text", p);
+}
+s = p = buf + 2;
+#line 414 "markmain.nw"
+ print_pair(out, "endquote", 0);
+ goto t;
+#line 422 "markmain.nw"
+cla: if (c == LA2) {
+#line 512 "markmain.nw"
+if (s > p) {
+ *s = 0;
+ print_pair(out, "text", p);
+}
+s = p = buf + 2;
+#line 422 "markmain.nw"
+ next(u); }
+ *s++ = LA1; goto c;
+#line 433 "markmain.nw"
+u: lexassert(state == Code || quoting);
+ if (c == LS1) copy(uls);
+ if (c == RS1 && quoting) next(urs);
+ if (c == RA1) next(ura);
+ if (c == '\0') { /* premature end --- it's not a use after all */
+
+#line 499 "markmain.nw"
+lexassert(p == buf + 2);
+p -= 2;
+p[0] = LA1;
+p[1] = LA2;
+#line 439 "markmain.nw"
+ goto c;
+ }
+ copy(u);
+#line 446 "markmain.nw"
+urs: lexassert(quoting);
+ if (c == RS2) { /* premature end --- it's not a use after all */
+
+#line 499 "markmain.nw"
+lexassert(p == buf + 2);
+p -= 2;
+p[0] = LA1;
+p[1] = LA2;
+#line 449 "markmain.nw"
+ next(ce);
+ }
+ *s++ = RS1; goto u;
+#line 456 "markmain.nw"
+uls: if (c == LS2) copy(uc);
+ goto u;
+#line 463 "markmain.nw"
+uc: lexassert(quoting || state == Code);
+ if (c == RS1) copy(ucrs);
+ if (c == '\0') {
+
+#line 499 "markmain.nw"
+lexassert(p == buf + 2);
+p -= 2;
+p[0] = LA1;
+p[1] = LA2;
+#line 467 "markmain.nw"
+ goto c;
+ }
+ copy(uc);
+#line 474 "markmain.nw"
+ucrs: if (c == RS2) copy(uce);
+ goto uc;
+#line 480 "markmain.nw"
+uce: if (c == RS2) copy(uce);
+ goto u;
+#line 486 "markmain.nw"
+ura: if (c == RA2) {
+#line 519 "markmain.nw"
+*s = 0;
+print_pair(out, "use", p);
+s = p = buf + 2;
+#line 486 "markmain.nw"
+ next(c); }
+ *s++ = RA1; goto u;
+#line 157 "markmain.nw"
+ done_converting:
+ (void)0;
+ }
+ }
+}
+#line 541 "markmain.nw"
+if (quoting) {
+ errorat(filename, last_open_quote, Warning, "open quote `[[' never closed");
+ quoting = 0;
+}
+#line 173 "markmain.nw"
+if (missing_newline) print_pair(out, "nl",0);
+#line 164 "markmain.nw"
+print_state(out, End, state, count);
+#line 94 "markmain.nw"
+}
+#line 550 "markmain.nw"
+int main(int argc, char **argv) {
+ FILE *fp;
+ int i;
+
+ progname = argv[0];
+ for (i = 1; i < argc && argv[i][0] == '-' && argv[i][1] != 0; i++)
+ switch(argv[i][1]) {
+ case 't':
+#line 583 "markmain.nw"
+if (isdigit(argv[i][2]))
+ tabsize = atoi(argv[i]+2);
+else if (argv[i][2]==0)
+ tabsize = 0; /* no tabs */
+else
+ errormsg(Error, "%s: ill-formed option %s", progname, argv[i]);
+#line 557 "markmain.nw"
+ break;
+ default : errormsg(Error, "%s: unknown option -%c", progname, argv[i][1]);
+ break;
+ }
+ if (i < argc)
+ for (; i < argc; i++) {
+ if (!strcmp(argv[i], "-")) {
+ markup(stdin,stdout,"");
+ } else
+ if ((fp=fopen(argv[i],"r"))==NULL) {
+ errormsg(Error, "%s: couldn't open file %s", progname, argv[i]);
+ fprintf(stdout, "@fatal couldn't open file %s\n", argv[i]);
+ } else {
+ markup(fp,stdout,argv[i]);
+ fclose(fp);
+ }
+ }
+ else
+ markup(stdin,stdout,"");
+ nowebexit(NULL);
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return errorlevel; /* slay warning */
+}
diff --git a/web/noweb/src/c/markmain.nw b/web/noweb/src/c/markmain.nw
new file mode 100644
index 0000000000..1542eff182
--- /dev/null
+++ b/web/noweb/src/c/markmain.nw
@@ -0,0 +1,588 @@
+% -*- mode: Noweb; noweb-code-mode: c-mode -*-
+% Copyright 1991 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+\section{Converting a {\tt noweb} file to tool markup}
+\subsection{Main program}
+This is the initial filter in the pipeline.
+Syntax from {\tt markup.ow}.
+Output may contain [[
+ @[begin|end] [code|docs] nnn ...
+ @text <line of text>
+ @quote
+ @endquote
+ @defn <module name>
+ @use <module name>
+ @nl
+ @file <filename>
+ @line nnn
+ @index [defn|use] <indexed string>
+ @index nl
+ @literal <literal text for weave or other tool>
+]]
+Here's the code that writes the output.
+We have one function to print the state, which takes care of
+[[@begin]] and [[@end]] and remembering what kind of chunk we have.
+Another function prints [[@name value]] pairs.
+If the [[value]] has a trailing newline, the pair is followed by [[@nl]].
+
+If the only way index entries were created was by tools, life would be easy.
+Permitting index definitions in the input causes two complications.
+First, it introduces newlines that don't belong to any chunk, but that must be counted.
+Second, it introduces a special state, [[CodeIndex]]
+in which a code chunk is about to be terminated
+but won't be until there are no more index definitions.
+<<state and printing definitions>>=
+typedef enum state {Code=1, Docs=2, CodeIndex=3} State;
+typedef enum mark {Begin=1, End=2} Mark;
+typedef enum index {Defn=1, Use=2, Newline=3} Index;
+
+static char *states[] = { "bad state", "code", "docs", "code" };
+static char *marks[] = { "bad mark", "begin", "end" };
+static char *indices[] = { "bad index", "defn", "use", "nl" };
+static char low_at_sign = '@';
+
+static void print_state(FILE *out, Mark be, State state, int count) {
+ fprintf(out, "%c%s %s %d\n", low_at_sign, marks[be], states[state], count);
+}
+
+static void print_index(FILE *out, Index idx, char *arg) {
+ if (arg)
+ fprintf(out, "%cindex %s %s\n", low_at_sign, indices[idx], arg);
+ else
+ fprintf(out, "%cindex %s\n", low_at_sign, indices[idx]);
+}
+
+static void print_pair(FILE *out, char *name, char *value) {
+ if (value) {
+ int last=strlen(value)-1;
+ if (last>=0 && value[last]=='\n')
+ fprintf(out, "%c%s %s%cnl\n", low_at_sign, name, value, low_at_sign);
+ else
+ fprintf(out, "%c%s %s\n", low_at_sign, name, value);
+ } else
+ fprintf(out, "%c%s\n", low_at_sign, name);
+}
+<<*>>=
+static char rcsid[] = "$Id: markmain.nw,v 2.29 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include "errors.h"
+#include "markup.h"
+#include "getline.h"
+#include "columns.h"
+
+<<state and printing definitions>>
+
+void markup (FILE* in, FILE *out, char *filename) {
+ State state = Docs; /* what we are reading */
+ int quoting = 0; /* currently quoting code? */
+ int count = 0; /* number of current chunk, from 0 */
+ int missing_newline = 0; /* was last line missing a trailing \n? */
+ int lineno = 0; /* number of lines read */
+ int last_open_quote = -1; /* line number of last unmatched open quote */
+
+ char *line; /* part of line up to mark (or end) */
+#define MAX_MODNAME 255
+ char modname[MAX_MODNAME+1] = ""; /* name of module currently being read,
+ [[""]] if no module is being read */
+
+ <<copy all lines from [[in]] to [[out]], adding markup>>
+}
+@
+A {\em noweb } file consists of a sequence of
+{\em chunks,} which may appear in any order.
+{\em noweb} supports two kinds of chunks: documentation chunks and code chunks.
+Documentation chunks begin with an at sign (@) at the beginning of a line,
+followed by a space
+(or with an at sign on a line by itself).
+They have no names.
+Code chunks begin with
+$$\hbox{\tt@<<{\em chunk name\/}@>>=}$$
+on a line by itself.
+The left double angle bracket ({\tt @<<}) must be in the first column.
+Chunks are terminated by the beginning of another chunk, or by end of file.
+If the first line in the file does not signal the beginning of a documentation
+or code chunk, the first chunk is assumed to be a documentation chunk.
+
+We implement this by just looping through the document, looking for the
+beginnings of chunks.
+We use [[state]] to keep track of what's ending.
+We add a little extra markup for file name and module names
+Starting code and starting documentation are notably different:
+code is started by a module definition, which must appear on a line by itself.
+Documentation is started by a character sequence,
+and arbitrary documentation text can follow on the same line.
+<<copy all lines from [[in]] to [[out]], adding markup>>=
+print_pair(out, "file", filename);
+print_state(out, Begin, state, count);
+while ((line = getline_expand(in)) != NULL) {
+ lineno++;
+ <<remember if a newline was missing from the last line>>
+ if (starts_code(line, filename, lineno)) {
+ <<complain and correct unmatched open quote, if any>>
+ print_state(out, End, state, count);
+ count++;
+ state = Code;
+ print_state(out, Begin, state, count);
+ getmodname(modname,MAX_MODNAME,line);
+ print_pair(out,"defn",modname);
+ print_pair(out,"nl",0); /* could be implicit but this is better */
+ } else if (is_def(line)) {
+ <<emit index definitions and index newline>>
+ if (state == Code)
+ state = CodeIndex;
+ } else {
+ if (starts_doc(line) || state == CodeIndex) {
+ <<complain and correct unmatched open quote, if any>>
+ print_state(out, End, state, count);
+ count++;
+ state = Docs; /* always reading docs after a stop */
+ print_state(out, Begin, state, count);
+ if (starts_doc(line))
+ line = first_doc_line(line);
+ }
+ { <<declarations for conversion engine>>
+ <<macro definitions for conversion engine>>
+ <<initialize conversion engine>>
+ <<if the line begins with two [[ESC]]s, append one>>
+ if (state == Code || quoting)
+ goto convert_code;
+ else
+ goto convert_docs;
+ <<conversion state machine>>
+ done_converting:
+ (void)0;
+ }
+ }
+}
+<<complain and correct unmatched open quote, if any>>
+<<add a trailing newline if one was missing>>
+print_state(out, End, state, count);
+@
+We make it safe to assume henceforth that every chunk ends with newline,
+even if the file didn't end with newline.
+If the file didn't end with newline, we add a newline to the last line
+before printing the final [[@end]].
+<<remember if a newline was missing from the last line>>=
+missing_newline = line[strlen(line)-1] != '\n';
+<<add a trailing newline if one was missing>>=
+if (missing_newline) print_pair(out, "nl",0);
+@
+The conversion engine copies the input [[line]] to the output [[buf]],
+using the pointers [[s]] on the left for the destination and [[t]] on the
+right for the source. [[c]] holds the current input character, and [[p]]
+points to the current piece of text about to be emitted.
+<<declarations for conversion engine>>=
+char *p, *s, *t, c;
+static char *buf;
+static int buflen = 0;
+<<initialize conversion engine>>=
+<<make [[buf]] big enough to hold all of [[line]], plus two more characters>>
+p = s = buf+2;
+t = line;
+c = *t++;
+@
+Using [[@@]] in the first column to escape an at sign was added after
+the state machine was designed, in response to a plea from Dirk
+Verworner:
+\begin{quote}
+We at the Humboldt-University of Berlin use your
+{\tt noweb} programs for our project.
+We've a simple description language, which sometimes an at sign
+on a line by itself requires.
+So I've a problem.
+\end{quote}
+It might be that I ought to add a special beginning-of-line state to
+the state machine, so that we could recognize with there, but I'd have
+to replicate it for both code and documentation.
+Because I only pay the cost once per input line, I don't mind using
+the following Band-Aid:
+<<if the line begins with two [[ESC]]s, append one>>=
+if (c == ESC && *t == ESC) { *s++ = ESC; c = *++t; ++t; }
+@
+To convert documentation lines, we have to track the quoting brackets.
+Within quoting brackets, we use the same engine as for within code lines
+(except for our treatment of square brackets).
+We have the state machine from hell. We can have ordinary text, quoted text in
+[[[[...]]]], or a use in [[[[<<...>>]]]].
+Ordinary text and quoted text can span lines, but uses can't.
+So, the four main states of our lexer are:
+\begin{quote}
+\begin{tabular}{ll}
+\tt t&Ordinary text\\
+\tt c&Code text\\
+\tt u&A use\\
+\tt uc&Quoted code within a use\\
+\end{tabular}
+\end{quote}
+That last state covers the case where we have [[[[<<...[[...]]...>>]]]].
+BTW, it's no coincidence that if we've just consumed a newline (i.e., we're at the
+start of a line), we must be in one of those four states.
+Moreover, since a newline in states [[u]] and [[uc]] means it's not really a use%
+\footnote{Because uses may not span lines.},
+those states fall back to state [[c]] (while prepending the opening [[<<]] that
+appeared to signal a use).
+So [[c]] and [[t]] are the major states. When scanning documentation,
+they correspond to [[quoting]] and [[!quoting]].
+@
+% l2h substitution chi X
+By the way, one reason for writing a state machine by hand instead of using a
+lexer generator is so I can test the machine using the wonderful $\chi$ATAC tool
+developed by Bob Horgan, Saul London, and Hira Agrawal. For more information
+send email to {\tt jrh@bellcore.com}.
+@
+We don't have to treat a newline specially, because [[print_pair]] inserts
+[[@nl]] if needed.
+<<emit text and goto [[done_converting]] if at end of line>>=
+if (c == '\0') {
+ <<emit [[p]] to [[s]] as text>>
+ goto done_converting;
+}
+@
+Markup is defined as follows:
+\begin{quote}
+\begin{tabular}{ll}
+\tt LA1 LA2&open a chunk\\
+\tt RA1 RA2&close a chunk\\
+\tt LS1 LS2&open a quote\\
+\tt RS1 RS2&close a quote\\
+\tt ESC&quotes the sequences above\\
+\end{tabular}
+\end{quote}
+By default we use angles for chunks and squares for quotes, at sign for escape:
+<<macro definitions for conversion engine>>=
+#define LA1 '<'
+#define LA2 '<'
+#define RA1 '>'
+#define RA2 '>'
+#define LS1 '['
+#define LS2 '['
+#define RS1 ']'
+#define RS2 ']'
+#define ESC '@'
+@
+Usually when we change state we advance the input pointer.
+Sometimes we also copy the current character.
+<<macro definitions for conversion engine>>=
+#define next(L) do { c = *t++; goto L; } while (0)
+#define copy(L) do { *s++ = c; c = *t++; goto L; } while (0)
+@
+Normally we don't check assertions in the lexer.
+To check them, we would [[#define lexassert assert]].
+<<macro definitions for conversion engine>>=
+#define lexassert(E) ((void)0)
+@
+From here on I intercalate the code that implements the state machine with the
+dot code that draws a picture of it.
+The picture can be found in file {\tt markup.ps}; it's too big to be useful as
+part of this document.
+The arcs in the picture are labelled with {\it char}/{\it output}, but the
+output may be omitted.
+In the code, we see
+[[goto]] when the picture has a [[-]] sign (denoting character not
+consumed), [[next]] when we're emitting some literal, and [[copy]] when
+we emit [[c]] (the next character).
+<<dot arcs>>=
+t -> at [label="@"]
+t -> la [label="<"]
+t -> ls [label="["]
+t -> t [label="c/c"]
+<<conversion state machine>>=
+convert_docs:
+t: lexassert(state == Docs && !quoting);
+ if (c == ESC) next(at);
+ if (c == LA1) next(la);
+ if (c == LS1) next(ls);
+ <<emit text and goto [[done_converting]] if at end of line>>
+ copy(t);
+<<dot arcs>>=
+at -> atls [label="["]
+at -> atla [label="<"]
+at -> atrs [label="]"]
+at -> atra [label=">"]
+at -> t [label="c-/@"]
+<<conversion state machine>>=
+at: if (c == LA1) next(atla);
+ if (c == LS1) next(atls);
+ if (c == RA1) next(atra);
+ if (c == RS1) next(atrs);
+ *s++ = ESC; goto t;
+<<dot arcs>>=
+atls -> t [label="[/[["]
+atls -> t [label="c-/@["]
+<<conversion state machine>>=
+atls: if (c == LS2) { *s++ = LS1; *s++ = LS2; next(t); }
+ *s++ = ESC; *s++ = LS1; goto t;
+<<dot arcs>>=
+atla -> t [label="</<<"]
+atla -> t [label="c-/@<"]
+<<conversion state machine>>=
+atla: if (c == LA2) { *s++ = LA1; *s++ = LA2; next(t); }
+ *s++ = ESC; *s++ = LA1; goto t;
+<<dot arcs>>=
+atrs -> t [label="]/]]"]
+atrs -> t [label="c-/@]"]
+<<conversion state machine>>=
+atrs: if (c == RS2) { *s++ = RS1; *s++ = RS2; next(t); }
+ *s++ = ESC; *s++ = RS1; goto t;
+<<dot arcs>>=
+atra -> t [label=">/>>"]
+atra -> t [label="c-/@>"]
+<<conversion state machine>>=
+atra: if (c == RA2) { *s++ = RA1; *s++ = RA2; next(t); }
+ *s++ = ESC; *s++ = RA1; goto t;
+<<dot arcs>>=
+la -> t [label="</<< (error)"]
+la -> t [label="c-/<"]
+<<conversion state machine>>=
+la: if (c == LA2) {
+ <<complain of unescaped @<< in documentation>>
+ *s++ = LA1; *s++ = LA2; next(t);
+ }
+ *s++ = LA1; goto t;
+@
+When we've seen [[[[]], we don't yet know whether it's the start of
+a quote or the start of a use---but we can emit the text so far.
+<<dot arcs>>=
+ls -> c [label="[ (emit text; quote)"]
+ls -> t [label="c-/["]
+<<conversion state machine>>=
+ls: lexassert(state == Docs);
+ if (c == LS2) {
+ <<emit [[p]] to [[s]] as text>>
+ quoting = 1; last_open_quote = lineno; print_pair(out, "quote", 0);
+ next(c);
+ }
+ *s++ = LS1;
+ goto t;
+@
+Here's the ordinary quote state.
+<<dot arcs>>=
+/*{ rank=same cat catla catra }*/
+c -> crs [label="] (docs only)"]
+c -> cla [label="<"]
+c -> cat [label="@"]
+c -> c [label="c/c"]
+<<conversion state machine>>=
+convert_code:
+c: lexassert(state == Code || quoting);
+ if (c == RS1 && quoting) next(crs);
+ if (c == LA1) next(cla);
+ if (c == ESC) next(cat);
+ <<emit text and goto [[done_converting]] if at end of line>>
+ copy(c);
+@
+In code, quoting square brackets is neither necessary nor permitted.
+<<dot arcs>>=
+cat -> catla [label="<"]
+cat -> catra [label=">"]
+cat -> c [label="c-/@"]
+<<conversion state machine>>=
+cat: if (c == LA1) next(catla);
+ if (c == RA1) next(catra);
+ *s++ = ESC; goto c;
+<<dot arcs>>=
+catla -> c [label="</<<"]
+catla -> c [label="c-/@<"]
+<<conversion state machine>>=
+catla: if (c == LA2) { *s++ = LA1; *s++ = LA2; next(c); }
+ *s++ = ESC; *s++ = LA1; goto c;
+<<dot arcs>>=
+catra -> c [label=">/>>"]
+catra -> c [label="c-/@>"]
+<<conversion state machine>>=
+catra: if (c == RA2) { *s++ = RA1; *s++ = RA2; next(c); }
+ *s++ = ESC; *s++ = RA1; goto c;
+@
+We can't end the quote until we've consumed all the closing [[]]]'s.
+<<dot arcs>>=
+crs -> ce [label="]"]
+crs -> c [label="c-/]"]
+<<conversion state machine>>=
+crs: if (c == RS2) next(ce);
+ *s++ = RS1; goto c;
+<<dot arcs>>=
+ce -> ce [label="]/]"]
+ce -> t [label="c- (emit text; endquote)"]
+<<conversion state machine>>=
+ce: lexassert(quoting);
+ if (c == RS2) copy(ce);
+ quoting = 0; <<emit [[p]] to [[s]] as text>> print_pair(out, "endquote", 0);
+ goto t;
+@
+Now's here where we might be seeing a use.
+<<dot arcs>>=
+cla -> u [label="< (emit text)"]
+cla -> c [label="c-/<"]
+<<conversion state machine>>=
+cla: if (c == LA2) { <<emit [[p]] to [[s]] as text>> next(u); }
+ *s++ = LA1; goto c;
+@
+When processing a use, we make sure [[[[...]]]] hide any closing angle brackets.
+<<dot arcs>>=
+u -> uls [label="[/["]
+u -> urs [label="] (docs only)"]
+u -> ura [label=">"]
+u -> c [label="eol- (prepend <<)"]
+u -> u [label="c/c"]
+<<conversion state machine>>=
+u: lexassert(state == Code || quoting);
+ if (c == LS1) copy(uls);
+ if (c == RS1 && quoting) next(urs);
+ if (c == RA1) next(ura);
+ if (c == '\0') { /* premature end --- it's not a use after all */
+ <<prepend opening angles to [[p]]>>
+ goto c;
+ }
+ copy(u);
+<<dot arcs>>=
+urs -> ce [label="] (not use; prepend <<)"]
+urs -> u [label="c-/]"]
+<<conversion state machine>>=
+urs: lexassert(quoting);
+ if (c == RS2) { /* premature end --- it's not a use after all */
+ <<prepend opening angles to [[p]]>>
+ next(ce);
+ }
+ *s++ = RS1; goto u;
+<<dot arcs>>=
+uls -> uc [label="[/["]
+uls -> u [label="c-"]
+<<conversion state machine>>=
+uls: if (c == LS2) copy(uc);
+ goto u;
+<<dot arcs>>=
+uc -> ucrs [label="]/]"]
+uc -> c [label="eol- (prepend <<)"]
+uc -> uc [label="c/c"]
+<<conversion state machine>>=
+uc: lexassert(quoting || state == Code);
+ if (c == RS1) copy(ucrs);
+ if (c == '\0') {
+ <<prepend opening angles to [[p]]>>
+ goto c;
+ }
+ copy(uc);
+<<dot arcs>>=
+ucrs -> uce [label="]/]"]
+ucrs -> uc [label="c-"]
+<<conversion state machine>>=
+ucrs: if (c == RS2) copy(uce);
+ goto uc;
+<<dot arcs>>=
+uce -> uce [label="]/]"]
+uce -> u [label="c-"]
+<<conversion state machine>>=
+uce: if (c == RS2) copy(uce);
+ goto u;
+<<dot arcs>>=
+ura -> c [label="> (emit use)"]
+ura -> u [label="c-/>"]
+<<conversion state machine>>=
+ura: if (c == RA2) { <<emit [[p]] to [[s]] as use>> next(c); }
+ *s++ = RA1; goto u;
+<<markup.dot>>=
+digraph lexer {
+ rotate=90
+ size="10,7.5"
+ ratio=fill
+ rankdir=LR
+ node [shape=circle]
+ <<dot arcs>>
+}
+@
+<<prepend opening angles to [[p]]>>=
+lexassert(p == buf + 2);
+p -= 2;
+p[0] = LA1;
+p[1] = LA2;
+<<make [[buf]] big enough to hold all of [[line]], plus two more characters>>=
+if (buf == NULL)
+ checkptr(buf = (char *) malloc(buflen = 128));
+if (buflen < strlen(line) + 1 + 2) {
+ while (buflen < strlen(line) + 1 + 2)
+ buflen *= 2;
+ checkptr(buf = (char *) realloc(buf, buflen));
+}
+<<emit [[p]] to [[s]] as text>>=
+if (s > p) {
+ *s = 0;
+ print_pair(out, "text", p);
+}
+s = p = buf + 2;
+@ emit the empty use regardless
+<<emit [[p]] to [[s]] as use>>=
+*s = 0;
+print_pair(out, "use", p);
+s = p = buf + 2;
+@
+<<complain of unescaped @<< in documentation>>=
+errorat(filename, lineno, Error, "unescaped @<< in documentation chunk");
+@
+<<emit index definitions and index newline>>=
+line = remove_def_marker(line);
+while (*line && isspace(*line)) line++;
+while (*line) {
+ char tmp;
+ char *s = line+1;
+ while (*s && !isspace(*s)) s++;
+ tmp = *s; *s = 0;
+ print_index(out, Defn, line);
+ *s = tmp;
+ while (isspace(*s)) s++;
+ line = s;
+}
+print_index(out, Newline, 0);
+<<complain and correct unmatched open quote, if any>>=
+if (quoting) {
+ errorat(filename, last_open_quote, Warning, "open quote `[[' never closed");
+ quoting = 0;
+}
+@
+Finally, we give the main program, which opens each file and passes it
+to [[markup]].
+Like many main programs, it's based on K \& R [[cat]].
+<<*>>=
+int main(int argc, char **argv) {
+ FILE *fp;
+ int i;
+
+ progname = argv[0];
+ for (i = 1; i < argc && argv[i][0] == '-' && argv[i][1] != 0; i++)
+ switch(argv[i][1]) {
+ case 't': <<handle [[-t]]>> break;
+ default : errormsg(Error, "%s: unknown option -%c", progname, argv[i][1]);
+ break;
+ }
+ if (i < argc)
+ for (; i < argc; i++) {
+ if (!strcmp(argv[i], "-")) {
+ markup(stdin,stdout,"");
+ } else
+ if ((fp=fopen(argv[i],"r"))==NULL) {
+ errormsg(Error, "%s: couldn't open file %s", progname, argv[i]);
+ fprintf(stdout, "@fatal couldn't open file %s\n", argv[i]);
+ } else {
+ markup(fp,stdout,argv[i]);
+ fclose(fp);
+ }
+ }
+ else
+ markup(stdin,stdout,"");
+ nowebexit(NULL);
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return errorlevel; /* slay warning */
+}
+@
+<<handle [[-t]]>>=
+if (isdigit(argv[i][2]))
+ tabsize = atoi(argv[i]+2);
+else if (argv[i][2]==0)
+ tabsize = 0; /* no tabs */
+else
+ errormsg(Error, "%s: ill-formed option %s", progname, argv[i]);
diff --git a/web/noweb/src/c/markup.c b/web/noweb/src/c/markup.c
new file mode 100644
index 0000000000..b982febd87
--- /dev/null
+++ b/web/noweb/src/c/markup.c
@@ -0,0 +1,123 @@
+#line 24 "markup.nw"
+static char rcsid[] = "$Id: markup.nw,v 2.24 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+static struct keepalive { char *s; struct keepalive *p; } keepalive[] =
+ { {rcsid, keepalive}, {rcsname, keepalive} }; /* avoid warnings */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include "markup.h"
+#include "strsave.h"
+#include "errors.h"
+
+#line 64 "markup.nw"
+char at_sign = '@'; /* should be the only place '@' is mentioned */
+#line 88 "markup.nw"
+static char def_marker[] = " %def ";
+#define def_length (6)
+
+#line 74 "markup.nw"
+int starts_doc(char *line) {
+ return (*line==at_sign && (line[1]=='\0' || isspace(line[1])));
+}
+
+char *first_doc_line(char *line) {
+ if (line[1]!='\0' && line[1] !='\n') return line+2;
+ else return line+1;
+}
+#line 91 "markup.nw"
+int is_def(char *line) {
+ int answer;
+ static int complained;
+
+#line 104 "markup.nw"
+{ static int checked = 0;
+ if (!checked) {
+ assert(strlen(def_marker) == def_length);
+ checked = 1;
+ }
+}
+#line 95 "markup.nw"
+ answer = (*line==at_sign && !strncmp(line+1, def_marker, def_length));
+
+#line 114 "markup.nw"
+if (answer && !complained) {
+ complained = 1;
+/*
+ fprintf(stderr, "Warning: @ %%def is deprecated. Use `-filter autodefs.xxx'\n"
+ " or `-filter btdefn'\n");
+*/
+}
+#line 97 "markup.nw"
+ return answer;
+}
+
+char *remove_def_marker(char *line) {
+ return line+1+def_length;
+}
+#line 144 "markup.nw"
+char *mod_start(char *s, int mark) {
+ return find_escaped(s,"<<","@<<", mark);
+}
+char *mod_end(char *s, int mark) {
+ return find_escaped(s,">>","@>>", mark);
+}
+#line 163 "markup.nw"
+int starts_code (char *line, char *filename, int lineno) {
+ char *tail;
+ if (mod_start(line,0) != line+2) return 0;
+ tail = mod_end(line+2,0);
+ if (tail == NULL || *tail++ != '=') return 0;
+ while (isspace(*tail)) tail++;
+ return (*tail == '\0');
+}
+
+void getmodname(char *dest, int size, char *source) {
+ /* excess characters in the module name are ignored */
+ char *p = strsave(source);
+ char *q = mod_start(p,1);
+
+ if (q==NULL)
+#line 184 "markup.nw"
+{
+ free(p);
+ impossible
+ ("I couldn't manage to extract a module name, but I'm sure I saw one");
+}
+#line 178 "markup.nw"
+ if (mod_end(q,1)==NULL)
+#line 184 "markup.nw"
+{
+ free(p);
+ impossible
+ ("I couldn't manage to extract a module name, but I'm sure I saw one");
+}
+#line 179 "markup.nw"
+ strncpy(dest,q,size-1);
+ dest[size-1] = '\0';
+ free(p);
+}
+#line 207 "markup.nw"
+char *find_escaped(register char *s, char *search, char *escape, int mark) {
+ register char first = *search;
+ register char first_escape = (escape != NULL ? *escape : '\0');
+ int searchlen = strlen(search);
+ int escapelen = (escape != NULL ? strlen(escape) : 0);
+
+ do {
+ while (*s && *s != first && *s != first_escape) s++;
+ if (!*s) break;
+ if (first_escape && !strncmp(s,escape,escapelen)) {
+ s += escapelen;
+ continue;
+ }
+ if (!strncmp(s,search,searchlen)) break;
+ s++;
+ } while (*s != '\0');
+ /* here either s is empty or it points to the first unescaped [[search]] */
+ if (*s == '\0') return NULL;
+ if (mark) *s = '\0';
+ return s+searchlen;
+}
diff --git a/web/noweb/src/c/markup.h b/web/noweb/src/c/markup.h
new file mode 100644
index 0000000000..e47229eef7
--- /dev/null
+++ b/web/noweb/src/c/markup.h
@@ -0,0 +1,13 @@
+extern char at_sign; /* the at sign */
+int starts_doc(char *);
+char *first_doc_line(char *);
+int is_def(char *);
+char *remove_def_marker(char *);
+char *mod_start (char *s, int mark); /* find the first module name */
+char *mod_end (char *s, int mark); /* find the end of module name */
+int starts_code (char *line, char *filename, int lineno);
+ /* does this line start module defn? */
+void getmodname(char *dest, int size, char *source);
+ /* extract module name and put in dest */
+char *find_escaped(register char *s, char *search, char *escape, int mark);
+ /* find escaped strings. See markup.nw for details */
diff --git a/web/noweb/src/c/markup.nw b/web/noweb/src/c/markup.nw
new file mode 100644
index 0000000000..bce1840830
--- /dev/null
+++ b/web/noweb/src/c/markup.nw
@@ -0,0 +1,227 @@
+% Copyright 1991 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+\subsection{Identifying the special {\tt noweb} control sequences}
+This file is supposed to contain all the definitions of how different
+things are distinguished in the source text.
+@
+Documentation is introduced only by an at sign (@) on a line by itself
+(optionally followed by spaces).
+It continues up to new documentation or a module definition.
+A module definition is a module name, followed by one equals sign (=),
+possibly followed by white space, on a line by itself.
+A module name is any test enclosed in double angle brackets ([[@<<...@>>]]).
+The ``unnamed'' module is called * (that is, [[@<<*@>>]]).
+
+Double angle brackets may be escaped in source by preceding them with
+the at sign.
+No other character, not even the at sign, needs to be escaped.
+This makes for more readable source, but makes it impossible to put an
+at sign immediately before a module name.
+If we liked we could try to hack this by creating a predefined module that
+expands to an at sign, but I won't bother.
+
+<<*>>=
+static char rcsid[] = "$Id: markup.nw,v 2.24 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+static struct keepalive { char *s; struct keepalive *p; } keepalive[] =
+ { {rcsid, keepalive}, {rcsname, keepalive} }; /* avoid warnings */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include "markup.h"
+#include "strsave.h"
+#include "errors.h"
+
+<<data definitions>>
+
+<<C functions>>
+@
+To quote from the man page:
+\begin{quote}
+A
+{\em noweb }
+file consists of a sequence of
+{\em chunks,}
+which may appear in any order.
+{\em noweb}
+supports two kinds of chunks: documentation chunks and code chunks.
+Documentation chunks begin with an at sign (@) at the beginning of a line,
+followed by a space
+(or with an at sign on a line by itself).
+They have no names.
+Code chunks begin with
+$$\hbox{\tt@<<{\em chunk name\/}@>>=}$$
+on a line by itself.
+The left double angle bracket ({\tt @<<}) must be in the first column.
+Chunks are terminated by the beginning of another chunk, or by end of file.
+If the first line in the file does not signal the beginning of a documentation
+or code chunk, the first chunk is assumed to be a documentation chunk.
+\end{quote}
+@
+<<data definitions>>=
+char at_sign = '@'; /* should be the only place '@' is mentioned */
+<<header>>=
+extern char at_sign; /* the at sign */
+@
+Here's how we recognize the start of a documentation chunk, and
+extract the first line of documentation from what follows the @ sign.
+<<header>>=
+int starts_doc(char *);
+char *first_doc_line(char *);
+<<C functions>>=
+int starts_doc(char *line) {
+ return (*line==at_sign && (line[1]=='\0' || isspace(line[1])));
+}
+
+char *first_doc_line(char *line) {
+ if (line[1]!='\0' && line[1] !='\n') return line+2;
+ else return line+1;
+}
+@
+An index line is a special case of starting documentation.
+<<header>>=
+int is_def(char *);
+char *remove_def_marker(char *);
+<<data definitions>>=
+static char def_marker[] = " %def ";
+#define def_length (6)
+<<C functions>>=
+int is_def(char *line) {
+ int answer;
+ static int complained;
+ <<first time through, assert we got the length right>>
+ answer = (*line==at_sign && !strncmp(line+1, def_marker, def_length));
+ <<if [[answer && !complained]], complain>>
+ return answer;
+}
+
+char *remove_def_marker(char *line) {
+ return line+1+def_length;
+}
+<<first time through, assert we got the length right>>=
+{ static int checked = 0;
+ if (!checked) {
+ assert(strlen(def_marker) == def_length);
+ checked = 1;
+ }
+}
+@
+Explicit deprecation is just too painful. I think the users won't
+stand for it.
+<<if [[answer && !complained]], complain>>=
+if (answer && !complained) {
+ complained = 1;
+/*
+ fprintf(stderr, "Warning: @ %%def is deprecated. Use `-filter autodefs.xxx'\n"
+ " or `-filter btdefn'\n");
+*/
+}
+@
+Recognizing module names (which introduce code chunks)
+and extracting them is the mission of the [[mod_start]] and [[mod_end]]
+functions.
+
+The basic idea is to find an instance of [[@<<]], while skipping every
+instance of [[@@<<]].
+That's the start of a module name.
+We find the end the same way.
+A function called [[find_escaped]] does the dirty work.
+If it succeeds, it returns a pointer to the first character after
+the special sequence, in this case the first character of the
+module name.
+(If it fails, it returns a null pointer.)
+If its [[mark]] paramter is set, it will put a [['\0']] in place
+of the special sequence, splitting the string into pieces.
+These two properties make it perfect for dissecting lines with module names.
+
+[[mod_start]] and [[mod_end]] just store the special sequences.
+<<header>>=
+char *mod_start (char *s, int mark); /* find the first module name */
+char *mod_end (char *s, int mark); /* find the end of module name */
+<<C functions>>=
+char *mod_start(char *s, int mark) {
+ return find_escaped(s,"@<<","@@<<", mark);
+}
+char *mod_end(char *s, int mark) {
+ return find_escaped(s,"@>>","@@>>", mark);
+}
+@
+Once we know how to [[mod_start]] and [[mod_end]], recognizing the
+beginning of a code chunk is easy. The only tricky bit is that if we
+see an unclosed, unescaped [[<<]] in a code chunk, this should be acceptable.
+Because in a documentation chunk, an unclosed, unescaped [[<<]] will
+already be caught with a ``module name doesn't end'' message, the
+right thing to do here is silently to let an unclosed [[<<]] pass.
+<<header>>=
+int starts_code (char *line, char *filename, int lineno);
+ /* does this line start module defn? */
+void getmodname(char *dest, int size, char *source);
+ /* extract module name and put in dest */
+<<C functions>>=
+int starts_code (char *line, char *filename, int lineno) {
+ char *tail;
+ if (mod_start(line,0) != line+2) return 0;
+ tail = mod_end(line+2,0);
+ if (tail == NULL || *tail++ != '=') return 0;
+ while (isspace(*tail)) tail++;
+ return (*tail == '\0');
+}
+
+void getmodname(char *dest, int size, char *source) {
+ /* excess characters in the module name are ignored */
+ char *p = strsave(source);
+ char *q = mod_start(p,1);
+
+ if (q==NULL) <<Error exit from getmodname>>
+ if (mod_end(q,1)==NULL) <<Error exit from getmodname>>
+ strncpy(dest,q,size-1);
+ dest[size-1] = '\0';
+ free(p);
+}
+<<Error exit from getmodname>>=
+{
+ free(p);
+ impossible
+ ("I couldn't manage to extract a module name, but I'm sure I saw one");
+}
+@
+Here we do the magic [[find_escaped]].
+Find an arbitrary character seqence, skipping an escaped sequence (if any),
+replacing the beginning with [['\0']] if [[mark]] is set.
+
+ If no [[search]] sequence in [[s]], returns [[NULL]].
+ Otherwise, returns a pointer to the first character after the
+ [[search]] sequence, and sets the first character to [['\0']], so
+ that [[s]] will point to the part of the string before the [[search]]
+ sequence. The [[escape]] sequence (if any) is always skipped,
+ even if the [[search]] sequence is a substring of it.
+
+[[escape]] will be ignored if it is either the [[NULL]] pointer
+or the null string ([[""]]).
+<<header>>=
+char *find_escaped(register char *s, char *search, char *escape, int mark);
+ /* find escaped strings. See markup.nw for details */
+<<C functions>>=
+char *find_escaped(register char *s, char *search, char *escape, int mark) {
+ register char first = *search;
+ register char first_escape = (escape != NULL ? *escape : '\0');
+ int searchlen = strlen(search);
+ int escapelen = (escape != NULL ? strlen(escape) : 0);
+
+ do {
+ while (*s && *s != first && *s != first_escape) s++;
+ if (!*s) break;
+ if (first_escape && !strncmp(s,escape,escapelen)) {
+ s += escapelen;
+ continue;
+ }
+ if (!strncmp(s,search,searchlen)) break;
+ s++;
+ } while (*s != '\0');
+ /* here either s is empty or it points to the first unescaped [[search]] */
+ if (*s == '\0') return NULL;
+ if (mark) *s = '\0';
+ return s+searchlen;
+}
diff --git a/web/noweb/src/c/markup.ps b/web/noweb/src/c/markup.ps
new file mode 100644
index 0000000000..ae0a4c7d58
--- /dev/null
+++ b/web/noweb/src/c/markup.ps
@@ -0,0 +1,1748 @@
+%!PS-Adobe-3.0
+%%Creator: graphviz version 2.26.3 (20100126.1600)
+%%Title: lexer
+%%Pages: (atend)
+%%BoundingBox: (atend)
+%%EndComments
+save
+%%BeginProlog
+/DotDict 200 dict def
+DotDict begin
+
+/setupLatin1 {
+mark
+/EncodingVector 256 array def
+ EncodingVector 0
+
+ISOLatin1Encoding 0 255 getinterval putinterval
+EncodingVector 45 /hyphen put
+
+% Set up ISO Latin 1 character encoding
+/starnetISO {
+ dup dup findfont dup length dict begin
+ { 1 index /FID ne { def }{ pop pop } ifelse
+ } forall
+ /Encoding EncodingVector def
+ currentdict end definefont
+} def
+/Times-Roman starnetISO def
+/Times-Italic starnetISO def
+/Times-Bold starnetISO def
+/Times-BoldItalic starnetISO def
+/Helvetica starnetISO def
+/Helvetica-Oblique starnetISO def
+/Helvetica-Bold starnetISO def
+/Helvetica-BoldOblique starnetISO def
+/Courier starnetISO def
+/Courier-Oblique starnetISO def
+/Courier-Bold starnetISO def
+/Courier-BoldOblique starnetISO def
+cleartomark
+} bind def
+
+%%BeginResource: procset graphviz 0 0
+/coord-font-family /Times-Roman def
+/default-font-family /Times-Roman def
+/coordfont coord-font-family findfont 8 scalefont def
+
+/InvScaleFactor 1.0 def
+/set_scale {
+ dup 1 exch div /InvScaleFactor exch def
+ scale
+} bind def
+
+% styles
+/solid { [] 0 setdash } bind def
+/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def
+/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def
+/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def
+/bold { 2 setlinewidth } bind def
+/filled { } bind def
+/unfilled { } bind def
+/rounded { } bind def
+/diagonals { } bind def
+
+% hooks for setting color
+/nodecolor { sethsbcolor } bind def
+/edgecolor { sethsbcolor } bind def
+/graphcolor { sethsbcolor } bind def
+/nopcolor {pop pop pop} bind def
+
+/beginpage { % i j npages
+ /npages exch def
+ /j exch def
+ /i exch def
+ /str 10 string def
+ npages 1 gt {
+ gsave
+ coordfont setfont
+ 0 0 moveto
+ (\() show i str cvs show (,) show j str cvs show (\)) show
+ grestore
+ } if
+} bind def
+
+/set_font {
+ findfont exch
+ scalefont setfont
+} def
+
+% draw text fitted to its expected width
+/alignedtext { % width text
+ /text exch def
+ /width exch def
+ gsave
+ width 0 gt {
+ [] 0 setdash
+ text stringwidth pop width exch sub text length div 0 text ashow
+ } if
+ grestore
+} def
+
+/boxprim { % xcorner ycorner xsize ysize
+ 4 2 roll
+ moveto
+ 2 copy
+ exch 0 rlineto
+ 0 exch rlineto
+ pop neg 0 rlineto
+ closepath
+} bind def
+
+/ellipse_path {
+ /ry exch def
+ /rx exch def
+ /y exch def
+ /x exch def
+ matrix currentmatrix
+ newpath
+ x y translate
+ rx ry scale
+ 0 0 1 0 360 arc
+ setmatrix
+} bind def
+
+/endpage { showpage } bind def
+/showpage { } def
+
+/layercolorseq
+ [ % layer color sequence - darkest to lightest
+ [0 0 0]
+ [.2 .8 .8]
+ [.4 .8 .8]
+ [.6 .8 .8]
+ [.8 .8 .8]
+ ]
+def
+
+/layerlen layercolorseq length def
+
+/setlayer {/maxlayer exch def /curlayer exch def
+ layercolorseq curlayer 1 sub layerlen mod get
+ aload pop sethsbcolor
+ /nodecolor {nopcolor} def
+ /edgecolor {nopcolor} def
+ /graphcolor {nopcolor} def
+} bind def
+
+/onlayer { curlayer ne {invis} if } def
+
+/onlayers {
+ /myupper exch def
+ /mylower exch def
+ curlayer mylower lt
+ curlayer myupper gt
+ or
+ {invis} if
+} def
+
+/curlayer 0 def
+
+%%EndResource
+%%EndProlog
+%%BeginSetup
+14 default-font-family set_font
+1 setmiterlimit
+% /arrowlength 10 def
+% /arrowwidth 5 def
+
+% make sure pdfmark is harmless for PS-interpreters other than Distiller
+/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse
+% make '<<' and '>>' safe on PS Level 1 devices
+/languagelevel where {pop languagelevel}{1} ifelse
+2 lt {
+ userdict (<<) cvn ([) cvn load put
+ userdict (>>) cvn ([) cvn load put
+} if
+
+%%EndSetup
+setupLatin1
+%%Page: 1 1
+%%PageBoundingBox: 36 36 576 682
+%%PageOrientation: Landscape
+0 0 1 beginpage
+gsave
+36 36 540 646 boxprim clip newpath
+0.393586 0.393586 set_scale 90 rotate 95.4667 -1459.47 translate
+% t
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+18 612 18 18 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+14.5 607.9 moveto 7 (t) alignedtext
+grestore
+% t->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 5.16 624.92 moveto
+-.69 636.13 3.59 648 18 648 curveto
+28.13 648 33.26 642.13 33.37 634.75 curveto
+stroke
+0 0 0 edgecolor
+newpath 36.72 633.73 moveto
+30.84 624.92 lineto
+29.95 635.48 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 36.72 633.73 moveto
+30.84 624.92 lineto
+29.95 635.48 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+8.5 652.4 moveto 19 (c/c) alignedtext
+grestore
+% at
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+186 463 21.04 21.54 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+178.5 458.9 moveto 15 (at) alignedtext
+grestore
+% t->at
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 19.99 593.94 moveto
+24.18 559.54 35.11 486.61 54 471 curveto
+81.9 447.94 125.49 450.25 154.87 455.42 curveto
+stroke
+0 0 0 edgecolor
+newpath 154.51 458.92 moveto
+165 457.42 lineto
+155.86 452.05 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 154.51 458.92 moveto
+165 457.42 lineto
+155.86 452.05 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+92.5 475.4 moveto 15 (@) alignedtext
+grestore
+% la
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+186 943 20.15 20.15 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+179.5 938.9 moveto 13 (la) alignedtext
+grestore
+% t->la
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 19.66 630.11 moveto
+23.87 673.16 35.9 780.31 54 811 curveto
+80.8 856.44 110.06 847.38 146 886 curveto
+154.79 895.45 163.2 906.92 170.03 917.1 curveto
+stroke
+0 0 0 edgecolor
+newpath 167.19 919.15 moveto
+175.58 925.62 lineto
+173.05 915.33 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 167.19 919.15 moveto
+175.58 925.62 lineto
+173.05 915.33 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+93.5 890.4 moveto 13 (<) alignedtext
+grestore
+% ls
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+186 1066 18.76 18.76 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+180.5 1061.9 moveto 11 (ls) alignedtext
+grestore
+% t->ls
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 18.69 630.23 moveto
+22.03 715.45 36.92 1071.17 54 1087 curveto
+82.87 1113.76 131.44 1095.83 160.93 1080.69 curveto
+stroke
+0 0 0 edgecolor
+newpath 162.63 1083.75 moveto
+169.78 1075.94 lineto
+159.31 1077.59 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 162.63 1083.75 moveto
+169.78 1075.94 lineto
+159.31 1077.59 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+97 1104.4 moveto 6 ([) alignedtext
+grestore
+% at->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 167.86 474.75 moveto
+161.07 479.04 153.25 483.85 146 488 curveto
+105.97 510.91 85.98 502.77 54 536 curveto
+40.88 549.64 31.82 568.94 26.07 584.69 curveto
+stroke
+0 0 0 edgecolor
+newpath 22.66 583.83 moveto
+22.76 594.42 lineto
+29.29 586.08 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 22.66 583.83 moveto
+22.76 594.42 lineto
+29.29 586.08 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+84.5 540.4 moveto 31 (c-/@) alignedtext
+grestore
+% atls
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+410 753 27.99 28.49 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+397.5 748.9 moveto 25 (atls) alignedtext
+grestore
+% at->atls
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 194.93 482.47 moveto
+202.4 498.01 213.77 520.08 226 538 curveto
+275.33 610.28 345.1 686.07 382.97 725.48 curveto
+stroke
+0 0 0 edgecolor
+newpath 380.64 728.11 moveto
+390.11 732.87 lineto
+385.68 723.25 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 380.64 728.11 moveto
+390.11 732.87 lineto
+385.68 723.25 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+290 702.4 moveto 6 ([) alignedtext
+grestore
+% atla
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+410 616 29.88 29.88 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+396.5 611.9 moveto 27 (atla) alignedtext
+grestore
+% at->atla
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 207.5 465 moveto
+243.07 469.35 314.73 482.56 360 521 curveto
+377.38 535.76 389.57 558.11 397.55 577.42 curveto
+stroke
+0 0 0 edgecolor
+newpath 394.36 578.85 moveto
+401.25 586.9 lineto
+400.88 576.31 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 394.36 578.85 moveto
+401.25 586.9 lineto
+400.88 576.31 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+286.5 525.4 moveto 13 (<) alignedtext
+grestore
+% atrs
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+410 361 30.07 30.57 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+396 356.9 moveto 28 (atrs) alignedtext
+grestore
+% at->atrs
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 205.49 454.13 moveto
+242.81 437.13 324.92 399.74 372.98 377.86 curveto
+stroke
+0 0 0 edgecolor
+newpath 374.46 381.03 moveto
+382.11 373.7 lineto
+371.56 374.66 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 374.46 381.03 moveto
+382.11 373.7 lineto
+371.56 374.66 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+290 447.4 moveto 6 (]) alignedtext
+grestore
+% atra
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+410 175 30.77 31.27 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+395.5 170.9 moveto 29 (atra) alignedtext
+grestore
+% at->atra
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 191.75 442.76 moveto
+198.17 422.15 209.82 389.77 226 365 curveto
+269.22 298.81 337.51 235.73 377.61 201.5 curveto
+stroke
+0 0 0 edgecolor
+newpath 380.11 203.98 moveto
+385.48 194.85 lineto
+375.59 198.63 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 380.11 203.98 moveto
+385.48 194.85 lineto
+375.59 198.63 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+286.5 369.4 moveto 13 (>) alignedtext
+grestore
+% la->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 167.07 950.59 moveto
+138.66 960.6 85.04 973.87 54 946 curveto
+31.41 925.71 21.75 717.39 18.93 640.4 curveto
+stroke
+0 0 0 edgecolor
+newpath 22.42 639.9 moveto
+18.57 630.03 lineto
+15.42 640.15 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 22.42 639.9 moveto
+18.57 630.03 lineto
+15.42 640.15 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+54.5 966.4 moveto 91 (</<< \(error\)) alignedtext
+grestore
+% la->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 167.97 934.02 moveto
+161.19 930.88 153.35 927.51 146 925 curveto
+106.21 911.42 82.02 934.34 54 903 curveto
+36.65 883.59 24.04 709.4 19.67 640.18 curveto
+stroke
+0 0 0 edgecolor
+newpath 23.16 639.77 moveto
+19.05 630.01 lineto
+16.17 640.21 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 23.16 639.77 moveto
+19.05 630.01 lineto
+16.17 640.21 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+85.5 929.4 moveto 29 (c-/<) alignedtext
+grestore
+% ls->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 167.72 1060.39 moveto
+138.15 1050.25 80.45 1025.84 54 983 curveto
+36.11 954.02 23.29 721.76 19.31 640.19 curveto
+stroke
+0 0 0 edgecolor
+newpath 22.8 639.97 moveto
+18.83 630.15 lineto
+15.81 640.31 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 22.8 639.97 moveto
+18.83 630.15 lineto
+15.81 640.31 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+89 1055.4 moveto 22 (c-/[) alignedtext
+grestore
+% c
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+410 925 18 18 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+406.5 920.9 moveto 7 (c) alignedtext
+grestore
+% ls->c
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 202.11 1055.86 moveto
+240.96 1031.4 340 969.06 385.93 940.15 curveto
+stroke
+0 0 0 edgecolor
+newpath 388.03 942.96 moveto
+394.63 934.67 lineto
+384.3 937.04 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 388.03 942.96 moveto
+394.63 934.67 lineto
+384.3 937.04 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+226.5 1043.4 moveto 133 ([ \(emit text; quote\)) alignedtext
+grestore
+% atls->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 381.47 754.8 moveto
+334.73 756.83 239.46 757.06 164 732 curveto
+113.21 715.14 92.78 719.88 54 683 curveto
+41.39 671.01 32.47 653.63 26.67 639.07 curveto
+stroke
+0 0 0 edgecolor
+newpath 29.89 637.7 moveto
+23.14 629.54 lineto
+23.33 640.13 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 29.89 637.7 moveto
+23.14 629.54 lineto
+23.33 640.13 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+167.5 747.4 moveto 37 (c-/@[) alignedtext
+grestore
+% atls->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 381.31 749.44 moveto
+318.21 740.62 164.24 713.5 54 648 curveto
+47.67 644.24 41.65 639.11 36.4 633.91 curveto
+stroke
+0 0 0 edgecolor
+newpath 38.73 631.27 moveto
+29.33 626.38 lineto
+33.62 636.06 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 38.73 631.27 moveto
+29.33 626.38 lineto
+33.62 636.06 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+175.5 715.4 moveto 21 ([/[[) alignedtext
+grestore
+% atla->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 379.88 615.69 moveto
+306.23 614.94 117.81 613.02 46.19 612.29 curveto
+stroke
+0 0 0 edgecolor
+newpath 46.16 608.79 moveto
+36.12 612.18 lineto
+46.08 615.79 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 46.16 608.79 moveto
+36.12 612.18 lineto
+46.08 615.79 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+165.5 617.4 moveto 41 (</<<) alignedtext
+grestore
+% atla->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 380.84 624.01 moveto
+374.05 625.6 366.81 627.06 360 628 curveto
+225.28 646.64 186.67 655.91 54 626 curveto
+50.73 625.26 47.36 624.28 44.06 623.17 curveto
+stroke
+0 0 0 edgecolor
+newpath 45.12 619.83 moveto
+34.52 619.62 lineto
+42.67 626.39 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 45.12 619.83 moveto
+34.52 619.62 lineto
+42.67 626.39 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+164.5 649.4 moveto 43 (c-/@<) alignedtext
+grestore
+% atrs->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 403.99 331.16 moveto
+397.5 307.59 384.6 276.2 360 261 curveto
+239.83 186.73 136.21 232.11 54 347 curveto
+27.23 384.41 20.33 522.69 18.58 583.26 curveto
+stroke
+0 0 0 edgecolor
+newpath 15.07 583.54 moveto
+18.31 593.63 lineto
+22.07 583.72 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 15.07 583.54 moveto
+18.31 593.63 lineto
+22.07 583.72 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+175.5 249.4 moveto 21 (]/]]) alignedtext
+grestore
+% atrs->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 379.57 357.91 moveto
+309.72 352.71 137.49 350.92 54 448 curveto
+36.69 468.13 25.79 542.64 20.94 583.95 curveto
+stroke
+0 0 0 edgecolor
+newpath 17.46 583.6 moveto
+19.81 593.93 lineto
+24.41 584.39 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 17.46 583.6 moveto
+19.81 593.93 lineto
+24.41 584.39 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+167.5 382.4 moveto 37 (c-/@]) alignedtext
+grestore
+% atra->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 378.84 170.32 moveto
+307.05 161.53 130.32 151.78 54 254 curveto
+34.41 280.23 22.76 503.58 19.19 583.61 curveto
+stroke
+0 0 0 edgecolor
+newpath 15.68 583.77 moveto
+18.74 593.92 lineto
+22.67 584.08 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 15.68 583.77 moveto
+18.74 593.92 lineto
+22.67 584.08 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+165.5 186.4 moveto 41 (>/>>) alignedtext
+grestore
+% atra->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 380.66 163.64 moveto
+310.44 138.59 132.7 88.21 54 186 curveto
+29.1 216.94 20.67 493.96 18.58 583.92 curveto
+stroke
+0 0 0 edgecolor
+newpath 15.08 583.86 moveto
+18.35 593.94 lineto
+22.08 584.02 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 15.08 583.86 moveto
+18.35 593.94 lineto
+22.08 584.02 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+164.5 135.4 moveto 43 (c-/@>) alignedtext
+grestore
+% c->c
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 396.29 936.8 moveto
+388.72 948.33 393.29 961 410 961 curveto
+422.14 961 427.87 954.31 427.2 946.23 curveto
+stroke
+0 0 0 edgecolor
+newpath 430.46 944.96 moveto
+423.71 936.8 lineto
+423.89 947.39 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 430.46 944.96 moveto
+423.71 936.8 lineto
+423.89 947.39 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+400.5 965.4 moveto 19 (c/c) alignedtext
+grestore
+% crs
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+647 472 25.02 25.02 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+637 467.9 moveto 20 (crs) alignedtext
+grestore
+% c->crs
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 415.11 907.71 moveto
+422.42 882.21 435.66 832.89 442 790 curveto
+446.82 757.4 437.37 517.95 460 494 curveto
+498.69 453.07 570 457.27 612.5 464.39 curveto
+stroke
+0 0 0 edgecolor
+newpath 611.93 467.84 moveto
+622.4 466.19 lineto
+613.18 460.96 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 611.93 467.84 moveto
+622.4 466.19 lineto
+613.18 460.96 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+460.5 498.4 moveto 85 (] \(docs only\)) alignedtext
+grestore
+% cla
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+647 1256 23.82 24.32 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+637.5 1251.9 moveto 19 (cla) alignedtext
+grestore
+% c->cla
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 410.25 943.35 moveto
+411.47 1003.13 418.59 1190.77 460 1231 curveto
+500.39 1270.24 570.88 1268.05 612.81 1262.38 curveto
+stroke
+0 0 0 edgecolor
+newpath 613.45 1265.82 moveto
+622.82 1260.88 lineto
+612.42 1258.9 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 613.45 1265.82 moveto
+622.82 1260.88 lineto
+612.42 1258.9 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+496.5 1268.4 moveto 13 (<) alignedtext
+grestore
+% cat
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+647 790 25.91 26.41 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+636 785.9 moveto 22 (cat) alignedtext
+grestore
+% c->cat
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 413.94 907.26 moveto
+421.74 873.87 440.15 803.81 460 790 curveto
+504.83 758.8 571.5 768.61 611.95 779 curveto
+stroke
+0 0 0 edgecolor
+newpath 611.07 782.39 moveto
+621.63 781.63 lineto
+612.9 775.63 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 611.07 782.39 moveto
+621.63 781.63 lineto
+612.9 775.63 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+495.5 794.4 moveto 15 (@) alignedtext
+grestore
+% crs->c
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 623.38 481.3 moveto
+575.38 500.42 470.06 543.56 460 558 curveto
+430.44 600.43 449.99 738.91 442 790 curveto
+436.09 827.82 425.19 870.7 417.77 897.79 curveto
+stroke
+0 0 0 edgecolor
+newpath 414.32 897.12 moveto
+415.02 907.7 lineto
+421.06 899 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 414.32 897.12 moveto
+415.02 907.7 lineto
+421.06 899 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+492 562.4 moveto 22 (c-/]) alignedtext
+grestore
+% ce
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+1386 472 22.24 22.24 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+1378 467.9 moveto 16 (ce) alignedtext
+grestore
+% crs->ce
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 672.01 472 moveto
+782.87 472 1229.87 472 1353.93 472 curveto
+stroke
+0 0 0 edgecolor
+newpath 1353.94 475.5 moveto
+1363.94 472 lineto
+1353.94 468.5 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 1353.94 475.5 moveto
+1363.94 472 lineto
+1353.94 468.5 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1042 476.4 moveto 6 (]) alignedtext
+grestore
+% cla->c
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 624.5 1245.82 moveto
+576.01 1223.78 465.53 1173.08 460 1166 curveto
+434.23 1133.03 418.62 1009.42 412.71 953.18 curveto
+stroke
+0 0 0 edgecolor
+newpath 416.19 952.78 moveto
+411.69 943.19 lineto
+409.23 953.49 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 416.19 952.78 moveto
+411.69 943.19 lineto
+409.23 953.49 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+488.5 1213.4 moveto 29 (c-/<) alignedtext
+grestore
+% u
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+921 1142 18.07 18.07 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+916 1137.9 moveto 10 (u) alignedtext
+grestore
+% cla->u
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 669.89 1246.48 moveto
+720.4 1225.46 841.14 1175.22 894.68 1152.95 curveto
+stroke
+0 0 0 edgecolor
+newpath 896.26 1156.08 moveto
+904.15 1149.01 lineto
+893.57 1149.62 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 896.26 1156.08 moveto
+904.15 1149.01 lineto
+893.57 1149.62 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+748.5 1216.4 moveto 91 (< \(emit text\)) alignedtext
+grestore
+% cat->c
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 620.73 793.72 moveto
+582.19 800.26 509.55 816.84 460 854 curveto
+444.02 865.99 431.19 884.58 422.52 899.74 curveto
+stroke
+0 0 0 edgecolor
+newpath 419.39 898.18 moveto
+417.68 908.64 lineto
+425.53 901.53 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 419.39 898.18 moveto
+417.68 908.64 lineto
+425.53 901.53 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+487.5 858.4 moveto 31 (c-/@) alignedtext
+grestore
+% catla
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+921 1011 34.24 34.74 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+904 1006.9 moveto 34 (catla) alignedtext
+grestore
+% cat->catla
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 662.44 811.45 moveto
+680.91 836.18 713.69 877.1 748 906 curveto
+789.74 941.16 844.52 972.31 881.15 991.37 curveto
+stroke
+0 0 0 edgecolor
+newpath 879.56 994.49 moveto
+890.05 995.95 lineto
+882.76 988.26 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 879.56 994.49 moveto
+890.05 995.95 lineto
+882.76 988.26 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+787.5 971.4 moveto 13 (<) alignedtext
+grestore
+% catra
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+921 683 36.13 36.13 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+903 678.9 moveto 36 (catra) alignedtext
+grestore
+% cat->catra
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 671.8 780.32 moveto
+718.37 762.13 819.45 722.66 877.55 699.97 curveto
+stroke
+0 0 0 edgecolor
+newpath 879.14 703.1 moveto
+887.19 696.2 lineto
+876.6 696.58 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 879.14 703.1 moveto
+887.19 696.2 lineto
+876.6 696.58 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+787.5 753.4 moveto 13 (>) alignedtext
+grestore
+% catla->c
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 886.88 1018.23 moveto
+872.48 1020.94 855.5 1023.67 840 1025 curveto
+799.26 1028.49 788.77 1028.17 748 1025 curveto
+618.84 1014.97 574.06 1041.43 460 980 curveto
+446.33 972.64 434.46 960.05 425.73 948.77 curveto
+stroke
+0 0 0 edgecolor
+newpath 428.41 946.5 moveto
+419.68 940.5 lineto
+422.76 950.64 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 428.41 946.5 moveto
+419.68 940.5 lineto
+422.76 950.64 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+626.5 1027.4 moveto 41 (</<<) alignedtext
+grestore
+% catla->c
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 886.46 1006.95 moveto
+851.48 1002.71 795.87 995.64 748 988 curveto
+632.3 969.54 495.32 942.35 437.71 930.67 curveto
+stroke
+0 0 0 edgecolor
+newpath 438.39 927.24 moveto
+427.9 928.68 lineto
+437 934.1 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 438.39 927.24 moveto
+427.9 928.68 lineto
+437 934.1 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+625.5 988.4 moveto 43 (c-/@<) alignedtext
+grestore
+% catra->c
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 885.32 677.41 moveto
+799.51 666.14 579.87 650.68 460 764 curveto
+440.63 782.31 423.51 856.07 415.25 897.1 curveto
+stroke
+0 0 0 edgecolor
+newpath 411.79 896.53 moveto
+413.29 907.02 lineto
+418.66 897.88 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 411.79 896.53 moveto
+413.29 907.02 lineto
+418.66 897.88 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+626.5 704.4 moveto 41 (>/>>) alignedtext
+grestore
+% catra->c
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 886.66 671.97 moveto
+822.29 653 679.54 618.96 564 649 curveto
+512.78 662.32 491.51 664.48 460 707 curveto
+437.52 737.33 450.35 753.19 442 790 curveto
+433.58 827.12 423.36 869.85 416.77 897.12 curveto
+stroke
+0 0 0 edgecolor
+newpath 413.3 896.58 moveto
+414.35 907.12 lineto
+420.11 898.22 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 413.3 896.58 moveto
+414.35 907.12 lineto
+420.11 898.22 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+625.5 653.4 moveto 43 (c-/@>) alignedtext
+grestore
+% ce->t
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1384.8 449.87 moveto
+1378.46 356.55 1340.69 0 1134 0 curveto
+186 0 186 0 186 0 curveto
+103.66 0 88.61 55.29 54 130 curveto
+34.94 171.15 22.4 486.48 18.96 583.61 curveto
+stroke
+0 0 0 edgecolor
+newpath 15.45 583.73 moveto
+18.6 593.84 lineto
+22.45 583.97 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 15.45 583.73 moveto
+18.6 593.84 lineto
+22.45 583.97 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+564 4.4 moveto 166 (c- \(emit text; endquote\)) alignedtext
+grestore
+% ce->ce
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1377.27 492.58 moveto
+1376.06 502.84 1378.97 512 1386 512 curveto
+1390.5 512 1393.32 508.24 1394.44 502.84 curveto
+stroke
+0 0 0 edgecolor
+newpath 1397.95 502.68 moveto
+1394.73 492.58 lineto
+1390.95 502.48 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 1397.95 502.68 moveto
+1394.73 492.58 lineto
+1390.95 502.48 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1378 516.4 moveto 16 (]/]) alignedtext
+grestore
+% u->c
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 902.9 1141.7 moveto
+836.31 1139.68 601.53 1124.45 460 1011 curveto
+440.84 995.64 427.53 970.8 419.5 951.76 curveto
+stroke
+0 0 0 edgecolor
+newpath 422.72 950.41 moveto
+415.77 942.41 lineto
+416.22 953 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 422.72 950.41 moveto
+415.77 942.41 lineto
+416.22 953 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+584 1125.4 moveto 126 (eol- \(prepend <<\)) alignedtext
+grestore
+% u->u
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 905.11 1151.22 moveto
+891.48 1163.35 896.78 1178 921 1178 curveto
+939.92 1178 947.29 1169.06 943.12 1159.36 curveto
+stroke
+0 0 0 edgecolor
+newpath 945.75 1157.04 moveto
+936.89 1151.22 lineto
+940.19 1161.29 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 945.75 1157.04 moveto
+936.89 1151.22 lineto
+940.19 1161.29 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+911.5 1182.4 moveto 19 (c/c) alignedtext
+grestore
+% uls
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+1134 1245 25.02 25.02 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+1124 1240.9 moveto 20 (uls) alignedtext
+grestore
+% u->uls
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 937.36 1149.91 moveto
+972.56 1166.93 1056 1207.28 1102.07 1229.56 curveto
+stroke
+0 0 0 edgecolor
+newpath 1100.78 1232.82 moveto
+1111.3 1234.02 lineto
+1103.82 1226.52 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 1100.78 1232.82 moveto
+1111.3 1234.02 lineto
+1103.82 1226.52 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1037 1226.4 moveto 16 ([/[) alignedtext
+grestore
+% urs
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+1134 829 25.91 26.41 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+1123 824.9 moveto 22 (urs) alignedtext
+grestore
+% u->urs
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 933.61 1128.95 moveto
+948.39 1112.79 972.35 1083.74 984 1054 curveto
+1007.36 994.35 967.43 964.93 1002 911 curveto
+1024.6 875.75 1068.31 853.1 1099.23 840.73 curveto
+stroke
+0 0 0 edgecolor
+newpath 1100.69 843.92 moveto
+1108.78 837.07 lineto
+1098.19 837.38 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 1100.69 843.92 moveto
+1108.78 837.07 lineto
+1098.19 837.38 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1002.5 915.4 moveto 85 (] \(docs only\)) alignedtext
+grestore
+% ura
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+1134 1112 27.8 27.8 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+1122 1107.9 moveto 24 (ura) alignedtext
+grestore
+% u->ura
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 939.16 1139.44 moveto
+973.77 1134.57 1049.82 1123.86 1096.01 1117.35 curveto
+stroke
+0 0 0 edgecolor
+newpath 1096.53 1120.81 moveto
+1105.94 1115.95 lineto
+1095.55 1113.88 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 1096.53 1120.81 moveto
+1105.94 1115.95 lineto
+1095.55 1113.88 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1038.5 1134.4 moveto 13 (>) alignedtext
+grestore
+% uls->u
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1109.2 1250.63 moveto
+1081.53 1255.6 1036.18 1259.72 1002 1243 curveto
+969.92 1227.3 946.45 1192.18 933.27 1167.79 curveto
+stroke
+0 0 0 edgecolor
+newpath 936.28 1165.99 moveto
+928.57 1158.72 lineto
+930.06 1169.21 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 936.28 1165.99 moveto
+928.57 1158.72 lineto
+930.06 1169.21 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1038.5 1258.4 moveto 13 (c-) alignedtext
+grestore
+% uc
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+1386 1245 22.24 22.24 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+1378 1240.9 moveto 16 (uc) alignedtext
+grestore
+% uls->uc
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1159.08 1245 moveto
+1205.11 1245 1302.98 1245 1353.83 1245 curveto
+stroke
+0 0 0 edgecolor
+newpath 1353.93 1248.5 moveto
+1363.93 1245 lineto
+1353.93 1241.5 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 1353.93 1248.5 moveto
+1363.93 1245 lineto
+1353.93 1241.5 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1255 1249.4 moveto 16 ([/[) alignedtext
+grestore
+% urs->ce
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1149.2 807.47 moveto
+1192.99 745.44 1319.36 566.4 1367.28 498.52 curveto
+stroke
+0 0 0 edgecolor
+newpath 1370.34 500.26 moveto
+1373.24 490.07 lineto
+1364.62 496.22 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 1370.34 500.26 moveto
+1373.24 490.07 lineto
+1364.62 496.22 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1180 764.4 moveto 166 (] \(not use; prepend <<\)) alignedtext
+grestore
+% urs->u
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1126.82 854.04 moveto
+1119.69 875.54 1107.05 906.39 1088 928 curveto
+1058.15 961.86 1028.5 945.47 1002 982 curveto
+982.63 1008.7 997.84 1024.06 984 1054 curveto
+972.55 1078.77 953.81 1103.76 939.74 1120.74 curveto
+stroke
+0 0 0 edgecolor
+newpath 937.05 1118.51 moveto
+933.26 1128.4 lineto
+942.39 1123.03 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 937.05 1118.51 moveto
+933.26 1128.4 lineto
+942.39 1123.03 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1034 986.4 moveto 22 (c-/]) alignedtext
+grestore
+% ura->c
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1130.95 1084.15 moveto
+1125.23 1037.23 1111.31 945.43 1088 924 curveto
+991.99 835.73 554.16 901.03 438.23 920.17 curveto
+stroke
+0 0 0 edgecolor
+newpath 437.33 916.77 moveto
+428.04 921.87 lineto
+438.48 923.68 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 437.33 916.77 moveto
+428.04 921.87 lineto
+438.48 923.68 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+750.5 887.4 moveto 87 (> \(emit use\)) alignedtext
+grestore
+% ura->u
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1107.59 1101.82 moveto
+1101.27 1099.82 1094.47 1098.03 1088 1097 curveto
+1050.25 1091 1039 1087.41 1002 1097 curveto
+980.91 1102.46 959.47 1114.74 943.95 1125.09 curveto
+stroke
+0 0 0 edgecolor
+newpath 941.78 1122.34 moveto
+935.54 1130.9 lineto
+945.76 1128.1 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 941.78 1122.34 moveto
+935.54 1130.9 lineto
+945.76 1128.1 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1030.5 1101.4 moveto 29 (c-/>) alignedtext
+grestore
+% uc->c
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1368.05 1257.92 moveto
+1328.1 1285.37 1227.92 1347 1134 1347 curveto
+647 1347 647 1347 647 1347 curveto
+559.44 1347 516.03 1352.29 460 1285 curveto
+438.84 1259.59 418.81 1034.38 412.24 953.64 curveto
+stroke
+0 0 0 edgecolor
+newpath 415.7 952.93 moveto
+411.41 943.25 lineto
+408.72 953.49 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 415.7 952.93 moveto
+411.41 943.25 lineto
+408.72 953.49 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+858 1351.4 moveto 126 (eol- \(prepend <<\)) alignedtext
+grestore
+% uc->uc
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1377.27 1265.58 moveto
+1376.06 1275.84 1378.97 1285 1386 1285 curveto
+1390.5 1285 1393.32 1281.24 1394.44 1275.84 curveto
+stroke
+0 0 0 edgecolor
+newpath 1397.95 1275.68 moveto
+1394.73 1265.58 lineto
+1390.95 1275.48 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 1397.95 1275.68 moveto
+1394.73 1265.58 lineto
+1390.95 1275.48 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1376.5 1289.4 moveto 19 (c/c) alignedtext
+grestore
+% ucrs
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+1492 1175 30.77 31.27 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+1477.5 1170.9 moveto 29 (ucrs) alignedtext
+grestore
+% uc->ucrs
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1404.46 1232.81 moveto
+1419.04 1223.18 1439.8 1209.47 1457.44 1197.82 curveto
+stroke
+0 0 0 edgecolor
+newpath 1459.39 1200.73 moveto
+1465.81 1192.3 lineto
+1455.53 1194.89 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 1459.39 1200.73 moveto
+1465.81 1192.3 lineto
+1455.53 1194.89 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1426 1222.4 moveto 16 (]/]) alignedtext
+grestore
+% ucrs->uc
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1460.27 1176.94 moveto
+1448.75 1178.83 1436.09 1182.39 1426 1189 curveto
+1415.64 1195.78 1407.11 1206.25 1400.63 1216.31 curveto
+stroke
+0 0 0 edgecolor
+newpath 1397.6 1214.56 moveto
+1395.47 1224.94 lineto
+1403.61 1218.16 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 1397.6 1214.56 moveto
+1395.47 1224.94 lineto
+1403.61 1218.16 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1427.5 1193.4 moveto 13 (c-) alignedtext
+grestore
+% uce
+gsave
+1 setlinewidth
+0 0 0 nodecolor
+1605 1068 27.99 28.49 ellipse_path stroke
+0 0 0 nodecolor
+14 /Times-Roman set_font
+1592.5 1063.9 moveto 25 (uce) alignedtext
+grestore
+% ucrs->uce
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1514.87 1153.35 moveto
+1532.86 1136.31 1558 1112.5 1577.16 1094.36 curveto
+stroke
+0 0 0 edgecolor
+newpath 1579.59 1096.88 moveto
+1584.45 1087.46 lineto
+1574.78 1091.8 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 1579.59 1096.88 moveto
+1584.45 1087.46 lineto
+1574.78 1091.8 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1542 1128.4 moveto 16 (]/]) alignedtext
+grestore
+% uce->u
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1583.16 1049.99 moveto
+1561.44 1033.95 1526.47 1013 1492 1013 curveto
+1134 1013 1134 1013 1134 1013 curveto
+1052.01 1013 974.6 1083.8 939.98 1120.5 curveto
+stroke
+0 0 0 edgecolor
+newpath 937.09 1118.47 moveto
+932.88 1128.19 lineto
+942.23 1123.22 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 937.09 1118.47 moveto
+932.88 1128.19 lineto
+942.23 1123.22 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1379.5 1017.4 moveto 13 (c-) alignedtext
+grestore
+% uce->uce
+gsave
+1 setlinewidth
+0 0 0 edgecolor
+newpath 1594.94 1094.47 moveto
+1594.37 1105.09 1597.72 1114 1605 1114 curveto
+1609.78 1114 1612.86 1110.16 1614.26 1104.52 curveto
+stroke
+0 0 0 edgecolor
+newpath 1617.75 1104.72 moveto
+1615.06 1094.47 lineto
+1610.78 1104.16 lineto
+closepath fill
+1 setlinewidth
+solid
+0 0 0 edgecolor
+newpath 1617.75 1104.72 moveto
+1615.06 1094.47 lineto
+1610.78 1104.16 lineto
+closepath stroke
+0 0 0 edgecolor
+14 /Times-Roman set_font
+1597 1118.4 moveto 16 (]/]) alignedtext
+grestore
+endpage
+showpage
+grestore
+%%PageTrailer
+%%EndPage: 1
+%%Trailer
+%%Pages: 1
+%%BoundingBox: 36 36 576 682
+end
+restore
+%%EOF
diff --git a/web/noweb/src/c/match.c b/web/noweb/src/c/match.c
new file mode 100644
index 0000000000..ced38e2316
--- /dev/null
+++ b/web/noweb/src/c/match.c
@@ -0,0 +1,26 @@
+#line 10 "match.nw"
+static char rcsid[] = "$Id: match.nw,v 1.21 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <string.h>
+#include "match.h"
+static int matches(char *line, char *search) {
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return !strncmp(line,search,strlen(search));
+}
+#line 24 "match.nw"
+int is_keyword(char *line, char *keyword) {
+ char low_at_sign = '@';
+ return *line==low_at_sign && matches(line+1,keyword) &&
+ (line[strlen(keyword)+1]==' ' || line[strlen(keyword)+1]=='\n' ||
+ line[strlen(keyword)+1]=='\0');
+}
+int is_begin(char *line, char *type) {
+ return is_keyword(line,"begin") && matches(line+1+6,type);
+}
+int is_end(char *line, char *type) {
+ return is_keyword(line,"end") && matches (line+1+4,type);
+}
+int is_index(char *line, char *type) {
+ return is_keyword(line,"index") && matches(line+1+6,type);
+}
diff --git a/web/noweb/src/c/match.h b/web/noweb/src/c/match.h
new file mode 100644
index 0000000000..a45efb1bbc
--- /dev/null
+++ b/web/noweb/src/c/match.h
@@ -0,0 +1,4 @@
+extern int is_keyword(char *line, char *keyword);
+extern int is_begin(char *line, char *type);
+extern int is_end(char *line, char *type);
+extern int is_index(char *line, char *type);
diff --git a/web/noweb/src/c/match.nw b/web/noweb/src/c/match.nw
new file mode 100644
index 0000000000..2d015a8a13
--- /dev/null
+++ b/web/noweb/src/c/match.nw
@@ -0,0 +1,38 @@
+\subsection{Code to recognize [[noweb]] markup on input}
+We recognize the input using matching functions, which can find [[@begin]],
+[[@end]], and other useful information.
+<<header>>=
+extern int is_keyword(char *line, char *keyword);
+extern int is_begin(char *line, char *type);
+extern int is_end(char *line, char *type);
+extern int is_index(char *line, char *type);
+<<*>>=
+static char rcsid[] = "$Id: match.nw,v 1.21 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <string.h>
+#include "match.h"
+static int matches(char *line, char *search) {
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return !strncmp(line,search,strlen(search));
+}
+@
+On 24 March 1996, I changed this to accept zero as a terminator
+because I strip newlines in the prettyprinter.
+Too bad if we just got worse at detecting bogus filters.
+<<*>>=
+int is_keyword(char *line, char *keyword) {
+ char low_at_sign = '@';
+ return *line==low_at_sign && matches(line+1,keyword) &&
+ (line[strlen(keyword)+1]==' ' || line[strlen(keyword)+1]=='\n' ||
+ line[strlen(keyword)+1]=='\0');
+}
+int is_begin(char *line, char *type) {
+ return is_keyword(line,"begin") && matches(line+1+6,type);
+}
+int is_end(char *line, char *type) {
+ return is_keyword(line,"end") && matches (line+1+4,type);
+}
+int is_index(char *line, char *type) {
+ return is_keyword(line,"index") && matches(line+1+6,type);
+}
diff --git a/web/noweb/src/c/mnt.c b/web/noweb/src/c/mnt.c
new file mode 100644
index 0000000000..c4d2aeb351
--- /dev/null
+++ b/web/noweb/src/c/mnt.c
@@ -0,0 +1,172 @@
+#line 9 "mnt.nw"
+static char rcsid[] = "$Id: mnt.nw,v 1.22 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+static struct keepalive { char *s; struct keepalive *p; } keepalive[] =
+ { {rcsid, keepalive}, {rcsname, keepalive} }; /* avoid warnings */
+#define _POSIX_C_SOURCE 200809L
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include "modules.h"
+#include "modtrees.h"
+#include "notangle.h"
+#include "errors.h"
+#include "columns.h"
+#include "strsave.h"
+
+#line 55 "mnt.nw"
+void add_uses_to_usecounts(Module mp);
+void emit_if_unused_and_conforming(Module mp);
+#line 91 "mnt.nw"
+static void emitfile(char *modname);
+
+#line 28 "mnt.nw"
+#define Clocformat "#line %L \"%F\"%N"
+static char *locformat = Clocformat;
+
+int main(int argc, char **argv) {
+ int i;
+
+ tabsize = 0; /* default for nt is not to use tabs */
+
+ progname = argv[0];
+ finalstage = 1;
+
+#line 49 "mnt.nw"
+read_defs(stdin);
+apply_each_module(remove_final_newline);
+#line 39 "mnt.nw"
+ for (i=1; i<argc; i++)
+ switch (*argv[i]) {
+ case '-':
+#line 150 "mnt.nw"
+ switch (*++argv[i]) {
+ case 'a':
+ if (strcmp(argv[i], "all"))
+ errormsg(Warning, "Ignoring unknown option -%s", argv[i]);
+ else {
+#line 52 "mnt.nw"
+apply_each_module(add_uses_to_usecounts);
+apply_each_module(emit_if_unused_and_conforming);
+#line 154 "mnt.nw"
+ }
+ break;
+ case 't': /* set tab size or turn off */
+ if (isdigit(argv[i][1]))
+ tabsize = atoi(argv[i]+1);
+ else if (argv[i][1]==0)
+ tabsize = 0; /* no tabs */
+ else
+ errormsg(Error, "%s: ill-formed option %s\n", argv[0], argv[i]);
+ break;
+ case 'L': /* have a #line number format */
+ locformat = argv[i] + 1;
+ if (!*locformat) locformat = Clocformat;
+ break;
+ default:
+ errormsg(Warning, "Ignoring unknown option -%s", argv[i]);
+ }
+#line 41 "mnt.nw"
+ break;
+ default: emitfile(argv[i]); break;
+ }
+ nowebexit(NULL);
+ return errorlevel; /* slay warning */
+}
+#line 58 "mnt.nw"
+void add_uses_to_usecounts(Module mp) {
+ Module used;
+ struct modpart *p;
+ for (p=mp->head; p!=NULL; p=p->next)
+ if (p->ptype == MODULE) {
+ used = lookup(p->contents);
+ if (used != NULL)
+ used->usecount++;
+ }
+}
+#line 74 "mnt.nw"
+void emit_if_unused_and_conforming(Module mp) {
+ char *index;
+ if (mp->usecount == 0 && strpbrk(mp->name, " \n\t\v\r\f") == NULL) {
+ if (index = strpbrk(mp->name, "[](){}!$&<>*?;|^`'\\\""),
+ index == NULL || (index[0] == '*' && index[1] == 0)) {
+ if (index == mp->name)
+ errormsg(Error, "<<*>> is not a good chunk name for noweb; "
+ "use notangle instead");
+ else
+ emitfile(mp->name);
+ } else {
+ errormsg(Error, "<<%s>> cannot be an output chunk; "
+ "it contains a metacharacter", mp->name);
+ }
+ }
+}
+#line 93 "mnt.nw"
+static void emitfile(char *modname) {
+ Module root = lookup(modname);
+ FILE *fp = tmpfile();
+ char *lfmt, *filename;
+
+#line 111 "mnt.nw"
+{ int n = strlen(modname) - 1;
+ if (n >= 0 && modname[n] == '*') {
+ lfmt = locformat;
+ filename = strsave(modname);
+ filename[n] = 0;
+ } else {
+ lfmt = "";
+ filename = modname;
+ }
+}
+#line 98 "mnt.nw"
+
+#line 145 "mnt.nw"
+if (root == NULL) {
+ errormsg(Error, "Chunk <<%s>> is undefined", filename);
+ return;
+}
+#line 99 "mnt.nw"
+ if (fp == NULL) errormsg(Fatal, "Calling tmpfile() failed");
+
+#line 122 "mnt.nw"
+resetloc();
+(void) expand(root, 0, 0, 0, lfmt, fp);
+putc('\n', fp);
+#line 101 "mnt.nw"
+ rewind(fp);
+
+#line 127 "mnt.nw"
+{ FILE *dest = fopen(filename, "r");
+ if (dest != NULL) {
+ int x, y;
+ do {
+ x = getc(fp);
+ y = getc(dest);
+ } while (x == y && x != EOF);
+ fclose(dest);
+ if (x == y) {
+ fclose(fp);
+ return;
+ }
+ }
+}
+#line 103 "mnt.nw"
+ remove(filename);
+ fclose(fp);
+ fp = fopen(filename, "w");
+ if (fp == NULL) {
+#line 142 "mnt.nw"
+errormsg(Error, "Can't open output file %s", filename);
+return;
+#line 106 "mnt.nw"
+ }
+
+#line 122 "mnt.nw"
+resetloc();
+(void) expand(root, 0, 0, 0, lfmt, fp);
+putc('\n', fp);
+#line 108 "mnt.nw"
+ fclose(fp);
+}
diff --git a/web/noweb/src/c/mnt.nw b/web/noweb/src/c/mnt.nw
new file mode 100644
index 0000000000..f18f6c5a30
--- /dev/null
+++ b/web/noweb/src/c/mnt.nw
@@ -0,0 +1,171 @@
+% -*- mode: Noweb; noweb-code-mode: c-mode -*-
+% Copyright 1991 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+\subsection{Expanding multiple files from a single source}
+This main program is used to make the monolithic {\tt noweb}
+script efficient.
+Tips of the hat to Ross Williams and Preston Briggs.
+<<*>>=
+static char rcsid[] = "$Id: mnt.nw,v 1.22 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+static struct keepalive { char *s; struct keepalive *p; } keepalive[] =
+ { {rcsid, keepalive}, {rcsname, keepalive} }; /* avoid warnings */
+#define _POSIX_C_SOURCE 200809L
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include "modules.h"
+#include "modtrees.h"
+#include "notangle.h"
+#include "errors.h"
+#include "columns.h"
+#include "strsave.h"
+
+<<local prototypes>>
+
+#define Clocformat "#line %L \"%F\"%N"
+static char *locformat = Clocformat;
+
+int main(int argc, char **argv) {
+ int i;
+
+ tabsize = 0; /* default for nt is not to use tabs */
+
+ progname = argv[0];
+ finalstage = 1;
+ <<read standard input into tree>>
+ for (i=1; i<argc; i++)
+ switch (*argv[i]) {
+ case '-': <<handle option in [[argv[i]]]>> break;
+ default: emitfile(argv[i]); break;
+ }
+ nowebexit(NULL);
+ return errorlevel; /* slay warning */
+}
+@
+<<read standard input into tree>>=
+read_defs(stdin);
+apply_each_module(remove_final_newline);
+<<write out all conforming roots>>=
+apply_each_module(add_uses_to_usecounts);
+apply_each_module(emit_if_unused_and_conforming);
+<<local prototypes>>=
+void add_uses_to_usecounts(Module mp);
+void emit_if_unused_and_conforming(Module mp);
+<<*>>=
+void add_uses_to_usecounts(Module mp) {
+ Module used;
+ struct modpart *p;
+ for (p=mp->head; p!=NULL; p=p->next)
+ if (p->ptype == MODULE) {
+ used = lookup(p->contents);
+ if (used != NULL)
+ used->usecount++;
+ }
+}
+@
+
+A conforming output chunk name has no spaces and no metacharacters.
+Names with spaces are silently ignored, but names that are otherwise
+conforming but that contain metacharacters cause complaints.
+<<*>>=
+void emit_if_unused_and_conforming(Module mp) {
+ char *index;
+ if (mp->usecount == 0 && strpbrk(mp->name, " \n\t\v\r\f") == NULL) {
+ if (index = strpbrk(mp->name, "[](){}!$&<>*?;|^`'\\\""),
+ index == NULL || (index[0] == '*' && index[1] == 0)) {
+ if (index == mp->name)
+ errormsg(Error, "@<<*@>> is not a good chunk name for noweb; "
+ "use notangle instead");
+ else
+ emitfile(mp->name);
+ } else {
+ errormsg(Error, "@<<%s@>> cannot be an output chunk; "
+ "it contains a metacharacter", mp->name);
+ }
+ }
+}
+<<local prototypes>>=
+static void emitfile(char *modname);
+<<*>>=
+static void emitfile(char *modname) {
+ Module root = lookup(modname);
+ FILE *fp = tmpfile();
+ char *lfmt, *filename;
+ <<set [[lfmt]] and [[filename]] from [[modname]]>>
+ <<complain and [[return]] if [[root == NULL]]>>
+ if (fp == NULL) errormsg(Fatal, "Calling tmpfile() failed");
+ <<expand [[root]] onto [[fp]]>>
+ rewind(fp);
+ <<if file [[filename]] has the same contents as [[fp]], close [[fp]] and [[return]]>>
+ remove(filename);
+ fclose(fp);
+ fp = fopen(filename, "w");
+ if (fp == NULL) {<<complain about [[filename]] and [[return]]>>}
+ <<expand [[root]] onto [[fp]]>>
+ fclose(fp);
+}
+<<set [[lfmt]] and [[filename]] from [[modname]]>>=
+{ int n = strlen(modname) - 1;
+ if (n >= 0 && modname[n] == '*') {
+ lfmt = locformat;
+ filename = strsave(modname);
+ filename[n] = 0;
+ } else {
+ lfmt = "";
+ filename = modname;
+ }
+}
+<<expand [[root]] onto [[fp]]>>=
+resetloc();
+(void) expand(root, 0, 0, 0, lfmt, fp);
+putc('\n', fp);
+@
+<<if file [[filename]] has the same contents as [[fp]], close [[fp]] and [[return]]>>=
+{ FILE *dest = fopen(filename, "r");
+ if (dest != NULL) {
+ int x, y;
+ do {
+ x = getc(fp);
+ y = getc(dest);
+ } while (x == y && x != EOF);
+ fclose(dest);
+ if (x == y) {
+ fclose(fp);
+ return;
+ }
+ }
+}
+<<complain about [[filename]] and [[return]]>>=
+errormsg(Error, "Can't open output file %s", filename);
+return;
+<<complain and [[return]] if [[root == NULL]]>>=
+if (root == NULL) {
+ errormsg(Error, "Chunk @<<%s@>> is undefined", filename);
+ return;
+}
+<<handle option in [[argv[i]]]>>=
+ switch (*++argv[i]) {
+ case 'a':
+ if (strcmp(argv[i], "all"))
+ errormsg(Warning, "Ignoring unknown option -%s", argv[i]);
+ else {<<write out all conforming roots>>}
+ break;
+ case 't': /* set tab size or turn off */
+ if (isdigit(argv[i][1]))
+ tabsize = atoi(argv[i]+1);
+ else if (argv[i][1]==0)
+ tabsize = 0; /* no tabs */
+ else
+ errormsg(Error, "%s: ill-formed option %s\n", argv[0], argv[i]);
+ break;
+ case 'L': /* have a #line number format */
+ locformat = argv[i] + 1;
+ if (!*locformat) locformat = Clocformat;
+ break;
+ default:
+ errormsg(Warning, "Ignoring unknown option -%s", argv[i]);
+ }
+@
diff --git a/web/noweb/src/c/modtrees.c b/web/noweb/src/c/modtrees.c
new file mode 100644
index 0000000000..b0b044cda3
--- /dev/null
+++ b/web/noweb/src/c/modtrees.c
@@ -0,0 +1,77 @@
+#line 14 "modtrees.nw"
+static char rcsid[] = "$Id: modtrees.nw,v 2.24 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "strsave.h"
+#include "modules.h"
+#include "modtrees.h"
+#include "errors.h"
+
+typedef struct tnode { /* tree node */
+ struct tnode *left, *right;
+ Module data;
+} TNODE;
+
+static struct tnode *root=NULL;
+
+#line 62 "modtrees.nw"
+static Module insert_tree(TNODE **rootptr, char *modname);
+static Module lookup_tree(TNODE **rootptr, char *modname);
+#line 33 "modtrees.nw"
+Module insert (char *modname) {
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return insert_tree (&root, modname);
+}
+
+static Module
+insert_tree(TNODE **rootptr, char *modname) {
+ if (*rootptr==NULL) {
+
+#line 58 "modtrees.nw"
+ checkptr(*rootptr=(struct tnode *) malloc (sizeof(struct tnode)));
+ (*rootptr)->left = (*rootptr)->right = NULL;
+#line 43 "modtrees.nw"
+ return (*rootptr)->data = newmodule(modname);
+ }
+ if (strcmp((*rootptr)->data->name,modname)==0) {
+ return (*rootptr)->data;
+ } else if (strcmp((*rootptr)->data->name,modname)<0) {
+ return insert_tree(&((*rootptr)->left),modname);
+ } else /* >0 */ {
+ return insert_tree(&((*rootptr)->right),modname);
+ }
+
+}
+#line 66 "modtrees.nw"
+Module lookup (char *modname) {
+ return lookup_tree (&root, modname);
+}
+
+static Module
+lookup_tree(TNODE **rootptr, char *modname) {
+ if (*rootptr==NULL) {
+ return NULL;
+ }
+ if (strcmp((*rootptr)->data->name,modname)==0) {
+ return (*rootptr)->data;
+ } else if (strcmp((*rootptr)->data->name,modname)<0) {
+ return lookup_tree(&((*rootptr)->left),modname);
+ } else /* >0 */ {
+ return lookup_tree(&((*rootptr)->right),modname);
+ }
+}
+#line 90 "modtrees.nw"
+static
+void apply_to_tree(TNODE *p, void (*fun)(Module)) {
+ if (p != NULL) {
+ apply_to_tree(p->left,fun);
+ (*fun)(p->data);
+ apply_to_tree(p->right,fun);
+ }
+}
+void apply_each_module(void (*fun)(Module)) {
+ apply_to_tree(root,fun);
+}
diff --git a/web/noweb/src/c/modtrees.h b/web/noweb/src/c/modtrees.h
new file mode 100644
index 0000000000..94b3b7357a
--- /dev/null
+++ b/web/noweb/src/c/modtrees.h
@@ -0,0 +1,4 @@
+Module insert (char *modname); /* add a module to the world */
+Module lookup (char *modname); /* return ptr to module or NULL */
+void apply_each_module(void (*fun)(Module));
+ /* apply [[fun]] to each module in the tree */
diff --git a/web/noweb/src/c/modtrees.nw b/web/noweb/src/c/modtrees.nw
new file mode 100644
index 0000000000..1d5220c3cd
--- /dev/null
+++ b/web/noweb/src/c/modtrees.nw
@@ -0,0 +1,100 @@
+% Copyright 1991 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+@
+\subsection{Support for looking up modules by name}
+Trees of modules.
+A table of modules with insert and lookup, but no delete.
+The key is the module name.
+<<header>>=
+Module insert (char *modname); /* add a module to the world */
+Module lookup (char *modname); /* return ptr to module or NULL */
+void apply_each_module(void (*fun)(Module));
+ /* apply [[fun]] to each module in the tree */
+<<*>>=
+static char rcsid[] = "$Id: modtrees.nw,v 2.24 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "strsave.h"
+#include "modules.h"
+#include "modtrees.h"
+#include "errors.h"
+
+typedef struct tnode { /* tree node */
+ struct tnode *left, *right;
+ Module data;
+} TNODE;
+
+static struct tnode *root=NULL;
+
+<<Function declarations>>
+<<*>>=
+Module insert (char *modname) {
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return insert_tree (&root, modname);
+}
+
+static Module
+insert_tree(TNODE **rootptr, char *modname) {
+ if (*rootptr==NULL) {
+ <<Allocate new tnode in **rootptr>>
+ return (*rootptr)->data = newmodule(modname);
+ }
+ if (strcmp((*rootptr)->data->name,modname)==0) {
+ return (*rootptr)->data;
+ } else if (strcmp((*rootptr)->data->name,modname)<0) {
+ return insert_tree(&((*rootptr)->left),modname);
+ } else /* >0 */ {
+ return insert_tree(&((*rootptr)->right),modname);
+ }
+
+}
+@
+
+Node allocation is perfectly standard.
+<<Allocate new tnode in **rootptr>>=
+ checkptr(*rootptr=(struct tnode *) malloc (sizeof(struct tnode)));
+ (*rootptr)->left = (*rootptr)->right = NULL;
+@
+<<Function declarations>>=
+static Module insert_tree(TNODE **rootptr, char *modname);
+static Module lookup_tree(TNODE **rootptr, char *modname);
+@
+<<*>>=
+Module lookup (char *modname) {
+ return lookup_tree (&root, modname);
+}
+
+static Module
+lookup_tree(TNODE **rootptr, char *modname) {
+ if (*rootptr==NULL) {
+ return NULL;
+ }
+ if (strcmp((*rootptr)->data->name,modname)==0) {
+ return (*rootptr)->data;
+ } else if (strcmp((*rootptr)->data->name,modname)<0) {
+ return lookup_tree(&((*rootptr)->left),modname);
+ } else /* >0 */ {
+ return lookup_tree(&((*rootptr)->right),modname);
+ }
+}
+@
+
+[[apply_each_module]] takes as argument a function and applies
+it to each module in the tree.
+This makes it easy to, for example, remove trailing newlines
+from each module.
+<<*>>=
+static
+void apply_to_tree(TNODE *p, void (*fun)(Module)) {
+ if (p != NULL) {
+ apply_to_tree(p->left,fun);
+ (*fun)(p->data);
+ apply_to_tree(p->right,fun);
+ }
+}
+void apply_each_module(void (*fun)(Module)) {
+ apply_to_tree(root,fun);
+}
diff --git a/web/noweb/src/c/modules.c b/web/noweb/src/c/modules.c
new file mode 100644
index 0000000000..2229bf0419
--- /dev/null
+++ b/web/noweb/src/c/modules.c
@@ -0,0 +1,226 @@
+#line 50 "modules.nw"
+static char rcsid[] = "$Id: modules.nw,v 2.26 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "modules.h"
+#include "modtrees.h"
+#include "errors.h"
+#include "columns.h"
+#include "strsave.h"
+
+#line 112 "modules.nw"
+static struct modpart *
+newmodpart(int type, char *s, Location *loc); /* create a new module part */
+
+static
+void append(Module mp, struct modpart *p);
+#line 229 "modules.nw"
+static int seekcycle(Module mp, Parent parent);
+#line 134 "modules.nw"
+static char *lastfilename = 0;
+static int lastlineno = -1;
+#line 41 "modules.nw"
+Module newmodule (char *modname) {
+ Module p = (Module) malloc (sizeof (struct module));
+ checkptr(p);
+ p->name = strsave(modname);
+ p->usecount = 0;
+ p->head = p->tail = NULL;
+ return p;
+}
+#line 74 "modules.nw"
+void add_part (Module mp, char *s, Parttype type, Location *loc) {
+ struct modpart *p = newmodpart(type,s,loc);
+ append (mp,p);
+}
+#line 79 "modules.nw"
+static struct modpart *
+newmodpart(int type, char *s, Location *loc) {
+ struct modpart *p = (struct modpart *) malloc (sizeof (struct modpart));
+ checkptr(p);
+ p->ptype = type;
+ if (s) {
+ p->contents = strsave(s);
+
+#line 106 "modules.nw"
+{ int k = strlen(p->contents)-1;
+ if (p->contents[k] == '\n') p->contents[k] = '\0';
+ else impossible("input line doesn't end with newline");
+}
+#line 87 "modules.nw"
+ }
+ if (loc) p->loc = *loc;
+ p->next = NULL;
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return p;
+}
+#line 95 "modules.nw"
+static
+void append(Module mp, struct modpart *p) {
+ /* append p to mp's list of modparts */
+ if (mp->head == NULL) {
+ mp->head = mp->tail = p;
+ } else {
+ mp->tail->next = p;
+ mp->tail = p;
+ }
+}
+#line 139 "modules.nw"
+void resetloc(void) {
+ lastfilename = 0;
+ lastlineno = -1;
+}
+#line 147 "modules.nw"
+int expand (Module mp, int indent, int partial_distance, Parent parent,
+ char *locformat, FILE *out) {
+ struct modpart *p;
+ Module newmod;
+ int error=Normal;
+ struct parent thismodule; /* the value only matters when we're expanding a module */
+
+
+#line 221 "modules.nw"
+thismodule.this = mp;
+thismodule.parent = parent;
+#line 155 "modules.nw"
+
+#line 224 "modules.nw"
+if (seekcycle(mp, parent)) {
+ errormsg(Error, "<<%s>>", mp->name);
+ return Error;
+}
+
+#line 157 "modules.nw"
+ for (p=mp->head; p!=NULL; p=p->next) {
+ switch (p->ptype) {
+ case STRING:
+#line 178 "modules.nw"
+if (*(p->contents) != '\0') {
+ if (*locformat) {
+ if (printloc(out,locformat,p->loc,partial_distance) && (p != mp->head))
+ indent_for(partial_distance, out);
+ } else if (partial_distance == 0) {
+ indent_for(indent, out);
+ partial_distance = indent;
+ }
+ fprintf(out,"%s",p->contents);
+ partial_distance = limitcolumn(p->contents, partial_distance);
+}
+#line 159 "modules.nw"
+ ; break;
+ case MODULE:
+#line 203 "modules.nw"
+newmod = lookup(p->contents);
+if (newmod==NULL) {
+ errormsg (Error, "undefined chunk name: <<%s>>", p->contents);
+ error=Error;
+} else {
+ int retcode;
+ if (*locformat == 0 && partial_distance == 0) {
+ indent_for(indent, out);
+ partial_distance = indent;
+ }
+ retcode = expand (newmod, partial_distance, partial_distance,
+ &thismodule, locformat, out);
+ if (retcode > error) error = retcode;
+}
+partial_distance = limitcolumn(p->contents, partial_distance + 2) + 2;
+ /* account for surrounding brackets */
+#line 160 "modules.nw"
+ ; break;
+ case NEWLINE:
+#line 190 "modules.nw"
+partial_distance = 0;
+putc('\n', out);
+lastlineno++;
+#line 161 "modules.nw"
+ ; break;
+ default: impossible("bad part type");
+ }
+ }
+ return error;
+}
+#line 231 "modules.nw"
+static int seekcycle(Module mp, Parent parent) {
+ if (parent == NULL) {
+ return 0;
+ } else if (parent->this == mp || seekcycle(mp, parent->parent)) {
+ if (parent->this == mp)
+ fprintf(stderr, "Cyclic code chunks: ");
+ fprintf(stderr, "<<%s>> -> ", parent->this->name);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+#line 253 "modules.nw"
+int printloc(FILE *fp, char *fmt, Location loc, int partial) {
+ char *p;
+ if (*fmt
+ && (loc.filename!=lastfilename || lastlineno != loc.lineno)) {
+ if (partial) putc('\n',fp);
+
+#line 265 "modules.nw"
+for (p = fmt; *p; p++) {
+ if (*p == '%') {
+ switch (*++p) {
+ case '%': putc('%', fp); break;
+ case 'N': putc('\n', fp); break;
+ case 'F': fprintf(fp, "%s", loc.filename); break;
+ case 'L': fprintf(fp, "%d", loc.lineno); break;
+ case '-': case '+':
+ if (isdigit(p[1]) && p[2] == 'L') {
+ fprintf(fp, "%d", *p == '+' ? loc.lineno + (p[1] - '0')
+ : loc.lineno - (p[1] - '0'));
+ p += 2;
+ } else
+
+#line 285 "modules.nw"
+{ static int complained = 0;
+ if (!complained) {
+ errormsg(Error,"Bad format sequence ``%%%c'' in -L%s",*p,fmt);
+ complained = 1;
+ }
+}
+#line 279 "modules.nw"
+ break;
+ default:
+#line 285 "modules.nw"
+{ static int complained = 0;
+ if (!complained) {
+ errormsg(Error,"Bad format sequence ``%%%c'' in -L%s",*p,fmt);
+ complained = 1;
+ }
+}
+#line 280 "modules.nw"
+ break;
+ }
+ } else putc(*p, fp);
+}
+#line 259 "modules.nw"
+ lastfilename = loc.filename;
+ lastlineno = loc.lineno;
+ return 1;
+ } else return 0;
+}
+#line 311 "modules.nw"
+void remove_final_newline (Module mp) {
+ /* remove trailing newline that must be in module */
+ if (mp->tail==NULL) /* module has no text */
+ return;
+ if (mp->tail->ptype != NEWLINE)
+ /* do nothing --- this is possible with nuweb front end
+ formerly: impossible("Module doesn't end with newline"); */
+ ;
+ else if (mp->tail == mp->head)
+ mp->head = mp->tail = NULL;
+ else {
+ struct modpart *p = mp->head;
+ while (p->next != mp->tail) p = p->next;
+ p->next = NULL;
+ }
+}
diff --git a/web/noweb/src/c/modules.h b/web/noweb/src/c/modules.h
new file mode 100644
index 0000000000..f6c8b50956
--- /dev/null
+++ b/web/noweb/src/c/modules.h
@@ -0,0 +1,37 @@
+typedef struct location { /* identify lines of source */
+ char *filename;
+ int lineno;
+} Location;
+
+typedef enum parttype {STRING=1, MODULE, NEWLINE} Parttype;
+
+struct modpart {
+ Parttype ptype; /* type of fragment: STRING, MODULE, NEWLINE */
+ char *contents;
+ Location loc; /* for String, where's it from ? */
+ struct modpart *next;
+};
+typedef struct module {
+ char *name;
+ int usecount;
+ struct modpart *head, *tail;
+} *Module;
+Module newmodule(char *modname); /* create a new, blank module */
+#define addstring(MP,S,L) add_part(MP,S,STRING,&L)
+ /* add a string to a module definition (stripping final newline) */
+#define addmodule(MP,S) add_part(MP,S,MODULE,0)
+ /* add a module reference to a module definition (stripping final newline) */
+#define addnewline(MP) add_part(MP,0,NEWLINE,0)
+void add_part (Module mp, char *s, Parttype type, Location *loc);
+typedef struct parent {
+ Module this;
+ struct parent *parent;
+} *Parent;
+
+int expand (Module mp, int indent, int partial_distance, Parent parent,
+ char *locformat, FILE *out);
+ /* expand a module, writing to file out */
+void resetloc(void);
+int printloc(FILE *fp, char *fmt, Location loc, int partial);
+void remove_final_newline (Module mp);
+ /* remove trailing newline that must be in module */
diff --git a/web/noweb/src/c/modules.nw b/web/noweb/src/c/modules.nw
new file mode 100644
index 0000000000..a3c5f0069c
--- /dev/null
+++ b/web/noweb/src/c/modules.nw
@@ -0,0 +1,326 @@
+% Copyright 1991 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+@
+\subsection{The internal structure of modules (chunks)}
+This code is so old, it dates back to when I used to call ``chunks'' ``modules.''
+@
+\subsubsection{Assembling modules from parts}
+Modules are linked lists.
+Each element of the list is either a string or a reference to another
+module name.
+During expansion of a module, strings are printed and module references
+are expanded.
+The structure of module references must be a dag or else [[expand]] will
+complain about a cycle.
+<<header>>=
+typedef struct location { /* identify lines of source */
+ char *filename;
+ int lineno;
+} Location;
+
+typedef enum parttype {STRING=1, MODULE, NEWLINE} Parttype;
+
+struct modpart {
+ Parttype ptype; /* type of fragment: STRING, MODULE, NEWLINE */
+ char *contents;
+ Location loc; /* for String, where's it from ? */
+ struct modpart *next;
+};
+@
+In order to facilitate expansion of all roots (and to identify roots),
+I keep a use counter in each module.
+<<header>>=
+typedef struct module {
+ char *name;
+ int usecount;
+ struct modpart *head, *tail;
+} *Module;
+<<header>>=
+Module newmodule(char *modname); /* create a new, blank module */
+<<C functions>>=
+Module newmodule (char *modname) {
+ Module p = (Module) malloc (sizeof (struct module));
+ checkptr(p);
+ p->name = strsave(modname);
+ p->usecount = 0;
+ p->head = p->tail = NULL;
+ return p;
+}
+<<*>>=
+static char rcsid[] = "$Id: modules.nw,v 2.26 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "modules.h"
+#include "modtrees.h"
+#include "errors.h"
+#include "columns.h"
+#include "strsave.h"
+
+<<Function declarations>>
+<<local data>>
+<<C functions>>
+@
+<<header>>=
+#define addstring(MP,S,L) add_part(MP,S,STRING,&L)
+ /* add a string to a module definition (stripping final newline) */
+#define addmodule(MP,S) add_part(MP,S,MODULE,0)
+ /* add a module reference to a module definition (stripping final newline) */
+#define addnewline(MP) add_part(MP,0,NEWLINE,0)
+void add_part (Module mp, char *s, Parttype type, Location *loc);
+<<C functions>>=
+void add_part (Module mp, char *s, Parttype type, Location *loc) {
+ struct modpart *p = newmodpart(type,s,loc);
+ append (mp,p);
+}
+<<C functions>>=
+static struct modpart *
+newmodpart(int type, char *s, Location *loc) {
+ struct modpart *p = (struct modpart *) malloc (sizeof (struct modpart));
+ checkptr(p);
+ p->ptype = type;
+ if (s) {
+ p->contents = strsave(s);
+ <<strip final newline from p->contents>>
+ }
+ if (loc) p->loc = *loc;
+ p->next = NULL;
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return p;
+}
+<<C functions>>=
+static
+void append(Module mp, struct modpart *p) {
+ /* append p to mp's list of modparts */
+ if (mp->head == NULL) {
+ mp->head = mp->tail = p;
+ } else {
+ mp->tail->next = p;
+ mp->tail = p;
+ }
+}
+<<strip final newline from p->contents>>=
+{ int k = strlen(p->contents)-1;
+ if (p->contents[k] == '\n') p->contents[k] = '\0';
+ else impossible("input line doesn't end with newline");
+}
+@
+<<Function declarations>>=
+static struct modpart *
+newmodpart(int type, char *s, Location *loc); /* create a new module part */
+
+static
+void append(Module mp, struct modpart *p);
+@
+\subsubsection{Expanding modules}
+[[expand]] returns 0 if all is well, nonzero if error.
+A [[struct parent]] chain lists modules currently being expanded,
+so I can detect cycles.
+[[partial_distance]] is the size of the line already written out when
+[[expand]] is called.
+<<header>>=
+typedef struct parent {
+ Module this;
+ struct parent *parent;
+} *Parent;
+
+int expand (Module mp, int indent, int partial_distance, Parent parent,
+ char *locformat, FILE *out);
+ /* expand a module, writing to file out */
+<<local data>>=
+static char *lastfilename = 0;
+static int lastlineno = -1;
+<<header>>=
+void resetloc(void);
+<<C functions>>=
+void resetloc(void) {
+ lastfilename = 0;
+ lastlineno = -1;
+}
+@
+[[indent]] is the amount by which this chunk should be indented.
+[[partial_distance]] is the width of what has already been written to the current line.
+<<C functions>>=
+int expand (Module mp, int indent, int partial_distance, Parent parent,
+ char *locformat, FILE *out) {
+ struct modpart *p;
+ Module newmod;
+ int error=Normal;
+ struct parent thismodule; /* the value only matters when we're expanding a module */
+
+ <<set [[thismodule = {mp, parent}]]>>
+ <<if [[mp]] is an ancestor, complain and return>>
+
+ for (p=mp->head; p!=NULL; p=p->next) {
+ switch (p->ptype) {
+ case STRING: <<print a string>>; break;
+ case MODULE: <<expand a module>>; break;
+ case NEWLINE: <<print a newline>>; break;
+ default: impossible("bad part type");
+ }
+ }
+ return error;
+}
+@
+If the previous line was not partial, this string starts a fresh line
+and it is necessary to indent.
+When emitting [[#line]] directives, don't indent---instead try to
+preserve the original column of the information in the source, as
+well as the line number.
+This means indenting by [[partial_distance]] if a [[#line]] directive
+is emitted, {\em except} when it's the first line of a module (hack! hack!).
+[[printloc]] returns nonzero when [[#line]] is actually emitted.
+
+<<print a string>>=
+if (*(p->contents) != '\0') {
+ if (*locformat) {
+ if (printloc(out,locformat,p->loc,partial_distance) && (p != mp->head))
+ indent_for(partial_distance, out);
+ } else if (partial_distance == 0) {
+ indent_for(indent, out);
+ partial_distance = indent;
+ }
+ fprintf(out,"%s",p->contents);
+ partial_distance = limitcolumn(p->contents, partial_distance);
+}
+<<print a newline>>=
+partial_distance = 0;
+putc('\n', out);
+lastlineno++;
+@
+Previously, when we expanded a module, the partial distance became the
+new indentation level. This was clearly wrong when we were at the
+beginning of the line, so I just hacked a special case for no
+[[locformat]] and zero [[partial_distance]]. It's essentially what
+would be done above for a string of length zero if that weren't hacked
+out as a special case.
+This change probably blows the case where the module being expanded is
+empty.
+<<expand a module>>=
+newmod = lookup(p->contents);
+if (newmod==NULL) {
+ errormsg (Error, "undefined chunk name: @<<%s@>>", p->contents);
+ error=Error;
+} else {
+ int retcode;
+ if (*locformat == 0 && partial_distance == 0) {
+ indent_for(indent, out);
+ partial_distance = indent;
+ }
+ retcode = expand (newmod, partial_distance, partial_distance,
+ &thismodule, locformat, out);
+ if (retcode > error) error = retcode;
+}
+partial_distance = limitcolumn(p->contents, partial_distance + 2) + 2;
+ /* account for surrounding brackets */
+@
+<<set [[thismodule = {mp, parent}]]>>=
+thismodule.this = mp;
+thismodule.parent = parent;
+<<if [[mp]] is an ancestor, complain and return>>=
+if (seekcycle(mp, parent)) {
+ errormsg(Error, "@<<%s@>>", mp->name);
+ return Error;
+}
+<<Function declarations>>=
+static int seekcycle(Module mp, Parent parent);
+<<C functions>>=
+static int seekcycle(Module mp, Parent parent) {
+ if (parent == NULL) {
+ return 0;
+ } else if (parent->this == mp || seekcycle(mp, parent->parent)) {
+ if (parent->this == mp)
+ fprintf(stderr, "Cyclic code chunks: ");
+ fprintf(stderr, "@<<%s@>> -> ", parent->this->name);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+@
+
+Printing locations means emitting [[#line]] numbers.
+[[printloc]] emits a [[#line]] only if the line emitted is out of sequence.
+It returns nonzero when [[#line]] is emitted; zero otherwise.
+The flag [[partial]] tells whether the preceding line was partial.
+If so, then a newline is necessary before [[#line]] can be emitted.
+<<header>>=
+int printloc(FILE *fp, char *fmt, Location loc, int partial);
+<<C functions>>=
+int printloc(FILE *fp, char *fmt, Location loc, int partial) {
+ char *p;
+ if (*fmt
+ && (loc.filename!=lastfilename || lastlineno != loc.lineno)) {
+ if (partial) putc('\n',fp);
+ <<write out the line number pragma>>
+ lastfilename = loc.filename;
+ lastlineno = loc.lineno;
+ return 1;
+ } else return 0;
+}
+<<write out the line number pragma>>=
+for (p = fmt; *p; p++) {
+ if (*p == '%') {
+ switch (*++p) {
+ case '%': putc('%', fp); break;
+ case 'N': putc('\n', fp); break;
+ case 'F': fprintf(fp, "%s", loc.filename); break;
+ case 'L': fprintf(fp, "%d", loc.lineno); break;
+ case '-': case '+':
+ if (isdigit(p[1]) && p[2] == 'L') {
+ fprintf(fp, "%d", *p == '+' ? loc.lineno + (p[1] - '0')
+ : loc.lineno - (p[1] - '0'));
+ p += 2;
+ } else
+ <<complain about bad format character>>
+ break;
+ default: <<complain about bad format character>> break;
+ }
+ } else putc(*p, fp);
+}
+<<complain about bad format character>>=
+{ static int complained = 0;
+ if (!complained) {
+ errormsg(Error,"Bad format sequence ``%%%c'' in -L%s",*p,fmt);
+ complained = 1;
+ }
+}
+@
+
+\subsubsection{Other operations on completed modules}
+For more elegant-looking output, we provide a primitive that removes
+the final newline from a module.
+
+We will use [[apply_each_module]] to remove trailing newlines
+from each module.
+This serves two purposes: first, our output looks nicer, and, second,
+it makes it possible to define a module that doesn't end with newline.
+
+As they are read in, all modules end with newline, by definition.%
+\footnote{Except of course if this input came from an uncorrected nuweb file,
+in which case modules needn't end with newlines. Eventually one hopes
+I'll fix numarkup to insert exactly the newlines that would be removed here.}
+We remove all of the trailing newlines.
+<<header>>=
+void remove_final_newline (Module mp);
+ /* remove trailing newline that must be in module */
+<<C functions>>=
+void remove_final_newline (Module mp) {
+ /* remove trailing newline that must be in module */
+ if (mp->tail==NULL) /* module has no text */
+ return;
+ if (mp->tail->ptype != NEWLINE)
+ /* do nothing --- this is possible with nuweb front end
+ formerly: impossible("Module doesn't end with newline"); */
+ ;
+ else if (mp->tail == mp->head)
+ mp->head = mp->tail = NULL;
+ else {
+ struct modpart *p = mp->head;
+ while (p->next != mp->tail) p = p->next;
+ p->next = NULL;
+ }
+}
diff --git a/web/noweb/src/c/notangle.c b/web/noweb/src/c/notangle.c
new file mode 100644
index 0000000000..ac5c3599ab
--- /dev/null
+++ b/web/noweb/src/c/notangle.c
@@ -0,0 +1,189 @@
+#line 18 "notangle.nw"
+static char rcsid[] = "$Id: notangle.nw,v 2.25 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#define MAX_MODNAME 255
+#line 23 "notangle.nw"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "strsave.h"
+#include "getline.h"
+#include "modules.h"
+#include "modtrees.h"
+#include "errors.h"
+#include "match.h"
+#include "notangle.h"
+
+#line 163 "notangle.nw"
+static void warn_dots(char *modname); /* warn about names ending in ... */
+
+#line 182 "notangle.nw"
+void insist(char *line, char *keyword, char *msg);
+
+#line 37 "notangle.nw"
+void emit_module_named (FILE *out, char *rootname, char *locformat) {
+ Module root = NULL; /* ptr to root module */
+
+ root = lookup(rootname);
+
+#line 167 "notangle.nw"
+if (root==NULL) {
+ errormsg(Fatal, "The root module <<%s>> was not defined.", rootname);
+ return;
+}
+#line 42 "notangle.nw"
+ (void) expand(root,0,0,0,locformat,out);
+ putc('\n',out); /* make output end with newline */
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+}
+#line 58 "notangle.nw"
+void read_defs(FILE *in) {
+ char modname[MAX_MODNAME+1] = ""; /* name of module currently being read,
+ [[""]] if no module is being read */
+ Module modptr = NULL; /* ptr to current module, or NULL */
+ char *line = NULL; /* buffer for input */
+ Location loc;
+
+ while ((line = getline_nw(in)) != NULL) {
+ if (is_keyword(line, "fatal")) exit(1);
+
+#line 103 "notangle.nw"
+if (is_keyword(line, "nl") || is_index(line, "nl")) {
+ loc.lineno++;
+#line 115 "notangle.nw"
+} else if (is_keyword(line,"file")) {
+
+#line 128 "notangle.nw"
+{ char temp[MAX_MODNAME+1];
+ if (strlen(line) >= MAX_MODNAME + strlen("@file "))
+ overflow("file name size");
+ strcpy(temp,line+strlen("@file "));
+ temp[strlen(temp)-1]='\0';
+ loc.filename = strsave(temp);
+}
+#line 117 "notangle.nw"
+ loc.lineno = 1;
+} else if (is_keyword(line, "line")) {
+
+#line 136 "notangle.nw"
+{ char temp[MAX_MODNAME+1];
+ if (strlen(line) >= MAX_MODNAME + strlen("@line "))
+ overflow("file name size");
+ strcpy(temp,line+strlen("@line "));
+ temp[strlen(temp)-1]='\0';
+
+#line 145 "notangle.nw"
+{ char *p;
+ for (p = temp; *p; p++)
+ if (!isdigit(*p))
+ errormsg(Error, "non-numeric line number in `@line %s'", temp);
+}
+#line 142 "notangle.nw"
+ loc.lineno = atoi(temp);
+}
+#line 120 "notangle.nw"
+ loc.lineno--;
+#line 106 "notangle.nw"
+}
+if (!is_begin(line, "code"))
+ continue;
+#line 68 "notangle.nw"
+
+#line 99 "notangle.nw"
+do { line = getline_nw(in);
+} while (line != NULL && !is_keyword(line,"defn") && !is_keyword(line,"text"));
+#line 69 "notangle.nw"
+ insist(line,"defn","code chunk had no definition line");
+
+#line 125 "notangle.nw"
+strcpy(modname,line+strlen("@defn "));
+modname[strlen(modname)-1]='\0';
+#line 71 "notangle.nw"
+ warn_dots(modname); /* names ending in ... aren't like web */
+ modptr = insert(modname); /* find or add module in table */
+
+ line = getline_nw(in);
+ insist(line,"nl","definition line not followed by newline");
+ loc.lineno++;
+ line = getline_nw(in);
+ while (line != NULL && !is_end(line,"code")) {
+ if (is_keyword(line,"nl")) {
+ addnewline(modptr);
+ loc.lineno++;
+ } else if (is_keyword(line,"text")) {
+ addstring(modptr,line+1+4+1,loc);
+ } else if (is_keyword(line,"use")) {
+ warn_dots(line+1+3+5);
+ addmodule(modptr,line+1+3+1);
+ } else if (is_index(line, "nl")) {
+ loc.lineno++;
+
+#line 115 "notangle.nw"
+} else if (is_keyword(line,"file")) {
+
+#line 128 "notangle.nw"
+{ char temp[MAX_MODNAME+1];
+ if (strlen(line) >= MAX_MODNAME + strlen("@file "))
+ overflow("file name size");
+ strcpy(temp,line+strlen("@file "));
+ temp[strlen(temp)-1]='\0';
+ loc.filename = strsave(temp);
+}
+#line 117 "notangle.nw"
+ loc.lineno = 1;
+} else if (is_keyword(line, "line")) {
+
+#line 136 "notangle.nw"
+{ char temp[MAX_MODNAME+1];
+ if (strlen(line) >= MAX_MODNAME + strlen("@line "))
+ overflow("file name size");
+ strcpy(temp,line+strlen("@line "));
+ temp[strlen(temp)-1]='\0';
+
+#line 145 "notangle.nw"
+{ char *p;
+ for (p = temp; *p; p++)
+ if (!isdigit(*p))
+ errormsg(Error, "non-numeric line number in `@line %s'", temp);
+}
+#line 142 "notangle.nw"
+ loc.lineno = atoi(temp);
+}
+#line 120 "notangle.nw"
+ loc.lineno--;
+#line 90 "notangle.nw"
+ } else if (!is_keyword(line, "index"))
+
+#line 184 "notangle.nw"
+errorat(loc.filename, loc.lineno, Error, "botched code chunk `%s'", line);
+#line 92 "notangle.nw"
+ line = getline_nw(in);
+ }
+
+#line 178 "notangle.nw"
+if (line==NULL) {
+ impossible("End of file occurred in mid-module");
+}
+#line 95 "notangle.nw"
+ }
+}
+#line 156 "notangle.nw"
+static
+void warn_dots(char *modname) {
+ if (!strcmp(modname+strlen(modname)-3,"..."))
+ errormsg(Warning, "Module name <<%s>> isn't completed as in web",
+ modname);
+}
+#line 172 "notangle.nw"
+void insist(char *line, char *keyword, char *msg) {
+
+#line 178 "notangle.nw"
+if (line==NULL) {
+ impossible("End of file occurred in mid-module");
+}
+#line 174 "notangle.nw"
+ if (!is_keyword(line,keyword))
+ impossible(msg);
+}
diff --git a/web/noweb/src/c/notangle.h b/web/noweb/src/c/notangle.h
new file mode 100644
index 0000000000..359c15150a
--- /dev/null
+++ b/web/noweb/src/c/notangle.h
@@ -0,0 +1,2 @@
+void emit_module_named (FILE *out, char *rootname, char *locformat);
+void read_defs(FILE *in); /* read module definitions */
diff --git a/web/noweb/src/c/notangle.nw b/web/noweb/src/c/notangle.nw
new file mode 100644
index 0000000000..c40c3f3684
--- /dev/null
+++ b/web/noweb/src/c/notangle.nw
@@ -0,0 +1,184 @@
+% Copyright 1991 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+@
+\subsection{Tangling a single file}
+A cheap imitation of tangle.
+The idea is a very cheap implementation of tangle.
+The markup of the file is described in file markup.ow.
+@
+The structure of the program is as follows: first we accumulate all of
+the module definitions, then we write out the definition of the
+root module (normally [["*"]]).
+The module definition information will be stored statically
+in a table supplied by [[modtrees.h]]; we'll cover the
+details later.
+<<header>>=
+void emit_module_named (FILE *out, char *rootname, char *locformat);
+<<*>>=
+static char rcsid[] = "$Id: notangle.nw,v 2.25 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#define MAX_MODNAME 255
+@
+<<*>>=
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "strsave.h"
+#include "getline.h"
+#include "modules.h"
+#include "modtrees.h"
+#include "errors.h"
+#include "match.h"
+#include "notangle.h"
+
+<<Function declarations>>
+
+void emit_module_named (FILE *out, char *rootname, char *locformat) {
+ Module root = NULL; /* ptr to root module */
+
+ root = lookup(rootname);
+ <<quit if we couldn't find the root>>
+ (void) expand(root,0,0,0,locformat,out);
+ putc('\n',out); /* make output end with newline */
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+}
+@
+We loop looking for the start of a code chunk.
+When we find one, we get the name of the module in which the code
+is to appear.
+Then we just keep adding lines to that module until
+we see a terminator.
+After we see the terminator we start all over again looking for another code
+chunk.
+<<header>>=
+void read_defs(FILE *in); /* read module definitions */
+<<*>>=
+void read_defs(FILE *in) {
+ char modname[MAX_MODNAME+1] = ""; /* name of module currently being read,
+ [[""]] if no module is being read */
+ Module modptr = NULL; /* ptr to current module, or NULL */
+ char *line = NULL; /* buffer for input */
+ Location loc;
+
+ while ((line = getline_nw(in)) != NULL) {
+ if (is_keyword(line, "fatal")) exit(1);
+ <<track line numbers, then [[continue]] unless [[line]] is [[@begin code]]>>
+ <<repeat [[line = getline_nw(in);]] until EOF, [[@defn]], or [[@text]]>>
+ insist(line,"defn","code chunk had no definition line");
+ <<copy module name into [[modname]]>>
+ warn_dots(modname); /* names ending in ... aren't like web */
+ modptr = insert(modname); /* find or add module in table */
+
+ line = getline_nw(in);
+ insist(line,"nl","definition line not followed by newline");
+ loc.lineno++;
+ line = getline_nw(in);
+ while (line != NULL && !is_end(line,"code")) {
+ if (is_keyword(line,"nl")) {
+ addnewline(modptr);
+ loc.lineno++;
+ } else if (is_keyword(line,"text")) {
+ addstring(modptr,line+1+4+1,loc);
+ } else if (is_keyword(line,"use")) {
+ warn_dots(line+1+3+5);
+ addmodule(modptr,line+1+3+1);
+ } else if (is_index(line, "nl")) {
+ loc.lineno++;
+ <<[[} else if (line]] contains [[@file]] or [[@line) {]] adjust [[loc]]>>
+ } else if (!is_keyword(line, "index"))
+ <<complain of botched code chunk>>
+ line = getline_nw(in);
+ }
+ <<if [[line==NULL]] die of premature end of file>>
+ }
+}
+@
+<<repeat [[line = getline_nw(in);]] until EOF, [[@defn]], or [[@text]]>>=
+do { line = getline_nw(in);
+} while (line != NULL && !is_keyword(line,"defn") && !is_keyword(line,"text"));
+@
+<<track line numbers, then [[continue]] unless [[line]] is [[@begin code]]>>=
+if (is_keyword(line, "nl") || is_index(line, "nl")) {
+ loc.lineno++;
+<<[[} else if (line]] contains [[@file]] or [[@line) {]] adjust [[loc]]>>
+}
+if (!is_begin(line, "code"))
+ continue;
+@
+The only tricky bit with the line numbers is to note that [[@line]] gives
+the line number of the {\em following} line, not of the line on which the
+[[@line]] appears. That means [[loc.lineno]] must be decremented after it is
+set, so that the next newline will increment it to the correct value.
+<<[[} else if (line]] contains [[@file]] or [[@line) {]] adjust [[loc]]>>=
+} else if (is_keyword(line,"file")) {
+ <<save name from [[line]] ([[@file ...]]) into [[loc.filename]]>>
+ loc.lineno = 1;
+} else if (is_keyword(line, "line")) {
+ <<save line number from [[line]] ([[@line ...]]) into [[loc.lineno]]>>
+ loc.lineno--;
+@
+When copying the module name or a file name,
+we have to strip the trailing newline.
+<<copy module name into [[modname]]>>=
+strcpy(modname,line+strlen("@defn "));
+modname[strlen(modname)-1]='\0';
+<<save name from [[line]] ([[@file ...]]) into [[loc.filename]]>>=
+{ char temp[MAX_MODNAME+1];
+ if (strlen(line) >= MAX_MODNAME + strlen("@file "))
+ overflow("file name size");
+ strcpy(temp,line+strlen("@file "));
+ temp[strlen(temp)-1]='\0';
+ loc.filename = strsave(temp);
+}
+<<save line number from [[line]] ([[@line ...]]) into [[loc.lineno]]>>=
+{ char temp[MAX_MODNAME+1];
+ if (strlen(line) >= MAX_MODNAME + strlen("@line "))
+ overflow("file name size");
+ strcpy(temp,line+strlen("@line "));
+ temp[strlen(temp)-1]='\0';
+ <<fail if string [[temp]] contains a non-digit>>
+ loc.lineno = atoi(temp);
+}
+<<fail if string [[temp]] contains a non-digit>>=
+{ char *p;
+ for (p = temp; *p; p++)
+ if (!isdigit(*p))
+ errormsg(Error, "non-numeric line number in `@line %s'", temp);
+}
+@
+In {\tt WEB}, module names ending in ``...'' may be prefixes
+for other names.
+We don't do anything like that here, but we do warn the user about
+``...'' in case he's got a file converted from {\tt WEB}.
+<<*>>=
+static
+void warn_dots(char *modname) {
+ if (!strcmp(modname+strlen(modname)-3,"..."))
+ errormsg(Warning, "Module name @<<%s@>> isn't completed as in web",
+ modname);
+}
+<<Function declarations>>=
+static void warn_dots(char *modname); /* warn about names ending in ... */
+
+@ Error checking is perenially dull.
+<<quit if we couldn't find the root>>=
+if (root==NULL) {
+ errormsg(Fatal, "The root module @<<%s@>> was not defined.", rootname);
+ return;
+}
+<<*>>=
+void insist(char *line, char *keyword, char *msg) {
+ <<if [[line==NULL]] die of premature end of file>>
+ if (!is_keyword(line,keyword))
+ impossible(msg);
+}
+<<if [[line==NULL]] die of premature end of file>>=
+if (line==NULL) {
+ impossible("End of file occurred in mid-module");
+}
+<<Function declarations>>=
+void insist(char *line, char *keyword, char *msg);
+<<complain of botched code chunk>>=
+errorat(loc.filename, loc.lineno, Error, "botched code chunk `%s'", line);
diff --git a/web/noweb/src/c/nwmktemp b/web/noweb/src/c/nwmktemp
new file mode 100755
index 0000000000..e179bd8944
--- /dev/null
+++ b/web/noweb/src/c/nwmktemp
Binary files differ
diff --git a/web/noweb/src/c/nwmktemp.c b/web/noweb/src/c/nwmktemp.c
new file mode 100644
index 0000000000..31b213065a
--- /dev/null
+++ b/web/noweb/src/c/nwmktemp.c
@@ -0,0 +1,43 @@
+#line 10 "nwmktemp.nw"
+#define _POSIX_C_SOURCE 200809L
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <unistd.h>
+#line 21 "nwmktemp.nw"
+static const char *tmpdir(void) {
+ char *tmpdir = getenv("TMPDIR");
+ if (tmpdir && *tmpdir)
+ return tmpdir;
+ else
+ return "/tmp";
+}
+#line 29 "nwmktemp.nw"
+int main(int argc, char **argv) {
+ char template[] = "nwtemp.XXXXXXXXXX";
+ const char *tmp = tmpdir();
+ char *path = malloc(strlen(tmp) + strlen(template) + 3); /* slash, newline, \0 */
+ int fd;
+
+ assert(argc == 1);
+
+ assert(path);
+ strcpy(path, tmp);
+ path[strlen(tmp)] = '/';
+ strcpy(path+strlen(tmp)+1, template);
+
+ fd = mkstemp(path);
+ if (fd < 0) {
+ perror(argv[0]);
+ free(path);
+ return 1;
+ } else {
+ printf("%s\n", path);
+ free(path);
+ close(fd);
+ return 0;
+ }
+}
diff --git a/web/noweb/src/c/nwmktemp.nw b/web/noweb/src/c/nwmktemp.nw
new file mode 100644
index 0000000000..10c4e20205
--- /dev/null
+++ b/web/noweb/src/c/nwmktemp.nw
@@ -0,0 +1,54 @@
+% -*- mode: Noweb; noweb-code-mode: c-mode -*-
+% Copyright 2018 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+
+\section{Temporary files}
+
+Noweb's shell scripts need a way to create a temporary file, securely.
+This program is a thin wrapper around [[mkstemp]].
+<<*>>=
+#define _POSIX_C_SOURCE 200809L
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <unistd.h>
+@
+Find a temporary directory.
+<<*>>=
+static const char *tmpdir(void) {
+ char *tmpdir = getenv("TMPDIR");
+ if (tmpdir && *tmpdir)
+ return tmpdir;
+ else
+ return "/tmp";
+}
+<<*>>=
+int main(int argc, char **argv) {
+ char template[] = "nwtemp.XXXXXXXXXX";
+ const char *tmp = tmpdir();
+ char *path = malloc(strlen(tmp) + strlen(template) + 3); /* slash, newline, \0 */
+ int fd;
+
+ assert(argc == 1);
+
+ assert(path);
+ strcpy(path, tmp);
+ path[strlen(tmp)] = '/';
+ strcpy(path+strlen(tmp)+1, template);
+
+ fd = mkstemp(path);
+ if (fd < 0) {
+ perror(argv[0]);
+ free(path);
+ return 1;
+ } else {
+ printf("%s\n", path);
+ free(path);
+ close(fd);
+ return 0;
+ }
+}
+@
diff --git a/web/noweb/src/c/pretty.nw b/web/noweb/src/c/pretty.nw
new file mode 100644
index 0000000000..0a5ac01f4c
--- /dev/null
+++ b/web/noweb/src/c/pretty.nw
@@ -0,0 +1,259 @@
+\section{Prettyprinting}
+
+\subsection{API for prettyprinting}
+
+Here is a suitable API for a prettyprinter for noweb.
+Input to be prettyprinted is a sequence of strings, newlines, and
+chunks used. A [[STRING]] is always free of newlines.
+<<API for prettyprinter>>=
+typedef enum parttype {
+ START_OF_CHUNK=1, END_OF_CHUNK, STRING, USE_CHUNK, NEWLINE,
+ LITERAL, DEFINITION, WHATSIT
+} Parttype;
+@ The prettyprinter calls back into the application as follows:
+<<API for prettyprinter>>=
+typedef void (*PrettyPrinterCallback) (void *closure, Parttype type, char *contents);
+@ The [[contents]] must be
+\begin{quote}
+\begin{tabular}{ll}
+[[START_OF_CHUNK]]&The name of the chunk being prettyprinted\\
+[[END_OF_CHUNK]]&[[NULL]]\\
+[[STRING]]&A string with no newlines\\
+[[LITERAL]]${}^*$&A string with no newlines, to get no further formatting\\
+[[USE_CHUNK]]&The name of the chunk referred to\\
+[[NEWLINE]]&[[NULL]]\\
+[[DEFINITION]]${}^*$&An identifier whose definition is in this chunk.\\
+[[WHATSIT]]&An uninterpreted string passed to the callback function
+\end{tabular}
+\end{quote}
+Items marked with a star ($*$) are legal only when the prettyprinter
+is calling back into the application.
+The identifier given in [[DEFINITION]] isn't printed, so if the
+prettyprinter wants to print it, it has to send it twice.
+@
+The prettyprinter exports two calls to the application.
+<<API for prettyprinter>>=
+typedef struct prettyprinter *PrettyPrinter;
+
+extern PrettyPrinter new_prettyprinter(PrettyPrinterCallback callback, void *closure);
+extern void prettyprint(PrettyPrinter pp, Parttype type, char *contents);
+@ The prettyprinter accepts calls to the [[prettyprint]] procedure.
+Any call to [[prettyprint]] may result in one or more callbacks to the
+procedure registered when [[new_prettyprinter]] is called.
+For any given [[PrettyPrinter]], the application must call
+[[prettyprint]] with [[type==END_OF_CHUNK]] exactly once, and that
+call must be the last call.
+
+<<header>>=
+<<API for prettyprinter>>
+@
+\subsection{Calling the prettyprinter}
+
+The assumption here is that we have zero or more prettyprinters
+satisfying the interface above---what are the mechanics of getting
+something prettyprinted.
+We select a prettyprinter based on
+the name of the root chunk.
+
+Because we want to support either a two-pass or one-pass algorithm,
+we don't say how lines will come in or go out, but we do say that we
+will strip all the trailing newlines.
+<<definitions>>=
+void pretty (char *getline(void *in), void *in,
+ void putline(void *out, char *line), void *out,
+ PrettyPrinter make_pp(void *cl, char *name), void *cl)
+{
+ char *line = NULL; /* buffer for input */
+ PrettyPrinter pp;
+ Location loc;
+
+ while ((line = getline(in)) != NULL) {
+ <<adjust [[loc]] if needed>>
+ <<if not [[@begin code]], copy line and [[continue]]>>
+ putline(out, line);
+
+ for (line = getline(in);
+ line && !is_keyword(line,"defn") && !is_keyword(line,"text");
+ line = getline(in)
+ ) putline(out, line);
+ insist(line,"defn","code chunk had no definition line");
+ putline(out, line);
+ pp = make_pp(cl, line+6); /* use chunk name */
+ if (!pp) { <<copy code chunk to [[out]]>>; continue; }
+
+ for (; line && !is_keyword(line, "nl") ;) {
+ line = getline(in); putline(out, line);
+ }
+ insist(line,"nl","definition line not followed by newline");
+ loc.lineno++;
+ for (line = getline(in);
+ line != NULL && !is_end(line,"code");
+ line = getline(in))
+ {
+ <<adjust [[loc]] if needed>>
+ if (is_keyword(line,"nl")) {
+ prettyprint(pp, NEWLINE, NULL);
+ } else if (is_keyword(line,"text")) {
+ prettyprint(pp, STRING, line+1+4+1);
+ } else if (is_keyword(line,"use")) {
+ prettyprint(pp, USE_CHUNK, line+1+3+1);
+ } else {
+ prettyprint(pp, WHATSIT, line);
+ }
+ }
+ prettyprint(pp, END_OF_CHUNK, NULL);
+ <<if [[line==NULL]] die of premature end of file>>
+ putline(out, line);
+ }
+}
+<<if not [[@begin code]], copy line and [[continue]]>>=
+if (!is_begin(line, "code")) {
+ putline(out, line);
+ continue;
+}
+<<copy code chunk to [[out]]>>=
+while ((line = getline(in)) != NULL) {
+ putline(out, line);
+ if (is_end(line, "code")) break;
+}
+@
+<<adjust [[loc]] if needed>>=
+{ if (is_keyword(line, "nl") || is_index(line, "nl")) {
+ loc.lineno++;
+ } else if (is_keyword(line,"file")) {
+ loc.filename = strsave(line + 6);
+ loc.lineno = 1;
+ } else if (is_keyword(line, "line")) {
+ <<save line number from [[line]] ([[@line ...]]) into [[loc.lineno]]>>
+ loc.lineno--;
+ }
+}
+@
+<<save line number from [[line]] ([[@line ...]]) into [[loc.lineno]]>>=
+{ char *temp = line+6;
+ <<fail if string [[temp]] contains a non-digit>>
+ loc.lineno = atoi(temp);
+}
+<<fail if string [[temp]] contains a non-digit>>=
+{ char *p;
+ for (p = temp; *p; p++)
+ if (!isdigit(*p))
+ errormsg(Error, "non-numeric line number in `@line %s'", temp);
+}
+<<definitions>>=
+void insist(char *line, char *keyword, char *msg) {
+ <<if [[line==NULL]] die of premature end of file>>
+ if (!is_keyword(line,keyword))
+ impossible(msg);
+}
+<<if [[line==NULL]] die of premature end of file>>=
+if (line==NULL) {
+ impossible("End of file occurred in mid-module");
+}
+<<declarations>>=
+void insist(char *line, char *keyword, char *msg);
+@
+\subsection{Simple callback procedure}
+We've got a callback to do I/O
+<<definitions>>=
+typedef struct io {
+ FILE *out;
+ void (*putline)(void *out, char *line);
+} *IO;
+
+static void write_pretty(void *closure, Parttype type, char *contents) {
+ IO io = (IO) closure;
+ switch(type) {
+ case START_OF_CHUNK: break;
+ case END_OF_CHUNK: break;
+ case STRING: fprintf(io->out, "@text %s\n", contents); break;
+ case LITERAL: fprintf(io->out, "@literal %s\n", contents); break;
+ case USE_CHUNK: fprintf(io->out, "@use %s\n", contents); break;
+ case NEWLINE: io->putline(io->out, "@nl"); break;
+ case DEFINITION: fprintf(io->out, "@index defn %s\n", contents); break;
+ case WHATSIT: io->putline(io->out, contents); break;
+ default: assert(0);
+ }
+}
+@
+
+\subsection{Sketch for a two-pass driver}
+The best plan would be to use a two-pass driver.
+On the first pass it would
+\begin{itemize}
+\item
+Read in all lines and builds a def-use tree.
+\item
+Decide on a prettyprinter for each root, either using the root name
+or a suffix (and probably based on info from the command line as well
+as defaults).
+\item
+Propagate info from parents to children.
+Inconsistent children (distinct prettyprinters) become new roots.
+\end{itemize}
+Then on the second pass it could use the propagated info to select a
+prettyprinter for each chunk.
+
+\subsection{One-pass driver}
+This just uses a single prettyprinter.
+This means get and put are just I/O.
+<<one-pass definitions>>=
+static char *get_stripped(void *in) {
+ FILE *fp = (FILE *)in;
+ char *line = getline_nw(fp);
+ if (line) {
+ int i = strlen(line) - 1;
+ if (i >= 0 && line[i] == '\n') line[i] = 0;
+ }
+ return line;
+}
+
+static void put_stripped(void *out, char *line) {
+ FILE *fp = (FILE *)out;
+ fputs(line, fp);
+ fputc('\n', fp);
+}
+@
+If we only ever use a single prettyprinter, we make the closure the
+I/O closure.
+As a trick, we return no prettyprinter if the chunk name has a blank.
+<<one-pass definitions>>=
+static PrettyPrinter make_pp(void *cl, char *name) {
+ if (strchr(name, ' ')) return NULL;
+ return new_prettyprinter(write_pretty, cl);
+}
+@
+The program is always a filter, so it uses stdin and stdout.
+<<one-pass definitions>>=
+main (int argc, char *argv[]) {
+ struct io io;
+ io.out = stdout;
+ io.putline = put_stripped;
+ pretty(get_stripped, stdin, put_stripped, stdout, make_pp, &io);
+ return 0;
+}
+@
+\subsection{Boilerplate}
+<<*>>=
+static char rcsid[] = "$Id: pretty.nw,v 1.19 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include "strsave.h"
+#include "getline.h"
+#include "match.h"
+#include "errors.h"
+#include "pretty.h"
+
+typedef struct location { /* identify lines of source */
+ char *filename;
+ int lineno;
+} Location;
+
+<<declarations>>
+<<definitions>>
+<<one-pass definitions>>
+
diff --git a/web/noweb/src/c/readme.nw b/web/noweb/src/c/readme.nw
new file mode 100644
index 0000000000..970878a664
--- /dev/null
+++ b/web/noweb/src/c/readme.nw
@@ -0,0 +1,61 @@
+% Copyright 1991-2018 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+% $Id: readme.nw,v 2.19 2008/10/06 01:03:05 nr Exp nr $
+
+Guidebook.
+
+Here's a breakdown of files by function.
+
+columns.nw Used to help accumulate indentations across module
+ boundaries by measuring the widths of various strings
+ in columns. Depends on your notion of tabs.
+
+errors.nw Functions that issue error messages.
+
+getline.nw Used to read text a line at a time, no matter how
+ long lines might be.
+
+main.nw Process options and so on before calling notangle.
+
+markup.nw Encapsulates all the definitions of how things are
+ labeled in the text: what is a module definition,
+ what terminates it, and so on.
+
+modtrees.nw Provides a table of modules with insert and lookup
+ (no delete). Also can apply an arbitrary function
+ to each module in the table.
+
+modules.nw Defines the abstraction of a module and the operations
+ on it.
+
+notangle.nw Reads a text on one file and writes a program on another.
+ Works by reading module definitions, then expanding
+ the module ``*''.
+
+strsave.nw Return a pointer to a fresh copy of a string.
+
+
+@ History of features.
+
+ 2 Feb 89: improve the visual quality of the output by removing the trailing
+ newline from every module and by tracking indentation.
+
+ 9 Feb 89: parameterize notangle by the name of the root module, and
+ make it a command line option. This will help in writing
+ multiple outputs from a single input.
+
+21 Mar 89: Make markup front end for noweave and notangle.
+ This breaks passing of options for notangle.
+ Tough.
+
+ Much improved cleanliness of implementation.
+
+?? ??? 90: Track string locations for emitting \#line pragmas
+
+Summer 91: Version 2: second syntax for tools, added noroots.
+
+
+@ Bugs.
+There's no distinction between errors and warnings.
+
+Also see the man page.
diff --git a/web/noweb/src/c/recognize.c b/web/noweb/src/c/recognize.c
new file mode 100644
index 0000000000..24469f07d8
--- /dev/null
+++ b/web/noweb/src/c/recognize.c
@@ -0,0 +1,215 @@
+#line 24 "recognize.nw"
+static char rcsid[] = "$Id: recognize.nw,v 1.24 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+static struct keepalive { char *s; struct keepalive *p; } keepalive[] =
+ { {rcsid, keepalive}, {rcsname, keepalive} }; /* avoid warnings */
+#line 39 "recognize.nw"
+#include <string.h>
+#include <stdlib.h>
+#line 54 "recognize.nw"
+typedef struct recognizer *Recognizer;
+#line 69 "recognize.nw"
+typedef void (*Callback) (void *closure, char *id, char *instance);
+#line 52 "recognize.nw"
+Recognizer new_recognizer(char *alphanum, char *symbols);
+#line 60 "recognize.nw"
+void add_ident(Recognizer r, char *id);
+void stop_adding(Recognizer r);
+#line 63 "recognize.nw"
+void search_for_ident(Recognizer r, char *input, Callback f, void *closure);
+#line 76 "recognize.nw"
+typedef struct goto_node Goto_Node;
+typedef struct move_node Move_Node;
+#line 79 "recognize.nw"
+typedef struct name_node {
+ struct name_node *next; /* points to the next name on the output list */
+ char *name;
+} Name_Node;
+#line 84 "recognize.nw"
+struct move_node {
+ Move_Node *next; /* points to the next node on the move list */
+ Goto_Node *state; /* the next state for this character */
+ unsigned char c;
+};
+#line 90 "recognize.nw"
+struct goto_node {
+ Name_Node *output; /* list of words ending in this state */
+ Move_Node *moves; /* list of possible moves */
+ Goto_Node *fail; /* and where to go when no move fits */
+ Goto_Node *next; /* next goto node with same depth */
+};
+#line 97 "recognize.nw"
+struct recognizer {
+ Goto_Node *root[256]; /* might want 128, depending on the character set */
+ char *alphas;
+ char *syms;
+ int max_depth;
+ Goto_Node **depths; /* an array, max_depth long, of lists of goto_nodes,
+ created while adding ids, used while building
+ the failure functions */
+};
+#line 322 "recognize.nw"
+int reject_match(Recognizer r, char *id, char *input, char *current);
+#line 114 "recognize.nw"
+static Goto_Node *goto_lookup(unsigned char c, Goto_Node *g)
+{
+ Move_Node *m = g->moves;
+ while (m && m->c != c)
+ m = m->next;
+ return m ? m->state : NULL;
+}
+#line 127 "recognize.nw"
+Recognizer new_recognizer(char *alphanum, char *symbols)
+{
+ Recognizer r = (Recognizer) calloc(1, sizeof(struct recognizer));
+ r->alphas = alphanum;
+ r->syms = symbols;
+ r->max_depth = 10;
+ r->depths = (Goto_Node **) calloc(r->max_depth, sizeof(Goto_Node *));
+ return r;
+}
+#line 142 "recognize.nw"
+void add_ident(Recognizer r, char *id)
+{
+ int depth = 2;
+ char *p = id;
+ unsigned char c = *p++;
+ Goto_Node *q = r->root[c];
+ if (!q)
+
+#line 162 "recognize.nw"
+{
+ q = (Goto_Node *) calloc(1, sizeof(Goto_Node));
+ r->root[c] = q;
+ q->next = r->depths[1];
+ r->depths[1] = q;
+}
+#line 150 "recognize.nw"
+ c = *p++;
+ while (c) {
+ Goto_Node *new = goto_lookup(c, q);
+ if (!new)
+
+#line 169 "recognize.nw"
+{
+ Move_Node *new_move = (Move_Node *) malloc(sizeof(Move_Node));
+ new = (Goto_Node *) calloc(1, sizeof(Goto_Node));
+ new_move->state = new;
+ new_move->c = c;
+ new_move->next = q->moves;
+ q->moves = new_move;
+ if (depth == r->max_depth)
+
+#line 182 "recognize.nw"
+{
+ int i;
+ Goto_Node **new_depths = (Goto_Node **) calloc(2*depth, sizeof(Goto_Node *));
+ r->max_depth = 2 * depth;
+ for (i=0; i<depth; i++)
+ new_depths[i] = r->depths[i];
+ free(r->depths);
+ r->depths = new_depths;
+}
+#line 178 "recognize.nw"
+ new->next = r->depths[depth];
+ r->depths[depth] = new;
+}
+#line 155 "recognize.nw"
+ q = new;
+ depth++;
+ c = *p++;
+ }
+
+#line 192 "recognize.nw"
+if (!q->output) {
+ char *copy = malloc(strlen(id) + 1);
+ strcpy(copy, id);
+ q->output = (Name_Node *) malloc(sizeof(Name_Node));
+ q->output->next = NULL;
+ q->output->name = copy;
+}
+#line 160 "recognize.nw"
+}
+#line 208 "recognize.nw"
+void stop_adding(Recognizer r)
+{
+ int depth;
+ for (depth=1; depth<r->max_depth; depth++) {
+ Goto_Node *g = r->depths[depth];
+ while (g) {
+ Move_Node *m = g->moves;
+ while (m) {
+ unsigned char a = m->c;
+ Goto_Node *s = m->state;
+ Goto_Node *state = g->fail;
+ while (state && !goto_lookup(a, state))
+ state = state->fail;
+ if (state)
+ s->fail = goto_lookup(a, state);
+ else
+ s->fail = r->root[a];
+ if (s->fail) {
+ Name_Node *p = s->fail->output;
+ while (p) {
+ Name_Node *q = (Name_Node *) malloc(sizeof(Name_Node));
+ q->name = p->name; /* depending on memory deallocation
+ strategy, we may need to copy this */
+ q->next = s->output;
+ s->output = q;
+ p = p->next;
+ }
+ }
+ m = m->next;
+ }
+ g = g->next;
+ }
+ }
+}
+#line 247 "recognize.nw"
+void search_for_ident(Recognizer r, char *input, Callback f, void *closure)
+{
+ Goto_Node *state = NULL;
+ char *current = input;
+ unsigned char c = (unsigned char) *current++;
+ while (c) {
+
+#line 263 "recognize.nw"
+{
+ while (state && !goto_lookup(c, state))
+ state = state->fail;
+ state = state ? goto_lookup(c, state) : r->root[c];
+}
+#line 254 "recognize.nw"
+
+#line 273 "recognize.nw"
+{
+ if (state) {
+ Name_Node *p = state->output;
+ while (p) {
+ if (!reject_match(r, p->name, input, current))
+ f(closure, p->name, current - strlen(p->name));
+ p = p->next;
+ }
+ }
+}
+#line 255 "recognize.nw"
+ c = *current++;
+ }
+}
+#line 297 "recognize.nw"
+int reject_match(Recognizer r, char *id, char *input, char *current)
+{
+ int len = strlen(id);
+ char first = id[0];
+ char last = id[len - 1];
+ char next = *current;
+ char prev = '\0';
+ current = current - len - 1;
+ if (input <= current)
+ prev = *current;
+ if (prev && strchr(r->alphas, first) && strchr(r->alphas, prev)) return 1;
+ if (next && strchr(r->alphas, last ) && strchr(r->alphas, next)) return 1;
+ if (prev && strchr(r->syms, first) && strchr(r->syms, prev)) return 1;
+ if (next && strchr(r->syms, last ) && strchr(r->syms, next)) return 1;
+ return 0;
+}
diff --git a/web/noweb/src/c/recognize.h b/web/noweb/src/c/recognize.h
new file mode 100644
index 0000000000..c2196365e7
--- /dev/null
+++ b/web/noweb/src/c/recognize.h
@@ -0,0 +1,6 @@
+typedef struct recognizer *Recognizer;
+typedef void (*Callback) (void *closure, char *id, char *instance);
+Recognizer new_recognizer(char *alphanum, char *symbols);
+void add_ident(Recognizer r, char *id);
+void stop_adding(Recognizer r);
+void search_for_ident(Recognizer r, char *input, Callback f, void *closure);
diff --git a/web/noweb/src/c/recognize.nw b/web/noweb/src/c/recognize.nw
new file mode 100644
index 0000000000..38b6bbb733
--- /dev/null
+++ b/web/noweb/src/c/recognize.nw
@@ -0,0 +1,322 @@
+% \documentstyle[noweb]{article}
+%
+% \setlength{\oddsidemargin}{0in}
+% \setlength{\evensidemargin}{0in}
+% \setlength{\topmargin}{0in}
+% \addtolength{\topmargin}{-\headheight}
+% \addtolength{\topmargin}{-\headsep}
+% \setlength{\textheight}{8.9in}
+% \setlength{\textwidth}{6.5in}
+% \setlength{\marginparwidth}{0.5in}
+
+\subsection{An Efficient String Matcher (by Preston Briggs)}
+\label{preston}
+
+\subsubsection{Introduction}
+
+The obvious approach to this problem would be quite expensive for
+large documents; however, there is an interesting paper describing an
+efficient solution~\cite{aho:efficient}.
+
+\paragraph{Boilerplate} \indent\null\par
+
+<<*>>=
+static char rcsid[] = "$Id: recognize.nw,v 1.24 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+static struct keepalive { char *s; struct keepalive *p; } keepalive[] =
+ { {rcsid, keepalive}, {rcsname, keepalive} }; /* avoid warnings */
+<<Include files>>
+<<header>>
+<<Type definitions>>
+<<Prototypes>>
+<<Function definitions>>
+@
+<<header>>=
+<<Exported type definitions>>
+<<Exported prototypes>>
+@
+<<Include files>>=
+#include <string.h>
+#include <stdlib.h>
+@
+
+\paragraph{External Interface}
+
+The externally visible interface was designed by Norman Ramsey.
+
+We assume that [[alphanum]] and [[symbols]] point to constant
+strings; {\sl i.e.,} we don't bother to copy them into separately
+allocated space.
+
+<<Exported prototypes>>=
+Recognizer new_recognizer(char *alphanum, char *symbols);
+<<Exported type definitions>>=
+typedef struct recognizer *Recognizer;
+@
+A copy is made of the string pointed to by [[id]].
+It won't hurt to add the same identifier multiple times to a given
+recognizer.
+<<Exported prototypes>>=
+void add_ident(Recognizer r, char *id);
+void stop_adding(Recognizer r);
+<<Exported prototypes>>=
+void search_for_ident(Recognizer r, char *input, Callback f, void *closure);
+@
+
+[[instance]] is a pointer to the place within [[input]] that we
+saw the identifier.
+<<Exported type definitions>>=
+typedef void (*Callback) (void *closure, char *id, char *instance);
+@
+
+\subsubsection{Defining the Automata}
+
+
+<<Type definitions>>=
+typedef struct goto_node Goto_Node;
+typedef struct move_node Move_Node;
+<<Type definitions>>=
+typedef struct name_node {
+ struct name_node *next; /* points to the next name on the output list */
+ char *name;
+} Name_Node;
+<<Type definitions>>=
+struct move_node {
+ Move_Node *next; /* points to the next node on the move list */
+ Goto_Node *state; /* the next state for this character */
+ unsigned char c;
+};
+<<Type definitions>>=
+struct goto_node {
+ Name_Node *output; /* list of words ending in this state */
+ Move_Node *moves; /* list of possible moves */
+ Goto_Node *fail; /* and where to go when no move fits */
+ Goto_Node *next; /* next goto node with same depth */
+};
+<<Type definitions>>=
+struct recognizer {
+ Goto_Node *root[256]; /* might want 128, depending on the character set */
+ char *alphas;
+ char *syms;
+ int max_depth;
+ Goto_Node **depths; /* an array, max_depth long, of lists of goto_nodes,
+ created while adding ids, used while building
+ the failure functions */
+};
+@
+
+\paragraph{A Utility Function}
+
+We need a function that, given the current state and a character, will
+return the next state as directed by the ``goto table.'' If there is
+no defined entry in the table, the function returns [[NULL]].
+<<Function definitions>>=
+static Goto_Node *goto_lookup(unsigned char c, Goto_Node *g)
+{
+ Move_Node *m = g->moves;
+ while (m && m->c != c)
+ m = m->next;
+ return m ? m->state : NULL;
+}
+@
+
+\subsubsection{Building the Automata}
+
+The [[max_depth]] should be initialized to be at least 2.
+<<Function definitions>>=
+Recognizer new_recognizer(char *alphanum, char *symbols)
+{
+ Recognizer r = (Recognizer) calloc(1, sizeof(struct recognizer));
+ r->alphas = alphanum;
+ r->syms = symbols;
+ r->max_depth = 10;
+ r->depths = (Goto_Node **) calloc(r->max_depth, sizeof(Goto_Node *));
+ return r;
+}
+@
+
+\paragraph{Building the Goto Table}
+
+We assume [[id]] is at least 1 character long.
+<<Function definitions>>=
+void add_ident(Recognizer r, char *id)
+{
+ int depth = 2;
+ char *p = id;
+ unsigned char c = *p++;
+ Goto_Node *q = r->root[c];
+ if (!q)
+ <<Create an entry for [[root[c]]]>>
+ c = *p++;
+ while (c) {
+ Goto_Node *new = goto_lookup(c, q);
+ if (!new)
+ <<Create a new goto entry and attach to [[q]]'s move list>>
+ q = new;
+ depth++;
+ c = *p++;
+ }
+ <<Set [[q->output]] to [[id]] (if not already present)>>
+}
+<<Create an entry for [[root[c]]]>>=
+{
+ q = (Goto_Node *) calloc(1, sizeof(Goto_Node));
+ r->root[c] = q;
+ q->next = r->depths[1];
+ r->depths[1] = q;
+}
+<<Create a new goto entry and attach to [[q]]'s move list>>=
+{
+ Move_Node *new_move = (Move_Node *) malloc(sizeof(Move_Node));
+ new = (Goto_Node *) calloc(1, sizeof(Goto_Node));
+ new_move->state = new;
+ new_move->c = c;
+ new_move->next = q->moves;
+ q->moves = new_move;
+ if (depth == r->max_depth)
+ <<Double the size of the [[depths]] array>>
+ new->next = r->depths[depth];
+ r->depths[depth] = new;
+}
+<<Double the size of the [[depths]] array>>=
+{
+ int i;
+ Goto_Node **new_depths = (Goto_Node **) calloc(2*depth, sizeof(Goto_Node *));
+ r->max_depth = 2 * depth;
+ for (i=0; i<depth; i++)
+ new_depths[i] = r->depths[i];
+ free(r->depths);
+ r->depths = new_depths;
+}
+<<Set [[q->output]] to [[id]] (if not already present)>>=
+if (!q->output) {
+ char *copy = malloc(strlen(id) + 1);
+ strcpy(copy, id);
+ q->output = (Name_Node *) malloc(sizeof(Name_Node));
+ q->output->next = NULL;
+ q->output->name = copy;
+}
+@
+
+%\newpage
+\paragraph{Building the Failure Functions}
+
+After all the strings have been added to the goto table, we can
+construct the failure functions. It's going to be hard to explain
+this one.
+<<Function definitions>>=
+void stop_adding(Recognizer r)
+{
+ int depth;
+ for (depth=1; depth<r->max_depth; depth++) {
+ Goto_Node *g = r->depths[depth];
+ while (g) {
+ Move_Node *m = g->moves;
+ while (m) {
+ unsigned char a = m->c;
+ Goto_Node *s = m->state;
+ Goto_Node *state = g->fail;
+ while (state && !goto_lookup(a, state))
+ state = state->fail;
+ if (state)
+ s->fail = goto_lookup(a, state);
+ else
+ s->fail = r->root[a];
+ if (s->fail) {
+ Name_Node *p = s->fail->output;
+ while (p) {
+ Name_Node *q = (Name_Node *) malloc(sizeof(Name_Node));
+ q->name = p->name; /* depending on memory deallocation
+ strategy, we may need to copy this */
+ q->next = s->output;
+ s->output = q;
+ p = p->next;
+ }
+ }
+ m = m->next;
+ }
+ g = g->next;
+ }
+ }
+}
+@
+
+\subsubsection{Using the Automata}
+
+<<Function definitions>>=
+void search_for_ident(Recognizer r, char *input, Callback f, void *closure)
+{
+ Goto_Node *state = NULL;
+ char *current = input;
+ unsigned char c = (unsigned char) *current++;
+ while (c) {
+ <<Goto the next state>>
+ <<Perform the callback for any outputs>>
+ c = *current++;
+ }
+}
+@
+This is all complicated by my use of [[NULL]] to indicate the
+initial state. However, we get a nice speedup by using the [[root]]
+array instead of walking down the move list for every character.
+<<Goto the next state>>=
+{
+ while (state && !goto_lookup(c, state))
+ state = state->fail;
+ state = state ? goto_lookup(c, state) : r->root[c];
+}
+@
+
+We walk down the output list, calling [[f]] with each name that is
+not rejected (see the next section).
+<<Perform the callback for any outputs>>=
+{
+ if (state) {
+ Name_Node *p = state->output;
+ while (p) {
+ if (!reject_match(r, p->name, input, current))
+ f(closure, p->name, current - strlen(p->name));
+ p = p->next;
+ }
+ }
+}
+@
+
+% \newpage
+\paragraph{Rejecting Matches}
+
+A problem with simple substring matching is that the string ``he''
+would match longer strings like ``she'' and ``her.'' Norman Ramsey
+suggested examining the characters occuring immediately before and
+after a match and rejecting the match if it appears to be part of a
+longer token. Of course, the concept of {\sl token\/} is
+language-dependent, so we may be occasionally mistaken.
+For the present, we'll consider the mechanism an experiment.
+
+<<Function definitions>>=
+int reject_match(Recognizer r, char *id, char *input, char *current)
+{
+ int len = strlen(id);
+ char first = id[0];
+ char last = id[len - 1];
+ char next = *current;
+ char prev = '\0';
+ current = current - len - 1;
+ if (input <= current)
+ prev = *current;
+ if (prev && strchr(r->alphas, first) && strchr(r->alphas, prev)) return 1;
+ if (next && strchr(r->alphas, last ) && strchr(r->alphas, next)) return 1;
+ if (prev && strchr(r->syms, first) && strchr(r->syms, prev)) return 1;
+ if (next && strchr(r->syms, last ) && strchr(r->syms, next)) return 1;
+ return 0;
+}
+@ Note we never reject a zero [[prev]] or [[next]], since some
+implementations of [[strchr]] always return true when searching for a
+zero character.
+@
+
+We need a prototype for [[reject_match]], since it's referenced
+before its definition.
+
+<<Prototypes>>=
+int reject_match(Recognizer r, char *id, char *input, char *current);
diff --git a/web/noweb/src/c/strsave.c b/web/noweb/src/c/strsave.c
new file mode 100644
index 0000000000..d27b5b60e1
--- /dev/null
+++ b/web/noweb/src/c/strsave.c
@@ -0,0 +1,17 @@
+#line 6 "strsave.nw"
+static char rcsid[] = "$Id: strsave.nw,v 2.21 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "strsave.h"
+#include "errors.h"
+
+char *strsave (char *s) {
+ char *t = malloc (strlen(s)+1);
+ checkptr(t);
+ strcpy(t,s);
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return t;
+}
diff --git a/web/noweb/src/c/strsave.h b/web/noweb/src/c/strsave.h
new file mode 100644
index 0000000000..e389136964
--- /dev/null
+++ b/web/noweb/src/c/strsave.h
@@ -0,0 +1 @@
+char *strsave (char *s); /* returns a pointer to a fresh copy of s */
diff --git a/web/noweb/src/c/strsave.nw b/web/noweb/src/c/strsave.nw
new file mode 100644
index 0000000000..658e58857c
--- /dev/null
+++ b/web/noweb/src/c/strsave.nw
@@ -0,0 +1,21 @@
+% Copyright 1991 by Norman Ramsey. All rights reserved.
+% See file COPYRIGHT for more information.
+<<header>>=
+char *strsave (char *s); /* returns a pointer to a fresh copy of s */
+<<*>>=
+static char rcsid[] = "$Id: strsave.nw,v 2.21 2008/10/06 01:03:05 nr Exp nr $";
+static char rcsname[] = "$Name: v2_12 $";
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "strsave.h"
+#include "errors.h"
+
+char *strsave (char *s) {
+ char *t = malloc (strlen(s)+1);
+ checkptr(t);
+ strcpy(t,s);
+ (void)rcsid; /* avoid a warning */
+ (void)rcsname; /* avoid a warning */
+ return t;
+}
diff --git a/web/noweb/src/csmake b/web/noweb/src/csmake
new file mode 100755
index 0000000000..7c658591e4
--- /dev/null
+++ b/web/noweb/src/csmake
@@ -0,0 +1,3 @@
+#!/bin/sh
+if [ $# -eq 0 ]; then set all install; fi # "$@" breaks make for empty args
+make CC=gcc BIN=/homes/nr/pkg/noweb/bin LIB=/homes/nr/pkg/noweb/lib MAN=/homes/nr/pkg/noweb/man TEXINPUTS=/homes/nr/pkg/tex/inputs "$@"
diff --git a/web/noweb/src/elisp/noweb-mode.el b/web/noweb/src/elisp/noweb-mode.el
new file mode 100644
index 0000000000..2371e6afda
--- /dev/null
+++ b/web/noweb/src/elisp/noweb-mode.el
@@ -0,0 +1,995 @@
+;; noweb-mode.el - edit noweb files with GNU Emacs
+;; Copyright (C) 1995 by Thorsten.Ohl @ Physik.TH-Darmstadt.de
+;; with a little help from Norman Ramsey <norman@bellcore.com>
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, write to the Free Software
+;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+;;
+;; See bottom of this file for information on language-dependent highlighting
+;;
+;; $Id: noweb-mode.el,v 1.19 2008/10/06 01:03:05 nr Exp nr $
+;; $Name: v2_12 $
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; THIS IS UNRELEASED CODE: IT IS MISSING FUNCTIONALITY AND IT NEEDS CLEANUP ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Put this into your ~/.emacs to use this mode automagically.
+;;
+;; (autoload 'noweb-mode "noweb-mode" "Editing noweb files." t)
+;; (setq auto-mode-alist (append (list (cons "\\.nw$" 'noweb-mode))
+;; auto-mode-alist))
+
+;; NEWS:
+;;
+;; Version 2.12
+;;
+;; From Christan Lynbeck <christian@defun.dk>, a small fix to make
+;; font-lock work with nowbe-mode. It is quite simple, narrow to the
+;; current chunk before calling the appropriate mode function. If one
+;; also sets `font-lock-dont-widen' to true, the effect is that
+;; highlighting only is done inside each chunk.
+;;
+;; Earlier versions:
+;;
+;; * [tho] M-n q, aka: M-x noweb-fill-chunk
+;;
+;; * [tho] M-n TAB, aka: M-x noweb-complete-chunk
+;;
+;; * [tho] noweb-occur
+;;
+;; * [nr] use `M-n' instead of `C-c n' as default command prefix
+;;
+;; * [nr] don't be fooled by
+;;
+;; @
+;; <<foo>>=
+;; int foo;
+;; @ %def foo
+;; Here starts a new documentation chunk!
+;; <<bar>>=
+;; int bar;
+;;
+;; * [nr] switch mode changing commands off during isearch-mode
+;;
+;; * [tho] noweb-goto-chunk proposes a default
+;;
+
+;; TODO:
+;;
+;; * replace obscure hacks like `(stringp (car (noweb-find-chunk)))'
+;; by something more reasonable like `(noweb-code-chunkp)'.
+;;
+;; * _maybe_ replace our `noweb-chunk-vector' by text properties. We
+;; could then use highlighting to jazz up the visual appearance.
+;;
+;; * wrapped `noweb-goto-next' and `noweb-goto-previous'
+;;
+;; * more range checks and error exits
+;;
+;; * commands for tangling, weaving, etc.
+;;
+;; * ...
+;;
+
+;;; Variables
+
+(defconst noweb-mode-RCS-Id
+ "$Id: noweb-mode.el,v 1.19 2008/10/06 01:03:05 nr Exp nr $")
+
+(defconst noweb-mode-RCS-Name
+ "$Name: v2_12 $")
+
+(defvar noweb-mode-prefix "\M-n"
+ "*Prefix key to use for noweb mode commands.
+The value of this variable is checked as part of loading noweb mode.
+After that, changing the prefix key requires manipulating keymaps.")
+
+(defvar noweb-mode-load-hook nil
+ "Hook that is run after noweb mode is loaded.")
+
+(defvar noweb-mode-hook nil
+ "Hook that is run after entering noweb mode.")
+
+(defvar noweb-select-code-mode-hook nil
+ "Hook that is run after the code mode is selected.
+This is the place to overwrite keybindings of the NOWEB-CODE-MODE.")
+
+(defvar noweb-select-doc-mode-hook nil
+ "Hook that is run after the documentation mode is selected.
+This is the place to overwrite keybindings of the NOWEB-DOC-MODE.")
+
+(defvar noweb-select-mode-hook nil
+ "Hook that is run after the documentation or the code mode is selected.
+This is the place to overwrite keybindings of the other modes.")
+
+(defvar noweb-doc-mode 'latex-mode
+ "Major mode for editing documentation chunks.")
+
+(defvar noweb-code-mode 'fundamental-mode
+ "Major mode for editing code chunks. This is set to FUNDAMENTAL-MODE
+by default, but you might want to change this in the Local Variables
+section of your file to something more appropriate, like C-MODE,
+FORTRAN-MODE, or even INDENTED-TEXT-MODE.")
+
+(defvar noweb-chunk-vector nil
+ "Vector of the chunks in this buffer.")
+
+(defvar noweb-narrowing nil
+ "If not NIL, the display will always be narrowed to the
+current chunk pair.")
+
+(defvar noweb-electric-@-and-< t
+ "If not nil, the keys `@' and `<' will be bound to NOWEB-ELECTRIC-@
+and NOWEB-ELECTRIC-<, respectively.")
+
+
+;;; Setup
+(defvar noweb-mode-prefix-map nil
+ "Keymap for noweb mode commands.")
+
+(defvar noweb-mode-menu-map nil
+ "Keymap for noweb mode menu commands.")
+
+(defvar noweb-mode nil
+ "Buffer local variable, T iff this buffer is edited in noweb mode.")
+
+(if (not (assq 'noweb-mode minor-mode-alist))
+ (setq minor-mode-alist (append minor-mode-alist
+ (list '(noweb-mode " Noweb")))))
+
+(defun noweb-minor-mode ()
+ "Minor meta mode for editing noweb files. See NOWEB-MODE."
+ (interactive)
+ (noweb-mode))
+
+(defun noweb-mode (&optional arg-for-desktop-read)
+ "Minor meta mode for editing noweb files.
+`Meta' refers to the fact that this minor mode is switching major
+modes depending on the location of point.
+
+The following special keystrokes are available in noweb mode:
+
+Movement:
+\\[noweb-next-chunk] \tgoto the next chunk
+\\[noweb-previous-chunk] \tgoto the previous chunk
+\\[noweb-goto-previous] \tgoto the previous chunk of the same name
+\\[noweb-goto-next] \tgoto the next chunk of the same name
+\\[noweb-goto-chunk] \tgoto a chunk
+\\[noweb-next-code-chunk] \tgoto the next code chunk
+\\[noweb-previous-code-chunk] \tgoto the previous code chunk
+\\[noweb-next-doc-chunk] \tgoto the next documentation chunk
+\\[noweb-previous-doc-chunk] \tgoto the previous documentation chunk
+
+Copying/Killing/Marking/Narrowing:
+\\[noweb-copy-chunk-as-kill] \tcopy the chunk the point is in into the kill ring
+\\[noweb-copy-chunk-pair-as-kill] \tcopy the pair of doc/code chunks the point is in
+\\[noweb-kill-chunk] \tkill the chunk the point is in
+\\[noweb-kill-chunk-pair] \tkill the pair of doc/code chunks the point is in
+\\[noweb-mark-chunk] \tmark the chunk the point is in
+\\[noweb-mark-chunk-pair] \tmark the pair of doc/code chunks the point is in
+\\[noweb-narrow-to-chunk] \tnarrow to the chunk the point is in
+\\[noweb-narrow-to-chunk-pair] \tnarrow to the pair of doc/code chunks the point is in
+\\[widen] \twiden
+\\[noweb-toggle-narrowing] \ttoggle auto narrowing
+
+Filling:
+\\[noweb-fill-chunk] \tfill the chunk at point according to mode.
+\\[noweb-fill-paragraph-chunk] \tfill the paragraph at point, restricted to chunk.
+
+Insertion:
+\\[noweb-insert-mode-line] \tinsert a line to set this file's code mode
+\\[noweb-new-chunk] \tinsert a new chunk at point
+\\[noweb-complete-chunk] \tcomplete the chunk name before point.
+\\[noweb-electric-@] \tinsert a `@' or start a new doc chunk.
+\\[noweb-electric-<] \tinsert a `<' or start a new code chunk.
+
+Modes:
+\\[noweb-set-doc-mode] \tchange the major mode for editing documentation chunks
+\\[noweb-set-code-mode] \tchange the major mode for editing code chunks
+
+Misc:
+\\[noweb-occur] \tfind all occurrences of the current chunk
+\\[noweb-update-chunk-vector] \tupdate the markers for chunks
+\\[noweb-describe-mode] \tdescribe noweb-mode
+\\[noweb-mode-version] \tshow noweb-mode's version in the minibuffer
+"
+ (interactive)
+ (mapcar 'noweb-make-variable-permanent-local
+ '(noweb-mode
+ noweb-narrowing
+ noweb-chunk-vector
+ post-command-hook
+ isearch-mode-hook
+ isearch-mode-end-hook
+ noweb-doc-mode
+ noweb-code-mode))
+ (setq noweb-mode t)
+ (noweb-setup-keymap)
+ (noweb-update-chunk-vector)
+ (add-hook 'post-command-hook 'noweb-post-command-hook)
+ (add-hook 'noweb-select-doc-mode-hook 'noweb-auto-fill-doc-mode)
+ (add-hook 'noweb-select-code-mode-hook 'noweb-auto-fill-code-mode)
+ (add-hook 'isearch-mode-hook 'noweb-note-isearch-mode)
+ (add-hook 'isearch-mode-end-hook 'noweb-note-isearch-mode-end)
+ (run-hooks 'noweb-mode-hook)
+ (message "noweb mode: use `M-x noweb-describe-mode' for further information"))
+
+(defun noweb-setup-keymap ()
+ "Setup the noweb-mode keymap. This function is rerun every time the
+major modes changes, because it might have grabbed the keys."
+ (if noweb-mode-prefix-map
+ nil
+ (setq noweb-mode-prefix-map (make-sparse-keymap))
+ (noweb-bind-keys))
+ (if noweb-mode-menu-map
+ nil
+ (setq noweb-mode-menu-map (make-sparse-keymap "Noweb"))
+ (noweb-bind-menu))
+ (if noweb-electric-@-and-<
+ (progn
+ (local-set-key "@" 'noweb-electric-@)
+ (local-set-key "<" 'noweb-electric-<)))
+ (local-set-key "\M-q" 'noweb-fill-paragraph-chunk)
+ (local-set-key noweb-mode-prefix noweb-mode-prefix-map)
+ (local-set-key [menu-bar noweb] (cons "Noweb" noweb-mode-menu-map)))
+
+ (defun noweb-bind-keys ()
+ "Establish noweb mode key bindings."
+ (define-key noweb-mode-prefix-map "\C-n" 'noweb-next-chunk)
+ (define-key noweb-mode-prefix-map "\C-p" 'noweb-previous-chunk)
+ (define-key noweb-mode-prefix-map "\M-n" 'noweb-goto-next)
+ (define-key noweb-mode-prefix-map "\M-m" 'noweb-insert-mode-line)
+ (define-key noweb-mode-prefix-map "\M-p" 'noweb-goto-previous)
+ (define-key noweb-mode-prefix-map "c" 'noweb-next-code-chunk)
+ (define-key noweb-mode-prefix-map "C" 'noweb-previous-code-chunk)
+ (define-key noweb-mode-prefix-map "d" 'noweb-next-doc-chunk)
+ (define-key noweb-mode-prefix-map "D" 'noweb-previous-doc-chunk)
+ (define-key noweb-mode-prefix-map "g" 'noweb-goto-chunk)
+ (define-key noweb-mode-prefix-map "\C-l" 'noweb-update-chunk-vector)
+ (define-key noweb-mode-prefix-map "\M-l" 'noweb-update-chunk-vector)
+ (define-key noweb-mode-prefix-map "w" 'noweb-copy-chunk-as-kill)
+ (define-key noweb-mode-prefix-map "W" 'noweb-copy-chunk-pair-as-kill)
+ (define-key noweb-mode-prefix-map "k" 'noweb-kill-chunk)
+ (define-key noweb-mode-prefix-map "K" 'noweb-kill-chunk-pair)
+ (define-key noweb-mode-prefix-map "m" 'noweb-mark-chunk)
+ (define-key noweb-mode-prefix-map "M" 'noweb-mark-chunk-pair)
+ (define-key noweb-mode-prefix-map "n" 'noweb-narrow-to-chunk)
+ (define-key noweb-mode-prefix-map "N" 'noweb-narrow-to-chunk-pair)
+ (define-key noweb-mode-prefix-map "t" 'noweb-toggle-narrowing)
+ (define-key noweb-mode-prefix-map "\t" 'noweb-complete-chunk)
+ (define-key noweb-mode-prefix-map "q" 'noweb-fill-chunk)
+ (define-key noweb-mode-prefix-map "i" 'noweb-new-chunk)
+ (define-key noweb-mode-prefix-map "o" 'noweb-occur)
+ (define-key noweb-mode-prefix-map "v" 'noweb-mode-version)
+ (define-key noweb-mode-prefix-map "h" 'noweb-describe-mode)
+ (define-key noweb-mode-prefix-map "\C-h" 'noweb-describe-mode))
+
+ (defun noweb-bind-menu ()
+ "Establish noweb mode menu bindings."
+ (define-key noweb-mode-menu-map [noweb-mode-version]
+ '("Version" . noweb-mode-version))
+ (define-key noweb-mode-menu-map [noweb-describe-mode]
+ '("Help" . noweb-describe-mode))
+ (define-key noweb-mode-menu-map [separator-noweb-help] '("--"))
+ (define-key noweb-mode-menu-map [noweb-occur]
+ '("Chunk occurrences" . noweb-occur))
+ (define-key noweb-mode-menu-map [noweb-update-chunk-vector]
+ '("Update the chunk vector" . noweb-update-chunk-vector))
+ (define-key noweb-mode-menu-map [noweb-new-chunk]
+ '("Insert new chunk" . noweb-new-chunk))
+ (define-key noweb-mode-menu-map [noweb-fill-chunk]
+ '("Fill current chunk" . noweb-fill-chunk))
+ (define-key noweb-mode-menu-map [noweb-complete-chunk]
+ '("Complete chunk name" . noweb-complete-chunk))
+ (define-key noweb-mode-menu-map [separator-noweb-chunks] '("--"))
+ (define-key noweb-mode-menu-map [noweb-toggle-narrowing]
+ '("Toggle auto narrowing" . noweb-toggle-narrowing))
+ (define-key noweb-mode-menu-map [noweb-narrow-to-chunk-pair]
+ '("Narrow to chunk pair" . noweb-narrow-to-chunk-pair))
+ (define-key noweb-mode-menu-map [noweb-narrow-to-chunk]
+ '("Narrow to chunk" . noweb-narrow-to-chunk))
+ (define-key noweb-mode-menu-map [noweb-mark-chunk-pair]
+ '("Mark chunk pair" . noweb-mark-chunk-pair))
+ (define-key noweb-mode-menu-map [noweb-mark-chunk]
+ '("Mark chunk" . noweb-mark-chunk))
+ (define-key noweb-mode-menu-map [noweb-kill-chunk-pair]
+ '("Kill chunk pair" . noweb-kill-chunk-pair))
+ (define-key noweb-mode-menu-map [noweb-kill-chunk]
+ '("Kill chunk" . noweb-kill-chunk))
+ (define-key noweb-mode-menu-map [noweb-copy-chunk-pair-as-kill]
+ '("Copy chunk pair" . noweb-copy-chunk-pair-as-kill))
+ (define-key noweb-mode-menu-map [noweb-copy-chunk-as-kill]
+ '("Copy chunk" . noweb-copy-chunk-as-kill))
+ (define-key noweb-mode-menu-map [separator-noweb-move] '("--"))
+ (define-key noweb-mode-menu-map [noweb-next-doc-chunk]
+ '("Next documentation chunk" . noweb-next-doc-chunk))
+ (define-key noweb-mode-menu-map [noweb-previous-doc-chunk]
+ '("Previous documentation chunk" . noweb-previous-doc-chunk))
+ (define-key noweb-mode-menu-map [noweb-next-code-chunk]
+ '("Next code chunk" . noweb-next-code-chunk))
+ (define-key noweb-mode-menu-map [noweb-previous-code-chunk]
+ '("Previous code chunk" . noweb-previous-code-chunk))
+ (define-key noweb-mode-menu-map [noweb-goto-chunk]
+ '("Goto chunk" . noweb-goto-chunk))
+ (define-key noweb-mode-menu-map [noweb-goto-next]
+ '("Next chunk of same name" . noweb-goto-next))
+ (define-key noweb-mode-menu-map [noweb-goto-previous]
+ '("Previous chunk of same name" . noweb-goto-previous))
+ (define-key noweb-mode-menu-map [noweb-next-chunk]
+ '("Next chunk" . noweb-next-chunk))
+ (define-key noweb-mode-menu-map [noweb-previous-chunk]
+ '("Previous chunk" . noweb-previous-chunk)))
+
+(defun noweb-make-variable-permanent-local (var)
+ "Declare VAR buffer local, but protect it from beeing killed
+by major mode changes."
+ (make-variable-buffer-local var)
+ (put var 'permanent-local 't))
+
+(defun noweb-note-isearch-mode ()
+ "Take note of an incremental search in progress"
+ (remove-hook 'post-command-hook 'noweb-post-command-hook))
+
+(defun noweb-note-isearch-mode-end ()
+ "Take note of an incremental search having ended"
+ (add-hook 'post-command-hook 'noweb-post-command-hook))
+
+(defun noweb-post-command-hook ()
+ "The hook being run after each command in noweb mode."
+ (noweb-select-mode)
+ ;; reinstall our keymap if the major mode screwed it up:
+ (noweb-setup-keymap))
+
+
+;;; Chunks
+
+(defvar *noweb-chunk-regexp*
+ "^\\(@\\( \\|$\\|\\( %def\\)\\)\\|<<\\(.*\\)>>=\\)"
+ "Regular expression usuable for finding chunk boundaries.")
+
+(defun noweb-update-chunk-vector ()
+ "Scan the whole buffer and place a marker at each \"^@\" and \"^<<\".
+Record them in NOWEB-CHUNK-VECTOR."
+ (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ (let ((chunk-list (list (cons 'doc (point-marker)))))
+ (while (re-search-forward *noweb-chunk-regexp* nil t)
+ (goto-char (match-beginning 0))
+ ;; If the 3rd subexpression matched @ %def, we're still in a code
+ ;; chunk (sort of), so don't place a marker here.
+ (if (not (match-beginning 3))
+ (setq chunk-list
+ ;; If the 4th subexpression matched inside <<...>>, we're seeing
+ ;; a new code chunk.
+ (cons (cons (if (match-beginning 4)
+ (buffer-substring (match-beginning 4) (match-end 4))
+ 'doc)
+ (point-marker))
+ chunk-list))
+ ;; Scan forward either to !/^@ %def/, which will start a docs chunk,
+ ;; or to /^<<.*>>=$/, which will start a code chunk.
+ (progn
+ (next-line 1)
+ (while (looking-at "@ %def")
+ (next-line 1))
+ (setq chunk-list
+ ;; Now we can tell code vs docs
+ (cons (cons (if (looking-at "<<\\(.*\\)>>=")
+ (buffer-substring (match-beginning 1) (match-end 1))
+ 'doc)
+ (point-marker))
+ chunk-list))))
+ (next-line 1))
+ (setq chunk-list (cons (cons 'doc (point-max-marker)) chunk-list))
+ (setq noweb-chunk-vector (vconcat (reverse chunk-list))))))
+
+(defun noweb-find-chunk ()
+ "Return a pair consisting of the name (or 'DOC) and the
+marker of the current chunk."
+ (if (not noweb-chunk-vector)
+ (noweb-update-chunk-vector))
+ (aref noweb-chunk-vector (noweb-find-chunk-index-buffer)))
+
+(defun noweb-find-chunk-index-buffer ()
+ "Return the index of the current chunk in NOWEB-CHUNK-VECTOR."
+ (noweb-find-chunk-index 0 (1- (length noweb-chunk-vector))))
+
+(defun noweb-find-chunk-index (low hi)
+ (if (= hi (1+ low))
+ low
+ (let ((med (/ (+ low hi) 2)))
+ (if (<= (point) (cdr (aref noweb-chunk-vector med)))
+ (noweb-find-chunk-index low med)
+ (noweb-find-chunk-index med hi)))))
+
+(defun noweb-chunk-region ()
+ "Return a pair consisting of the beginning and end of the current chunk."
+ (interactive)
+ (let ((start (noweb-find-chunk-index-buffer)))
+ (cons (marker-position (cdr (aref noweb-chunk-vector start)))
+ (marker-position (cdr (aref noweb-chunk-vector (1+ start)))))))
+
+(defun noweb-chunk-pair-region ()
+ "Return a pair consisting of the beginning and end of the current pair of
+documentation and code chunks."
+ (interactive)
+ (let* ((start (noweb-find-chunk-index-buffer))
+ (end (1+ start)))
+ (if (stringp (car (aref noweb-chunk-vector start)))
+ (cons (marker-position (cdr (aref noweb-chunk-vector (1- start))))
+ (marker-position (cdr (aref noweb-chunk-vector end))))
+ (while (not (stringp (car (aref noweb-chunk-vector end))))
+ (setq end (1+ end)))
+ (cons (marker-position (cdr (aref noweb-chunk-vector start)))
+ (marker-position (cdr (aref noweb-chunk-vector (1+ end))))))))
+
+(defun noweb-chunk-vector-aref (i)
+ (if (< i 0)
+ (error "Before first chunk."))
+ (if (>= i (length noweb-chunk-vector))
+ (error "Beyond last chunk."))
+ (aref noweb-chunk-vector i))
+
+(defun noweb-complete-chunk ()
+ "Complete the chunk name before point, if any."
+ (interactive)
+ (if (stringp (car (aref noweb-chunk-vector
+ (noweb-find-chunk-index-buffer))))
+ (let ((end (point))
+ (beg (save-excursion
+ (if (re-search-backward "<<"
+ (save-excursion
+ (beginning-of-line)
+ (point))
+ t)
+ (match-end 0)
+ nil))))
+ (if beg
+ (let* ((pattern (buffer-substring beg end))
+ (alist (noweb-build-chunk-alist))
+ (completion (try-completion pattern alist)))
+ (cond ((eq completion t))
+ ((null completion)
+ (message "Can't find completion for \"%s\"" pattern)
+ (ding))
+ ((not (string= pattern completion))
+ (delete-region beg end)
+ (insert completion)
+ (if (not (looking-at ">>"))
+ (insert ">>")))
+ (t
+ (message "Making completion list...")
+ (with-output-to-temp-buffer "*Completions*"
+ (display-completion-list (all-completions pattern alist)))
+ (message "Making completion list...%s" "done"))))
+ (message "Not at chunk name...")))
+ (message "Not in code chunk...")))
+
+
+;;; Filling, etc
+
+(defun noweb-hide-code-quotes ()
+ "Replace all non blank characters in [[...]] code quotes
+in the current buffer (you might want to narrow to the interesting
+region first) by `*'. Return a list of pairs with the position and
+value of the original strings."
+ (save-excursion
+ (let ((quote-list nil))
+ (goto-char (point-min))
+ (while (re-search-forward "\\[\\[" nil 'move)
+ (let ((beg (match-end 0))
+ (end (if (re-search-forward "\\]\\]" nil t)
+ (match-beginning 0)
+ (point-max))))
+ (goto-char beg)
+ (while (< (point) end)
+ ;; Move on to the next word:
+ (let ((b (progn
+ (skip-chars-forward " \t\n" end)
+ (point)))
+ (e (progn
+ (skip-chars-forward "^ \t\n" end)
+ (point))))
+ (if (> e b)
+ ;; Save the string and a marker to the end of the
+ ;; replacement text. A marker to the beginning is
+ ;; useless. See NOWEB-RESTORE-CODE-QUOTES.
+ (save-excursion
+ (setq quote-list (cons (cons (copy-marker e)
+ (buffer-substring b e))
+ quote-list))
+ (goto-char b)
+ (insert-char ?* (- e b) t)
+ (delete-char (- e b))))))))
+ (reverse quote-list))))
+
+(defun noweb-restore-code-quotes (quote-list)
+ "Reinsert the strings modified by `noweb-hide-code-quotes'."
+ (save-excursion
+ (mapcar '(lambda (q)
+ (let* ((e (marker-position (car q)))
+ ;; Slightly inefficient, but correct way to find
+ ;; the beginning of the word to be replaced.
+ ;; Using the marker at the beginning will loose
+ ;; if whitespace has been rearranged
+ (b (save-excursion
+ (goto-char e)
+ (skip-chars-backward "*")
+ (point))))
+ (delete-region b e)
+ (goto-char b)
+ (insert (cdr q))))
+ quote-list)))
+
+(defun noweb-fill-chunk ()
+ "Fill the current chunk according to mode.
+Run `fill-region' on documentation chunks and `indent-region' on code
+chunks."
+ (interactive)
+ (save-restriction
+ (noweb-narrow-to-chunk)
+ (if (stringp (car (noweb-find-chunk)))
+ (progn
+ ;; Narrow to the code section proper; w/o the first and any
+ ;; index declaration lines.
+ (narrow-to-region (progn
+ (goto-char (point-min))
+ (forward-line 1)
+ (point))
+ (progn
+ (goto-char (point-max))
+ (forward-line -1)
+ (while (looking-at "@")
+ (forward-line -1))
+ (forward-line 1)
+ (point)))
+ (if (or indent-region-function indent-line-function)
+ (indent-region (point-min) (point-max) nil)
+ (error "No indentation functions defined in %s!" major-mode)))
+ (let ((quote-list (noweb-hide-code-quotes)))
+ (fill-region (point-min) (point-max))
+ (noweb-restore-code-quotes quote-list)))))
+
+(defun noweb-fill-paragraph-chunk (&optional justify)
+ "Fill a paragraph in the current chunk."
+ (interactive "P")
+ (noweb-update-chunk-vector)
+ (save-restriction
+ (noweb-narrow-to-chunk)
+ (if (stringp (car (noweb-find-chunk)))
+ (progn
+ ;; Narrow to the code section proper; w/o the first and any
+ ;; index declaration lines.
+ (narrow-to-region (progn
+ (goto-char (point-min))
+ (forward-line 1)
+ (point))
+ (progn
+ (goto-char (point-max))
+ (forward-line -1)
+ (while (looking-at "@")
+ (forward-line -1))
+ (forward-line 1)
+ (point)))
+ (fill-paragraph justify))
+ (let ((quote-list (noweb-hide-code-quotes)))
+ (fill-paragraph justify)
+ (noweb-restore-code-quotes quote-list)))))
+
+(defun noweb-auto-fill-doc-chunk ()
+ "Replacement for `do-auto-fill'."
+ (save-restriction
+ (narrow-to-region (car (noweb-chunk-region))
+ (save-excursion
+ (end-of-line)
+ (point)))
+ (let ((quote-list (noweb-hide-code-quotes)))
+ (do-auto-fill)
+ (noweb-restore-code-quotes quote-list))))
+
+(defun noweb-auto-fill-doc-mode ()
+ "Install the improved auto fill function, iff necessary."
+ (if auto-fill-function
+ (setq auto-fill-function 'noweb-auto-fill-doc-chunk)))
+
+(defun noweb-auto-fill-code-mode ()
+ "Install the default auto fill function, iff necessary."
+ (if auto-fill-function
+ (setq auto-fill-function 'do-auto-fill)))
+
+;;; Marking
+
+(defun noweb-mark-chunk ()
+ "Mark the current chunk."
+ (interactive)
+ (let ((r (noweb-chunk-region)))
+ (goto-char (car r))
+ (push-mark (cdr r) nil t)))
+
+(defun noweb-mark-chunk-pair ()
+ "Mark the current pair of documentation and code chunks."
+ (interactive)
+ (let ((r (noweb-chunk-pair-region)))
+ (goto-char (car r))
+ (push-mark (cdr r) nil t)))
+
+
+;;; Narrowing
+
+(defun noweb-toggle-narrowing (&optional arg)
+ "Toggle if we should narrow the display to the current pair of
+documentation and code chunks after each movement. With argument:
+switch narrowing on."
+ (interactive "P")
+ (if (or arg (not noweb-narrowing))
+ (progn
+ (setq noweb-narrowing t)
+ (noweb-narrow-to-chunk-pair))
+ (setq noweb-narrowing nil)
+ (widen)))
+
+(defun noweb-narrow-to-chunk ()
+ "Narrow the display to the current chunk."
+ (interactive)
+ (let ((r (noweb-chunk-region)))
+ (narrow-to-region (car r) (cdr r))))
+
+(defun noweb-narrow-to-chunk-pair ()
+ "Narrow the display to the current pair of documentation and code chunks."
+ (interactive)
+ (let ((r (noweb-chunk-pair-region)))
+ (narrow-to-region (car r) (cdr r))))
+
+
+;;; Killing
+
+(defun noweb-kill-chunk ()
+ "Kill the current chunk."
+ (interactive)
+ (let ((r (noweb-chunk-region)))
+ (kill-region (car r) (cdr r))))
+
+(defun noweb-kill-chunk-pair ()
+ "Kill the current pair of chunks."
+ (interactive)
+ (let ((r (noweb-chunk-pair-region)))
+ (kill-region (car r) (cdr r))))
+
+(defun noweb-copy-chunk-as-kill ()
+ "Place the current chunk on the kill ring."
+ (interactive)
+ (let ((r (noweb-chunk-region)))
+ (copy-region-as-kill (car r) (cdr r))))
+
+(defun noweb-copy-chunk-pair-as-kill ()
+ "Place the current pair of chunks on the kill ring."
+ (interactive)
+ (let ((r (noweb-chunk-pair-region)))
+ (copy-region-as-kill (car r) (cdr r))))
+
+
+;;; Movement
+
+(defun noweb-sign (n)
+ "Return the sign of N."
+ (if (< n 0) -1 1))
+
+(defun noweb-next-doc-chunk (&optional cnt)
+ "Goto to the Nth documentation chunk from point."
+ (interactive "p")
+ (widen)
+ (let ((start (noweb-find-chunk-index-buffer))
+ (i 1))
+ (while (<= i (abs cnt))
+ (setq start (+ (noweb-sign cnt) start))
+ (while (stringp (car (noweb-chunk-vector-aref start)))
+ (setq start (+ (noweb-sign cnt) start)))
+ (setq i (1+ i)))
+ (goto-char (marker-position (cdr (noweb-chunk-vector-aref start))))
+ (forward-char 1))
+ (if noweb-narrowing
+ (noweb-narrow-to-chunk-pair)))
+
+(defun noweb-previous-doc-chunk (&optional n)
+ "Goto to the -Nth documentation chunk from point."
+ (interactive "p")
+ (noweb-next-doc-chunk (- n)))
+
+(defun noweb-next-code-chunk (&optional cnt)
+ "Goto to the Nth code chunk from point."
+ (interactive "p")
+ (widen)
+ (let ((start (noweb-find-chunk-index-buffer))
+ (i 1))
+ (while (<= i (abs cnt))
+ (setq start (+ (noweb-sign cnt) start))
+ (while (not (stringp (car (noweb-chunk-vector-aref start))))
+ (setq start (+ (noweb-sign cnt) start)))
+ (setq i (1+ i)))
+ (goto-char (marker-position (cdr (noweb-chunk-vector-aref start))))
+ (next-line 1))
+ (if noweb-narrowing
+ (noweb-narrow-to-chunk-pair)))
+
+(defun noweb-previous-code-chunk (&optional n)
+ "Goto to the -Nth code chunk from point."
+ (interactive "p")
+ (noweb-next-code-chunk (- n)))
+
+(defun noweb-next-chunk (&optional n)
+ "If in a documentation chunk, goto to the Nth documentation
+chunk from point, else goto to the Nth code chunk from point."
+ (interactive "p")
+ (if (stringp (car (aref noweb-chunk-vector
+ (noweb-find-chunk-index-buffer))))
+ (noweb-next-code-chunk n)
+ (noweb-next-doc-chunk n)))
+
+(defun noweb-previous-chunk (&optional n)
+ "If in a documentation chunk, goto to the -Nth documentation
+chunk from point, else goto to the -Nth code chunk from point."
+ (interactive "p")
+ (noweb-next-chunk (- n)))
+
+(defvar noweb-chunk-history nil
+ "")
+
+(defun noweb-goto-chunk ()
+ "Goto the named chunk."
+ (interactive)
+ (widen)
+ (let* ((completion-ignore-case t)
+ (alist (noweb-build-chunk-alist))
+ (chunk (completing-read
+ "Chunk: " alist nil t
+ (noweb-goto-chunk-default)
+ noweb-chunk-history)))
+ (goto-char (cdr (assoc chunk alist))))
+ (if noweb-narrowing
+ (noweb-narrow-to-chunk-pair)))
+
+(defun noweb-goto-chunk-default ()
+ (save-excursion
+ (if (re-search-backward "<<"
+ (save-excursion
+ (beginning-of-line)
+ (point))
+ 'move)
+ (goto-char (match-beginning 0)))
+ (if (re-search-forward "<<\\(.*\\)>>"
+ (save-excursion
+ (end-of-line)
+ (point))
+ t)
+ (buffer-substring (match-beginning 1) (match-end 1))
+ nil)))
+
+(defun noweb-build-chunk-alist ()
+ (if (not noweb-chunk-vector)
+ (noweb-update-chunk-vector))
+ ;; The naive recursive solution will exceed MAX-LISP-EVAL-DEPTH in
+ ;; buffers w/ many chunks. Maybe there is a tail recursivce solution,
+ ;; but iterative solutions should be acceptable for dealing with vectors.
+ (let ((alist nil)
+ (i (1- (length noweb-chunk-vector))))
+ (while (>= i 0)
+ (let* ((chunk (aref noweb-chunk-vector i))
+ (name (car chunk))
+ (marker (cdr chunk)))
+ (if (and (stringp name)
+ (not (assoc name alist)))
+ (setq alist (cons (cons name marker) alist))))
+ (setq i (1- i)))
+ alist))
+
+(defun noweb-goto-next (&optional cnt)
+ "Goto the continuation of the current chunk."
+ (interactive "p")
+ (widen)
+ (if (not noweb-chunk-vector)
+ (noweb-update-chunk-vector))
+ (let ((start (noweb-find-chunk-index-buffer)))
+ (if (not (stringp (car (aref noweb-chunk-vector start))))
+ (setq start (1+ start)))
+ (if (stringp (car (noweb-chunk-vector-aref start)))
+ (let ((name (car (noweb-chunk-vector-aref start)))
+ (i 1))
+ (while (<= i (abs cnt))
+ (setq start (+ (noweb-sign cnt) start))
+ (while (not (equal (car (noweb-chunk-vector-aref start))
+ name))
+ (setq start (+ (noweb-sign cnt) start)))
+ (setq i (1+ i)))
+ (goto-char (marker-position
+ (cdr (noweb-chunk-vector-aref start))))
+ (next-line 1))))
+ (if noweb-narrowing
+ (noweb-narrow-to-chunk-pair)))
+
+(defun noweb-goto-previous (&optional cnt)
+ "Goto the previous chunk."
+ (interactive "p")
+ (noweb-goto-next (- cnt)))
+
+(defun noweb-occur (arg)
+ "Find all occurences of the current chunk.
+This function simply runns OCCUR on \"<<NAME>>\"."
+ (interactive "P")
+ (let ((n (if (and arg
+ (numberp arg))
+ arg
+ 0))
+ (idx (noweb-find-chunk-index-buffer)))
+ (if (stringp (car (aref noweb-chunk-vector idx)))
+ (occur (regexp-quote (concat "<<"
+ (car (aref noweb-chunk-vector idx))
+ ">>"))
+ n)
+ (setq idx (1+ idx))
+ (while (not (stringp (car (aref noweb-chunk-vector idx))))
+ (setq idx (1+ idx)))
+ (occur (regexp-quote (concat "<<"
+ (car (aref noweb-chunk-vector idx))
+ ">>"))
+ n))))
+
+
+;;; Insertion
+
+(defun noweb-new-chunk (name)
+ "Insert a new chunk."
+ (interactive "sChunk name: ")
+ (insert "@ \n<<" name ">>=\n")
+ (save-excursion
+ (insert "@ %def \n"))
+ (noweb-update-chunk-vector))
+
+(defun noweb-at-beginning-of-line ()
+ (equal (save-excursion
+ (beginning-of-line)
+ (point))
+ (point)))
+
+(defun noweb-electric-@ (arg)
+ "Smart incarnation of `@', starting a new documentation chunk, maybe.
+If given an numerical argument, it will act just like the dumb `@'.
+Otherwise and if at the beginning of a line in a code chunk:
+insert \"@ \" and update the chunk vector."
+ (interactive "P")
+ (if arg
+ (self-insert-command (if (numberp arg) arg 1))
+ (if (and (noweb-at-beginning-of-line)
+ (stringp (car (noweb-find-chunk))))
+ (progn
+ (insert "@ ")
+ (noweb-update-chunk-vector))
+ (self-insert-command 1))))
+
+(defun noweb-electric-< (arg)
+ "Smart incarnation of `<', starting a new code chunk, maybe.
+If given an numerical argument, it will act just like the dumb `<'.
+Otherwise and if at the beginning of a line in a documentation chunk:
+insert \"<<>>=\" and a newline if necessary. Leave point in the middle
+and and update the chunk vector."
+ (interactive "P")
+ (if arg
+ (self-insert-command (if (numberp arg) arg 1))
+ (if (and (noweb-at-beginning-of-line)
+ (not (stringp (car (noweb-find-chunk)))))
+ (progn
+ (insert "<<")
+ (save-excursion
+ (insert ">>=")
+ (if (not (looking-at "\\s *$"))
+ (newline)))
+ (noweb-update-chunk-vector))
+ (self-insert-command 1))))
+
+
+;;; Modes
+
+(defun noweb-chunk-boundary-backward ()
+ "Find beginning of current chunk."
+ (save-match-data
+ (save-excursion
+ (when (re-search-backward *noweb-chunk-regexp* nil 'move)
+ (goto-char (match-beginning 0)))
+ (point))))
+
+(defun noweb-chunk-boundary-forward ()
+ "Find beginning of next chunk."
+ (save-match-data
+ (save-excursion
+ (when (re-search-forward *noweb-chunk-regexp* nil 'move)
+ (goto-char (match-beginning 0)))
+ (point))))
+
+
+(defun noweb-select-mode ()
+ "Select NOWEB-DOC-MODE or NOWEB-CODE-MODE, as appropriate."
+ (interactive)
+ (let ((beg (noweb-chunk-boundary-backward))
+ (end (noweb-chunk-boundary-forward)))
+ (save-restriction
+ (narrow-to-region beg end)
+ (if (= (char-after beg) ?<)
+ ;; Inside a code chunk
+ (if (equal major-mode noweb-code-mode)
+ nil
+ (funcall noweb-code-mode)
+ (run-hooks 'noweb-select-code-mode-hook)
+ (run-hooks 'noweb-select-mode-hook))
+ ;; Inside a documentation chunk
+ (if (equal major-mode noweb-doc-mode)
+ nil
+ (funcall noweb-doc-mode)
+ (run-hooks 'noweb-select-doc-mode-hook)
+ (run-hooks 'noweb-select-mode-hook))))))
+
+(defun noweb-set-doc-mode (mode)
+ "Change the major mode for editing documentation chunks."
+ (interactive "CNew major mode for documentation chunks: ")
+ (setq noweb-doc-mode mode))
+
+(defun noweb-set-code-mode (mode)
+ "Change the major mode for editing code chunks."
+ (interactive "CNew major mode for code chunks: ")
+ (setq noweb-code-mode mode))
+
+
+;;; Misc
+
+(defun noweb-mode-version ()
+ "Echo the RCS identification of noweb mode."
+ (interactive)
+ (message "Thorsten's noweb-mode (PRERELEASE). RCS: %s"
+ noweb-mode-RCS-Id))
+
+(defun noweb-describe-mode ()
+ "Describe noweb mode."
+ (interactive)
+ (describe-function 'noweb-mode))
+
+(defun noweb-insert-mode-line (arg)
+ "Insert line that will set the noweb mode of this file in emacs"
+ (interactive "CNoweb code mode for this file: ")
+ (save-excursion
+ (goto-char (point-min))
+ (insert "% -*- mode: Noweb; noweb-code-mode: " (symbol-name arg) " -*-\n")))
+
+
+;;; Debugging
+
+(defun noweb-log (s)
+ (let ((b (current-buffer)))
+ (switch-to-buffer (get-buffer-create "*noweb-log*"))
+ (goto-char (point-max))
+ (setq buffer-read-only nil)
+ (insert s)
+ (setq buffer-read-only t)
+ (switch-to-buffer b)))
+
+
+;;; Finale
+
+(run-hooks 'noweb-mode-load-hook)
+(provide 'noweb-mode)
+
+
+;; Local Variables:
+;; mode:emacs-lisp
+;; End:
+
diff --git a/web/noweb/src/icon/Makefile b/web/noweb/src/icon/Makefile
new file mode 100644
index 0000000000..7d9b8db1eb
--- /dev/null
+++ b/web/noweb/src/icon/Makefile
@@ -0,0 +1,151 @@
+SHELL=/bin/sh
+LIB=/dev/null # to be overridden
+BIN=/dev/null # to be overridden
+ICONC=iconc -p -L/usr/X11R6/lib # override to icont if no iconc on your system
+ICONT=icont # override to iconc if all filters should be compiled
+CPIF=| cpif # change to ">" to insure all sources always made
+
+LIBEXECS=totex disambiguate noidx tohtml elide l2h docs2comments \
+ autodefs.tex autodefs.icon autodefs.yacc autodefs.sml autodefs.pascal \
+ autodefs.promela autodefs.lrtl autodefs.asdl autodefs.mmix xchunks pipedocs
+LIBSPECIAL=autodefs.cee
+BINEXECS=noindex sl2h htmltoc
+EXECS=$(LIBEXECS) $(BINEXECS) $(LIBSPECIAL) pdcached
+SRCS=totex.icn disambiguate.icn noidx.icn texdefs.icn icondefs.icn \
+ yaccdefs.icn noindex.icn smldefs.icn tohtml.icn cdefs.icn elide.icn \
+ l2h.icn sl2h.icn pascaldefs.icn promeladefs.icn lrtldefs.icn asdldefs.icn \
+ mmixdefs.icn htmltoc.icn xchunks.icn docs2comments.icn pipedocs.icn pdcached.icn
+
+.SUFFIXES: .nw .icn .html .tex .dvi
+.nw.icn:
+ notangle -L'#line %-1L "%F"%N' $*.nw $(CPIF) $*.icn
+.nw.html:
+ noweave -filter l2h -autodefs icon -html -index $*.nw | htmltoc > $*.html
+.nw.tex:
+ noweave -delay -autodefs icon -index $*.nw > $*.tex
+.tex.dvi:
+ latex $*; while grep -s 'Rerun to get cross' $*.log; do latex $*; done
+
+all: $(EXECS)
+source: $(SRCS)
+touch: $(SRCS)
+ touch $(SRCS)
+
+boot:
+ touch $(SRCS)
+
+install: $(EXECS)
+ cp $(LIBEXECS) $(LIB)
+ cp $(BINEXECS) $(BIN)
+ cp $(LIBSPECIAL) $(LIB)/autodefs.c
+
+uninstall:
+ for i in $(LIBEXECS); do rm -f $(LIB)/$$i; done
+ for i in $(BINEXECS); do rm -f $(BIN)/$$i; done
+ rm -f $(LIB)/autodefs.c
+
+clean:
+ /bin/rm -f *.tex *.dvi *.aux *.log *.blg *.bbl *~ *.toc *.html *.u1 *.u2
+ /bin/rm -f *.[ch] *.ps *.gz
+ /bin/rm -f $(EXECS)
+ /bin/rm -f sl2h
+
+clobber: clean
+ /bin/rm -f *.icn
+
+texdefs.icn: texdefs.nw defns.nw
+ notangle -L'#line %-1L "%F"%N' texdefs.nw defns.nw $(CPIF) texdefs.icn
+icondefs.icn: icondefs.nw defns.nw
+ notangle -L'#line %-1L "%F"%N' icondefs.nw defns.nw $(CPIF) icondefs.icn
+yaccdefs.icn: yaccdefs.nw defns.nw
+ notangle -L'#line %-1L "%F"%N' yaccdefs.nw defns.nw $(CPIF) yaccdefs.icn
+smldefs.icn: smldefs.nw defns.nw
+ notangle -L'#line %-1L "%F"%N' smldefs.nw defns.nw $(CPIF) smldefs.icn
+cdefs.icn: cdefs.nw defns.nw
+ notangle -L'#line %-1L "%F"%N' cdefs.nw defns.nw $(CPIF) cdefs.icn
+pascaldefs.icn: pascaldefs.nw defns.nw
+ notangle -L'#line %-1L "%F"%N' pascaldefs.nw defns.nw $(CPIF) pascaldefs.icn
+promeladefs.icn: promeladefs.nw defns.nw
+ notangle -L'#line %-1L "%F"%N' promeladefs.nw defns.nw $(CPIF) promeladefs.icn
+lrtldefs.icn: lrtldefs.nw defns.nw
+ notangle -L'#line %-1L "%F"%N' lrtldefs.nw defns.nw $(CPIF) lrtldefs.icn
+asdldefs.icn: asdldefs.nw defns.nw
+ notangle -L'#line %-1L "%F"%N' asdldefs.nw defns.nw $(CPIF) asdldefs.icn
+mmixdefs.icn: mmixdefs.nw defns.nw
+ notangle -L'#line %-1L "%F"%N' mmixdefs.nw defns.nw $(CPIF) mmixdefs.icn
+
+autodefs.tex: texdefs.icn
+ $(ICONT) -o autodefs.tex texdefs.icn
+
+autodefs.icon: icondefs.icn
+ $(ICONC) -o autodefs.icon icondefs.icn
+
+autodefs.yacc: yaccdefs.icn
+ $(ICONT) -o autodefs.yacc yaccdefs.icn
+
+autodefs.sml: smldefs.icn
+ $(ICONT) -o autodefs.sml smldefs.icn
+
+autodefs.cee: cdefs.icn
+ $(ICONT) -o autodefs.cee cdefs.icn
+
+autodefs.pascal: pascaldefs.icn
+ $(ICONT) -o autodefs.pascal pascaldefs.icn
+
+autodefs.promela: promeladefs.icn
+ $(ICONT) -o autodefs.promela promeladefs.icn
+
+autodefs.lrtl: lrtldefs.icn
+ $(ICONT) -o autodefs.lrtl lrtldefs.icn
+
+autodefs.asdl: asdldefs.icn
+ $(ICONT) -o autodefs.asdl asdldefs.icn
+
+autodefs.mmix: mmixdefs.icn
+ $(ICONT) -o autodefs.mmix mmixdefs.icn
+
+totex: totex.icn
+ $(ICONC) totex.icn
+
+totexnr: totexnr.icn
+ $(ICONT) totexnr.icn
+
+tohtml: tohtml.icn
+ $(ICONC) tohtml.icn
+
+docs2comments: docs2comments.icn
+ $(ICONT) docs2comments.icn # no longer compiles with iconc
+
+xchunks: xchunks.icn
+ $(ICONT) xchunks.icn
+
+l2h.icn: l2h.nw
+ notangle -L'#line %-1L "%F"%N' -R'l2h.icn' l2h.nw $(CPIF) l2h.icn
+l2h: l2h.icn
+ $(ICONT) -o l2h l2h.icn # no longer compiles with iconc
+
+sl2h.icn: l2h.nw
+ notangle -L'#line %-1L "%F"%N' -R'sl2h.icn' l2h.nw $(CPIF) sl2h.icn
+sl2h: sl2h.icn
+ $(ICONT) -o sl2h sl2h.icn # no longer compiles with iconc
+
+noindex: noindex.icn
+ $(ICONT) noindex.icn
+
+noidx: noidx.icn
+ $(ICONT) noidx.icn # no longer compiles with iconc
+
+elide: elide.icn
+ $(ICONT) elide.icn
+
+pipedocs: pipedocs.icn
+ $(ICONT) pipedocs.icn
+
+pdcached: pdcached.icn
+ $(ICONT) pdcached.icn
+
+disambiguate: disambiguate.icn
+ $(ICONT) disambiguate.icn
+
+htmltoc: htmltoc.icn
+ $(ICONT) htmltoc.icn
diff --git a/web/noweb/src/icon/asdldefs.icn b/web/noweb/src/icon/asdldefs.icn
new file mode 100644
index 0000000000..a1d2a88dbd
--- /dev/null
+++ b/web/noweb/src/icon/asdldefs.icn
@@ -0,0 +1,85 @@
+#line 3 "asdldefs.nw"
+procedure main(args)
+ go()
+end
+#line 7 "asdldefs.nw"
+global idchars
+procedure postpass(name, arg)
+ static kind
+ initial { idchars := &letters ++ &digits ++ '_.'
+ kind := "bogus"
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then (arg || "--") ? (tab(find("--") \ 1) ? {
+ if (optwhite(), any(&lcase), t := tab(many(idchars)), optwhite(), ="=")
+ then
+ undotted(t)
+ while tab(upto(idchars)) do
+ if (="imports", any(' \t')) then
+ (tab(upto(idchars)), tab(many(idchars)))
+ else if any(&ucase) then undotted(tab(many(idchars)))
+ else tab(many(idchars))
+ })
+ }
+ return
+end
+
+procedure undotted(s)
+ return if upto('.', s) then &null else writedefn(s)
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+#line 41 "asdldefs.nw"
+procedure rcsinfo ()
+ return "$Id: asdldefs.nw,v 1.15 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+#line 1 "defns.nw"
+procedure go()
+ local line
+ while line := read() do {
+ apply(prepass, line)
+ write(line)
+ if match("@fatal ", line) then exit(1)
+ apply(postpass, line)
+ }
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+#line 18 "defns.nw"
+procedure writedefn(defn, locl)
+ static indextext
+ initial indextext := ""
+ if /defn then
+ *indextext > 0 &
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 23 "defns.nw"
+ else {
+ if *indextext + *defn > 65 then
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 25 "defns.nw"
+ write(if \locl then "@index localdefn " else "@index defn ", defn)
+ indextext ||:= " " || defn
+ }
+ return
+end
+#line 35 "defns.nw"
+procedure rcsinfo_too ()
+ return "$Id: defns.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/asdldefs.nw b/web/noweb/src/icon/asdldefs.nw
new file mode 100644
index 0000000000..b7ff2febc8
--- /dev/null
+++ b/web/noweb/src/icon/asdldefs.nw
@@ -0,0 +1,46 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+\section{Finding definitions in $\lambda$-RTL}
+<<*>>=
+procedure main(args)
+ go()
+end
+<<*>>=
+global idchars
+procedure postpass(name, arg)
+ static kind
+ initial { idchars := &letters ++ &digits ++ '_.'
+ kind := "bogus"
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then (arg || "--") ? (tab(find("--") \ 1) ? {
+ if (optwhite(), any(&lcase), t := tab(many(idchars)), optwhite(), ="=")
+ then
+ undotted(t)
+ while tab(upto(idchars)) do
+ if (="imports", any(' \t')) then
+ (tab(upto(idchars)), tab(many(idchars)))
+ else if any(&ucase) then undotted(tab(many(idchars)))
+ else tab(many(idchars))
+ })
+ }
+ return
+end
+
+procedure undotted(s)
+ return if upto('.', s) then &null else writedefn(s)
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: asdldefs.nw,v 1.15 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+@
diff --git a/web/noweb/src/icon/cdefs.icn b/web/noweb/src/icon/cdefs.icn
new file mode 100644
index 0000000000..a74d46fc5d
--- /dev/null
+++ b/web/noweb/src/icon/cdefs.icn
@@ -0,0 +1,180 @@
+#line 2 "cdefs.nw"
+global decls_ok
+procedure main(args)
+ decls_ok := !args == "-decl"
+ go()
+end
+#line 8 "cdefs.nw"
+global typespecs, storespecs, typequals, otherspecs, structlike
+procedure postpass(name, arg)
+ local tok, stat
+ static kind
+ initial {
+ kind := "bogus"
+ storespecs := set(["typedef", "extern", "static", "auto", "register"])
+ typespecs := set(["void", "char", "float", "short", "signed",
+ "int", "double", "long", "unsigned"])
+ typequals := set(["const", "volatile"])
+ otherspecs := storespecs ++ typequals
+ structlike := set(["struct", "union", "enum"])
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : arg ? {
+ if kind ~== "code" then return
+ if any(' \t') then return
+ if (="#define", tab(many(' \t'))) then return wd(c_ident_token())
+ if find("dclproto") then return
+ if ="}" then {
+ if c_ident_token() == "while" then fail # don't get tripped by do { ... } while
+
+#line 61 "cdefs.nw"
+while x := declarator() do {
+ wd(x, stat)
+ if c_token() == "," then &null else return
+}
+#line 31 "cdefs.nw"
+ } else {
+ specifier_count := 0
+ stat := &null # haven't seen static yet
+ seenType := &null
+ while (
+ (/decls_ok & c_ident_token() == "extern", return) |
+ (member(typespecs, c_ident_token()), seenType := 1) | # swallow type
+ (member(otherspecs, tok := c_ident_token()),
+ stat := look_for_static(stat, tok)) | # swallow a specifier
+ (member(structlike, c_ident_token()), # struct with optional tag
+ c_ident_token() | &null) |
+ (/seenType, any(&ucase, c_ident_token()), seenType := 1)
+ # assume a typedef'd type, skip
+ ) do
+ specifier_count +:= 1
+## write(&errout, "skipped ", specifier_count, " specifiers")
+ if f := scan_function() then
+ if /decls_ok & c_token() == (";"|",") then fail else {
+## write(&errout, "function ", image(f), " followed by ",
+## image(c_token()) | "<EOL>")
+ wd(f, stat)
+ return
+ }
+ if specifier_count > 0 then {
+#line 61 "cdefs.nw"
+while x := declarator() do {
+ wd(x, stat)
+ if c_token() == "," then &null else return
+}
+#line 54 "cdefs.nw"
+ }
+ }
+ }
+ }
+ return
+end
+#line 66 "cdefs.nw"
+procedure wd(x, stat)
+ static reserved
+ initial reserved := set([
+ "asm", "auto", "break", "case", "char", "const", "continue",
+ "default", "double", "do", "else", "enum", "extern", "float", "for",
+ "goto", "if", "int", "long", "register", "return", "short",
+ "signed", "sizeof", "static", "struct", "switch", "typedef", "union",
+ "unsigned", "void", "volatile", "while"])
+ if member(reserved, x) then return
+ return writedefn(x, stat)
+end
+
+procedure prepass(name, arg)
+ return
+end
+
+procedure c_ident_token()
+ static alpha, alnum
+ initial { alpha := '_' ++ &letters; alnum := alpha ++ &digits }
+ tab(many(' \t'))
+ if any(alpha) then suspend tab(many(alnum))
+end
+
+procedure c_token()
+ static alpha, alnum
+ initial { alpha := '_' ++ &letters; alnum := alpha ++ &digits }
+ tab(many(' \t'))
+ if any(alpha) then suspend tab(many(alnum)) else suspend move(1)
+end
+
+procedure scan_function()
+ (f := c_ident_token(),
+#write(&errout, " try function ", image(f)),
+ tab(many(' \t')) | &null,
+ any('('),
+ *tab(bal()) > 0 |
+ (="(", *tab(bal(',', '[{(', ')}]')) > 0, =",", optwhite(), pos(0)),
+#write(&errout, " caught function trailing ", image(&subject[&pos:0])),
+ suspend f
+ )
+end
+
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+
+procedure declarator()
+ while c_token() == "*" do
+ while member(typequals, c_token())
+ (c_token() == "(", d := declarator(), c_token() == ")") |
+ (d := c_ident_token()) |
+ fail
+ while c_token() == ("[", "(") do
+ (tab(bal('])','[(',')]')), c_token())
+ return d
+end
+#line 123 "cdefs.nw"
+procedure look_for_static(stat, tok)
+ return (tok == "static") | stat
+end
+#line 127 "cdefs.nw"
+procedure rcsinfo ()
+ return "$Id: cdefs.nw,v 1.19 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+#line 1 "defns.nw"
+procedure go()
+ local line
+ while line := read() do {
+ apply(prepass, line)
+ write(line)
+ if match("@fatal ", line) then exit(1)
+ apply(postpass, line)
+ }
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+#line 18 "defns.nw"
+procedure writedefn(defn, locl)
+ static indextext
+ initial indextext := ""
+ if /defn then
+ *indextext > 0 &
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 23 "defns.nw"
+ else {
+ if *indextext + *defn > 65 then
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 25 "defns.nw"
+ write(if \locl then "@index localdefn " else "@index defn ", defn)
+ indextext ||:= " " || defn
+ }
+ return
+end
+#line 35 "defns.nw"
+procedure rcsinfo_too ()
+ return "$Id: defns.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/cdefs.nw b/web/noweb/src/icon/cdefs.nw
new file mode 100644
index 0000000000..186f47d3b3
--- /dev/null
+++ b/web/noweb/src/icon/cdefs.nw
@@ -0,0 +1,132 @@
+\section{Finding definitions in ANSI C}
+<<*>>=
+global decls_ok
+procedure main(args)
+ decls_ok := !args == "-decl"
+ go()
+end
+<<*>>=
+global typespecs, storespecs, typequals, otherspecs, structlike
+procedure postpass(name, arg)
+ local tok, stat
+ static kind
+ initial {
+ kind := "bogus"
+ storespecs := set(["typedef", "extern", "static", "auto", "register"])
+ typespecs := set(["void", "char", "float", "short", "signed",
+ "int", "double", "long", "unsigned"])
+ typequals := set(["const", "volatile"])
+ otherspecs := storespecs ++ typequals
+ structlike := set(["struct", "union", "enum"])
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : arg ? {
+ if kind ~== "code" then return
+ if any(' \t') then return
+ if (="#define", tab(many(' \t'))) then return wd(c_ident_token())
+ if find("dclproto") then return
+ if ="}" then {
+ if c_ident_token() == "while" then fail # don't get tripped by do { ... } while
+ <<eat declarators>>
+ } else {
+ specifier_count := 0
+ stat := &null # haven't seen static yet
+ seenType := &null
+ while (
+ (/decls_ok & c_ident_token() == "extern", return) |
+ (member(typespecs, c_ident_token()), seenType := 1) | # swallow type
+ (member(otherspecs, tok := c_ident_token()),
+ stat := look_for_static(stat, tok)) | # swallow a specifier
+ (member(structlike, c_ident_token()), # struct with optional tag
+ c_ident_token() | &null) |
+ (/seenType, any(&ucase, c_ident_token()), seenType := 1)
+ # assume a typedef'd type, skip
+ ) do
+ specifier_count +:= 1
+## write(&errout, "skipped ", specifier_count, " specifiers")
+ if f := scan_function() then
+ if /decls_ok & c_token() == (";"|",") then fail else {
+## write(&errout, "function ", image(f), " followed by ",
+## image(c_token()) | "<EOL>")
+ wd(f, stat)
+ return
+ }
+ if specifier_count > 0 then {<<eat declarators>>}
+ }
+ }
+ }
+ return
+end
+<<eat declarators>>=
+while x := declarator() do {
+ wd(x, stat)
+ if c_token() == "," then &null else return
+}
+<<*>>=
+procedure wd(x, stat)
+ static reserved
+ initial reserved := set([
+ "asm", "auto", "break", "case", "char", "const", "continue",
+ "default", "double", "do", "else", "enum", "extern", "float", "for",
+ "goto", "if", "int", "long", "register", "return", "short",
+ "signed", "sizeof", "static", "struct", "switch", "typedef", "union",
+ "unsigned", "void", "volatile", "while"])
+ if member(reserved, x) then return
+ return writedefn(x, stat)
+end
+
+procedure prepass(name, arg)
+ return
+end
+
+procedure c_ident_token()
+ static alpha, alnum
+ initial { alpha := '_' ++ &letters; alnum := alpha ++ &digits }
+ tab(many(' \t'))
+ if any(alpha) then suspend tab(many(alnum))
+end
+
+procedure c_token()
+ static alpha, alnum
+ initial { alpha := '_' ++ &letters; alnum := alpha ++ &digits }
+ tab(many(' \t'))
+ if any(alpha) then suspend tab(many(alnum)) else suspend move(1)
+end
+
+procedure scan_function()
+ (f := c_ident_token(),
+#write(&errout, " try function ", image(f)),
+ tab(many(' \t')) | &null,
+ any('('),
+ *tab(bal()) > 0 |
+ (="(", *tab(bal(',', '[{(', ')}]')) > 0, =",", optwhite(), pos(0)),
+#write(&errout, " caught function trailing ", image(&subject[&pos:0])),
+ suspend f
+ )
+end
+
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+
+procedure declarator()
+ while c_token() == "*" do
+ while member(typequals, c_token())
+ (c_token() == "(", d := declarator(), c_token() == ")") |
+ (d := c_ident_token()) |
+ fail
+ while c_token() == ("[", "(") do
+ (tab(bal('])','[(',')]')), c_token())
+ return d
+end
+<<*>>=
+procedure look_for_static(stat, tok)
+ return (tok == "static") | stat
+end
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: cdefs.nw,v 1.19 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+@
diff --git a/web/noweb/src/icon/defns.nw b/web/noweb/src/icon/defns.nw
new file mode 100644
index 0000000000..f168d25b29
--- /dev/null
+++ b/web/noweb/src/icon/defns.nw
@@ -0,0 +1,40 @@
+<<*>>=
+procedure go()
+ local line
+ while line := read() do {
+ apply(prepass, line)
+ write(line)
+ if match("@fatal ", line) then exit(1)
+ apply(postpass, line)
+ }
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+@
+[[indextext]] is a hack to introduce suitable ``[[@index nl]],'' but it
+messes up the line counts!
+<<*>>=
+procedure writedefn(defn, locl)
+ static indextext
+ initial indextext := ""
+ if /defn then
+ *indextext > 0 & <<flush index>>
+ else {
+ if *indextext + *defn > 65 then <<flush index>>
+ write(if \locl then "@index localdefn " else "@index defn ", defn)
+ indextext ||:= " " || defn
+ }
+ return
+end
+<<flush index>>=
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+<<*>>=
+procedure rcsinfo_too ()
+ return "$Id: defns.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+@
diff --git a/web/noweb/src/icon/disambiguate.icn b/web/noweb/src/icon/disambiguate.icn
new file mode 100644
index 0000000000..da547d37d6
--- /dev/null
+++ b/web/noweb/src/icon/disambiguate.icn
@@ -0,0 +1,67 @@
+#line 7 "disambiguate.nw"
+global chunknames
+
+procedure remember(name)
+ initial chunknames := table()
+ if *name = 0 then fail
+ /chunknames[name[1]] := set()
+ insert(chunknames[name[1]], name)
+ return
+end
+#line 20 "disambiguate.nw"
+procedure disambiguate(arg)
+ local s
+ if *arg = 0 then fail
+ search := chunknames[arg[1]]
+ if /search then fatal("Can't resolve ", arg, "...")
+ every match(arg, n := !search) do
+ if /s then s := n
+ else fatal("Ambiguous abbreviation: <<", arg, "...>> could denote\n\t<<",
+ s, ">> or\n\t<<", n, ">>")
+ if *s = 0 then fatal("Can't resolve ", arg, "...")
+ return s
+end
+#line 35 "disambiguate.nw"
+global lines, defns, uses, names, firstdefnout
+
+procedure main(args)
+ lines := []
+ while put(lines, line := read()) do
+ apply(pass1, line)
+ every apply(pass2, !lines)
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+
+procedure pass1(name, chunkname)
+ initial chunknames := set()
+ case name of {
+ "defn" | "use" :
+ if chunkname[0-:3] ~== "..." then remember(chunkname)
+ }
+ return
+end
+
+procedure pass2(name, arg)
+ case name of {
+ "defn" | "use" :
+ if arg[0:-3] == "..." then arg := disambiguate(arg[1:-3])
+ }
+ write("@", name, (" " || \arg) | "")
+ if name == "fatal" then exit(1)
+ return
+end
+#line 68 "disambiguate.nw"
+procedure fatal(L[])
+ write!(["@fatal disambiguate "] ||| L)
+ write!([&errout, "noweb error in disambiguate: "] ||| L)
+ exit(1)
+end
+
+#line 75 "disambiguate.nw"
+procedure rcsinfo ()
+ return "$Id: disambiguate.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/disambiguate.nw b/web/noweb/src/icon/disambiguate.nw
new file mode 100644
index 0000000000..8f23d515b1
--- /dev/null
+++ b/web/noweb/src/icon/disambiguate.nw
@@ -0,0 +1,80 @@
+\section{Disambiguating abbreviated chunk names}
+This code disambiguates chunk names ending in [[...]].
+If used, it belongs right after [[markup]] in the pipeline.
+
+The first pass calls [[remember]] on each name {\em not} ending in dots.
+For efficiency, I keep a table of sets indexed by the first character of the name.
+<<*>>=
+global chunknames
+
+procedure remember(name)
+ initial chunknames := table()
+ if *name = 0 then fail
+ /chunknames[name[1]] := set()
+ insert(chunknames[name[1]], name)
+ return
+end
+@
+
+The second pass calls [[disambiguate]] on each name that {\em does} end in dots.
+<<*>>=
+procedure disambiguate(arg)
+ local s
+ if *arg = 0 then fail
+ search := chunknames[arg[1]]
+ if /search then fatal("Can't resolve ", arg, "...")
+ every match(arg, n := !search) do
+ if /s then s := n
+ else fatal("Ambiguous abbreviation: @<<", arg, "...@>> could denote\n\t@<<",
+ s, "@>> or\n\t@<<", n, "@>>")
+ if *s = 0 then fatal("Can't resolve ", arg, "...")
+ return s
+end
+@
+The
+<<*>>=
+global lines, defns, uses, names, firstdefnout
+
+procedure main(args)
+ lines := []
+ while put(lines, line := read()) do
+ apply(pass1, line)
+ every apply(pass2, !lines)
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+
+procedure pass1(name, chunkname)
+ initial chunknames := set()
+ case name of {
+ "defn" | "use" :
+ if chunkname[0-:3] ~== "..." then remember(chunkname)
+ }
+ return
+end
+
+procedure pass2(name, arg)
+ case name of {
+ "defn" | "use" :
+ if arg[0:-3] == "..." then arg := disambiguate(arg[1:-3])
+ }
+ write("@", name, (" " || \arg) | "")
+ if name == "fatal" then exit(1)
+ return
+end
+@
+<<*>>=
+procedure fatal(L[])
+ write!(["@fatal disambiguate "] ||| L)
+ write!([&errout, "noweb error in disambiguate: "] ||| L)
+ exit(1)
+end
+
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: disambiguate.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+@
diff --git a/web/noweb/src/icon/docs2comments.icn b/web/noweb/src/icon/docs2comments.icn
new file mode 100644
index 0000000000..0f8e914378
--- /dev/null
+++ b/web/noweb/src/icon/docs2comments.icn
@@ -0,0 +1,180 @@
+#line 8 "docs2comments.nw"
+global format, subst, firstline, lastline, allchunks, chunks, width
+record wrap(l, r) # put fore and aft of line
+record breakup(strings) # split up these strings with spaces
+record tr(old, new) # translate old chars to new
+global left_quote, right_quote
+
+procedure main(args)
+ format := wrap("/* ", " */")
+ subst := breakup(["/*","*/"])
+ width := 80
+ left_quote := "[["
+ right_quote := "]]"
+ while a := get(args) do
+ case a of {
+ "-ml" | "-m3" : (format := wrap("(* ", " *)"), subst := breakup(["(*", "*)"]))
+ "-awk" | "-icn" | "-icon" : format := wrap("# ")
+ "-lisp" | "-scm" : format := wrap(";;; ")
+ "-c++" : format := wrap("// ")
+ "-c" : { format := wrap(" * "); firstline := "/*"; lastline := " */"
+ subst := breakup(["/*", "*/"])
+ }
+ "-ocamlweb" : { format := wrap(" "); firstline := "(*"; lastline := " *)"
+ subst := breakup(["(*", "*)"])
+ left_quote := "["; right_quote := "]"
+ }
+ "-pascal" : { format := wrap("{ ", " }"); subst := tr("{}", "--") }
+ "-f77" : format := wrap("C ")
+ "-f90" : format := wrap("! ")
+ "-tex" : format := wrap("%% ")
+ "-lua" : format := wrap("-- ")
+
+ "-all" : allchunks := 1
+ "-one" : allchunks := &null
+ default :
+ a ?
+ if (="-w", width <- integer(tab(many(&digits))), pos(0)) then
+ &null
+ else if ="-L" then
+ &null # deliberately ignore requests for #line
+ else {
+ write("@fatal unknown argument '", a, "' to docs2comments")
+ exit(1)
+ }
+ }
+
+#line 96 "docs2comments.nw"
+chunks := []
+while line := read() do
+ line ?
+ if ="@end docs" | ="@end code" then {
+ if (\holding)[-1] == "" then pull (holding)
+ put(chunks, code(preceding_defn, \defn_pending, holding) | docs(holding))
+## if type(chunks[-1]) == "code" then
+## every write("##### " || (
+## "preceding defn is " || image(preceding_defn) |
+## "defn pending is " || image(defn_pending) |
+## "Holding chunk with these lines:" | image(!holding)))
+ defn_pending := &null
+ holding := &null
+ chunks := drain(chunks)
+ } else if ="@begin docs" then {
+ indocs := 1
+ holding := [""]
+ } else if ="@begin code" then {
+ indocs := &null
+ holding := [""]
+ } else if \indocs then {
+ if ="@text " then {
+ grab(tab(0), holding)
+ } else if ="@quote" & pos(0) then {
+ grab(left_quote, holding)
+ } else if ="@endquote" & pos(0) then {
+ grab(right_quote, holding)
+ } else if ="@nl" & pos(0) then {
+ put(\holding, "")
+ }
+ } else if ="@defn " then {
+ defn_pending := tab(0)
+ if holding[-1] == "" then pull (holding)
+ preceding_defn := holding
+ holding := []
+ } else {
+ if match("@xref ") & (\holding)[-1] == "" then pull(holding)
+ put(\holding, line)
+ }
+drain(put(chunks, docs([])))
+#line 53 "docs2comments.nw"
+ return
+end
+#line 57 "docs2comments.nw"
+procedure insert_blanks(s, bad)
+ s ? {
+ r := ""
+ while r ||:= tab(find(bad)) do {
+ r ||:= bad[1]
+ every i := 2 to *bad do r ||:= " " || bad[i]
+ =bad
+ }
+ return r || tab(0)
+ }
+end
+#line 70 "docs2comments.nw"
+procedure comment(s)
+ case type(subst) of {
+ "breakup" : every s := insert_blanks(s, !subst.strings)
+ "tr" : s := map(s, subst.old, subst.new)
+ "null" : &null
+ default : stop("unknown substitution of type ", type(subst))
+ }
+ if /format.r then
+ return format.l || s
+ else {
+ if *s < width then s ||:= repl(" ", width - *s)
+ return format.l || s || format.r
+ }
+end
+#line 88 "docs2comments.nw"
+procedure grab(s, holding)
+ return (\holding)[-1] := holding[-1] || s
+end
+
+record docs(lines)
+record code(preceding, defn, lines)
+
+#line 138 "docs2comments.nw"
+procedure emit_as_comments(c)
+ type(c) == "docs" | runerr(1, "Unexpected code chunk")
+ every write("@text ", comment(trailing_nonblank(\c.lines)), "\n@nl")
+ return
+end
+
+procedure trailing_nonblank(l)
+ local suspended
+ every s := !l do
+ if \suspended | *s > 0 then {
+ suspended := 1
+ suspend s
+ }
+end
+
+
+procedure drain(chunks)
+ static n
+ initial n := -1
+ if type(c := chunks[-2]) == "code" then {
+ write("@begin code ", n +:= 1)
+ every write(!c.preceding | ("@defn " || c.defn) | "@nl")
+ write("@text ", \firstline, "\n@nl")
+ every i := (if \allchunks then 1 else *chunks -2) to *chunks - 2 do
+ emit_as_comments(chunks[i])
+ write("@text ", comment("<" || c.defn || ">="), "\n@nl")
+ write("@text ", \lastline, "\n@nl")
+ copyxreflines(\c.lines)
+ bad := &null
+ (bad := get(\c.lines)) == "@nl" |
+ { write(&errout, "expected newline after definition; got ", image(bad));
+ runerr(1, bad) }
+ every write(!c.lines)
+ c := chunks[-1]
+ if type(c) == "docs" & upto(\c.lines[1], ~' \n\t') then {
+ write("@text ", \firstline, "\n@nl")
+ emit_as_comments(c)
+ write("@text ", \lastline, "\n@nl")
+ write("@nl")
+ chunks := []
+ } else
+ chunks := [c]
+ write("@end code ", n)
+ }
+ return chunks
+end
+
+procedure copyxreflines(l)
+ while match("@xref ", l[1]) do {
+ #write(&errout, "COPYING ", image(l[1]))
+ get(l) #write(get(l))
+ }
+ return
+end
diff --git a/web/noweb/src/icon/docs2comments.nw b/web/noweb/src/icon/docs2comments.nw
new file mode 100644
index 0000000000..1a6935e457
--- /dev/null
+++ b/web/noweb/src/icon/docs2comments.nw
@@ -0,0 +1,192 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+
+\section{Convert documentation chunks to comments}
+
+Options indicate what language and comment style is preferred,
+plus whether to attach one or all nearby doc chunks to code.
+One is the default.
+<<*>>=
+global format, subst, firstline, lastline, allchunks, chunks, width
+record wrap(l, r) # put fore and aft of line
+record breakup(strings) # split up these strings with spaces
+record tr(old, new) # translate old chars to new
+global left_quote, right_quote
+
+procedure main(args)
+ format := wrap("/* ", " */")
+ subst := breakup(["/*","*/"])
+ width := 80
+ left_quote := "[["
+ right_quote := "]]"
+ while a := get(args) do
+ case a of {
+ "-ml" | "-m3" : (format := wrap("(* ", " *)"), subst := breakup(["(*", "*)"]))
+ "-awk" | "-icn" | "-icon" : format := wrap("# ")
+ "-lisp" | "-scm" : format := wrap(";;; ")
+ "-c++" : format := wrap("// ")
+ "-c" : { format := wrap(" * "); firstline := "/*"; lastline := " */"
+ subst := breakup(["/*", "*/"])
+ }
+ "-ocamlweb" : { format := wrap(" "); firstline := "(*"; lastline := " *)"
+ subst := breakup(["(*", "*)"])
+ left_quote := "["; right_quote := "]"
+ }
+ "-pascal" : { format := wrap("{ ", " }"); subst := tr("{}", "--") }
+ "-f77" : format := wrap("C ")
+ "-f90" : format := wrap("! ")
+ "-tex" : format := wrap("%% ")
+ "-lua" : format := wrap("-- ")
+
+ "-all" : allchunks := 1
+ "-one" : allchunks := &null
+ default :
+ a ?
+ if (="-w", width <- integer(tab(many(&digits))), pos(0)) then
+ &null
+ else if ="-L" then
+ &null # deliberately ignore requests for #line
+ else {
+ write("@fatal unknown argument '", a, "' to docs2comments")
+ exit(1)
+ }
+ }
+ <<transform [[&input]]>>
+ return
+end
+@
+<<*>>=
+procedure insert_blanks(s, bad)
+ s ? {
+ r := ""
+ while r ||:= tab(find(bad)) do {
+ r ||:= bad[1]
+ every i := 2 to *bad do r ||:= " " || bad[i]
+ =bad
+ }
+ return r || tab(0)
+ }
+end
+@
+<<*>>=
+procedure comment(s)
+ case type(subst) of {
+ "breakup" : every s := insert_blanks(s, !subst.strings)
+ "tr" : s := map(s, subst.old, subst.new)
+ "null" : &null
+ default : stop("unknown substitution of type ", type(subst))
+ }
+ if /format.r then
+ return format.l || s
+ else {
+ if *s < width then s ||:= repl(" ", width - *s)
+ return format.l || s || format.r
+ }
+end
+@
+[[grab]] concatenates a string [[s]] onto the last line being held in
+list [[holding]].
+<<*>>=
+procedure grab(s, holding)
+ return (\holding)[-1] := holding[-1] || s
+end
+
+record docs(lines)
+record code(preceding, defn, lines)
+
+<<transform [[&input]]>>=
+chunks := []
+while line := read() do
+ line ?
+ if ="@end docs" | ="@end code" then {
+ if (\holding)[-1] == "" then pull (holding)
+ put(chunks, code(preceding_defn, \defn_pending, holding) | docs(holding))
+## if type(chunks[-1]) == "code" then
+## every write("##### " || (
+## "preceding defn is " || image(preceding_defn) |
+## "defn pending is " || image(defn_pending) |
+## "Holding chunk with these lines:" | image(!holding)))
+ defn_pending := &null
+ holding := &null
+ chunks := drain(chunks)
+ } else if ="@begin docs" then {
+ indocs := 1
+ holding := [""]
+ } else if ="@begin code" then {
+ indocs := &null
+ holding := [""]
+ } else if \indocs then {
+ if ="@text " then {
+ grab(tab(0), holding)
+ } else if ="@quote" & pos(0) then {
+ grab(left_quote, holding)
+ } else if ="@endquote" & pos(0) then {
+ grab(right_quote, holding)
+ } else if ="@nl" & pos(0) then {
+ put(\holding, "")
+ }
+ } else if ="@defn " then {
+ defn_pending := tab(0)
+ if holding[-1] == "" then pull (holding)
+ preceding_defn := holding
+ holding := []
+ } else {
+ if match("@xref ") & (\holding)[-1] == "" then pull(holding)
+ put(\holding, line)
+ }
+drain(put(chunks, docs([])))
+@
+<<*>>=
+procedure emit_as_comments(c)
+ type(c) == "docs" | runerr(1, "Unexpected code chunk")
+ every write("@text ", comment(trailing_nonblank(\c.lines)), "\n@nl")
+ return
+end
+
+procedure trailing_nonblank(l)
+ local suspended
+ every s := !l do
+ if \suspended | *s > 0 then {
+ suspended := 1
+ suspend s
+ }
+end
+
+
+procedure drain(chunks)
+ static n
+ initial n := -1
+ if type(c := chunks[-2]) == "code" then {
+ write("@begin code ", n +:= 1)
+ every write(!c.preceding | ("@defn " || c.defn) | "@nl")
+ write("@text ", \firstline, "\n@nl")
+ every i := (if \allchunks then 1 else *chunks -2) to *chunks - 2 do
+ emit_as_comments(chunks[i])
+ write("@text ", comment("<" || c.defn || ">="), "\n@nl")
+ write("@text ", \lastline, "\n@nl")
+ copyxreflines(\c.lines)
+ bad := &null
+ (bad := get(\c.lines)) == "@nl" |
+ { write(&errout, "expected newline after definition; got ", image(bad));
+ runerr(1, bad) }
+ every write(!c.lines)
+ c := chunks[-1]
+ if type(c) == "docs" & upto(\c.lines[1], ~' \n\t') then {
+ write("@text ", \firstline, "\n@nl")
+ emit_as_comments(c)
+ write("@text ", \lastline, "\n@nl")
+ write("@nl")
+ chunks := []
+ } else
+ chunks := [c]
+ write("@end code ", n)
+ }
+ return chunks
+end
+
+procedure copyxreflines(l)
+ while match("@xref ", l[1]) do {
+ #write(&errout, "COPYING ", image(l[1]))
+ get(l) #write(get(l))
+ }
+ return
+end
diff --git a/web/noweb/src/icon/elide.icn b/web/noweb/src/icon/elide.icn
new file mode 100644
index 0000000000..0c5e809407
--- /dev/null
+++ b/web/noweb/src/icon/elide.icn
@@ -0,0 +1,71 @@
+#line 17 "elide.nw"
+procedure main(args)
+ elide := []
+ every put(elide, globpat(!args))
+ while line := read() do
+ if match("@begin code ", line) then
+ {
+#line 35 "elide.nw"
+accum := [line]
+while line := read() & not match("@defn ", line) do
+ put(accum, line)
+line ? {
+ ="@defn " | fatal("This can't happen")
+ if globmatch(!elide) then {
+ while line := get(accum) | read() & not match("@end code ", line) do # drain
+ if line == "@nl" then write("@index nl") # grotesque, but may keep lines right
+ } else
+ every write(!accum | line)
+}
+#line 22 "elide.nw"
+ }
+ else {
+ write(line)
+ if match("@fatal ", line) then exit(1)
+ }
+ return
+end
+#line 61 "elide.nw"
+procedure globpat(s)
+ static specials
+ initial specials := '?*\\'
+ l := []
+ s ?
+ while not pos(0) do
+ put(l,
+ if not any(specials) then
+ tab(upto(specials)|0)
+ else case move(1) of {
+ "?" : &cset
+ "*" : &null
+ "\\" : move(1)
+ })
+ return l
+end
+#line 82 "elide.nw"
+procedure doglobmatch(pat, i)
+ local p
+ suspend if p := pat[i] then
+ case type(p) of {
+ "string" : =p
+ "cset" : tab(any(p))
+ "null" : tab(&pos to *&subject+1)
+ } || doglobmatch(pat, i+1)
+ else (pos(0), "")
+end
+#line 96 "elide.nw"
+procedure globmatch(pattern, s)
+ return if \s then s ? doglobmatch(pattern, 1)
+ else doglobmatch(pattern, 1)
+end
+#line 101 "elide.nw"
+procedure fatal(L[])
+ write!(["@fatal elide "] ||| L)
+ write!([&errout, "noweb error in elide: "] ||| L)
+ exit(1)
+end
+#line 107 "elide.nw"
+procedure rcsinfo ()
+ return "$Id: elide.nw,v 1.19 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/elide.nw b/web/noweb/src/icon/elide.nw
new file mode 100644
index 0000000000..f135274447
--- /dev/null
+++ b/web/noweb/src/icon/elide.nw
@@ -0,0 +1,112 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+\section{Eliding unwanted code chunks}
+
+This filter removes from the [[markup]] token stream any code chunk
+ whose name matches any of the ``globbing'' patterns given it as
+ arguments. These are the familiar file name globbing patterns. For
+ example: [[elide 'RefMan_Ch*']] will prevent weaving a chunk
+ defined as ``\LA{}RefMan\_Chapter\_14\RA{}''.
+
+You could also use this filter when tangling, but it's not clear why you'd want to.
+
+@
+\subsection{Eliding}
+The main loop simply copies the input to the output.
+We stop only if we see [[@begin code]], because that means we might
+need to elide.
+<<*>>=
+procedure main(args)
+ elide := []
+ every put(elide, globpat(!args))
+ while line := read() do
+ if match("@begin code ", line) then
+ {<<see about eliding this chunk>>}
+ else {
+ write(line)
+ if match("@fatal ", line) then exit(1)
+ }
+ return
+end
+@
+To see about eliding, we accumulate lines until we see [[@defn]].
+At that point we can either keep the chunk, which means printing the
+accumulated lines and returning to the main loop, or elide it, which
+means draining the input until the next [[@end code]].
+<<see about eliding this chunk>>=
+accum := [line]
+while line := read() & not match("@defn ", line) do
+ put(accum, line)
+line ? {
+ ="@defn " | fatal("This can't happen")
+ if globmatch(!elide) then {
+ while line := get(accum) | read() & not match("@end code ", line) do # drain
+ if line == "@nl" then write("@index nl") # grotesque, but may keep lines right
+ } else
+ every write(!accum | line)
+}
+@
+\subsection{Globbing}
+
+I do globbing in two stages: first I turn the globbing string into
+a pattern. A pattern is a list of the following kinds of data items:
+\begin{quote}
+\begin{tabular}{ll}
+string&match that string\\
+cset&match one character in that cset\\
+nil&match anything\\
+\end{tabular}
+\end{quote}
+[[globpat]] turns a globbing string into a pattern.
+It doesn't handle the {\tt [} metacharacter, but it might one day.
+<<*>>=
+procedure globpat(s)
+ static specials
+ initial specials := '?*\\'
+ l := []
+ s ?
+ while not pos(0) do
+ put(l,
+ if not any(specials) then
+ tab(upto(specials)|0)
+ else case move(1) of {
+ "?" : &cset
+ "*" : &null
+ "\\" : move(1)
+ })
+ return l
+end
+@
+Giving a globbing pattern [[pat]] and an index [[i]], [[doglobmatch]]
+returns the string (if any) matched by [[pat[i:0]]].
+[[doglobmatch]] scans the current subject.
+<<*>>=
+procedure doglobmatch(pat, i)
+ local p
+ suspend if p := pat[i] then
+ case type(p) of {
+ "string" : =p
+ "cset" : tab(any(p))
+ "null" : tab(&pos to *&subject+1)
+ } || doglobmatch(pat, i+1)
+ else (pos(0), "")
+end
+@
+[[globmatch(p)]] matches the pattern [[p]] against the current
+subject, or a subject can be supplied as the second argument.
+<<*>>=
+procedure globmatch(pattern, s)
+ return if \s then s ? doglobmatch(pattern, 1)
+ else doglobmatch(pattern, 1)
+end
+<<*>>=
+procedure fatal(L[])
+ write!(["@fatal elide "] ||| L)
+ write!([&errout, "noweb error in elide: "] ||| L)
+ exit(1)
+end
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: elide.nw,v 1.19 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+@
diff --git a/web/noweb/src/icon/htmltoc.icn b/web/noweb/src/icon/htmltoc.icn
new file mode 100644
index 0000000000..fd29051070
--- /dev/null
+++ b/web/noweb/src/icon/htmltoc.icn
@@ -0,0 +1,218 @@
+#line 37 "htmltoc.nw"
+$define sentinel "<tableofcontents>"
+$define sentinel_end "</tableofcontents>"
+#line 44 "htmltoc.nw"
+record ioc(number, level, text)
+#line 46 "htmltoc.nw"
+global contents
+#line 52 "htmltoc.nw"
+procedure readfile(f)
+ local old_contents
+ intoc := &null
+ contents := []
+ old_contents := []
+ no := 0
+
+ file := list()
+ while l := read(f) do l ? {
+#line 71 "htmltoc.nw"
+if =sentinel then {
+ intoc := "in table of contents"
+ put(file, l)
+} else if =sentinel_end then {
+ intoc := &null
+ put(file, l)
+} else if \intoc then {
+ put(old_contents, l)
+} else if /intoc then {
+ if
+#line 88 "htmltoc.nw"
+(pre := tab(upto('<')), ="<", skip(), tab(any('hH')), n := tab(many(&digits)),
+ skip(), =">")
+#line 80 "htmltoc.nw"
+ then {
+
+#line 102 "htmltoc.nw"
+if (c := tab(upto('<')), ="</", skip(), tab(any('hH')), =n, skip(), =">") then {
+ no +:= 1
+ c ? c := strip_toc_anchors() || tab(0)
+ addcontents(no, n, c)
+
+#line 112 "htmltoc.nw"
+put(file, pre || "<h" || n || "><a name=toc" || no || ">" || c ||
+ "</a></h" || n || ">" || tab(0))
+#line 107 "htmltoc.nw"
+} else
+ write(&errout, "Unterminated <h", n, ">", tab(0), "...")
+#line 82 "htmltoc.nw"
+ } else
+ put(file, l)
+}
+#line 60 "htmltoc.nw"
+ }
+ if \intoc then {
+ push(old_contents, sentinel_end)
+ every l := !copy(old_contents) do l ? {
+#line 71 "htmltoc.nw"
+if =sentinel then {
+ intoc := "in table of contents"
+ put(file, l)
+} else if =sentinel_end then {
+ intoc := &null
+ put(file, l)
+} else if \intoc then {
+ put(old_contents, l)
+} else if /intoc then {
+ if
+#line 88 "htmltoc.nw"
+(pre := tab(upto('<')), ="<", skip(), tab(any('hH')), n := tab(many(&digits)),
+ skip(), =">")
+#line 80 "htmltoc.nw"
+ then {
+
+#line 102 "htmltoc.nw"
+if (c := tab(upto('<')), ="</", skip(), tab(any('hH')), =n, skip(), =">") then {
+ no +:= 1
+ c ? c := strip_toc_anchors() || tab(0)
+ addcontents(no, n, c)
+
+#line 112 "htmltoc.nw"
+put(file, pre || "<h" || n || "><a name=toc" || no || ">" || c ||
+ "</a></h" || n || ">" || tab(0))
+#line 107 "htmltoc.nw"
+} else
+ write(&errout, "Unterminated <h", n, ">", tab(0), "...")
+#line 82 "htmltoc.nw"
+ } else
+ put(file, l)
+}
+#line 63 "htmltoc.nw"
+ }
+ }
+
+ return file
+end
+#line 92 "htmltoc.nw"
+procedure skip()
+ suspend tab(many(' \t')) | ""
+end
+#line 117 "htmltoc.nw"
+procedure strip_toc_anchors()
+ local s, p
+ if (="<a name=toc", tab(many(&digits)), =">", s := strip_toc_anchors(), ="</a>") then
+ return s
+ else {
+ s := to_next_anchor_or_end_anchor() | runerr(1, "never found an anchor")
+ if pos(0) | at_end_anchor() then
+ return s
+ else
+ return s || tab_past_anchor_start() || strip_toc_anchors() ||
+ tab_past_anchor_end()
+ }
+end
+#line 132 "htmltoc.nw"
+procedure at_end_anchor()
+ &subject[&pos:0] ?
+ return tab_past_anchor_end()
+end
+
+procedure at_start_anchor()
+ &subject[&pos:0] ?
+ return tab_past_anchor_start()
+end
+
+procedure tab_past_anchor_end()
+ suspend ="<" || optwhite() || ="/" || optwhite() || =("a"|"A") || optwhite() || =">"
+end
+
+procedure tab_past_anchor_start()
+ suspend ="<" || optwhite() || =("a"|"A") || white() || tab(upto('>')) || =">"
+end
+
+procedure to_next_anchor_or_end_anchor()
+ return (1(tab(upto('<')), at_start_anchor() | at_end_anchor()) | tab(0)) \ 1
+end
+
+procedure white()
+ suspend tab(many(' \t'))
+end
+procedure optwhite()
+ suspend white() | ""
+end
+#line 171 "htmltoc.nw"
+procedure addcontents(no, n, s)
+ if map(s) ~== "contents" & find(n, toclevels) then
+ put(contents, ioc(no, n, strip_tags(s)))
+ return
+end
+
+procedure strip_tags(s)
+ s ? {
+ r := ""
+ while r ||:= tab(upto('<')) do (tab(upto('>')), =">")
+ return r || tab(0)
+ }
+end
+#line 191 "htmltoc.nw"
+global minlevel
+
+procedure tocindent(level)
+ return repl(" ", level-minlevel)
+end
+
+procedure writetoc()
+ local level
+ minlevel := 99
+ every minlevel >:= (!contents).level
+ level := minlevel - 1 # triggers opening list
+
+ every l := !contents do {
+
+#line 215 "htmltoc.nw"
+while level > l.level do {
+ write(tocindent(level), "</ul>")
+ level -:= 1
+}
+while level < l.level do {
+ level +:= 1
+ write(tocindent(level), "<ul compact>")
+}
+#line 205 "htmltoc.nw"
+ write(tocindent(level),
+ "<li><a href=\"#toc", l.number, "\">", l.text, "</a></li>")
+ }
+
+#line 226 "htmltoc.nw"
+while level >= minlevel do {
+ write(tocindent(level), "</ul>")
+ level -:= 1
+}
+#line 209 "htmltoc.nw"
+end
+#line 235 "htmltoc.nw"
+procedure add_contents(f)
+ file := readfile(f)
+
+ every l := !file do {
+ write(l)
+ if match(sentinel, l) then writetoc()
+ }
+end
+#line 246 "htmltoc.nw"
+global toclevels
+procedure main(args)
+ if args[1] ? (="-", toclevels := tab(many(&digits)), pos(0)) then get(args)
+ else toclevels := "2345"
+ if *args = 0 then add_contents(&input)
+ else every add_contents(openfile(!args))
+ return
+end
+
+procedure openfile(f)
+ return open(f) | stop("Cannot open file ", f)
+end
+#line 259 "htmltoc.nw"
+procedure rcsinfo ()
+ return "$Id: htmltoc.nw,v 1.20 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/htmltoc.nw b/web/noweb/src/icon/htmltoc.nw
new file mode 100644
index 0000000000..cf80e3ffc5
--- /dev/null
+++ b/web/noweb/src/icon/htmltoc.nw
@@ -0,0 +1,264 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+\title{htmltoc -- A Table of Contents Generater for HTML}
+\author{stephen parker\thanks{Revisions by Norman Ramsey}\\
+ \texttt{stephen@stephen.uk.eu.org}}
+
+\tableofcontents
+
+\section{Introduction}
+\texttt{htmltoc} reads an HTML document on standard input and writes the
+same document, but optionally including a table of contents on output.
+The motivation for this program was Norman Ramsey's \texttt{htmltoc}
+program included with the \texttt{noweb} distribution which this program
+has no advantages over other than not being written in perl.
+
+% noweave mangles the references in rawhtml blocks if you're not
+% careful. don't ask me why.
+\begin{rawhtml}
+This html document is created from a noweb
+<a href="http://lila.york.ac.uk/htmltoc/htmltoc.nw">source</a>
+document which also produces the notangled
+<a href="http://lila.york.ac.uk/htmltoc/htmltoc.icn">icon source</a>.
+The <a href="http://lila.york.ac.uk/htmltoc/mkfile">mkfile</a> to control
+this is also available; if you haven't got mk then it shouldn't be too
+hard to turn it into a Makefile.
+\end{rawhtml}
+
+\section{Implementation}
+The Icon source follows the usual pattern.
+<<*>>=
+<<Preprocessor constants>>
+<<Data structures>>
+<<Global Variables>>
+<<Procedures>>
+@ Any text between the marks [["<tableofcontents>"]] and
+[["</tableofcontents>"]] is replaced on output with a table
+of contents for the document.
+<<Preprocessor constants>>=
+$define sentinel "<tableofcontents>"
+$define sentinel_end "</tableofcontents>"
+@ The TOC is created from the header items in the text. These
+are stored in an [[ioc]] record. The headers are sequentially
+numbered and the level of the heading and the heading text are
+stored in a list of [[ioc]]s named [[contents]].
+<<Data structures>>=
+record ioc(number, level, text)
+<<Global Variables>>=
+global contents
+@ HTMLtoc must make two passes through the file in order to
+generate a TOC before the actual material. Since we'd like
+HTMLtoc to run in a pipeline we actually store the entire
+input in a list named [[file]].
+<<Procedures>>=
+procedure readfile(f)
+ local old_contents
+ intoc := &null
+ contents := []
+ old_contents := []
+ no := 0
+
+ file := list()
+ while l := read(f) do l ? { <<handle line>> }
+ if \intoc then {
+ push(old_contents, sentinel_end)
+ every l := !copy(old_contents) do l ? { <<handle line>> }
+ }
+
+ return file
+end
+@ The variable [[intoc]] is [[1]] if we are between the TOC markers
+on input. [[no]] is incremented for each header read.
+<<handle line>>=
+if =sentinel then {
+ intoc := "in table of contents"
+ put(file, l)
+} else if =sentinel_end then {
+ intoc := &null
+ put(file, l)
+} else if \intoc then {
+ put(old_contents, l)
+} else if /intoc then {
+ if <<[[l]] includes a header>> then {
+ <<add header line to [[contents]] and [[file]]>>
+ } else
+ put(file, l)
+}
+@ We look for a string of the form \verb|<[Hh][0-9]>| which
+signifies the beginning of a header. This isn't nice Icon.
+<<[[l]] includes a header>>=
+(pre := tab(upto('<')), ="<", skip(), tab(any('hH')), n := tab(many(&digits)),
+ skip(), =">")
+@ [[skip]] skips white space, if present.
+<<Procedures>>=
+procedure skip()
+ suspend tab(many(' \t')) | ""
+end
+@ The scanning environment contains a header, the
+\verb|<[Hh][0-9]>| has already been consumed, so
+the text of the header can by found by scanning for the close of header.
+The header number,
+[[no]] is incremented and then [[addcontents()]] is
+called to add the item to the [[contents]] list.
+<<add header line to [[contents]] and [[file]]>>=
+if (c := tab(upto('<')), ="</", skip(), tab(any('hH')), =n, skip(), =">") then {
+ no +:= 1
+ c ? c := strip_toc_anchors() || tab(0)
+ addcontents(no, n, c)
+ <<append modified line to [[file]]>>
+} else
+ write(&errout, "Unterminated <h", n, ">", tab(0), "...")
+@ We also need to label the heading in the text, so
+we can reference it from the TOC.
+<<append modified line to [[file]]>>=
+put(file, pre || "<h" || n || "><a name=toc" || no || ">" || c ||
+ "</a></h" || n || ">" || tab(0))
+@ When stripping these, we rely on their having been put there by this
+program.
+<<Procedures>>=
+procedure strip_toc_anchors()
+ local s, p
+ if (="<a name=toc", tab(many(&digits)), =">", s := strip_toc_anchors(), ="</a>") then
+ return s
+ else {
+ s := to_next_anchor_or_end_anchor() | runerr(1, "never found an anchor")
+ if pos(0) | at_end_anchor() then
+ return s
+ else
+ return s || tab_past_anchor_start() || strip_toc_anchors() ||
+ tab_past_anchor_end()
+ }
+end
+@
+<<Procedures>>=
+procedure at_end_anchor()
+ &subject[&pos:0] ?
+ return tab_past_anchor_end()
+end
+
+procedure at_start_anchor()
+ &subject[&pos:0] ?
+ return tab_past_anchor_start()
+end
+
+procedure tab_past_anchor_end()
+ suspend ="<" || optwhite() || ="/" || optwhite() || =("a"|"A") || optwhite() || =">"
+end
+
+procedure tab_past_anchor_start()
+ suspend ="<" || optwhite() || =("a"|"A") || white() || tab(upto('>')) || =">"
+end
+
+procedure to_next_anchor_or_end_anchor()
+ return (1(tab(upto('<')), at_start_anchor() | at_end_anchor()) | tab(0)) \ 1
+end
+
+procedure white()
+ suspend tab(many(' \t'))
+end
+procedure optwhite()
+ suspend white() | ""
+end
+@ [[addcontents()]] should simply append the [[ioc]]
+record for the header to the [[contents]] list. But
+one problem is that the text in the header may not
+be simple -- it might contain markup. One case where
+we don't want to copy this markup is if it is
+a \verb|<a name="|... token, since then there would be
+multiple targets for this name. Any markup of the
+form \verb|<| ... \verb|>| is stripped from the header --
+this harsh rule may be relaxed in future.
+We also avoid adding the line ``Contents'' to the contents.
+<<Procedures>>=
+procedure addcontents(no, n, s)
+ if map(s) ~== "contents" & find(n, toclevels) then
+ put(contents, ioc(no, n, strip_tags(s)))
+ return
+end
+
+procedure strip_tags(s)
+ s ? {
+ r := ""
+ while r ||:= tab(upto('<')) do (tab(upto('>')), =">")
+ return r || tab(0)
+ }
+end
+@
+The procedure [[writetoc()]] writes the TOC on
+output using the [[contents]] list. We keep a current
+header level in the integer variable [[level]]. As
+we iterate through the [[contents]] list we insert \verb|<ul compact>|s and
+\verb|</ul>|s as required for formatting.
+<<Procedures>>=
+global minlevel
+
+procedure tocindent(level)
+ return repl(" ", level-minlevel)
+end
+
+procedure writetoc()
+ local level
+ minlevel := 99
+ every minlevel >:= (!contents).level
+ level := minlevel - 1 # triggers opening list
+
+ every l := !contents do {
+ <<adjust [[level]] to [[l.level]]>>
+ write(tocindent(level),
+ "<li><a href=\"#toc", l.number, "\">", l.text, "</a></li>")
+ }
+ <<close any lists>>
+end
+@ We write out a \verb|</ul>| for each level we are beyond the
+current item, and a \verb|<ul compact>| for each level we are below
+the current. The call to [[repl()]] merely writes the correct
+number of tabs so as to make the contents look ok.
+<<adjust [[level]] to [[l.level]]>>=
+while level > l.level do {
+ write(tocindent(level), "</ul>")
+ level -:= 1
+}
+while level < l.level do {
+ level +:= 1
+ write(tocindent(level), "<ul compact>")
+}
+@ At the end of the contents we need to write as many
+\verb|</ul>|s as are required.
+<<close any lists>>=
+while level >= minlevel do {
+ write(tocindent(level), "</ul>")
+ level -:= 1
+}
+@ The [[add_contents()]] procedure simply reads the input using
+[[readfile()]] then writes it out again. If the
+sentinel line is found then the TOC is written at
+that point.
+<<Procedures>>=
+procedure add_contents(f)
+ file := readfile(f)
+
+ every l := !file do {
+ write(l)
+ if match(sentinel, l) then writetoc()
+ }
+end
+@
+[[main]] makes the program read its arguments or act as a filter.
+<<Procedures>>=
+global toclevels
+procedure main(args)
+ if args[1] ? (="-", toclevels := tab(many(&digits)), pos(0)) then get(args)
+ else toclevels := "2345"
+ if *args = 0 then add_contents(&input)
+ else every add_contents(openfile(!args))
+ return
+end
+
+procedure openfile(f)
+ return open(f) | stop("Cannot open file ", f)
+end
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: htmltoc.nw,v 1.20 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+@
diff --git a/web/noweb/src/icon/icondefs.icn b/web/noweb/src/icon/icondefs.icn
new file mode 100644
index 0000000000..2a36826fb6
--- /dev/null
+++ b/web/noweb/src/icon/icondefs.icn
@@ -0,0 +1,77 @@
+#line 2 "icondefs.nw"
+global showlocal
+procedure main(args)
+ showlocal := !args == "-local"
+ go()
+end
+#line 8 "icondefs.nw"
+procedure postpass(name, arg)
+ static kind, definers
+ initial { kind := "bogus"
+ definers := ["global"]
+ if \showlocal then every put(definers, "local" | "static")
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if =("procedure "|"record ") then {
+ tab(many(' '))
+ writedefn(tab(upto(' ()')))
+ } else if (tab(many(' ')) | "", =!definers, tab(many(' '))) then {
+ while (not any('#')) & writedefn(tab(upto(', #'))) do tab(many(', '))
+ if not any('#') then writedefn(tab(0))
+ }
+ }
+ return
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+#line 32 "icondefs.nw"
+procedure rcsinfo ()
+ return "$Id: icondefs.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+#line 1 "defns.nw"
+procedure go()
+ local line
+ while line := read() do {
+ apply(prepass, line)
+ write(line)
+ if match("@fatal ", line) then exit(1)
+ apply(postpass, line)
+ }
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+#line 18 "defns.nw"
+procedure writedefn(defn, locl)
+ static indextext
+ initial indextext := ""
+ if /defn then
+ *indextext > 0 &
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 23 "defns.nw"
+ else {
+ if *indextext + *defn > 65 then
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 25 "defns.nw"
+ write(if \locl then "@index localdefn " else "@index defn ", defn)
+ indextext ||:= " " || defn
+ }
+ return
+end
+#line 35 "defns.nw"
+procedure rcsinfo_too ()
+ return "$Id: defns.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/icondefs.nw b/web/noweb/src/icon/icondefs.nw
new file mode 100644
index 0000000000..f843011489
--- /dev/null
+++ b/web/noweb/src/icon/icondefs.nw
@@ -0,0 +1,37 @@
+\section{Finding Icon definitions}
+<<*>>=
+global showlocal
+procedure main(args)
+ showlocal := !args == "-local"
+ go()
+end
+<<*>>=
+procedure postpass(name, arg)
+ static kind, definers
+ initial { kind := "bogus"
+ definers := ["global"]
+ if \showlocal then every put(definers, "local" | "static")
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if =("procedure "|"record ") then {
+ tab(many(' '))
+ writedefn(tab(upto(' ()')))
+ } else if (tab(many(' ')) | "", =!definers, tab(many(' '))) then {
+ while (not any('#')) & writedefn(tab(upto(', #'))) do tab(many(', '))
+ if not any('#') then writedefn(tab(0))
+ }
+ }
+ return
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: icondefs.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+@
diff --git a/web/noweb/src/icon/l2h.icn b/web/noweb/src/icon/l2h.icn
new file mode 100644
index 0000000000..46f3143733
--- /dev/null
+++ b/web/noweb/src/icon/l2h.icn
@@ -0,0 +1,2237 @@
+#line 217 "l2h.nw"
+procedure star(cs)
+ suspend cs | (cs || "*")
+end
+#line 596 "l2h.nw"
+procedure asciiCharCode(S)
+ return emit_text(S, char(2(optwhite(), TeXnumber(), optwhite())))
+end
+procedure TeXnumber()
+ return integer(
+ (="'", "8r" || tab(many(&digits))) |
+ (="\"", "16r" || tab(many(&digits))) |
+ tab(many(&digits)))
+end
+#line 671 "l2h.nw"
+procedure convert(S, optstring)
+ static specials
+ initial {
+
+#line 819 "l2h.nw"
+activetab := table(unknown_cs)
+activeclosure := table()
+#line 969 "l2h.nw"
+cstab := table(unknown_cs)
+csclosure := table()
+#line 987 "l2h.nw"
+unknown_set := set()
+#line 1015 "l2h.nw"
+every begintab | endtab := table(unknown_env)
+every begincl | endcl := table()
+#line 1028 "l2h.nw"
+unknown_envs := set()
+#line 1381 "l2h.nw"
+liststack := []
+# write(&errout, "Initialized liststack")
+suspendstack := []
+#line 1961 "l2h.nw"
+countertab := table()
+#line 1969 "l2h.nw"
+accent_name := table()
+accent_valid := table('')
+accent_name ["`"] := "grave"
+accent_valid["`"] := 'AEIOUaeiou'
+accent_name ["'"] := "acute"
+accent_valid["'"] := 'AEIOUYaeiouy'
+accent_name ["^"] := "circ"
+accent_valid["^"] := 'AEIOUaeiou'
+accent_name ["hat"] := "circ"
+accent_valid["hat"] := 'AEIOUaeiou'
+accent_name ["\""] := "uml"
+accent_valid["\""] := 'AEIOUaeiouy'
+accent_name ["~"] := "tilde"
+accent_valid["~"] := 'ANOano'
+accent_name ["="] := "bar"
+accent_name ["."] := "dot"
+accent_name ["u"] := "u"
+accent_name ["v"] := "v"
+accent_name ["H"] := "H"
+accent_name ["t"] := "t"
+accent_name ["c"] := "cedil"
+accent_valid["c"] := 'Cc'
+accent_name ["d"] := "underdot"
+accent_name ["b"] := "underbar"
+#line 2675 "l2h.nw"
+csfunctions := table()
+#line 675 "l2h.nw"
+
+#line 114 "l2h.nw"
+substitution(",", " ")
+substitution(" ", " ")
+substitution("\n", "\n")
+substitution("\t", " ")
+ignore("raggedright")
+ignore("@")
+ignore("/") # no italic correction
+substitution("", "\n") # \<newline> treated as request for newline
+every c := !"$%#{}_" do
+ substitution(c, c)
+substitution("&", "&amp;")
+argblock("emph", "em")
+every argblock("footnote" | "footnotetext" | "thanks",
+ " <b>[</b>", "<b>]</b> ") # put footnotes in bold brackets
+substitution("today", &date)
+#line 132 "l2h.nw"
+ignore("textrm") # html can't switch to default font!
+argblock("textit", "i")
+argblock("textbf", "b")
+argblock("textsl", "i")
+ignore("textsc")
+argblock("texttt", "tt")
+ignore("textsf")
+ignore("boldmath")
+# \boldmath could be done by introducing S.mathfont, but I don't want to!
+#line 142 "l2h.nw"
+ignore("mathrm") # html can't switch to default font!
+argblock("mathit", "i")
+argblock("mathbf", "b")
+argblock("mathtt", "tt")
+ignore("mathsf")
+argblock("mathcal", "i")
+every ignore("scriptstyle"|"displaystyle"|"scriptscriptstyle")
+every ignore("mathord"|"mathbin"|"mathrel")
+#line 152 "l2h.nw"
+every ignore("tiny" | "scriptsize" | "footnotesize" | "small" | "normalsize" |
+ "large" | "Large" | "LARGE" | "huge" | "Huge")
+#line 160 "l2h.nw"
+every accent(key(accent_name))
+every ignore("dag" | "ddag")
+substitution("S", "&sect;")
+substitution("P", "&para;")
+substitution("copyright", "&copy;")
+substitution("pounds", "&pound;")
+substitution("o", "&oslash;")
+substitution("O", "&Oslash;")
+substitution("aa", "&aring;")
+substitution("AA", "&Aring;")
+substitution("ae", "&aelig;")
+substitution("AE", "&Aelig;")
+#line 175 "l2h.nw"
+argblockv("part", "h1", &null, "*[")
+argblockv("chapter", "h1", &null, "*[")
+argblockv("section", "h2", &null, "*[")
+argblockv("subsection", "h3", &null, "*[")
+argblockv("subsubsection", "h4", &null, "*[")
+argblockv("paragraph", "h5", &null, "*[")
+argblockv("subparagraph", "h6", &null, "*[")
+ignore("appendix")
+auxfile("tableofcontents", "toc",
+ "<p>\n<tableofcontents>\n<b>[Table of contents]</b>\n</tableofcontents>\n<p>",
+ "<h2>Table of Contents</h2>\n<tableofcontents>\n", "\n</tableofcontents>\n")
+cstab["tableofcontents"] := Ctableofcontents # override to call set_toclevel
+ignore("listoftables")
+ignore("listoffigures")
+ignore("addtocontents", "{{")
+ignoreenv("filecontents", "{")
+#line 198 "l2h.nw"
+cstab["("] := Cmath
+cstab[")"] := Cmath_end
+cstab["["] := Cdisplaymath
+cstab["]"] := Cdisplaymath_end
+ignoreenv("equation")
+every table_env(star("eqnarray"), 0, " ", "<blockquote><i>", "</i></blockquote>")
+ # also lame
+substitution("frac", "<b>frac</b>")
+substitution("sqrt", "<b>frac</b>")
+every substitution("ldots" | "cdots" | "vdots", "...")
+ignore("left")
+ignore("right")
+ignore("overline")
+substitution(":", " ")
+substitution(";", " ")
+ignore("!")
+#line 223 "l2h.nw"
+substitution("Diamond", "&lt;&gt;")
+substitution("langle", "&lt;")
+substitution("rangle", "&gt;")
+substitution("le", "&lt;=")
+substitution("ne", "!=")
+substitution("ge", "&gt;=")
+substitution("times", "&times;")
+substitution("divide", "&divide;")
+substitution("bmod", "</i>mod<i>") # better hook in with math
+substitution("equiv", "===")
+every x := "arccos" | "arcsin" | "arctan" | "arg" | "cos" | "cosh" |
+ "cot" | "coth" | "csc" | "deg" | "det" | "dim" | "exp" |
+ "gcd" | "hom" | "lim" | "liminf" | "limsup" | "ln" | "log" |
+ "max" | "min" | "sec" | "sin" | "sinh" | "sup" | "tan" | "tanh"
+do
+ substitution(x, "</i>" || x || "<i>")
+substitution("liminf", "</i>lim inf<i>")
+substitution("limsup", "</i>lim sup<i>")
+every x := "alpha" | "beta" | "gamma" | "delta" | "epsilon" | "zeta" | "eta" |
+ "theta" | "iota" | "kappa" | "lambda" | "nu" | "xi" | "pi" |
+ "rho" | "sigma" | "tau" | "upsilon" | "phi" | "chi" | "psi" | "omega" |
+ "in"
+do
+ substitution(x, "<b>" || x || "</b>")
+substitution("mu", "&micro;")
+every x := "Gamma" | "Delta" | "Theta" | "Lambda" | "Xi" | "Pi" | "Sigma" |
+ "Upsilon" | "Phi" | "Psi" | "Omega"
+do
+ substitution(x, "<b>" || x || "</b>")
+#line 255 "l2h.nw"
+substitution("lfloor", "</i>|_<i>")
+substitution("rfloor", "</i>_|<i>")
+substitution("leq", "&lt;=")
+substitution("geq", "&gt;=")
+substitution("ll", "&laquo;")
+substitution("gg", "&raquo;")
+substitution("Rightarrow", "==&gt;")
+substitution("rightarrow", "--&gt;")
+substitution("approx", "<u>~</u>")
+#line 268 "l2h.nw"
+envblock("quote", "blockquote")
+envblock("quotation", "blockquote")
+envblock("center", "blockquote")
+envblock("flushleft", "blockquote")
+envblock("flushright", "blockquote")
+envblock("verse", "blockquote")
+verbatim("verbatim", escape_HTML_specials, "pre")
+cstab["verb"] := Cverb
+cstab["verb*"] := Cverb
+csclosure["verb*"] := 1
+cstab["verbatiminput"] := Cverbatiminput
+csclosure["verbatiminput"] := verbatim_cl(escape_HTML_specials)
+#line 284 "l2h.nw"
+cstab["item"] := Citem
+csclosure["item"] := [item_cl("<li>", "", "<li>")]
+listenv("itemize", "ul")
+listenv("enumerate", "ol")
+listenv("description", "dl")
+#line 292 "l2h.nw"
+ignore("documentstyle", "[{")
+ignore("documentclass", "[{")
+ignore("usepackage", "[{")
+ignore("pagestyle", "{")
+ignore("thispagestyle", "{")
+ignore("pagenumbering", "{")
+ignore("newcounter", "{")
+ignore("global")
+ignore("etalchar") # used in the .bbl files: \newcommand{\etalchar}[1]{$^{#1}$}
+#line 307 "l2h.nw"
+argblockv("title", "h1")
+argblockv("author","address")
+argblockv("date", "b")
+substitution("maketitle", "<!--title goes here-->")
+ignoreenv("titlepage")
+envblock("abstract", "<h2>Abstract</h2><blockquote>", "</blockquote>")
+#line 322 "l2h.nw"
+cstab["label"] := Clabel
+cstab["ref"] := Cref
+cstab["pageref"] := Cref
+cstab["subpageref"] := Cref
+cstab["chunklabel"] := Clabel
+#line 332 "l2h.nw"
+ignore("bibliographystyle", "{")
+auxfile("bibliography", "bbl", "<b>[BibTeX bibliography]</b>", &null, &null, "{")
+envblock("thebibliography", "<h2>References</h2>", "", "{")
+every cstab["cite" | "citeN" | "opencite" | "openciteN" | "citeyear"] := Ccite
+cstab["bibitem"] := Cbibitem
+ignore("newblock")
+ignore("nocite", "{")
+#line 343 "l2h.nw"
+every ignore("input" | "include" | "includeonly", "{")
+# filecontents not done yet
+#line 348 "l2h.nw"
+cstab["\\"] := Cbackback
+substitution("linebreak", "<br>")
+ignore("-")
+ignoreenv("sloppypar")
+ignore("sloppy")
+#line 357 "l2h.nw"
+substitution("pagebreak", "<hr>")
+substitution("newpage", "<hr>")
+substitution("clearpage", "<hr>")
+ignore("enlargethispage", "*{")
+#line 364 "l2h.nw"
+ignore("mbox")
+ignore("makebox", "([[") # ( comes from picture area
+ignore("fbox")
+ignore("framebox", "[[") # could insert horizontal rules, but why?
+ignore("newsavebox", 1)
+ignore("sbox", 2)
+ignore("savebox", "{[[{")
+ignore("usebox", 1)
+envblock("minipage", "blockquote", &null, "[{")
+argblock("parbox", "blockquote", &null, "[{")
+#line 377 "l2h.nw"
+ignore("hspace", "*{")
+ignore("hfil")
+ignore("hfill")
+ignore("vspace", "*{")
+ignore("vfil")
+ignore("vfill")
+#line 386 "l2h.nw"
+ignore("newlength", "{")
+ignore("setlength", "{{")
+ignore("addtolength", "{{")
+#line 392 "l2h.nw"
+envblock("picture", "<b>[picture]</b>", "", "((")
+ignore("put", "({")
+ignore("multiput", "(({{")
+ignore("dashbox", "{([")
+ignore("line", "({")
+ignore("vector", "({")
+ignore("shortstack", "[")
+ignore("circle", "*{")
+ignore("oval", "([")
+ignore("frame")
+ignore("thinlines")
+ignore("thicklines")
+#line 408 "l2h.nw"
+every envblock(star("figure"), "<hr>", "<hr>", "[")
+every envblock(star("table"), "<hr>", "<hr>", "[")
+argblock("caption", "b") # captions in bold
+#line 415 "l2h.nw"
+envblock("tabbing", "blockquote")
+# \= is accent
+ignore(">")
+ignore("+")
+ignore("kill")
+#line 423 "l2h.nw"
+tabular("array", "[")
+tabular("tabular", "[")
+tabular("tabularx", "{[")
+tabular("tabular*", "{[")
+every cstab["multicolumn"|"multispan"] := Cmulticolumn
+cstab["span"] := Cspan
+cstab["noalign"] := Cnoalign
+cstab["hline"] := Chline
+cstab["toprule"] := Chline
+cstab["midrule"] := Chline
+cstab["bottomrule"] := Chline
+ignore("cline", "{")
+ignore("newcolumntype", "{{")
+#line 439 "l2h.nw"
+ignore("newcommand", "A[[{")
+ignore("renewcommand", "A[[{")
+ignore("providecommand", "A[[{")
+ignore("newenvironment", "{[{{")
+ignore("renewenvironment", "{[{{")
+ignore("newtheorem", "{{")
+#line 450 "l2h.nw"
+cstab["setcounter"] := Csetcounter
+ignore("addtocounter", "{{")
+#line 455 "l2h.nw"
+cstab["makeatletter"] := Cmakeatletter
+cstab["makeatother"] := Cmakeatother
+#line 460 "l2h.nw"
+every fontchange("tt" | "ttfamily", "tt")
+every fontchange("bf" | "bfseries", "b")
+every fontchange("it" | "itshape", "i")
+fontchange("sl", "i")
+fontchange("em", "em")
+ignore("rm") # html can't switch to default font!
+ignore("sf")
+ignore("sc")
+#line 470 "l2h.nw"
+ignore("rmfamily")
+ignore("normalfont")
+#line 473 "l2h.nw"
+ignoreenv("document")
+#line 475 "l2h.nw"
+substitution("LaTeX", "LaTeX")
+#line 477 "l2h.nw"
+ignore("numberline", "{")
+ignore("protect")
+ignore("onecolumn")
+ignore("twocolumn", "C")
+ignore("typeout", "[{")
+ignore("closedbib")
+#line 484 "l2h.nw"
+every ignore("leftmargini" | "leftmarginii" | "labelsep" | "fboxsep", "=")
+every ignore("tabcolsep", "=")
+every ignore("evensidemargin" | "marginparsep" | "marginparwidth" |
+ "oddsidemargin" | "textheight" | "textwidth" | "topmargin", "=")
+#line 489 "l2h.nw"
+ignore("DeclareMathVersion", "{")
+ignore("mathversion", "{")
+ignore("setpapersize", "{")
+ignore("setmarginsrb", "{{{{{{{{")
+ignore("marginparwidth", "=")
+ignore("marginparsep", "=")
+#line 498 "l2h.nw"
+ignoreenv("multicols", "{C")
+cstab["citeN"] := Ccite
+ignore("afterpage", "{")
+every cstab["psfig"|"epsfig"] := Cepsfig
+cstab["includegraphics"] := Cincludegraphics
+ignore("newcolumntype", "{{")
+#line 507 "l2h.nw"
+cstab["kill"] := Ckill
+#line 511 "l2h.nw"
+activesubst("~", "&nbsp;")
+argblock("centerline", "<br>", "<br>")
+substitution("cr", "<br>")
+substitution("hrule", "<hr>")
+substitution("vrule", "|")
+substitution("hrulefill", "------")
+ignore("hyphenation", "{")
+ignore("hbox")
+ignore("rlap")
+ignore("llap")
+ignore("vbox")
+ignore("vtop")
+ignore("hidewidth")
+ignore("message", "{")
+ignore("relax")
+ignore("null")
+ignore("offinterlineskip")
+ignore("omit")
+ignore("newdimen", "{")
+ignore("nobreak")
+#line 532 "l2h.nw"
+cstab["par"] := implicit_paragraph
+cstab["smallskip"] := implicit_paragraph
+cstab["medskip"] := implicit_paragraph
+cstab["bigskip"] := implicit_paragraph
+cstab["vskip"] := implicit_paragraph
+csclosure["vskip"] := "="
+#line 544 "l2h.nw"
+every ignore("begingroup" | "endgroup" | "bgroup" | "egroup")
+#line 546 "l2h.nw"
+cstab["newif"] := Cnewif
+cstab["iffalse"] := Ciffalse
+cstab["iftrue"] := Ciftrue
+cstab["ifhtml"] := Ciftrue # false in LaTeX, but true when converting!
+cstab["else"] := Celse
+cstab["fi"] := Cfi
+cstab["ifx"] := cstab["if"] := cstab["ifnum"] := Ciffalse
+#line 556 "l2h.nw"
+ignore("let", "A=")
+every ignore("hfuzz" | "parindent" | "parskip" | "baselineskip", "=")
+every ignore("hbadness" | "hsize" | "vsize" | "overfullrule" | "tabskip", "=")
+every ignore("extrarowheight" | "codemargin", "=")
+every ignore("looseness", "=")
+substitution("hskip", " ", "=")
+ignore("setbox", "{=")
+every ignore("box" | "unhbox" | "unvbox", "{")
+#line 565 "l2h.nw"
+ignore("unskip")
+ignore("hss")
+ignore("phantom", "{")
+every ignore("kern" | "lower" | "spacefactor", "=") # a cheat, but works
+every ignore("clubpenalty" | "widowpenalty", "=")
+#line 578 "l2h.nw"
+every ignore("expandafter" | "indent" | "noindent" | "leavevmode" | "strut")
+ignore("def", 1)
+#line 581 "l2h.nw"
+substitution("TeX", "TeX")
+substitution("BibTeX", "BibTeX")
+substitution("MF", "METAFONT")
+#line 594 "l2h.nw"
+cstab["char"] := asciiCharCode
+#line 608 "l2h.nw"
+macro("nwanchorto", 2, "<a href=\"#$1\">#2</a>")
+macro("nwanchorname", 2, "<a name=\"#$1\">#2</a>")
+ignore("nwaddbox", "{")
+verbatim("latexonly", do_nothing)
+verbatim("rawhtml", emit_text)
+#line 617 "l2h.nw"
+substitution("quad", " ")
+#line 624 "l2h.nw"
+ignore("noweboptions", 1)
+#line 630 "l2h.nw"
+substitution("nowebindex", "<nowebindex>")
+substitution("nowebchunks", "<nowebchunks>")
+ignore("nowebsize")
+#line 634 "l2h.nw"
+envblock("fields", "blockquote", &null, "[") # lame; could try to <tt> 1st col
+envblock("fields*", "blockquote", &null, "{") # lame; could try to <tt> 1st col
+ignore("citeauthoryear", "{{{")
+ignore("authoryear", "{{")
+substitution("bibrule", "--------")
+let("bibskip", "par")
+every cstab["anoncite"|"authorcite"] := Ccite
+#line 644 "l2h.nw"
+ignore("pssilent")
+ignore("psnoisy")
+#line 1012 "l2h.nw"
+cstab["begin"] := do_begin
+cstab["end"] := do_end
+#line 1385 "l2h.nw"
+cstab["suspend"] := Csuspend
+cstab["resume"] := Cresume
+#line 1603 "l2h.nw"
+cstab["uppercase"] := Cuppercase
+#line 1899 "l2h.nw"
+cstab["contentsline"] := Ccontentsline
+#line 676 "l2h.nw"
+
+#line 2677 "l2h.nw"
+csfunctions["argblock"] := argblock
+csfunctions["argblockv"] := argblockv
+csfunctions["envblock"] := envblock
+csfunctions["fontchange"] := fontchange
+csfunctions["ignore"] := ignore
+csfunctions["ignoreenv"] := ignoreenv
+csfunctions["let"] := let
+csfunctions["letenv"] := letenv
+csfunctions["listenv"] := listenv
+csfunctions["substitution"] := substitution
+csfunctions["activesubst"] := activesubst
+csfunctions["closure"] := let_closure
+csfunctions["let_closure"] := let_closure
+csfunctions["newcommand"] := l2h_macro
+csfunctions["macro"] := l2h_macro
+csfunctions["environment"] := l2h_environment
+csfunctions["tabular"] := tabular
+#line 677 "l2h.nw"
+ specials := '\\{}<>-\'`"%$&~\n\0\1'
+ }
+
+ if \optstring then return optstring ? convert(S)
+ else {
+
+#line 867 "l2h.nw"
+l := S.newtext
+S.newtext := []
+while c := get(l) do
+ c.proc!c.args
+#line 700 "l2h.nw"
+if S.mode == "V" & any(~'\\{}<>%\n\t ') then S.mode := "H"
+emit_text(S, tab(upto(specials) | 0))
+while not pos(0) do
+ if S.mode == "Q" then { # quoting
+ emit_text(S, tab(upto('\1') | 0))
+ if ="\1" then {
+ emit_text(S, "\1")
+ S.mode := S.quotemode
+ }
+ } else {
+ if any(S.activechars) then
+ do_activechar(S, move(1))
+ else
+ case move(1) of {
+ "\\" : {
+#line 941 "l2h.nw"
+cs := if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1)
+if /S.ignoring | cs == ("else"|"fi") | cstab[cs] === (Ciffalse|Ciftrue) then
+ do_cs(S, cs)
+else
+ &null # error("### Ignoring \\", cs)
+#line 714 "l2h.nw"
+ }
+ "{" : {
+#line 915 "l2h.nw"
+push(S.closes, []) # fresh set of closing tasks
+while c := get(S.open) do
+ c.proc!c.args
+#line 715 "l2h.nw"
+ }
+ "}" : {
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 716 "l2h.nw"
+ }
+ "%" : {
+#line 1066 "l2h.nw"
+parse_dynamic_add(S)
+delay_newtext(S)
+eat_comment(S)
+#line 717 "l2h.nw"
+ }
+ "\n" : {
+#line 1313 "l2h.nw"
+emit_text(S, "\n")
+if /S.ignoring then Cnewline(S)
+#line 718 "l2h.nw"
+ }
+ "$" : {
+#line 1301 "l2h.nw"
+if /S.ignoring then
+ if ="$" then
+ if S.mode == "M" then { Cdisplaymath_end(S); S.mode := "V" }
+ else { Cdisplaymath(S); S.mode := "M" }
+ else
+ if S.mode == "M" then { Cmath_end(S); S.mode := "H" }
+ else { Cmath(S); S.mode := "M" }
+#line 719 "l2h.nw"
+ }
+ "&" : ampersand(S)
+ "\0" : {S.quotemode := S.mode; S.mode := "Q"; emit_text(S, "\0")}
+ # remaining cases simply escape HTML specials
+ "<" : emit_text(S, "&lt;")
+ ">" : emit_text(S, "&gt;")
+ "\"" : emit_text(S, "&quot;")
+ "-" : {
+#line 735 "l2h.nw"
+if S.mode == "V" then S.mode := "H"
+if S.mode == "H" then
+ if ="--" then emit_text(S, "&mdash;")
+ else if ="-" then emit_text(S, "&ndash;")
+ else emit_text(S, "-")
+else
+ emit_text(S, "-")
+#line 726 "l2h.nw"
+ }
+ "`" : {
+#line 746 "l2h.nw"
+if S.mode == "V" then S.mode := "H"
+if \html_quotes & S.mode == "H" then
+ if ="`" then emit_text(S, "&ldquo;")
+ else emit_text(S, "&lsquo;")
+else
+ emit_text(S, "`")
+#line 727 "l2h.nw"
+ }
+ "'" : {
+#line 753 "l2h.nw"
+if S.mode == "V" then S.mode := "H"
+if \html_quotes & S.mode == "H" & ="'" then emit_text(S, "&rdquo;")
+else emit_text(S, "'")
+#line 728 "l2h.nw"
+ }
+ }
+ if S.mode == "V" & any(~'\\{}<>%\n\t ') then S.mode := "H"
+ emit_text(S, tab(upto(specials++S.activechars) | 0))
+ }
+return 1(. S.the_text, S.the_text := "") # what's been converted
+#line 683 "l2h.nw"
+ }
+end
+#line 744 "l2h.nw"
+global html_quotes # render quotes as HTML 4 entities
+#line 760 "l2h.nw"
+record state(mode, quotemode
+#line 788 "l2h.nw"
+, text, the_text
+#line 804 "l2h.nw"
+, ignoring
+#line 822 "l2h.nw"
+, activechars
+#line 844 "l2h.nw"
+, newtext
+#line 887 "l2h.nw"
+, delayed_newtext
+#line 897 "l2h.nw"
+, open, closes
+#line 949 "l2h.nw"
+, csletters
+#line 1082 "l2h.nw"
+, comment
+#line 1521 "l2h.nw"
+, ifstack
+#line 1628 "l2h.nw"
+, tables
+#line 760 "l2h.nw"
+ )
+ # mode is Q, H, V, or M
+ # quotemode is saved mode: H, V, or M
+#line 766 "l2h.nw"
+procedure converter(mode)
+ /mode := "V"
+ return state(mode, mode
+#line 790 "l2h.nw"
+, accumulate_text, ""
+#line 806 "l2h.nw"
+, &null
+#line 824 "l2h.nw"
+, '~'
+#line 846 "l2h.nw"
+, []
+#line 889 "l2h.nw"
+, []
+#line 899 "l2h.nw"
+, [], []
+#line 951 "l2h.nw"
+, &letters
+#line 1084 "l2h.nw"
+, ""
+#line 1523 "l2h.nw"
+, []
+#line 1630 "l2h.nw"
+, []
+#line 768 "l2h.nw"
+ )
+end
+#line 774 "l2h.nw"
+procedure reset(S)
+
+#line 792 "l2h.nw"
+S.text := accumulate_text
+S.the_text := ""
+#line 808 "l2h.nw"
+S.ignoring := &null
+#line 826 "l2h.nw"
+S.activechars := '~'
+#line 848 "l2h.nw"
+S.newtext := []
+#line 891 "l2h.nw"
+S.delayed_newtext := []
+#line 901 "l2h.nw"
+every S.open | S.closes := []
+#line 953 "l2h.nw"
+S.csletters := &letters
+#line 1086 "l2h.nw"
+S.comment := ""
+#line 1525 "l2h.nw"
+if *S.ifstack > 0 then S.ifstack := [] # keeps GC down
+#line 1632 "l2h.nw"
+S.tables := []
+#line 776 "l2h.nw"
+ return S
+end
+#line 783 "l2h.nw"
+procedure accumulate_text(S, text)
+ S.the_text ||:= text
+ return
+end
+#line 800 "l2h.nw"
+procedure emit_text(S, text)
+ return if \S.ignoring then "" else S.text(S, text)
+end
+#line 813 "l2h.nw"
+global activetab, activeclosure
+procedure do_activechar(S, c)
+ (activetab[c])(S, c, activeclosure[c])
+ return
+end
+#line 852 "l2h.nw"
+record closure(proc, args)
+#line 857 "l2h.nw"
+procedure before_next_newtext(S, proc, args)
+ push(S.newtext, closure(proc, args))
+end
+
+procedure after_next_newtext(S, proc, args)
+ put(S.newtext, closure(proc, args))
+end
+#line 876 "l2h.nw"
+procedure delay_newtext(S)
+ push(S.delayed_newtext, S.newtext)
+ S.newtext := []
+ return
+end
+
+procedure undelay_newtext(S)
+ S.newtext := \pop(S.delayed_newtext) |
+ {write(&errout, "This can't happen: no delayed_newtext"); &null[0]}
+end
+#line 903 "l2h.nw"
+procedure after_next_open(S, proc, args)
+ return put(S.open, closure(proc, args))
+end
+
+procedure before_next_close(S, proc, args)
+ return push(S.closes[1], closure(proc, args)) # lost at top level
+end
+
+procedure after_next_close(S, proc, args)
+ return put(S.closes[1], closure(proc, args)) # lost at top level
+end
+#line 960 "l2h.nw"
+global cstab, csclosure
+
+procedure do_cs(S, cs)
+ tab(many(' \t')) # skip white space following CS
+ if pos(0) | any('\n') then before_next_newtext(S, skipblanks, [S])
+ (cstab[cs])(S, cs, csclosure[cs])
+ return
+end
+#line 976 "l2h.nw"
+global show_unknowns
+procedure unknown_cs(S, cs, cl)
+# if S.text === ignore_text then return # a bit of a hack -- should no longer be needed
+ if \show_unknowns then S.text(S, "<b>\\" || cs || "</b>")
+ if not member(unknown_set, cs) then {
+ write(\unknown_file, "Warning: unknown control sequence \\", cs)
+ insert(unknown_set, cs)
+ }
+ return
+end
+#line 989 "l2h.nw"
+global cstab, csclosure, unknown_set
+#line 995 "l2h.nw"
+global begintab, endtab, begincl, endcl
+
+procedure do_begin(S, cs, cl)
+ (="{", env := tab(upto('}')), ="}") | error("botched \\begin{...}")
+
+#line 915 "l2h.nw"
+push(S.closes, []) # fresh set of closing tasks
+while c := get(S.open) do
+ c.proc!c.args
+#line 1000 "l2h.nw"
+ (begintab[env])(S, env, begincl[env])
+ return
+end
+
+procedure do_end(S, cs, cl)
+ (="{", env := tab(upto('}')), ="}") | error("botched \\end{...}")
+ # write(&errout, "calling ", image(endtab[env]), " for \\end{", env, "}")
+ (endtab[env])(S, env, endcl[env])
+
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 1009 "l2h.nw"
+ return
+end
+#line 1018 "l2h.nw"
+procedure unknown_env(S, env, cl)
+### if S.text === ignore_text then return # a bit of a hack # no longer needed
+ if \show_unknowns then S.text(S, "<b>{" || env || "}</b>")
+ if not member(unknown_envs, env) then {
+ write(\unknown_file, "Warning: unknown environment {", env, "}")
+ insert(unknown_envs, env)
+ }
+ return
+end
+#line 1030 "l2h.nw"
+global unknown_envs
+#line 1034 "l2h.nw"
+procedure warn_unknown(s, type, mark, rmark)
+ if *s > 0 then {
+ pushout("Unknown " || type || ": ")
+ every pushout(((\mark | "")\1) || !sort(s) || ((\rmark | "")\1) || " ")
+ pushout("\n")
+ }
+end
+#line 1042 "l2h.nw"
+procedure pushout(s)
+ static col
+ initial col := 0
+ if find("\n", s) then
+ s ? {
+ pushout(tab(upto('\n')))
+ while ="\n" do {col := 0; write(&errout)}
+ pushout(tab(0))
+ }
+ else {
+ col +:= *s
+ if col >= 79 then {writes(&errout, "\n "); col := *s + 2}
+ writes(&errout, s)
+ }
+ return
+end
+#line 1070 "l2h.nw"
+procedure eat_comment(S)
+ S.comment ||:= tab(upto('\n') | 0)
+ if pos(0) then
+ before_next_newtext(S, eat_comment, [S])
+ else {
+ undelay_newtext(S)
+ Ccomment(S)
+ S.comment := ""
+ }
+ return
+end
+#line 1106 "l2h.nw"
+record verbatim_cl(output, terminator, html, translate_blank)
+
+procedure verbatim(name, output, html)
+ begintab[name] := Cverbatim
+ begincl [name] := verbatim_cl(output, &null, html)
+ return
+end
+
+procedure Cverbatim(S, cs, cl)
+ if cl === begincl[cs] & /cl.terminator then
+ cl := begincl[cs] :=
+ verbatim_cl(cl.output, "\\end{" || cs || "}", cl.html, cl.translate_blank)
+ emit_text(S, tag(\cl.html))
+ delay_newtext(S)
+ do_verbatim(S, cl)
+ return
+end
+#line 1128 "l2h.nw"
+procedure do_verbatim(S, cl)
+ if cl.output(S, tab(find(cl.terminator)), cl) then {
+ =cl.terminator
+ emit_text(S, endtag(\cl.html))
+ undelay_newtext(S)
+ } else {
+ cl.output(S, tab(0), cl)
+ before_next_newtext(S, do_verbatim, [S, cl])
+ }
+ return
+end
+#line 1142 "l2h.nw"
+procedure escape_HTML_specials(S, s, cl)
+ s ? {
+ while emit_text(S, tab(upto('&<>" '))) do
+ case move(1) of {
+ "\"" : emit_text(S, "&quot;")
+ "&" : emit_text(S, "&amp;")
+ "<" : emit_text(S, "&lt;")
+ ">" : emit_text(S, "&gt;")
+ " " : emit_text(S, if \cl.translate_blank then "&middot;" else " ")
+ }
+ emit_text(S, tab(0))
+ }
+ return
+end
+#line 1160 "l2h.nw"
+procedure Cverb(S, cs, cl)
+ Cverbatim(S, cs, verbatim_cl(escape_HTML_specials, move(1), "tt", cl))
+ return
+end
+#line 1166 "l2h.nw"
+procedure Cverbatiminput(S, cs, cl)
+ local filename, f, line
+ if ="{" & filename := tab(upto('}')) & ="}" then {
+ f := \open(filename) | { emit_text(S, "<strong>Could not read file</strong> <tt>")
+ escape_HTML_specials(S, filename, cl)
+ emit_text(S, "</tt>")
+ return
+ }
+ emit_text(S, "\n<pre>\n")
+ while line := read(f) do {
+ escape_HTML_specials(S, line, cl)
+ emit_text(S, "\n")
+ }
+ emit_text(S, "</pre>\n")
+ close(f)
+ }
+ return
+end
+#line 1190 "l2h.nw"
+procedure csarg(S)
+ return 2(="{", tab(bal('}', '{', '}')), ="}") |
+ (optwhite(),
+ if ="\\" then
+ "\\" || (tab(many(S.csletters)) | move(1))
+ else
+ move(1))
+end
+#line 1225 "l2h.nw"
+procedure apply_args(S, p, as, args_wanted)
+ delay_newtext(S)
+ do_apply_args(S, closure(p, as), args_wanted, [], "", 0)
+ return
+end
+
+procedure do_apply_args(S, cl, wanted_count, args_seen, current_arg, brace_depth)
+ local open_comment
+ # invariant : we have an open brace
+# pushtrace("APPLY")
+ while *args_seen < wanted_count & not pos(0) do {
+ while *args_seen < wanted_count & brace_depth = 0 & not pos(0) do {
+ tab(many(' \t\n'))
+ case c := move(1) of {
+ "\\" : put(args_seen, "\\" ||
+ if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1))
+ "{" : { current_arg := "" ; brace_depth := 1 }
+ "}" : { error("Insufficient arguments to macro ", macro.name) }
+ "%" : if tab(upto('\n')) then ="\n" else open_comment := tab(0)
+ default : put(args_seen, c)
+ }
+ }
+ while brace_depth > 0 & not pos(0) do {
+ current_arg ||:= tab(upto('\\{}%') | 0)
+ case move(1) of {
+ "%" : if tab(upto('\n')) then ="\n" else open_comment := tab(0)
+ "\\" : current_arg ||:= "\\" ||
+ if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1)
+ "{" : { current_arg ||:= "{" ; brace_depth +:= 1 }
+ "}" : { brace_depth -:= 1
+ if brace_depth > 0 then
+ current_arg ||:= "}"
+ else {
+ put(args_seen, current_arg)
+ current_arg := ""
+ }
+ }
+ }
+ }
+ }
+ if *args_seen = wanted_count then {
+ undelay_newtext(S)
+ cl.proc ! (cl.args ||| args_seen)
+ } else if \open_comment then {
+ delay_newtext(S)
+ before_next_newtext(S, skip_comment_and_continue,
+ [S, closure(do_apply_args, [S, cl, wanted_count, args_seen,
+ current_arg, brace_depth])])
+ } else
+ before_next_newtext(S, do_apply_args, [S, cl, wanted_count, args_seen,
+ current_arg, brace_depth])
+# poptrace()
+ return
+end
+#line 1284 "l2h.nw"
+procedure skip_comment_and_continue(S, cl)
+ tab(upto('\n') | 0)
+ if pos(0) then
+ before_next_newtext(S, skip_comment_and_continue, [S, cl])
+ else {
+ ="\n"
+ undelay_newtext(S)
+# <take actions appropriate to new text>>
+ }
+ return
+end
+#line 1316 "l2h.nw"
+procedure Cnewline(S)
+ tab(many(' \t'))
+ if match("\n") then implicit_paragraph(S)
+ if pos(0) then before_next_newtext(S, Cnewline, [S])
+end
+#line 1325 "l2h.nw"
+procedure skipblanks(S)
+ tab(many(' \t'))
+ if ="\n" then Cnewline(S)
+ else if pos(0) then before_next_newtext(S, skipblanks, [S])
+end
+#line 1334 "l2h.nw"
+procedure implicit_paragraph(S, cs, cl)
+ if S.mode ~== "V" then {
+ S.mode := "V"
+ Cparagraph(S)
+ }
+ cs_ignore(S, cs, \cl)
+end
+#line 1347 "l2h.nw"
+procedure stop_skipping(S)
+ while S.newtext[1].proc === (Cnewline|skipblanks) do pop(S.newtext)
+end
+#line 1357 "l2h.nw"
+record item_cl(before, after, ifnone)
+
+procedure Citem(S, cs, cl)
+ if pos(0) then
+ after_next_newtext(S, Citem, [S, cs, cl])
+ else if ="[" then {
+ delay_newtext(S)
+ with_upto_bracket(S, "", convert_bracketed, cl)
+ } else {
+ skipblanks(S)
+ emit_text(S, cl[1].ifnone)
+ \liststack[1] := \liststack[1] + 1
+ }
+end
+#line 1372 "l2h.nw"
+procedure convert_bracketed(S, contents, cl)
+ emit_text(S, cl[1].before ||
+ convert(converter("H"), "{" || contents || "}") ||
+ cl[1].after)
+ optwhite()
+end
+#line 1379 "l2h.nw"
+global liststack, suspendstack
+#line 1388 "l2h.nw"
+procedure listenv(env, html)
+ begintab[env] := Clist
+ begincl[env] := html
+ endtab[env] := Clist_end
+ endcl[env] := html
+end
+
+procedure push_item_closure(cs)
+ push(csclosure["item"],
+ if cs == "description" then item_cl("<dt>", "<dd>", "<dt><dd>")
+ else item_cl("<li>", "--", "<li>"))
+end
+
+procedure Clist(S, cs, cl)
+ push(liststack, 1)
+ push_item_closure(cs)
+ emit_text(S, tag(cl))
+end
+
+procedure Cresume(S, cs, cl)
+ local n, env
+ (="{", env := tab(upto('}')), ="}") | error("botched \\resume{...}")
+ n := pop(suspendstack) | error("\\resume not balanced by corresponding \\suspend")
+ push(liststack, n)
+ push_item_closure(env)
+ if env == "enumerate" then
+ emit_text(S, tag(begincl[env] || " start=\"" || n || "\""))
+ else
+ emit_text(S, tag(begincl[env]))
+end
+
+procedure Clist_end(S, cs, cl)
+ emit_text(S, endtag(cl))
+ pop(csclosure["item"])
+ pop(liststack)
+end
+
+procedure Csuspend(S, cs, cl)
+ local env
+ (="{", env := tab(upto('}')), ="}") | error("botched \\suspend{...}")
+ emit_text(S, endtag(endcl[env]))
+ pop(csclosure["item"])
+ push(suspendstack, pop(liststack))
+end
+#line 1437 "l2h.nw"
+global labels_seen
+
+procedure Clabel(S, cs, cl)
+ initial /labels_seen := set()
+ insert(labels_seen, l := csarg(S)) | fail
+ emit_text(S, "<a name=\"" || l || "\"><b>[*]</b></a>")
+end
+
+procedure Cref(S, cs, cl)
+ local prefix, prefix_tag
+ initial /labels_seen := set()
+ prefix_tag := (\cl)[1] | ""
+ prefix := (\cl)[2] | ""
+ l := prefix || csarg(S) | fail
+ emit_text(S, prefix_tag || "<a href=\"#" || l || "\">[" ||
+ (if member(labels_seen, l) then "&lt;-" else "-&gt;") || "]</a>")
+end
+#line 1463 "l2h.nw"
+procedure Ccite(S, cs, cl, bracketed_text)
+ if ="[" then {
+ delay_newtext(S)
+ with_upto_bracket(S, "", do_cite, cl)
+ } else
+ do_cite(S, &null, cl)
+end
+
+procedure do_cite(S, commentary, cl)
+ local key
+ if \commentary then
+ optwhite()
+ if pos(0) then before_next_newtext(S, do_cite, [S, commentary, cl])
+ else {
+ key := csarg(S)
+ \commentary := convert(converter("H"), "{" || \commentary || "}")
+ emit_text(S, "<b>[cite&nbsp;")
+ key ? {
+ while k := tab(upto(",")) & ="," do
+ emit_text(S, "<a href=\"#NWcite-" || k || "\">" || k || "</a>, ")
+ if k := tab(0) then
+ emit_text(S, "<a href=\"#NWcite-" || k || "\">" || k || "</a>")
+ }
+ emit_text(S, ", <i>" || \commentary || "</i>")
+ emit_text(S, "]</b>")
+ }
+end
+#line 1491 "l2h.nw"
+procedure Cbibitem(S, cs, cl)
+ local label, key
+ static counter
+ initial counter := 0
+ if ="[" then {
+ delay_newtext(S)
+ with_upto_bracket(S, "", finish_bibitem, [])
+ } else {
+ label := "<b>[" || (counter +:= 1) || "]</b>"
+ apply_args(S, do_bibitem_key, [S, label], 1)
+ }
+end
+
+procedure do_bibitem_key(S, label, key)
+ return emit_text(S, "<a name=\"NWcite-" || key || "\">" || label || "</a> ")
+end
+
+procedure finish_bibitem(S, contents, args)
+ local key, label
+ optwhite()
+ label := convert(converter("H"), "{" || contents || "}")
+ key := apply_args(S, do_bibitem_key, [S, label], 1)
+end
+#line 1529 "l2h.nw"
+record ifrec(on_else, on_fi)
+#line 1538 "l2h.nw"
+procedure Ciffalse(S, cs, cl)
+#error("### \\", cs, " -> false (S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)}, ")")
+ push(S.ifstack, ifrec(S.ignoring, S.ignoring))
+ S.ignoring := 1
+end
+
+procedure Ciftrue(S, cs, cl)
+#error("### \\", cs, " -> true (S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)}, ")")
+ push(S.ifstack, ifrec(1, S.ignoring))
+end
+
+procedure Celse(S, cs, cl)
+ S.ignoring := S.ifstack[1].on_else
+#error("### \\else -> S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)})
+end
+
+procedure Cfi(S, cs, cl)
+ S.ignoring := S.ifstack[1].on_fi
+#error("### \\fi -> S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)})
+ pop(S.ifstack)
+end
+#line 1563 "l2h.nw"
+procedure Cnewif(S, cs, cl)
+ local newif, newcs
+ tab(many(' \t\n'))
+ if pos(0) then
+ after_next_newtext(S, Cnewif, [S, cs, cl])
+ else {
+ newif := csarg(S)
+ newif ?
+ if ="\\if" & newcs := tab(many(S.csletters)) & pos(0) then {
+
+#line 1580 "l2h.nw"
+cstab[newcs || "false"] := Csetif
+cstab[newcs || "true"] := Csetif
+cstab["if" || newcs] := Ciffalse
+#line 1573 "l2h.nw"
+ } else
+ error("\\newif argument botch: " || newif)
+ }
+end
+#line 1584 "l2h.nw"
+procedure Csetif(S, cs, cl)
+ local base, tag
+ if cs ? (base := tab(find("true"|"false")), tag := =("true"|"false"), pos(0)) then {
+ cstab["if" || base] := if tag == "true" then Ciftrue else Ciffalse
+ } else {
+ error("This can't happen --- setif botch (not urgent)")
+ }
+end
+#line 1598 "l2h.nw"
+procedure Cuppercase(S, cs, cl)
+ l := map(csarg(S), &lcase, &ucase) | fail
+ emit_text(S, l)
+end
+#line 1613 "l2h.nw"
+record table_info(index, # number of this cell in the row
+ alignment, # the alignment of this cell
+ width, # how many columns this cell will span
+ alignments, # default alignments for this table
+ brace_depth, # size of S.closes after start of cell
+ cell_text) # value of S.text to use to scan this cell
+#line 1637 "l2h.nw"
+procedure start_table_cell(S, text)
+ local this, attributes
+
+ text ? {
+ tab(many(' \t\n'))
+ if pos(0) then return
+ }
+# write(&errout, "starting cell with ", image(text))
+
+ this := S.tables[1] | fatal("starting cell with no current table")
+ S.text := this.cell_text
+
+if /(\this).brace_depth then write(&errout, "starting table cell, ", image(this), " has null brace depth")
+ # use this to start the current cell
+ if this.index = 1 then emit_text(S, "<tr>")
+ attributes := \this.alignment | aligneq("top")
+ if this.width > 1 then attributes ||:= " colspan=" || this.width
+ emit_text(S, "<td" || attributes || ">")
+
+ # now update state for the next cell
+ this.index +:= this.width # advance to next cell
+ this.alignment := this.alignments[this.index] | &null
+ this.width := 1
+ # can't set cell_text until we hit &
+
+
+#line 915 "l2h.nw"
+push(S.closes, []) # fresh set of closing tasks
+while c := get(S.open) do
+ c.proc!c.args
+#line 1663 "l2h.nw"
+ emit_text(S, text)
+ return
+end
+#line 1670 "l2h.nw"
+procedure ampersand(S)
+ local this
+ this := S.tables[1]
+
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 1674 "l2h.nw"
+ if /this then
+ emit_text(S, " --- ")
+ else {
+ emit_text(S, "") # be sure cell gets started, even if empty
+ emit_text(S, "</td>")
+ if S.text ~=== start_table_cell then
+ this.cell_text := S.text
+ S.text := start_table_cell
+ this.brace_depth := *S.closes + 1 # will open at start of cell
+#write(&errout, "set brace depth for ", image(this))
+ }
+ tab(many(' \t\n'))
+## write(&errout, " past &, text = ", image(S.text), ", next = ",
+## image(&subject[&pos:0]))
+ return
+end
+#line 1699 "l2h.nw"
+procedure Cbackback(S, cs, cl)
+ local this
+ this := S.tables[1]
+ cs_ignore(S, cs, "[", Cbackback_continue, [S, this])
+end
+
+procedure Cbackback_continue(S, this)
+#if /(\this).brace_depth then write(&errout, image(this), " has null brace depth")
+ if /this | *S.closes > this.brace_depth then { # ordinary \\
+ S.text(S, "<br>")
+ } else { # row terminator
+## write(&errout, "ending row with ", image(&subject[&pos:0]))
+ emit_text(S, "") # be sure cell gets started, even if empty
+
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 1713 "l2h.nw"
+ emit_text(S, "</td></tr>\n")
+ tab(many(' \t\n'))
+ if S.text ~=== start_table_cell then
+ this.cell_text := S.text
+ this.index := 1
+ this.alignment := this.alignments[this.index] | &null
+ this.width := 1
+ S.text := start_table_cell
+ this.brace_depth := *S.closes + 1 # about to open
+ }
+end
+#line 1727 "l2h.nw"
+procedure Chline(S, cs, cl)
+ if \S.tables[1] then return
+ else emit_text(S, "<hr>")
+ return
+end
+#line 1737 "l2h.nw"
+procedure Ctabular_end(S, cs, cl)
+ local this
+ if S.text ~=== start_table_cell | S.tables[1].index > 1 then {# row in progress
+ emit_text(S, "") # be sure cell gets started, even if empty
+
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 1742 "l2h.nw"
+ emit_text(S, "</td></tr>")
+ }
+ if S.text === start_table_cell then # abort it
+ S.text := S.tables[1].cell_text
+ emit_text(S, "</table>")
+ xxx := pop(S.tables)
+#write(&errout, "popped ", image(xxx))
+ return
+end
+#line 1754 "l2h.nw"
+procedure Ctabular(S, cs, cl)
+ cs_ignore(S, cs, cl, Ctabular_continue, [S])
+ return
+end
+
+procedure Ctabular_continue(S)
+ a := csarg() # alignment
+#write(&errout, "Alignment ", a)
+ emit_text(S, if upto('|', a) then "<table border>" else "<table>")
+ emit_text(S, "<!-- alignment is " || a || "-->")
+ a := alignments(a)
+ emit_text(S, "<!-- " || *a || " columns-->")
+ push(S.tables, table_info(1, a[1] | "l", 1, a, *S.closes+1, S.text))
+#write(&errout, "pushed ", image(S.tables[1]))
+ S.text := start_table_cell
+ optwhite()
+ return
+end
+#line 1777 "l2h.nw"
+procedure tabular(env, ignore)
+ begintab[env] := Ctabular
+ begincl[env] := ignore
+ endtab[env] := Ctabular_end
+ endcl[env] := ignore
+end
+#line 1786 "l2h.nw"
+procedure aligneq(a)
+ return " align=\"" || a || "\""
+end
+
+procedure valigneq(a)
+ return " valign=\"" || a || "\""
+end
+
+procedure alignments(s)
+ a := []
+ s ? {
+ while not pos(0) do
+ case move(1) of {
+ "l" | "X" | "Y" | "p" :
+ { put(a, aligneq("left") || valigneq("top")); skip_bracket() }
+ "c" : put(a, aligneq("center"))
+ "r" : put(a, aligneq("right"))
+ "m" : { put(a, aligneq("left") || valigneq("center")); skip_bracket() }
+ "b" : { put(a, aligneq("left") || valigneq("bottom")); skip_bracket() }
+ "@" | "<" | ">" | "!" : skip_bracket()
+ "|" : &null
+ default : &null # unrecognized...
+ }
+ }
+ return a
+end
+#line 1813 "l2h.nw"
+procedure skip_bracket()
+ if ="{" then {
+ n := 1
+ while n > 0 & not pos(0) do {
+ tab(upto('{}\\') | 0)
+ case move(1) of {
+ "{" : n +:= 1
+ "}" : n -:= 1
+ "\\" : move(1)
+ }
+ }
+ }
+ return
+end
+#line 1831 "l2h.nw"
+procedure Cmulticolumn(S, cs, cl)
+ local this
+ this := S.tables[1]
+ n := integer(csarg()) | error("\\multicolumn or \\multispan not followed by integer")
+ if cs == "multicolumn" then a := alignments(csarg())
+# write(&errout, "\\", cs, " n = ", n, ", a = ", (\a)[1] | "???",
+# ", text = ", image(S.text))
+ if /this then return # \multicolumn without table?
+ this.width := n
+ this.alignment := (\a)[1]
+ return
+end
+
+procedure Cspan(S, cs, cl)
+ (\S.tables[1]).width +:= 1
+ return
+end
+#line 1850 "l2h.nw"
+procedure Cnoalign(S, cs, cl)
+ apply_args(S, finish_noalign, [S], 1)
+ return
+end
+
+procedure finish_noalign(S, arg)
+ return if \S.ignoring then "" else
+ accumulate_text(S, "<br>" || convert(converter("V"), "{" || arg || "}") || "<br>")
+end
+#line 1862 "l2h.nw"
+procedure auxfile(cs, ext, placeholder, header, trailer, ignore)
+ cstab[cs] := Cauxfile
+ csclosure[cs] := aux_cl(ext, placeholder, header, trailer, \ignore | "")
+end
+#line 1869 "l2h.nw"
+record aux_cl(ext, placeholder, header, trailer, ignore)
+
+procedure Cauxfile(S, cs, cl)
+ local auxfile, T
+ if auxfile := open(basename(\curfile) || "." || cl.ext) then {
+ T := converter("V")
+ Cmakeatletter(T)
+ S.text(S, \cl.header)
+ while line := read(auxfile) do
+ S.text(S, convert(T, line || "\n"))
+ close(auxfile)
+ S.text(S, \cl.trailer)
+ } else {
+ S.text(S, \cl.placeholder)
+ }
+ cs_ignore(S, cs, cl.ignore)
+ if \auxfile then return
+end
+#line 1888 "l2h.nw"
+procedure basename(name)
+ reverse(name) ? {
+ tab(upto('.')) & ="."
+ return reverse(tab(0))
+ }
+end
+#line 1901 "l2h.nw"
+procedure Ctableofcontents(S, cs, cl)
+ S.mode := "V"
+ Cauxfile(S, cs, cl)
+ set_toclevel(S)
+end
+#line 1910 "l2h.nw"
+procedure set_toclevel(S, l)
+ static toclevel, initiallevel
+ if /initiallevel := \l then
+ S.text(S, "<ul compact>")
+ if /l := \initiallevel then
+ S.text(S, "</ul>")
+ if /l then return # never set a level
+ /toclevel := l
+ while toclevel < l do {
+ S.text(S, "<ul compact>")
+ toclevel +:= 1
+ }
+ while toclevel > l do {
+ S.text(S, "</ul>")
+ toclevel -:= 1
+ }
+ return
+end
+#line 1931 "l2h.nw"
+procedure Ccontentsline(S, cs, cl)
+ local type, level
+ static leveltab
+ initial {
+#line 1945 "l2h.nw"
+l := ["part", "chapter", "section", "subsection", "subsubsection",
+ "paragraph", "subparagraph"]
+leveltab := table()
+every i := 1 to *l do
+ leveltab[l[i]] := i - 2 # making section level 1
+#line 1934 "l2h.nw"
+ }
+ l := \leveltab[csarg()] | fail
+ if l > \countertab["tocdepth"] then
+ cs_ignore(S, cs, "{{") # skip this one
+ else {
+ set_toclevel(S, l)
+ S.text(S, "<li>")
+ after_next_open(S, after_next_close, [S, cs_ignore, [S, cs, "{"]])
+ }
+end
+#line 1953 "l2h.nw"
+global countertab
+
+procedure Csetcounter(S, cs, cl)
+ local counter
+ (counter := csarg(), countertab[counter] := integer(csarg())) |
+ cs_ignore(S, cs, "{{")
+end
+#line 1967 "l2h.nw"
+global accent_name, accent_valid
+#line 1998 "l2h.nw"
+procedure accent(cs)
+ cstab[cs] := Caccent
+end
+
+procedure Caccent(S, cs, cl)
+ static warned
+ initial warned := table()
+ arg := csarg(S) | return
+ if arg == "\\i" then arg := "i"
+ if arg == "\\j" then arg := "j"
+ if *arg = 1 & any(accent_valid[cs], arg) then
+ S.text(S, "&" || arg || accent_name[cs] || ";")
+ else {
+
+#line 2016 "l2h.nw"
+/warned[cs] := set()
+if not member(warned[cs], arg) then {
+ write(&errout, "Warning: Can't handle \\", cs, " with arg `", arg, "'")
+ insert(warned[cs], arg)
+}
+#line 2012 "l2h.nw"
+ S.text(S, arg)
+ }
+end
+#line 2026 "l2h.nw"
+procedure fontchange(tex, html)
+ cstab[tex] := Cfontchange
+ csclosure[tex] := html
+end
+#line 2031 "l2h.nw"
+procedure Cfontchange(S, tex, html)
+ S.text(S, tag(html))
+ before_next_close(S, emit_text, [S, endtag(html)])
+end
+#line 2051 "l2h.nw"
+procedure ignore(cs, template)
+ /template := ""
+ cstab[cs] := cs_ignore
+ csclosure[cs] := template
+end
+
+procedure ignoreenv(env, template)
+ /template := ""
+ begintab[env] := cs_ignore
+ begincl[env] := template
+ endtab[env] := do_nothing
+end
+#line 2070 "l2h.nw"
+procedure cs_ignore(S, cs, template, proc, args)
+ local saved_ignore
+ saved_ignore := S.ignoring
+ S.ignoring := 1
+ if type(template) == "integer" then template := repl("{", template)
+ return do_ignore(S, template, saved_ignore, proc, args)
+end
+#line 2084 "l2h.nw"
+procedure do_ignore(S, template, saved_ignore, proc, args)
+ if *template > 0 then
+ if optwhite() & pos(0) then
+ after_next_newtext(S, do_ignore, [S, template, saved_ignore, proc, args])
+ else
+ case template[1] of {
+ "{" : { S.ignoring := 1
+ after_next_open(S, ignore_til_close,
+ [S, template[2:0], saved_ignore, proc, args])
+ }
+ "A" : { csarg(S) # had better be in one input
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ }
+ "[" : if optwhite() & ="[" then {
+ delay_newtext(S)
+ with_upto_bracket(S, "", ignore_bracket_plus,
+ [S, template[2:0], saved_ignore, proc, args])
+ } else
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ "C" : # a total cheat, means ``copy optional arg''
+ if optwhite() & ="[" then {
+ S.ignoring := &null
+ delay_newtext(S)
+ with_upto_bracket(S, "", copy_bracket_plus,
+ [S, template[2:0], saved_ignore, proc, args])
+ } else
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ "=" : { delay_newtext(S)
+ eat_assignment(S, do_ignore, [S, template[2:0], saved_ignore, proc,args])
+ }
+ "*" : { (="*", optwhite())
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ }
+ "(" : { (="(", tab(upto(')')), =")", optwhite())
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ }
+ }
+ else {
+ S.ignoring := saved_ignore
+ (\proc)!(\args)
+ }
+end
+
+procedure ignore_til_close(S, template, saved_ignore, proc, args)
+ before_next_close(S, do_ignore, [S, template, saved_ignore, proc, args])
+end
+#line 2133 "l2h.nw"
+procedure do_nothing(S, cs, cl)
+ return
+end
+#line 2144 "l2h.nw"
+procedure with_upto_bracket(S, bracketed_text, proc, args)
+ bracketed_text ||:= tab(upto(']') | 0)
+ if pos(0) then
+ before_next_newtext(S, with_upto_bracket, [S, bracketed_text, proc, args])
+ else {
+ ="]"
+ undelay_newtext(S)
+ (\proc)(S, bracketed_text, args)
+ }
+ return
+end
+#line 2158 "l2h.nw"
+procedure ignore_bracket_plus(S, contents, args)
+ # contents are ignored
+ do_ignore!args
+end
+#line 2164 "l2h.nw"
+procedure copy_bracket_plus(S, contents, args)
+ local should_ignore
+ should_ignore := args[3] | fail # saved_ignore arg to do_ignore
+ if /should_ignore then
+ S.text(S, convert(converter("H"), "{" || contents || "}"))
+ do_ignore!args
+end
+#line 2177 "l2h.nw"
+procedure eat_assignment(S, proc, args)
+ static decimal_chars, hex_chars, oct_chars
+ initial {
+ decimal_chars := &digits ++ '.,+-'
+ hex_chars := &digits ++ 'abcdefABCDEF'
+ oct_chars := '0124567'
+ }
+ optwhite()
+ ="=" # so what if we swallow multiple = signs
+ optwhite()
+ if pos(0) then {
+ before_next_newtext(S, eat_assignment, [S, proc, args])
+ return
+ } else if glue() then { # finished
+ } else if any(decimal_chars) then {
+ tab(many(decimal_chars))
+ optwhite()
+ if ="\\" then
+ tab(many(S.csletters)) | move(1)
+ # else assume assignment of the form \hangafter=2
+ } else if ="\"" then {
+ tab(many(hex_chars)) & optwhite()
+ } else if ="\'" then {
+ tab(many(oct_chars)) & optwhite()
+ } else if =("\\"|"`\\") then
+ tab(many(S.csletters)) | move(1)
+ undelay_newtext(S)
+ (\proc)!args
+end
+#line 2207 "l2h.nw"
+procedure dimen()
+ static decimal_chars
+ initial decimal_chars := &digits ++ '.,'
+ suspend (optwhite(),
+ if any('+-') then (move(1), optwhite()) else "",
+ tab(many(decimal_chars)), optwhite(),
+ (="true", optwhite()) | &null,
+ =("em"|"ex"|"pt"|"pc"|"in"|"bp"|"cm"|"mm"|"dd"|"cc"|"sp"|"mu"))
+end
+#line 2217 "l2h.nw"
+procedure glue()
+ suspend (dimen(),
+ (optwhite(), ="plus", dimen()) | "",
+ (optwhite(), ="minus", dimen()) | "")
+end
+#line 2231 "l2h.nw"
+procedure substitution(tex, html, ignore_template)
+ # ignore mode for now
+ cstab[tex] := Cemit_ig
+ csclosure[tex] := emit_ig_cl(html, \ignore_template | "")
+end
+#line 2239 "l2h.nw"
+record emit_ig_cl(html, template)
+
+procedure Cemit_ig(S, cs, cl)
+ emit_text(S, cl.html)
+ if *cl.template > 0 then
+ cs_ignore(S, cs, cl.template)
+end
+#line 2249 "l2h.nw"
+procedure activesubst(char, html, ignore_template)
+ local S
+ # ignore mode for now
+ activetab[char] := Cemit_ig
+ activeclosure[char] := emit_ig_cl(html, \ignore_template | "")
+ S := \dynamic_add_hack | return
+ if upto(S.activechars, char) then return # already active
+ if S.activechars ++:= cset(char) then {
+ before_next_close(S, delete_active_char, [S, char])
+ } else impossible("ugh")
+ return
+end
+
+procedure delete_active_char(S, char)
+ S.activechars --:= char
+ return
+end
+#line 2282 "l2h.nw"
+procedure envblock(env, left, right, ignore_template)
+ /ignore_template := ""
+ begintab[env] := Cemit_ig
+ begincl[env] := emit_ig_cl(if /right then tag(left) else left, ignore_template)
+ endtab[env] := Cemit
+ endcl[env] := if /right then endtag(left) else right
+end
+#line 2291 "l2h.nw"
+procedure Cemit(S, cs, cl)
+ S.text(S, cl)
+end
+#line 2303 "l2h.nw"
+record blockpair(left, right, ignore)
+
+procedure argblock(tex, html, right, ignore)
+ # called as is envblock
+ /ignore := ""
+ cstab[tex] := Cblock
+ csclosure[tex] :=
+ if /right then blockpair (tag(html), endtag(html), ignore)
+ else blockpair (html, right, ignore)
+end
+#line 2316 "l2h.nw"
+procedure argblockv(tex, html, right, ignore)
+ argblock(tex, html, right, ignore)
+ cstab[tex] := CblockV
+end
+#line 2321 "l2h.nw"
+procedure Cblock(S, cs, cl, done_ignoring)
+ if /done_ignoring & *cl.ignore > 0 then {
+ cs_ignore(S, cs, cl.ignore, Cblock, [S, cs, cl, 1])
+ } else if pos(0) then {
+ after_next_newtext(S, do_cs, [S, cs, cl])
+ } else if match("{") then {
+ S.text(S, cl.left)
+ after_next_open(S, before_next_close, [S, emit_text, [S, cl.right]])
+ } else {
+# S.text(S, cl.left || csarg(S) || cl.right)
+ apply_args(S, Cblock_continue, [S, cl], 1)
+ }
+ return
+end
+
+procedure Cblock_continue(S, cl, title)
+ S.text (S, cl.left || title || cl.right)
+ return
+end
+#line 2341 "l2h.nw"
+procedure CblockV(S, cs, cl)
+ S.mode := "V"
+ Cblock(S, cs, cl)
+ return
+end
+#line 2353 "l2h.nw"
+record macro_defn(name, arg_count, body, mode)
+#line 2357 "l2h.nw"
+record raw_arg(number)
+record converted_arg(number, mode)
+#line 2361 "l2h.nw"
+procedure expand_macro(S, macro, args)
+ every a := !macro.body do
+ case type(a) of {
+ "string" : emit_text(S, a)
+ "raw_arg" : emit_text(S, args[a.number]) | impossible("missing arg")
+ "converted_arg" : S.text(S, convert(S, "{" || args[a.number] || "}"))
+ }
+# poptrace()
+ return
+end
+#link pushtrace
+#line 2375 "l2h.nw"
+procedure do_macro(S, macro, args_seen, current_arg, brace_depth)
+ # invariant : we have an open brace
+# write(&errout, "scanning args for macro ", macro.name)
+# write(&errout, "seen ", *args_seen, " want ", macro.arg_count)
+ while *args_seen < macro.arg_count & not pos(0) do {
+ while *args_seen < macro.arg_count & brace_depth = 0 & not pos(0) do {
+# write(&errout, "seen ", *args_seen, " want ", macro.arg_count,
+# " current ", image(current_arg), " braces ", brace_depth)
+ tab(many(' \t\n'))
+ case c := move(1) of {
+ "\\" : put(args_seen, "\\" ||
+ if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1))
+ "{" : { current_arg := "" ; brace_depth := 1 }
+ "}" : { error("Insufficient arguments to macro ", macro.name) }
+ default : put(args_seen, c)
+ }
+ }
+ while brace_depth > 0 & not pos(0) do {
+# write(&errout, "seen ", *args_seen, " want ", macro.arg_count,
+# " current ", image(current_arg), " braces ", brace_depth)
+ current_arg ||:= tab(upto('\\{}') | 0)
+ case move(1) of {
+ "\\" : current_arg ||:= "\\" ||
+ if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1)
+ "{" : { current_arg ||:= "{" ; brace_depth +:= 1 }
+ "}" : { brace_depth -:= 1
+ if brace_depth > 0 then
+ current_arg ||:= "}"
+ else {
+ put(args_seen, current_arg)
+ current_arg := ""
+ }
+ }
+ }
+ }
+ }
+# write(&errout, "seen ", *args_seen, " want ", macro.arg_count,
+# " current ", image(current_arg), " braces ", brace_depth)
+ if *args_seen = macro.arg_count then {
+# write(&errout, "Arguments for macro ", macro.name, ":")
+# every write(&errout, "\t", image(!args_seen))
+ expand_macro(S, macro, args_seen)
+ undelay_newtext(S)
+ } else
+ before_next_newtext(S, do_macro, [S, macro, args_seen, current_arg, brace_depth])
+ return
+end
+#line 2428 "l2h.nw"
+procedure Cmacro(S, cs, cl)
+# pushtrace("MACRO")
+ delay_newtext(S)
+# apply_args(S, closure(expand_macro, [cl]), cl.arg_count)
+ do_macro(S, cl, [], "", 0)
+ return
+end
+#line 2439 "l2h.nw"
+procedure macro(name, arg_count, body, mode)
+ m := macro_defn(name, arg_count, parse_body(body), mode)
+ cstab[name] := Cmacro
+ csclosure[name] := m
+ return
+end
+
+procedure begin_macro(env, arg_count, body, mode)
+ m := macro_defn(env, arg_count, parse_body(body), mode)
+ begintab[env] := Cmacro
+ begincl[env] := m
+ return
+end
+
+procedure parse_body(body)
+ b := []
+ body ? {
+ put(b, tab(upto('#') | 0))
+ while ="#" do {
+ put(b, ="#" | (="$", raw_arg(argnum())) | converted_arg(argnum())) |
+ error("malformed macro arg #", tab(0))
+ put(b, tab(upto('#') | 0))
+ }
+ }
+ return b
+end
+
+procedure argnum()
+ if any(&digits) then return integer(move(1)) else fail
+end
+#line 2472 "l2h.nw"
+procedure l2h_macro(name, count, body[])
+ count := integer(count) |
+ return error("must give # of arguments to l2h macro ", name)
+ s := ""
+ every s ||:= " " || (1(b := !body, type(b) == "string"))
+ s := s[2:0] # strip leading space if any
+ return macro(name, count, s)
+end
+#line 2482 "l2h.nw"
+procedure l2h_environment(env, count, body[])
+ count := integer(count) |
+ return error("must give # of arguments to l2h environment ", env)
+ s := ""
+ every s ||:= " " || (1(b := !body, type(b) == "string"))
+ s := s[2:0] # strip leading space if any
+ return begin_macro(env, count, s)
+end
+#line 2497 "l2h.nw"
+record table_closure(args, amp, open, close)
+
+procedure table_env(env, args, amp, open, close)
+ begintab[env] := Ctable
+ begincl[env] := table_closure(args, amp,
+ if /close then tag(\open) | &null else open,
+ if /close then endtag(\open) | &null else close)
+ endtab[env] := Ctable_end
+ endcl[env] := []
+end
+#line 2508 "l2h.nw"
+procedure Ctable(S, env, cl)
+ local amp
+## amp := S.ampersand
+## S.ampersand := cl.amp
+ S.text(S, \cl.open)
+ push(endcl[env], amp)
+ cs_ignore(S, env, cl.args)
+end
+
+procedure Ctable_end(S, env, cl)
+# S.ampersand := pop(cl)
+ S.text(S, \begincl[env].close)
+end
+#line 2524 "l2h.nw"
+procedure Cepsfig(S, cs, cl)
+ apply_args(S, do_epsfig, [S], 1)
+end
+
+procedure do_epsfig(S, arg)
+ local args
+ args := []
+ arg ?
+ while not pos(0) do {
+ tab(many(' \t\n'))
+ put(args, eqsplit(tab(upto(',') | 0)))
+ }
+ if a := !args & a.name == ("file"|"figure") then
+ emit_text(S, "<a href=" || image(a.value) || "><b>[</b>PostScript figure " ||
+ a.value || "<b>]</b></a>")
+ else
+ emit_text(S, "<b>[</b>Ill-understood PostScript figure<b>]</b>")
+end
+
+record apair(name, value)
+
+procedure eqsplit(s)
+ p := apair()
+ s ? (p.name := tab(upto('=')), ="=", p.value := tab(0))
+ return p
+end
+#line 2552 "l2h.nw"
+procedure Cincludegraphics(S, cs, cl)
+ local saved_ignore
+ saved_ignore := S.ignoring
+ S.ignoring := 1
+ do_ignore(S, "[", saved_ignore, apply_args, [S, do_includegraphics, [S], 1])
+end
+
+procedure do_includegraphics(S, arg)
+ local base, ext
+ if arg ? (base := tab(find(ext := ".ps" | ".eps" | ".epsi")), =ext, pos(0)) then
+ emit_text(S, "<a href=" || image(arg) || "><b>[</b>PostScript figure " ||
+ arg || "<b>]</b></a>")
+ else if arg ? (base := tab(find(ext := ".png" | ".gif" | ".jpg")), =ext, pos(0)) then
+ emit_text(S, "<img src=" || image(arg) || ">")
+ else
+ emit_text(S, "<b>[</b>Ill-understood graphics<b>]</b>")
+end
+#line 2574 "l2h.nw"
+procedure let(lhs, rhs)
+ cstab[lhs] := cstab[rhs]
+ csclosure[lhs] := csclosure[rhs]
+end
+
+procedure let_closure(lhs, cl[])
+ csclosure[lhs] := if *cl = 1 then cl[1] else cl
+end
+
+procedure letenv(lhs, rhs)
+ begintab[lhs] := begintab[rhs]
+ endtab[lhs] := endtab[rhs]
+ begincl[lhs] := begincl[rhs]
+ endcl[lhs] := endcl[rhs]
+end
+#line 2595 "l2h.nw"
+procedure tag(html)
+ return "<" || html || ">"
+end
+
+procedure endtag(html)
+ return "</" || html || ">"
+end
+#line 2605 "l2h.nw"
+procedure Ccomment(S)
+ if *S.comment > 0 then {
+ S.text(S, "<!--")
+ S.comment ? {
+ while S.text(S, tab(find("--"))) do {
+ move(2)
+ S.text(S, "- - ")
+ }
+ S.text(S, tab(0))
+ }
+ S.text(S, "-->")
+ }
+ S.comment := ""
+ return
+end
+#line 2621 "l2h.nw"
+procedure Cparagraph(S)
+ S.text(S, "<p>")
+end
+#line 2625 "l2h.nw"
+procedure Cmath(S)
+
+#line 915 "l2h.nw"
+push(S.closes, []) # fresh set of closing tasks
+while c := get(S.open) do
+ c.proc!c.args
+#line 2627 "l2h.nw"
+ S.text(S, "<i>")
+end
+
+procedure Cmath_end(S)
+ S.text(S, "</i>")
+
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 2633 "l2h.nw"
+end
+#line 2635 "l2h.nw"
+procedure Cdisplaymath(S)
+
+#line 915 "l2h.nw"
+push(S.closes, []) # fresh set of closing tasks
+while c := get(S.open) do
+ c.proc!c.args
+#line 2637 "l2h.nw"
+ S.text(S, "<blockquote><i>")
+end
+
+procedure Cdisplaymath_end(S)
+ S.text(S, "</i></blockquote>")
+
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 2643 "l2h.nw"
+end
+#line 2645 "l2h.nw"
+procedure Cmakeatletter(S)
+ S.csletters ++:= '@'
+end
+
+procedure Cmakeatother(S)
+ S.csletters --:= '@'
+end
+#line 2655 "l2h.nw"
+procedure Ckill(S, cs, cl)
+ S.the_text := ""
+end
+#line 2673 "l2h.nw"
+global csfunctions
+#line 2700 "l2h.nw"
+global dynamic_add_hack
+procedure parse_dynamic_add(S)
+ if (optwhite(), =("l2h"|"sl2h"), skipwhite(),
+ p := tab(upto(' \t')),
+#line 2717 "l2h.nw"
+((p := \csfunctions[p]) |
+{ dynamic_warn(p); fail })
+#line 2703 "l2h.nw"
+ ,
+ skipwhite(), any(~'\n')) then {
+ a := []
+ while (any(~'\n'), l := tab(upto(' \t\n') | 0)) do {
+ put(a, if p === (l2h_macro|l2h_environment) then l else map(l, "#", " "))
+ skipwhite()
+ }
+ dynamic_add_hack := S
+ p!a
+ dynamic_add_hack := &null
+ return
+ }
+end
+#line 2720 "l2h.nw"
+procedure dynamic_warn(p)
+ static badprocs
+ initial badprocs := set()
+ if not member(badprocs, p) then {
+ write(&errout, "Warning: % l2h ", p, " not recognized -- ignored")
+ insert(badprocs, p)
+ }
+end
+#line 2732 "l2h.nw"
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+#line 2737 "l2h.nw"
+procedure skipwhite()
+ suspend tab(many(' \t'))
+end
+#line 2829 "l2h.nw"
+global errstatus
+procedure error(args[])
+ errstatus := 1
+ return write!([&errout, (\curfile || ":") | "line ", curline, ": "] ||| args)
+end
+#line 2878 "l2h.nw"
+procedure fatal(L[])
+ write!(["@fatal l2h "] ||| L)
+ write!([&errout, "noweb error in l2h: "] ||| L)
+ exit(1)
+end
+#line 2885 "l2h.nw"
+procedure rcsinfo ()
+ return "$Id: l2h.nw,v 1.24 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+#line 2745 "l2h.nw"
+procedure main(args)
+ local line
+ errstatus := 0
+ every arg := !args do
+ case arg of {
+ "-show-unknowns" : show_unknowns := 1
+ "-html-quotes" : html_quotes := 1
+ default : fatal("unknown arg ", image(arg))
+ }
+ while line := read() do
+ apply(filter, line)
+ warn_unknown(\unknown_set, "control sequences", "\\")
+ warn_unknown(\unknown_envs, "environments", "{", "}")
+ if errstatus > 0 then
+ write("@fatal l2h Error occurred in l2h conversion")
+ exit(errstatus)
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+#line 2771 "l2h.nw"
+global curfile, curline
+
+procedure filter(name, arg)
+ static S, code
+ initial S := converter("V")
+### write(" mode ", S.mode)
+ case name of {
+ "begin" : {
+#line 2817 "l2h.nw"
+write("@", name, (" " || \arg) | "")
+#line 2778 "l2h.nw"
+ ; if match("code ", arg) then code := 1}
+ "end" : {if match("docs ", arg) then
+#line 2795 "l2h.nw"
+if S.mode ~== "V" then write("@text <p>")
+#line 2780 "l2h.nw"
+
+#line 2817 "l2h.nw"
+write("@", name, (" " || \arg) | "")
+#line 2780 "l2h.nw"
+ ; code := &null; S.mode := "V"}
+ "quote" : { outtext("\0" ? convert(S)) }
+ "endquote" : { outtext("\1" ? convert(S)) }
+ "file" : {
+#line 2817 "l2h.nw"
+write("@", name, (" " || \arg) | "")
+#line 2783 "l2h.nw"
+ ; curfile := arg; curline := 1}
+ "line" : {
+#line 2817 "l2h.nw"
+write("@", name, (" " || \arg) | "")
+#line 2784 "l2h.nw"
+ ; curline := integer(arg)}
+ "defn" : { write("@", name, " ", convert_use_or_def(arg)) }
+ "use" : { write("@", name, " ", convert_use_or_def(arg)) }
+ "text" : {if \code then
+#line 2817 "l2h.nw"
+write("@", name, (" " || \arg) | "")
+#line 2787 "l2h.nw"
+ else outtext(arg ? convert(S)) }
+ "nl" : {if \code then
+#line 2817 "l2h.nw"
+write("@", name, (" " || \arg) | "")
+#line 2788 "l2h.nw"
+ else outtext("\n" ? convert(S)); curline +:= 1}
+ "fatal" : {
+#line 2817 "l2h.nw"
+write("@", name, (" " || \arg) | "")
+#line 2789 "l2h.nw"
+ ; exit(1)}
+ default : {
+#line 2817 "l2h.nw"
+write("@", name, (" " || \arg) | "")
+#line 2790 "l2h.nw"
+ }
+ }
+ return
+end
+#line 2799 "l2h.nw"
+procedure convert_use_or_def(s)
+ r := ""
+ s ? {
+ while r ||:= quickconv(tab(find("[["))) do {
+ (r ||:= ="[[") | fatal("impossible missing [[")
+ (r ||:= tab(find("]]")) || tab(many(']'))) |
+ fatal("impossible missing ]] in ", image(s))
+ }
+ return r || quickconv(tab(0))
+ }
+end
+
+procedure quickconv(s)
+ static C
+ initial C := converter("H")
+ return 1(("{" || s || "}" ? convert(C)), reset(C))
+end
+#line 2819 "l2h.nw"
+procedure outtext(s)
+ s ?
+ while not pos(0) do
+ if ="\n" then write("@nl")
+ else if ="\0" then write("@quote")
+ else if ="\1" then write("@endquote")
+ else write("@text ", tab(upto('\n\0\1') | 0))
+ return
+end
diff --git a/web/noweb/src/icon/l2h.nw b/web/noweb/src/icon/l2h.nw
new file mode 100644
index 0000000000..268039c558
--- /dev/null
+++ b/web/noweb/src/icon/l2h.nw
@@ -0,0 +1,2898 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+\documentclass{article}
+\usepackage{noweb,multicol}
+
+\title{Converting {\LaTeX} to HTML}
+\author{Norman Ramsey\\{\tt nr@eecs.harvard.edu}}
+
+\noweboptions{smallcode}
+\setcounter{secnumdepth}{1}
+
+\begin{document}
+@
+\pagenumbering{roman}
+\maketitle
+\tableofcontents
+\pagenumbering{arabic}
+@
+\section{Introduction}
+This program provides an infrastructure for converting {\LaTeX} to
+HTML.
+That infrastructure can be used to make a {\tt noweb} filter or to
+make a standalone conversion program.
+The program is roughly divided into three parts.
+Section~\ref{cs-decls} assigns a meaning (treatment) to each control
+sequence.
+The first part is roughly declarative, and in principle it could be
+ replaced by a data file.
+The declarations can be augmented dynamically by putting formal
+comments in a {\LaTeX} or noweb file---the so-called
+``nifty \verb+% l2h+ escape hatch,'' which is utterly necessary and utterly
+undocumented.
+Section~\ref{engine} describes the engine used to do the conversion,
+and
+Sections \ref{imp-decl}~and~\ref{html-format} gives the procedures
+that do the individual conversions.
+
+This program was motivated by my dissatisfaction with
+\texttt{latex2html}.
+In particular, \texttt{latex2html} is slow, and its output is full of
+chartjunk.
+Design decisions are driven by two goals:
+\begin{itemize}
+\item
+Translate input eagerly as it is read in, in one pass whenever
+possible.
+For example, I take care to translate the body of [[\textbf{...}]]
+without reading the entire argument.
+Instead, I open the macro by emitting [[<b>]], and I note that a
+corresponding [[</b>]] should be emitted when the matching close brace
+is reached.
+Most environments, including tables, are treated similarly.
+The result is that \texttt{l2h} is \emph{fast}; it can comfortably
+handle documents of hundreds of pages, whereas \texttt{latex2html}
+starts bogging down at around 50~pages.%
+\footnote{Measurement taken late in 1994}
+\item
+Use simple, natural translations to HTML whenever possible, and limit
+functionality to simple translation.
+For example, I do \emph{not} offer options to split documents up into
+sections and to create hyperlinks between sections---that sort of
+thing can and should be done by pure HTML tools.
+Also, I make no real attempt to do anything fancy with equations or
+pictures.
+These things have no natural equivalents in HTML.
+If you want to run {\LaTeX}, produce images, and embed them, look
+elsewhere.
+\end{itemize}
+Finally, the program has to be able to translate a fragment at a time,
+because it needs to work selectively on parts of the noweb pipeline.
+For example, the argument to a {\LaTeX} control sequence might be
+split into three pieces, one of which could be noweb quoted code.
+Passing pieces in and getting results back incrementally
+would be completely straightforward in a language with
+message-passing concurrency, but we don't have that in Icon.
+If I understood co-expressions, I might be able to use them, but
+instead I use a continuation-passing, closure-passing style,
+constantly creating actions to be executed on future input events.
+Significant events include open and close braces as well as the simple
+arrival of new text.
+This style makes sense if one has some familiarity with continuations
+\cite{appel:continuation,appel:compiling}, but for Icon programmers
+it's bizarre.
+
+
+{\bf Disclaimers}:
+This program may be the worst I have ever written.
+It started as a weekend hack, then took on a life of its own.
+As I gradually assimilated the weirdness of writing
+continuation-passing code in Icon, I came up with better and better
+ways of doing things, but all the old ways are still here.
+I really ought to clean things up and document them, but that would
+not help me get tenure.
+Please excuse the weak or absent documentation.
+
+
+
+@
+\section{Descriptions of control sequences}
+\label{cs-decls}
+
+This section defines behavior for each control sequence we know how to
+convert.
+The definitions have a declarative flavor, since most are done by
+procedure calls.
+These calls initialize the machinery descriped in Section~\ref{cs-tables}.
+
+{\LaTeX} control sequences come first, using
+ the same organization as the quick reference card from the
+second edition of the {\LaTeX} manual.
+Other control sequences follow.
+@
+\subsection{{\LaTeX} control sequences}
+\subsubsection{Sentences and paragraphs}
+<<control-sequence assignments>>=
+substitution(",", " ")
+substitution(" ", " ")
+substitution("\n", "\n")
+substitution("\t", " ")
+ignore("raggedright")
+ignore("@")
+ignore("/") # no italic correction
+substitution("", "\n") # \<newline> treated as request for newline
+every c := !"$%#{}_" do
+ substitution(c, c)
+substitution("&", "&amp;")
+argblock("emph", "em")
+every argblock("footnote" | "footnotetext" | "thanks",
+ " <b>[</b>", "<b>]</b> ") # put footnotes in bold brackets
+substitution("today", &date)
+@
+\subsubsection{Type style}
+<<control-sequence assignments>>=
+ignore("textrm") # html can't switch to default font!
+argblock("textit", "i")
+argblock("textbf", "b")
+argblock("textsl", "i")
+ignore("textsc")
+argblock("texttt", "tt")
+ignore("textsf")
+ignore("boldmath")
+# \boldmath could be done by introducing S.mathfont, but I don't want to!
+<<control-sequence assignments>>=
+ignore("mathrm") # html can't switch to default font!
+argblock("mathit", "i")
+argblock("mathbf", "b")
+argblock("mathtt", "tt")
+ignore("mathsf")
+argblock("mathcal", "i")
+every ignore("scriptstyle"|"displaystyle"|"scriptscriptstyle")
+every ignore("mathord"|"mathbin"|"mathrel")
+@ HTML has only one size.
+<<control-sequence assignments>>=
+every ignore("tiny" | "scriptsize" | "footnotesize" | "small" | "normalsize" |
+ "large" | "Large" | "LARGE" | "huge" | "Huge")
+@
+\subsubsection{Accents and symbols}
+I've used a document from the W3~consortium to identify escapes for
+symbols.
+Older browsers won't support these symbols.
+<<control-sequence assignments>>=
+every accent(key(accent_name))
+every ignore("dag" | "ddag")
+substitution("S", "&sect;")
+substitution("P", "&para;")
+substitution("copyright", "&copy;")
+substitution("pounds", "&pound;")
+substitution("o", "&oslash;")
+substitution("O", "&Oslash;")
+substitution("aa", "&aring;")
+substitution("AA", "&Aring;")
+substitution("ae", "&aelig;")
+substitution("AE", "&Aelig;")
+@
+\subsubsection{Sectioning and table of contents}
+<<control-sequence assignments>>=
+argblockv("part", "h1", &null, "*[")
+argblockv("chapter", "h1", &null, "*[")
+argblockv("section", "h2", &null, "*[")
+argblockv("subsection", "h3", &null, "*[")
+argblockv("subsubsection", "h4", &null, "*[")
+argblockv("paragraph", "h5", &null, "*[")
+argblockv("subparagraph", "h6", &null, "*[")
+ignore("appendix")
+auxfile("tableofcontents", "toc",
+ "<p>\n<tableofcontents>\n<b>[Table of contents]</b>\n</tableofcontents>\n<p>",
+ "<h2>Table of Contents</h2>\n<tableofcontents>\n", "\n</tableofcontents>\n")
+cstab["tableofcontents"] := Ctableofcontents # override to call set_toclevel
+ignore("listoftables")
+ignore("listoffigures")
+ignore("addtocontents", "{{")
+ignoreenv("filecontents", "{")
+@
+\subsubsection{Mathematical formulas}
+Here we see our first assignments to [[cstab]], which is the real
+technology underlying these seemingly declarative calls.
+I'll assign to [[cstab]] directly when some really special behavior is
+called for. In this case, it's going in and out of math mode.
+<<control-sequence assignments>>=
+cstab["("] := Cmath
+cstab[")"] := Cmath_end
+cstab["["] := Cdisplaymath
+cstab["]"] := Cdisplaymath_end
+ignoreenv("equation")
+every table_env(star("eqnarray"), 0, " ", "<blockquote><i>", "</i></blockquote>")
+ # also lame
+substitution("frac", "<b>frac</b>")
+substitution("sqrt", "<b>frac</b>")
+every substitution("ldots" | "cdots" | "vdots", "...")
+ignore("left")
+ignore("right")
+ignore("overline")
+substitution(":", " ")
+substitution(";", " ")
+ignore("!")
+@ The [[star]] procedure lets us define \verb+eqnarray+ and
+\verb+eqnarray*+ in one fell swoop.
+<<*>>=
+procedure star(cs)
+ suspend cs | (cs || "*")
+end
+@
+There are a gazillion symbols. I'll add them on demand.
+<<control-sequence assignments>>=
+substitution("Diamond", "&lt;&gt;")
+substitution("langle", "&lt;")
+substitution("rangle", "&gt;")
+substitution("le", "&lt;=")
+substitution("ne", "!=")
+substitution("ge", "&gt;=")
+substitution("times", "&times;")
+substitution("divide", "&divide;")
+substitution("bmod", "</i>mod<i>") # better hook in with math
+substitution("equiv", "===")
+every x := "arccos" | "arcsin" | "arctan" | "arg" | "cos" | "cosh" |
+ "cot" | "coth" | "csc" | "deg" | "det" | "dim" | "exp" |
+ "gcd" | "hom" | "lim" | "liminf" | "limsup" | "ln" | "log" |
+ "max" | "min" | "sec" | "sin" | "sinh" | "sup" | "tan" | "tanh"
+do
+ substitution(x, "</i>" || x || "<i>")
+substitution("liminf", "</i>lim inf<i>")
+substitution("limsup", "</i>lim sup<i>")
+every x := "alpha" | "beta" | "gamma" | "delta" | "epsilon" | "zeta" | "eta" |
+ "theta" | "iota" | "kappa" | "lambda" | "nu" | "xi" | "pi" |
+ "rho" | "sigma" | "tau" | "upsilon" | "phi" | "chi" | "psi" | "omega" |
+ "in"
+do
+ substitution(x, "<b>" || x || "</b>")
+substitution("mu", "&micro;")
+every x := "Gamma" | "Delta" | "Theta" | "Lambda" | "Xi" | "Pi" | "Sigma" |
+ "Upsilon" | "Phi" | "Psi" | "Omega"
+do
+ substitution(x, "<b>" || x || "</b>")
+@
+Here are some lonesome math symbols.
+<<control-sequence assignments>>=
+substitution("lfloor", "</i>|_<i>")
+substitution("rfloor", "</i>_|<i>")
+substitution("leq", "&lt;=")
+substitution("geq", "&gt;=")
+substitution("ll", "&laquo;")
+substitution("gg", "&raquo;")
+substitution("Rightarrow", "==&gt;")
+substitution("rightarrow", "--&gt;")
+substitution("approx", "<u>~</u>")
+@
+\subsubsection{Displayed paragraphs}
+HTML really has only one kind of displayed paragraph---the block quotation.
+<<control-sequence assignments>>=
+envblock("quote", "blockquote")
+envblock("quotation", "blockquote")
+envblock("center", "blockquote")
+envblock("flushleft", "blockquote")
+envblock("flushright", "blockquote")
+envblock("verse", "blockquote")
+verbatim("verbatim", escape_HTML_specials, "pre")
+cstab["verb"] := Cverb
+cstab["verb*"] := Cverb
+csclosure["verb*"] := 1
+cstab["verbatiminput"] := Cverbatiminput
+csclosure["verbatiminput"] := verbatim_cl(escape_HTML_specials)
+@ \verb*+\verb* uses visible blanks+.
+@
+\subsubsection{Lists}
+<<control-sequence assignments>>=
+cstab["item"] := Citem
+csclosure["item"] := [item_cl("<li>", "", "<li>")]
+listenv("itemize", "ul")
+listenv("enumerate", "ol")
+listenv("description", "dl")
+@
+\subsubsection{Global or ignorable}
+<<control-sequence assignments>>=
+ignore("documentstyle", "[{")
+ignore("documentclass", "[{")
+ignore("usepackage", "[{")
+ignore("pagestyle", "{")
+ignore("thispagestyle", "{")
+ignore("pagenumbering", "{")
+ignore("newcounter", "{")
+ignore("global")
+ignore("etalchar") # used in the .bbl files: \newcommand{\etalchar}[1]{$^{#1}$}
+@
+\subsubsection{Title page and abstract}
+I could be clever and have \verb+\title+ have a side effect
+that sticks in the right boilerplate when we see \verb+\begin{document}+,
+but for now it's not worth the hassle.
+<<control-sequence assignments>>=
+argblockv("title", "h1")
+argblockv("author","address")
+argblockv("date", "b")
+substitution("maketitle", "<!--title goes here-->")
+ignoreenv("titlepage")
+envblock("abstract", "<h2>Abstract</h2><blockquote>", "</blockquote>")
+@
+\subsubsection{Cross-reference}
+A more ambitious scheme would make labels anchor at preceding
+sectioning commands, but it's hard to see how to do that in one pass.
+Instead, I just use some conventional glyphs.
+I use special procedures for the cross-references so I can have an
+arrow pointing either forward or backward, depending on the direction
+of the reference.
+<<control-sequence assignments>>=
+cstab["label"] := Clabel
+cstab["ref"] := Cref
+cstab["pageref"] := Cref
+cstab["subpageref"] := Cref
+cstab["chunklabel"] := Clabel
+@
+\subsubsection{Bibliography and citation}
+For the bibliography, I actually go grubbing for a {\tt .bbl} file if
+I can find one.
+<<control-sequence assignments>>=
+ignore("bibliographystyle", "{")
+auxfile("bibliography", "bbl", "<b>[BibTeX bibliography]</b>", &null, &null, "{")
+envblock("thebibliography", "<h2>References</h2>", "", "{")
+every cstab["cite" | "citeN" | "opencite" | "openciteN" | "citeyear"] := Ccite
+cstab["bibitem"] := Cbibitem
+ignore("newblock")
+ignore("nocite", "{")
+@
+\subsubsection{Splitting the input}
+All input is ignored. Those things are in their own files.
+<<control-sequence assignments>>=
+every ignore("input" | "include" | "includeonly", "{")
+# filecontents not done yet
+@
+\subsubsection{Line breaking}
+<<control-sequence assignments>>=
+cstab["\\"] := Cbackback
+substitution("linebreak", "<br>")
+ignore("-")
+ignoreenv("sloppypar")
+ignore("sloppy")
+@
+\subsubsection{Page breaking}
+I simulate forced page breaks by horizontal rules.
+<<control-sequence assignments>>=
+substitution("pagebreak", "<hr>")
+substitution("newpage", "<hr>")
+substitution("clearpage", "<hr>")
+ignore("enlargethispage", "*{")
+@
+\subsubsection{Boxes}
+<<control-sequence assignments>>=
+ignore("mbox")
+ignore("makebox", "([[") # ( comes from picture area
+ignore("fbox")
+ignore("framebox", "[[") # could insert horizontal rules, but why?
+ignore("newsavebox", 1)
+ignore("sbox", 2)
+ignore("savebox", "{[[{")
+ignore("usebox", 1)
+envblock("minipage", "blockquote", &null, "[{")
+argblock("parbox", "blockquote", &null, "[{")
+@
+\subsubsection{Space}
+<<control-sequence assignments>>=
+ignore("hspace", "*{")
+ignore("hfil")
+ignore("hfill")
+ignore("vspace", "*{")
+ignore("vfil")
+ignore("vfill")
+@
+\subsubsection{Length}
+<<control-sequence assignments>>=
+ignore("newlength", "{")
+ignore("setlength", "{{")
+ignore("addtolength", "{{")
+@
+\subsubsection{Pictures}
+<<control-sequence assignments>>=
+envblock("picture", "<b>[picture]</b>", "", "((")
+ignore("put", "({")
+ignore("multiput", "(({{")
+ignore("dashbox", "{([")
+ignore("line", "({")
+ignore("vector", "({")
+ignore("shortstack", "[")
+ignore("circle", "*{")
+ignore("oval", "([")
+ignore("frame")
+ignore("thinlines")
+ignore("thicklines")
+@
+\subsubsection{Figures and Tables}
+I surround figures and tables with horizontal rules.
+<<control-sequence assignments>>=
+every envblock(star("figure"), "<hr>", "<hr>", "[")
+every envblock(star("table"), "<hr>", "<hr>", "[")
+argblock("caption", "b") # captions in bold
+@
+\subsubsection{{\tt tabbing} environment}
+I can't see how to do anything sensible with {\tt tabbing}.
+<<control-sequence assignments>>=
+envblock("tabbing", "blockquote")
+# \= is accent
+ignore(">")
+ignore("+")
+ignore("kill")
+@
+\subsubsection{{\tt array} and {\tt tabular} environment}
+<<control-sequence assignments>>=
+tabular("array", "[")
+tabular("tabular", "[")
+tabular("tabularx", "{[")
+tabular("tabular*", "{[")
+every cstab["multicolumn"|"multispan"] := Cmulticolumn
+cstab["span"] := Cspan
+cstab["noalign"] := Cnoalign
+cstab["hline"] := Chline
+cstab["toprule"] := Chline
+cstab["midrule"] := Chline
+cstab["bottomrule"] := Chline
+ignore("cline", "{")
+ignore("newcolumntype", "{{")
+@
+\subsubsection{Definitions}
+<<control-sequence assignments>>=
+ignore("newcommand", "A[[{")
+ignore("renewcommand", "A[[{")
+ignore("providecommand", "A[[{")
+ignore("newenvironment", "{[{{")
+ignore("renewenvironment", "{[{{")
+ignore("newtheorem", "{{")
+@
+\subsubsection{Numbering}
+We have to have a special [[setcounter]] so we can ignore the right stuff
+in the table of contents.
+<<control-sequence assignments>>=
+cstab["setcounter"] := Csetcounter
+ignore("addtocounter", "{{")
+@
+\subsubsection{Other {\LaTeX} control sequences}
+<<control-sequence assignments>>=
+cstab["makeatletter"] := Cmakeatletter
+cstab["makeatother"] := Cmakeatother
+@
+Here are all the old-style font changes.
+<<control-sequence assignments>>=
+every fontchange("tt" | "ttfamily", "tt")
+every fontchange("bf" | "bfseries", "b")
+every fontchange("it" | "itshape", "i")
+fontchange("sl", "i")
+fontchange("em", "em")
+ignore("rm") # html can't switch to default font!
+ignore("sf")
+ignore("sc")
+@ And some new ones
+<<control-sequence assignments>>=
+ignore("rmfamily")
+ignore("normalfont")
+<<control-sequence assignments>>=
+ignoreenv("document")
+<<control-sequence assignments>>=
+substitution("LaTeX", "LaTeX")
+<<control-sequence assignments>>=
+ignore("numberline", "{")
+ignore("protect")
+ignore("onecolumn")
+ignore("twocolumn", "C")
+ignore("typeout", "[{")
+ignore("closedbib")
+<<control-sequence assignments>>=
+every ignore("leftmargini" | "leftmarginii" | "labelsep" | "fboxsep", "=")
+every ignore("tabcolsep", "=")
+every ignore("evensidemargin" | "marginparsep" | "marginparwidth" |
+ "oddsidemargin" | "textheight" | "textwidth" | "topmargin", "=")
+<<control-sequence assignments>>=
+ignore("DeclareMathVersion", "{")
+ignore("mathversion", "{")
+ignore("setpapersize", "{")
+ignore("setmarginsrb", "{{{{{{{{")
+ignore("marginparwidth", "=")
+ignore("marginparsep", "=")
+@
+\subsection{Control sequences from various {\LaTeX} packages}
+<<control-sequence assignments>>=
+ignoreenv("multicols", "{C")
+cstab["citeN"] := Ccite
+ignore("afterpage", "{")
+every cstab["psfig"|"epsfig"] := Cepsfig
+cstab["includegraphics"] := Cincludegraphics
+ignore("newcolumntype", "{{")
+@
+A (perhaps vain) attempt to implement \verb+\kill+.
+<<control-sequence assignments>>=
+cstab["kill"] := Ckill
+@
+\subsection{Plain {\TeX} control sequences}
+<<control-sequence assignments>>=
+activesubst("~", "&nbsp;")
+argblock("centerline", "<br>", "<br>")
+substitution("cr", "<br>")
+substitution("hrule", "<hr>")
+substitution("vrule", "|")
+substitution("hrulefill", "------")
+ignore("hyphenation", "{")
+ignore("hbox")
+ignore("rlap")
+ignore("llap")
+ignore("vbox")
+ignore("vtop")
+ignore("hidewidth")
+ignore("message", "{")
+ignore("relax")
+ignore("null")
+ignore("offinterlineskip")
+ignore("omit")
+ignore("newdimen", "{")
+ignore("nobreak")
+<<control-sequence assignments>>=
+cstab["par"] := implicit_paragraph
+cstab["smallskip"] := implicit_paragraph
+cstab["medskip"] := implicit_paragraph
+cstab["bigskip"] := implicit_paragraph
+cstab["vskip"] := implicit_paragraph
+csclosure["vskip"] := "="
+@
+We can't give the grouping control sequences their real meaning, because
+that would blow our brace balance when ignoring definitions and the like.
+The proper solution would be to distinguish between grouping and braces,
+but that would require much more sophistication than we've got just now.
+<<control-sequence assignments>>=
+every ignore("begingroup" | "endgroup" | "bgroup" | "egroup")
+<<control-sequence assignments>>=
+cstab["newif"] := Cnewif
+cstab["iffalse"] := Ciffalse
+cstab["iftrue"] := Ciftrue
+cstab["ifhtml"] := Ciftrue # false in LaTeX, but true when converting!
+cstab["else"] := Celse
+cstab["fi"] := Cfi
+cstab["ifx"] := cstab["if"] := cstab["ifnum"] := Ciffalse
+@
+Lots of assignable things:
+<<control-sequence assignments>>=
+ignore("let", "A=")
+every ignore("hfuzz" | "parindent" | "parskip" | "baselineskip", "=")
+every ignore("hbadness" | "hsize" | "vsize" | "overfullrule" | "tabskip", "=")
+every ignore("extrarowheight" | "codemargin", "=")
+every ignore("looseness", "=")
+substitution("hskip", " ", "=")
+ignore("setbox", "{=")
+every ignore("box" | "unhbox" | "unvbox", "{")
+<<control-sequence assignments>>=
+ignore("unskip")
+ignore("hss")
+ignore("phantom", "{")
+every ignore("kern" | "lower" | "spacefactor", "=") # a cheat, but works
+every ignore("clubpenalty" | "widowpenalty", "=")
+@
+Backslashes and delimiters.
+<<new l2h.nw init declarative statements>>=
+substitution("backslash", "\\")
+ignore("delimiter", "=")
+@
+@ Other stuff to be ignored:
+<<control-sequence assignments>>=
+every ignore("expandafter" | "indent" | "noindent" | "leavevmode" | "strut")
+ignore("def", 1)
+<<control-sequence assignments>>=
+substitution("TeX", "TeX")
+substitution("BibTeX", "BibTeX")
+substitution("MF", "METAFONT")
+@
+\subsubsection{HTML support for \TeX\ [[\char]]}
+
+Process the numeric argument of a \TeX\ [[\char]] command that is of the form
+`[[\char123]]' or `[[\char 123]]' (the [[\char]] has already been scanned, it
+is no longer in the input)
+and return the character with that code, which we hope will be ASCII
+for reasonable implementations of Icon.
+Also gobble any trailing whitespace.
+<<control-sequence assignments>>=
+cstab["char"] := asciiCharCode
+<<*>>=
+procedure asciiCharCode(S)
+ return emit_text(S, char(2(optwhite(), TeXnumber(), optwhite())))
+end
+procedure TeXnumber()
+ return integer(
+ (="'", "8r" || tab(many(&digits))) |
+ (="\"", "16r" || tab(many(&digits))) |
+ tab(many(&digits)))
+end
+@
+\subsection{HTML support}
+<<control-sequence assignments>>=
+macro("nwanchorto", 2, "<a href=\"#$1\">#2</a>")
+macro("nwanchorname", 2, "<a name=\"#$1\">#2</a>")
+ignore("nwaddbox", "{")
+verbatim("latexonly", do_nothing)
+verbatim("rawhtml", emit_text)
+@
+\subsection{Other control sequences}
+Here's some stuff that might be plain {\TeX}.
+<<control-sequence assignments>>=
+substitution("quad", " ")
+@
+I get to include my favorite {\TeX} hacks.
+We define ignoring loosely; the count denotes the number of balanced-brace pairs.
+We also ignore everything before an ignored balanced-brace pair, which means
+it works for \verb+\def+.
+<<control-sequence assignments>>=
+ignore("noweboptions", 1)
+@
+Now, here are a couple of righteous hacks!
+The idea is that most views will ignore this stuff, but the indexer might
+use it to get clever about dumping chunks and all in the right places.
+<<control-sequence assignments>>=
+substitution("nowebindex", "<nowebindex>")
+substitution("nowebchunks", "<nowebchunks>")
+ignore("nowebsize")
+<<control-sequence assignments>>=
+envblock("fields", "blockquote", &null, "[") # lame; could try to <tt> 1st col
+envblock("fields*", "blockquote", &null, "{") # lame; could try to <tt> 1st col
+ignore("citeauthoryear", "{{{")
+ignore("authoryear", "{{")
+substitution("bibrule", "--------")
+let("bibskip", "par")
+every cstab["anoncite"|"authorcite"] := Ccite
+@
+This will always have to be patched by hand, but it may be worth it.
+<<control-sequence assignments>>=
+ignore("pssilent")
+ignore("psnoisy")
+@
+
+
+\section{The conversion engine}
+\label{engine}
+
+The converter doesn't have the luxury of working on the whole text at
+once; instead it has to accept and convert a piece at a time.
+If I really understood co-expressions, I would surely make them sit up
+and beg.
+Since I don't, I keep some state around, and I pass continuations and
+closures like there's no tomorrow.
+
+
+@
+\subsection{Basic conversion}
+Here's the basic engine, which works by string scanning.
+The initial boilerplate sets up the second argument (if any) as
+[[&subject]].
+The characters [[-]], [[']], and~[[`]] are special because they start
+{\TeX} ligature.
+We also have the odd specials [["\0"]] and [["\1"]], which are
+used to delimit quoted code in noweb.
+Woe betide the hapless user who has real nulls or 1s in his {\LaTeX} file.
+<<*>>=
+procedure convert(S, optstring)
+ static specials
+ initial {
+ <<initialization>>
+ <<control-sequence assignments>>
+ <<assign to dynamic-add table>>
+ specials := '\\{}<>-\'`"%$&~\n\0\1'
+ }
+
+ if \optstring then return optstring ? convert(S)
+ else {
+ <<scan, convert, and return result>>
+ }
+end
+@
+If I were a good dog, I would make a state diagram.
+Since I'm not, I'll just say that we either
+accumulate text using the function [[S.text]], which exists for that
+purpose, or else we do something special upon encountering a special character.
+
+The [[<<take actions appropriate to new text>>]]
+chunk may do something special with the text in
+case we're not in the default state (for example, we may be scanning
+for the end of a comment).
+
+Encountering a non-threatening character throws the converter into
+horizontal mode.
+<<scan, convert, and return result>>=
+<<take actions appropriate to new text>>
+if S.mode == "V" & any(~'\\{}<>%\n\t ') then S.mode := "H"
+emit_text(S, tab(upto(specials) | 0))
+while not pos(0) do
+ if S.mode == "Q" then { # quoting
+ emit_text(S, tab(upto('\1') | 0))
+ if ="\1" then {
+ emit_text(S, "\1")
+ S.mode := S.quotemode
+ }
+ } else {
+ if any(S.activechars) then
+ do_activechar(S, move(1))
+ else
+ case move(1) of {
+ "\\" : {<<control sequence>>}
+ "{" : {<<take open-group actions>>}
+ "}" : {<<take close-group actions>>}
+ "%" : {<<comment>>}
+ "\n" : {<<newline>>}
+ "$" : {<<dollar sign>>}
+ "&" : ampersand(S)
+ "\0" : {S.quotemode := S.mode; S.mode := "Q"; emit_text(S, "\0")}
+ # remaining cases simply escape HTML specials
+ "<" : emit_text(S, "&lt;")
+ ">" : emit_text(S, "&gt;")
+ "\"" : emit_text(S, "&quot;")
+ "-" : {<<deal with dash ligatures>>}
+ "`" : {<<deal with open quotes>>}
+ "'" : {<<deal with close quotes>>}
+ }
+ if S.mode == "V" & any(~'\\{}<>%\n\t ') then S.mode := "H"
+ emit_text(S, tab(upto(specials++S.activechars) | 0))
+ }
+return 1(. S.the_text, S.the_text := "") # what's been converted
+<<deal with dash ligatures>>=
+if S.mode == "V" then S.mode := "H"
+if S.mode == "H" then
+ if ="--" then emit_text(S, "&mdash;")
+ else if ="-" then emit_text(S, "&ndash;")
+ else emit_text(S, "-")
+else
+ emit_text(S, "-")
+@
+<<*>>=
+global html_quotes # render quotes as HTML 4 entities
+<<deal with open quotes>>=
+if S.mode == "V" then S.mode := "H"
+if \html_quotes & S.mode == "H" then
+ if ="`" then emit_text(S, "&ldquo;")
+ else emit_text(S, "&lsquo;")
+else
+ emit_text(S, "`")
+<<deal with close quotes>>=
+if S.mode == "V" then S.mode := "H"
+if \html_quotes & S.mode == "H" & ="'" then emit_text(S, "&rdquo;")
+else emit_text(S, "'")
+@
+The definition of a converter's state is distributed.
+We've already seen the use of [[mode]].
+<<*>>=
+record state(mode, quotemode <<other fields of state>>)
+ # mode is Q, H, V, or M
+ # quotemode is saved mode: H, V, or M
+@
+To create a new state, the default mode is vertical
+<<*>>=
+procedure converter(mode)
+ /mode := "V"
+ return state(mode, mode <<initial values for other fields of state>>)
+end
+@
+To avoid repeated memory allocation, we provide a routine to reset a
+converter to its initial state.
+<<*>>=
+procedure reset(S)
+ <<code to reset [[S]]>>
+ return S
+end
+@
+The basic action performed by the
+[[S.text]] function is to accumulate converted text in [[S.the_text]].
+[[S.text]] is usually [[accumulate_text]].
+<<*>>=
+procedure accumulate_text(S, text)
+ S.the_text ||:= text
+ return
+end
+<<other fields of state>>=
+, text, the_text
+<<initial values for other fields of state>>=
+, accumulate_text, ""
+<<code to reset [[S]]>>=
+S.text := accumulate_text
+S.the_text := ""
+@
+[[emit_text]] just uses the current value of [[S.text]], provided we aren't
+currently ignoring tokens.
+Its primary use is to appear in closures, when we don't know what
+[[S.text]] will be when the closure is executed.
+<<*>>=
+procedure emit_text(S, text)
+ return if \S.ignoring then "" else S.text(S, text)
+end
+<<other fields of state>>=
+, ignoring
+<<initial values for other fields of state>>=
+, &null
+<<code to reset [[S]]>>=
+S.ignoring := &null
+@
+Active characters are like control sequences.
+The only one active by default is the~[[~]].
+<<*>>=
+global activetab, activeclosure
+procedure do_activechar(S, c)
+ (activetab[c])(S, c, activeclosure[c])
+ return
+end
+<<initialization>>=
+activetab := table(unknown_cs)
+activeclosure := table()
+<<other fields of state>>=
+, activechars
+<<initial values for other fields of state>>=
+, '~'
+<<code to reset [[S]]>>=
+S.activechars := '~'
+@
+\subsection{Action and continuation hooks}
+We provide hooks so that actions can be taken at various points.
+The major ones are:
+\begin{description}
+\item[\tt newtext]
+When the next string is passed in for conversion.
+\item[open brace]
+After the next open brace or begin environment.
+\item[close brace]
+Before the next close brace or end environment.
+\end{description}
+@
+\subsubsection{{\tt newtext}}
+[[newtext]] is a list of closures to be executed (actions to take)
+ when the next input comes.
+<<other fields of state>>=
+, newtext
+<<initial values for other fields of state>>=
+, []
+<<code to reset [[S]]>>=
+S.newtext := []
+@
+A closure is simply a procedure with arguments.
+<<*>>=
+record closure(proc, args)
+@
+[[before_next_newtext]] and [[after_next_newtext]]
+add to the list of actions to be taken (at the left and right, respectively).
+<<*>>=
+procedure before_next_newtext(S, proc, args)
+ push(S.newtext, closure(proc, args))
+end
+
+procedure after_next_newtext(S, proc, args)
+ put(S.newtext, closure(proc, args))
+end
+@
+When taking the actions, be careful to avoid infinite loop, e.g., on empty lines.
+<<take actions appropriate to new text>>=
+l := S.newtext
+S.newtext := []
+while c := get(l) do
+ c.proc!c.args
+@
+Some control sequences temporarily override all actions to be taken on
+a new input, using [[delay_newtext]].
+ [[undelay_newtext]] restores actions.
+<<*>>=
+procedure delay_newtext(S)
+ push(S.delayed_newtext, S.newtext)
+ S.newtext := []
+ return
+end
+
+procedure undelay_newtext(S)
+ S.newtext := \pop(S.delayed_newtext) |
+ {write(&errout, "This can't happen: no delayed_newtext"); &null[0]}
+end
+<<other fields of state>>=
+, delayed_newtext
+<<initial values for other fields of state>>=
+, []
+<<code to reset [[S]]>>=
+S.delayed_newtext := []
+@
+\subsubsection{Opening and closing groups}
+There's only one list of actions to be taken at the next open,
+but there's a whole stack of lists of actions to be taken at closes.
+<<other fields of state>>=
+, open, closes
+<<initial values for other fields of state>>=
+, [], []
+<<code to reset [[S]]>>=
+every S.open | S.closes := []
+<<*>>=
+procedure after_next_open(S, proc, args)
+ return put(S.open, closure(proc, args))
+end
+
+procedure before_next_close(S, proc, args)
+ return push(S.closes[1], closure(proc, args)) # lost at top level
+end
+
+procedure after_next_close(S, proc, args)
+ return put(S.closes[1], closure(proc, args)) # lost at top level
+end
+<<take open-group actions>>=
+push(S.closes, []) # fresh set of closing tasks
+while c := get(S.open) do
+ c.proc!c.args
+<<take close-group actions>>=
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+<<old>>=
+procedure Cbegingroup(S, cs, cl)
+ <<take open-group actions>>
+end
+<<old>>=
+procedure Cendgroup(S, cs, cl)
+ <<take close-group actions>>
+end
+<<old control-sequence assignments>>=
+cstab["begingroup"] := Cbegingroup
+cstab["endgroup"] := Cendgroup
+cstab["bgroup"] := Cbegingroup
+cstab["egroup"] := Cendgroup
+@
+\subsection{Handling control sequences and environments}
+OK, to eat a control sequence, first scan it, then execute it using [[do_cs]].
+[[S.csletters]] records the current set of ``letters'' for control
+sequences (so we can interpret \verb+\makeatletter+).
+<<control sequence>>=
+cs := if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1)
+if /S.ignoring | cs == ("else"|"fi") | cstab[cs] === (Ciffalse|Ciftrue) then
+ do_cs(S, cs)
+else
+ &null # error("### Ignoring \\", cs)
+<<other fields of state>>=
+, csletters
+<<initial values for other fields of state>>=
+, &letters
+<<code to reset [[S]]>>=
+S.csletters := &letters
+@
+To execute a control sequence, look up its procedure in [[cstab]],
+and pass in the name of the control sequence, plus the closure
+argument from [[csclosure]].
+\label{cs-tables}
+<<*>>=
+global cstab, csclosure
+
+procedure do_cs(S, cs)
+ tab(many(' \t')) # skip white space following CS
+ if pos(0) | any('\n') then before_next_newtext(S, skipblanks, [S])
+ (cstab[cs])(S, cs, csclosure[cs])
+ return
+end
+<<initialization>>=
+cstab := table(unknown_cs)
+csclosure := table()
+@
+The default action for an unknown control sequence is [[unknown_cs]].
+If the global [[show_unknowns]] is set we dump the control sequence into the
+output in bold. We save the unknown sequences for later warning messages.
+<<*>>=
+global show_unknowns
+procedure unknown_cs(S, cs, cl)
+# if S.text === ignore_text then return # a bit of a hack -- should no longer be needed
+ if \show_unknowns then S.text(S, "<b>\\" || cs || "</b>")
+ if not member(unknown_set, cs) then {
+ write(\unknown_file, "Warning: unknown control sequence \\", cs)
+ insert(unknown_set, cs)
+ }
+ return
+end
+<<initialization>>=
+unknown_set := set()
+<<*>>=
+global cstab, csclosure, unknown_set
+@
+The control sequences \verb+\begin+ and \verb+\end+ are treated
+specially,
+so we can have a similar machinery for environments.
+<<*>>=
+global begintab, endtab, begincl, endcl
+
+procedure do_begin(S, cs, cl)
+ (="{", env := tab(upto('}')), ="}") | error("botched \\begin{...}")
+ <<take open-group actions>>
+ (begintab[env])(S, env, begincl[env])
+ return
+end
+
+procedure do_end(S, cs, cl)
+ (="{", env := tab(upto('}')), ="}") | error("botched \\end{...}")
+ # write(&errout, "calling ", image(endtab[env]), " for \\end{", env, "}")
+ (endtab[env])(S, env, endcl[env])
+ <<take close-group actions>>
+ return
+end
+<<control-sequence assignments>>=
+cstab["begin"] := do_begin
+cstab["end"] := do_end
+<<initialization>>=
+every begintab | endtab := table(unknown_env)
+every begincl | endcl := table()
+<<*>>=
+procedure unknown_env(S, env, cl)
+### if S.text === ignore_text then return # a bit of a hack # no longer needed
+ if \show_unknowns then S.text(S, "<b>{" || env || "}</b>")
+ if not member(unknown_envs, env) then {
+ write(\unknown_file, "Warning: unknown environment {", env, "}")
+ insert(unknown_envs, env)
+ }
+ return
+end
+<<initialization>>=
+unknown_envs := set()
+<<*>>=
+global unknown_envs
+@
+\subsection{Issuing warnings about unknown control sequences and environments}
+<<*>>=
+procedure warn_unknown(s, type, mark, rmark)
+ if *s > 0 then {
+ pushout("Unknown " || type || ": ")
+ every pushout(((\mark | "")\1) || !sort(s) || ((\rmark | "")\1) || " ")
+ pushout("\n")
+ }
+end
+<<*>>=
+procedure pushout(s)
+ static col
+ initial col := 0
+ if find("\n", s) then
+ s ? {
+ pushout(tab(upto('\n')))
+ while ="\n" do {col := 0; write(&errout)}
+ pushout(tab(0))
+ }
+ else {
+ col +:= *s
+ if col >= 79 then {writes(&errout, "\n "); col := *s + 2}
+ writes(&errout, s)
+ }
+ return
+end
+@
+\subsection{Procedures related to parsing {\TeX}}
+\subsubsection{Comment-skipping}
+This logic gobbles text into [[S.comment]]
+until a newline is encountered, at which point it calls
+[[Ccomment]] to format the comment.
+All other new-text actions go on hold until the comment is over.
+<<comment>>=
+parse_dynamic_add(S)
+delay_newtext(S)
+eat_comment(S)
+<<*>>=
+procedure eat_comment(S)
+ S.comment ||:= tab(upto('\n') | 0)
+ if pos(0) then
+ before_next_newtext(S, eat_comment, [S])
+ else {
+ undelay_newtext(S)
+ Ccomment(S)
+ S.comment := ""
+ }
+ return
+end
+<<other fields of state>>=
+, comment
+<<initial values for other fields of state>>=
+, ""
+<<code to reset [[S]]>>=
+S.comment := ""
+@
+Verbatim text is a little bit like comment text---we keep swallowing
+under special rules until we find a terminator.
+There are at least three classes of rules:
+\begin{itemize}
+\item
+Copy text, but escape the HTML specials.
+This corresponds to an ordinary {\LaTeX} \texttt{verbatim}
+environment.
+\item
+Copy text while changing nothing.
+This correspondes to a \texttt{rawhtml} environment.
+\item
+Throw everything on the floor.
+This corresponds to a \texttt{latexonly} environment.
+\end{itemize}
+We store an output method, a string that terminates the environment,
+and possibly tag for an HTML wrapper around the environment.
+<<*>>=
+record verbatim_cl(output, terminator, html, translate_blank)
+
+procedure verbatim(name, output, html)
+ begintab[name] := Cverbatim
+ begincl [name] := verbatim_cl(output, &null, html)
+ return
+end
+
+procedure Cverbatim(S, cs, cl)
+ if cl === begincl[cs] & /cl.terminator then
+ cl := begincl[cs] :=
+ verbatim_cl(cl.output, "\\end{" || cs || "}", cl.html, cl.translate_blank)
+ emit_text(S, tag(\cl.html))
+ delay_newtext(S)
+ do_verbatim(S, cl)
+ return
+end
+@
+If we find the terminator, we're finished.
+Otherwise, we swallow the whole input and make sure our action on next
+input is to continue scanning.
+<<*>>=
+procedure do_verbatim(S, cl)
+ if cl.output(S, tab(find(cl.terminator)), cl) then {
+ =cl.terminator
+ emit_text(S, endtag(\cl.html))
+ undelay_newtext(S)
+ } else {
+ cl.output(S, tab(0), cl)
+ before_next_newtext(S, do_verbatim, [S, cl])
+ }
+ return
+end
+@
+When writing verbatim text, we still have to convert HTML specials.
+<<*>>=
+procedure escape_HTML_specials(S, s, cl)
+ s ? {
+ while emit_text(S, tab(upto('&<>" '))) do
+ case move(1) of {
+ "\"" : emit_text(S, "&quot;")
+ "&" : emit_text(S, "&amp;")
+ "<" : emit_text(S, "&lt;")
+ ">" : emit_text(S, "&gt;")
+ " " : emit_text(S, if \cl.translate_blank then "&middot;" else " ")
+ }
+ emit_text(S, tab(0))
+ }
+ return
+end
+@
+The \verb+\verb+ control sequence's terminator is the first character
+following \verb+\verb+.
+<<*>>=
+procedure Cverb(S, cs, cl)
+ Cverbatim(S, cs, verbatim_cl(escape_HTML_specials, move(1), "tt", cl))
+ return
+end
+@
+<<*>>=
+procedure Cverbatiminput(S, cs, cl)
+ local filename, f, line
+ if ="{" & filename := tab(upto('}')) & ="}" then {
+ f := \open(filename) | { emit_text(S, "<strong>Could not read file</strong> <tt>")
+ escape_HTML_specials(S, filename, cl)
+ emit_text(S, "</tt>")
+ return
+ }
+ emit_text(S, "\n<pre>\n")
+ while line := read(f) do {
+ escape_HTML_specials(S, line, cl)
+ emit_text(S, "\n")
+ }
+ emit_text(S, "</pre>\n")
+ close(f)
+ }
+ return
+end
+@
+\subsubsection{Arguments}
+It's occasionally necessary to collect the argument of a control
+sequence.
+[[csarg]] does the job.
+<<*>>=
+procedure csarg(S)
+ return 2(="{", tab(bal('}', '{', '}')), ="}") |
+ (optwhite(),
+ if ="\\" then
+ "\\" || (tab(many(S.csletters)) | move(1))
+ else
+ move(1))
+end
+@
+[[csarg()]] works only if the whole
+argument is in the same line; otherwise it only returns the opening curly
+brace, `[[{]]'. Another problem with [[csarg()]] is that it does not cope with
+[[%]] or [[\]] in the input (due to the use of the Icon function [[bal()]] to
+balance curly brackets), as such a escaped or commented out curly brace is
+handled incorrectly.
+
+The solution provided here is not trivial. The problem is that if we have
+`[[\foo{bar]]' in a line and the `[[baz}]]' is in another line then due to the
+way how l2h works the Icon command associated with [[foo]] will have to
+terminate before the `[[baz}]]' gets read, and as such cannot do anything
+useful except register a callback to finish the job.
+
+@
+
+[[apply_arg(S, cl)]] scans an argument (preceded by optional
+whitespace), then invokes the closure on that argument.
+Its use should subsume [[csarg]], but that may take a while yet.
+<<*>>=
+@
+[[apply_args(S, p, as, n]] scans [[n]] arguments from the
+input, puts them in a list [[args]], then calls [[p!(as ||| args)]].
+This is a bit weak, because we really want to turn off comment
+skipping for some arguments.
+N.B. the arguments are \emph{not} converted.
+<<*>>=
+procedure apply_args(S, p, as, args_wanted)
+ delay_newtext(S)
+ do_apply_args(S, closure(p, as), args_wanted, [], "", 0)
+ return
+end
+
+procedure do_apply_args(S, cl, wanted_count, args_seen, current_arg, brace_depth)
+ local open_comment
+ # invariant : we have an open brace
+# pushtrace("APPLY")
+ while *args_seen < wanted_count & not pos(0) do {
+ while *args_seen < wanted_count & brace_depth = 0 & not pos(0) do {
+ tab(many(' \t\n'))
+ case c := move(1) of {
+ "\\" : put(args_seen, "\\" ||
+ if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1))
+ "{" : { current_arg := "" ; brace_depth := 1 }
+ "}" : { error("Insufficient arguments to macro ", macro.name) }
+ "%" : if tab(upto('\n')) then ="\n" else open_comment := tab(0)
+ default : put(args_seen, c)
+ }
+ }
+ while brace_depth > 0 & not pos(0) do {
+ current_arg ||:= tab(upto('\\{}%') | 0)
+ case move(1) of {
+ "%" : if tab(upto('\n')) then ="\n" else open_comment := tab(0)
+ "\\" : current_arg ||:= "\\" ||
+ if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1)
+ "{" : { current_arg ||:= "{" ; brace_depth +:= 1 }
+ "}" : { brace_depth -:= 1
+ if brace_depth > 0 then
+ current_arg ||:= "}"
+ else {
+ put(args_seen, current_arg)
+ current_arg := ""
+ }
+ }
+ }
+ }
+ }
+ if *args_seen = wanted_count then {
+ undelay_newtext(S)
+ cl.proc ! (cl.args ||| args_seen)
+ } else if \open_comment then {
+ delay_newtext(S)
+ before_next_newtext(S, skip_comment_and_continue,
+ [S, closure(do_apply_args, [S, cl, wanted_count, args_seen,
+ current_arg, brace_depth])])
+ } else
+ before_next_newtext(S, do_apply_args, [S, cl, wanted_count, args_seen,
+ current_arg, brace_depth])
+# poptrace()
+ return
+end
+<<*>>=
+procedure skip_comment_and_continue(S, cl)
+ tab(upto('\n') | 0)
+ if pos(0) then
+ before_next_newtext(S, skip_comment_and_continue, [S, cl])
+ else {
+ ="\n"
+ undelay_newtext(S)
+# <take actions appropriate to new text>>
+ }
+ return
+end
+@
+\subsubsection{Misc specials}
+Ampersands are covered in the table section (\ref{tabular}).
+@
+The dollar sign is for entering and exiting math mode:
+<<dollar sign>>=
+if /S.ignoring then
+ if ="$" then
+ if S.mode == "M" then { Cdisplaymath_end(S); S.mode := "V" }
+ else { Cdisplaymath(S); S.mode := "M" }
+ else
+ if S.mode == "M" then { Cmath_end(S); S.mode := "H" }
+ else { Cmath(S); S.mode := "M" }
+@
+Newlines emit themselves, plus start skipping blanks until they get to
+some nonblank text.
+We have to identify a blank line so we can insert a paragraph marker.
+<<newline>>=
+emit_text(S, "\n")
+if /S.ignoring then Cnewline(S)
+<<*>>=
+procedure Cnewline(S)
+ tab(many(' \t'))
+ if match("\n") then implicit_paragraph(S)
+ if pos(0) then before_next_newtext(S, Cnewline, [S])
+end
+@
+Other procedures might want to skip white space, which includes
+newlines, but we don't want to miss a paragraph.
+<<*>>=
+procedure skipblanks(S)
+ tab(many(' \t'))
+ if ="\n" then Cnewline(S)
+ else if pos(0) then before_next_newtext(S, skipblanks, [S])
+end
+@
+Paragraphs count only in horizontal or math mode (and they better not
+happen in math mode!).
+<<*>>=
+procedure implicit_paragraph(S, cs, cl)
+ if S.mode ~== "V" then {
+ S.mode := "V"
+ Cparagraph(S)
+ }
+ cs_ignore(S, cs, \cl)
+end
+@
+Here's a real hack. I use it to stop skipping blanks when the noweb
+filter sees text quoted by [[[[...]]]].
+That text is never converted, but we don't want to skip blanks that
+follow it.
+<<*>>=
+procedure stop_skipping(S)
+ while S.newtext[1].proc === (Cnewline|skipblanks) do pop(S.newtext)
+end
+@
+\subsubsection{Items}
+For items, we actually want to do something with the optional arguments,
+namely, convert them.
+We wrap them in braces so that any font changes and so on will be
+appropriately limited in their effects.
+<<*>>=
+record item_cl(before, after, ifnone)
+
+procedure Citem(S, cs, cl)
+ if pos(0) then
+ after_next_newtext(S, Citem, [S, cs, cl])
+ else if ="[" then {
+ delay_newtext(S)
+ with_upto_bracket(S, "", convert_bracketed, cl)
+ } else {
+ skipblanks(S)
+ emit_text(S, cl[1].ifnone)
+ \liststack[1] := \liststack[1] + 1
+ }
+end
+<<*>>=
+procedure convert_bracketed(S, contents, cl)
+ emit_text(S, cl[1].before ||
+ convert(converter("H"), "{" || contents || "}") ||
+ cl[1].after)
+ optwhite()
+end
+<<*>>=
+global liststack, suspendstack
+<<initialization>>=
+liststack := []
+# write(&errout, "Initialized liststack")
+suspendstack := []
+<<control-sequence assignments>>=
+cstab["suspend"] := Csuspend
+cstab["resume"] := Cresume
+<<*>>=
+procedure listenv(env, html)
+ begintab[env] := Clist
+ begincl[env] := html
+ endtab[env] := Clist_end
+ endcl[env] := html
+end
+
+procedure push_item_closure(cs)
+ push(csclosure["item"],
+ if cs == "description" then item_cl("<dt>", "<dd>", "<dt><dd>")
+ else item_cl("<li>", "--", "<li>"))
+end
+
+procedure Clist(S, cs, cl)
+ push(liststack, 1)
+ push_item_closure(cs)
+ emit_text(S, tag(cl))
+end
+
+procedure Cresume(S, cs, cl)
+ local n, env
+ (="{", env := tab(upto('}')), ="}") | error("botched \\resume{...}")
+ n := pop(suspendstack) | error("\\resume not balanced by corresponding \\suspend")
+ push(liststack, n)
+ push_item_closure(env)
+ if env == "enumerate" then
+ emit_text(S, tag(begincl[env] || " start=\"" || n || "\""))
+ else
+ emit_text(S, tag(begincl[env]))
+end
+
+procedure Clist_end(S, cs, cl)
+ emit_text(S, endtag(cl))
+ pop(csclosure["item"])
+ pop(liststack)
+end
+
+procedure Csuspend(S, cs, cl)
+ local env
+ (="{", env := tab(upto('}')), ="}") | error("botched \\suspend{...}")
+ emit_text(S, endtag(endcl[env]))
+ pop(csclosure["item"])
+ push(suspendstack, pop(liststack))
+end
+@
+\subsubsection{Labels and references}
+These could be done by [[argblock]], except I want to make it possible to have
+different text depending on whether the references point forward or backward.
+<<*>>=
+global labels_seen
+
+procedure Clabel(S, cs, cl)
+ initial /labels_seen := set()
+ insert(labels_seen, l := csarg(S)) | fail
+ emit_text(S, "<a name=\"" || l || "\"><b>[*]</b></a>")
+end
+
+procedure Cref(S, cs, cl)
+ local prefix, prefix_tag
+ initial /labels_seen := set()
+ prefix_tag := (\cl)[1] | ""
+ prefix := (\cl)[2] | ""
+ l := prefix || csarg(S) | fail
+ emit_text(S, prefix_tag || "<a href=\"#" || l || "\">[" ||
+ (if member(labels_seen, l) then "&lt;-" else "-&gt;") || "]</a>")
+end
+@
+\subsubsection{Citations}
+The important thing about a citation key is that it makes a hot line
+to the appropriate item in the bibliography.
+[[Ccite]] and [[Cbibitem]] work together to make it happen.
+
+Optional arg might contain blanks, so it might be split, but
+ I assume the citation key isn't split between inputs.
+<<*>>=
+procedure Ccite(S, cs, cl, bracketed_text)
+ if ="[" then {
+ delay_newtext(S)
+ with_upto_bracket(S, "", do_cite, cl)
+ } else
+ do_cite(S, &null, cl)
+end
+
+procedure do_cite(S, commentary, cl)
+ local key
+ if \commentary then
+ optwhite()
+ if pos(0) then before_next_newtext(S, do_cite, [S, commentary, cl])
+ else {
+ key := csarg(S)
+ \commentary := convert(converter("H"), "{" || \commentary || "}")
+ emit_text(S, "<b>[cite&nbsp;")
+ key ? {
+ while k := tab(upto(",")) & ="," do
+ emit_text(S, "<a href=\"#NWcite-" || k || "\">" || k || "</a>, ")
+ if k := tab(0) then
+ emit_text(S, "<a href=\"#NWcite-" || k || "\">" || k || "</a>")
+ }
+ emit_text(S, ", <i>" || \commentary || "</i>")
+ emit_text(S, "]</b>")
+ }
+end
+<<*>>=
+procedure Cbibitem(S, cs, cl)
+ local label, key
+ static counter
+ initial counter := 0
+ if ="[" then {
+ delay_newtext(S)
+ with_upto_bracket(S, "", finish_bibitem, [])
+ } else {
+ label := "<b>[" || (counter +:= 1) || "]</b>"
+ apply_args(S, do_bibitem_key, [S, label], 1)
+ }
+end
+
+procedure do_bibitem_key(S, label, key)
+ return emit_text(S, "<a name=\"NWcite-" || key || "\">" || label || "</a> ")
+end
+
+procedure finish_bibitem(S, contents, args)
+ local key, label
+ optwhite()
+ label := convert(converter("H"), "{" || contents || "}")
+ key := apply_args(S, do_bibitem_key, [S, label], 1)
+end
+@
+\subsubsection{Conditionals}
+The idea here is that an \verb+\if+$\cdots$ control sequence will conditionally
+ignore text, and that \verb+\fi+ restores the previous state.
+To keep track of state, we have an ``if stack'' that records what
+[[S.text]] should be upon encountering \verb+\else+ and \verb+\fi+.
+<<other fields of state>>=
+, ifstack
+<<initial values for other fields of state>>=
+, []
+<<code to reset [[S]]>>=
+if *S.ifstack > 0 then S.ifstack := [] # keeps GC down
+@
+What's on the ifstack is
+<<*>>=
+record ifrec(on_else, on_fi)
+@ It's possible that one day this code will need to be updated to delay
+new-text actions (and to do God knows what if
+new-text actions have already been delayed).
+@
+Every \verb+\if+$\cdots$ is equivalent either to \verb+\iffalse+
+of \verb+\iftrue+, so we begin by defining those, as well as \verb+\else+
+and \verb+\fi+
+<<*>>=
+procedure Ciffalse(S, cs, cl)
+#error("### \\", cs, " -> false (S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)}, ")")
+ push(S.ifstack, ifrec(S.ignoring, S.ignoring))
+ S.ignoring := 1
+end
+
+procedure Ciftrue(S, cs, cl)
+#error("### \\", cs, " -> true (S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)}, ")")
+ push(S.ifstack, ifrec(1, S.ignoring))
+end
+
+procedure Celse(S, cs, cl)
+ S.ignoring := S.ifstack[1].on_else
+#error("### \\else -> S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)})
+end
+
+procedure Cfi(S, cs, cl)
+ S.ignoring := S.ifstack[1].on_fi
+#error("### \\fi -> S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)})
+ pop(S.ifstack)
+end
+@
+Now, all that's left is to handle \verb+\newif+.
+This part is all boilerplate.
+<<*>>=
+procedure Cnewif(S, cs, cl)
+ local newif, newcs
+ tab(many(' \t\n'))
+ if pos(0) then
+ after_next_newtext(S, Cnewif, [S, cs, cl])
+ else {
+ newif := csarg(S)
+ newif ?
+ if ="\\if" & newcs := tab(many(S.csletters)) & pos(0) then {
+ <<make [[newcs]] a new \verb+\if+-like thing>>
+ } else
+ error("\\newif argument botch: " || newif)
+ }
+end
+@
+And here we do the real work:
+<<make [[newcs]] a new \verb+\if+-like thing>>=
+cstab[newcs || "false"] := Csetif
+cstab[newcs || "true"] := Csetif
+cstab["if" || newcs] := Ciffalse
+<<*>>=
+procedure Csetif(S, cs, cl)
+ local base, tag
+ if cs ? (base := tab(find("true"|"false")), tag := =("true"|"false"), pos(0)) then {
+ cstab["if" || base] := if tag == "true" then Ciftrue else Ciffalse
+ } else {
+ error("This can't happen --- setif botch (not urgent)")
+ }
+end
+@
+\subsection{Upper case}
+
+This is a very simple implementation of [[\uppercase]]: it requires to
+have all of its argument immediately.
+<<*>>=
+procedure Cuppercase(S, cs, cl)
+ l := map(csarg(S), &lcase, &ucase) | fail
+ emit_text(S, l)
+end
+<<control-sequence assignments>>=
+cstab["uppercase"] := Cuppercase
+@
+\subsection{HTML support for array and tabular environments}
+We handle tables by using [[S.text]] to implement a little state machine.
+There are only two states: waiting to start a new cell, and the
+ordinary state of converting text.
+
+The rest of the state information is held in a list of [[table_info]]
+records that tell us what to expect for the next cell.
+<<*>>=
+record table_info(index, # number of this cell in the row
+ alignment, # the alignment of this cell
+ width, # how many columns this cell will span
+ alignments, # default alignments for this table
+ brace_depth, # size of S.closes after start of cell
+ cell_text) # value of S.text to use to scan this cell
+@ This state could conceivably be extended to include pre- and
+post-content for each cell, \`a la plain {\TeX}'s [[\halign]] or the
+{\LaTeX} [[<{}]] and [[>{}]] directives, but for now I won't bother.
+
+I should probably also add a [[rows_taken]] field and use it to
+implement [[multirow]] support.
+@
+Here's a stack that keeps track of all currently active tabular environments.
+<<other fields of state>>=
+, tables
+<<initial values for other fields of state>>=
+, []
+<<code to reset [[S]]>>=
+S.tables := []
+@
+Accumulating text forces the transition between states.
+While I'm at it, I update the state for the next cell.
+<<*>>=
+procedure start_table_cell(S, text)
+ local this, attributes
+
+ text ? {
+ tab(many(' \t\n'))
+ if pos(0) then return
+ }
+# write(&errout, "starting cell with ", image(text))
+
+ this := S.tables[1] | fatal("starting cell with no current table")
+ S.text := this.cell_text
+
+if /(\this).brace_depth then write(&errout, "starting table cell, ", image(this), " has null brace depth")
+ # use this to start the current cell
+ if this.index = 1 then emit_text(S, "<tr>")
+ attributes := \this.alignment | aligneq("top")
+ if this.width > 1 then attributes ||:= " colspan=" || this.width
+ emit_text(S, "<td" || attributes || ">")
+
+ # now update state for the next cell
+ this.index +:= this.width # advance to next cell
+ this.alignment := this.alignments[this.index] | &null
+ this.width := 1
+ # can't set cell_text until we hit &
+
+ <<take open-group actions>>
+ emit_text(S, text)
+ return
+end
+@
+Hitting an ampersand closes and opens groups, and it advances to the
+next cell.
+<<*>>=
+procedure ampersand(S)
+ local this
+ this := S.tables[1]
+ <<take close-group actions>>
+ if /this then
+ emit_text(S, " --- ")
+ else {
+ emit_text(S, "") # be sure cell gets started, even if empty
+ emit_text(S, "</td>")
+ if S.text ~=== start_table_cell then
+ this.cell_text := S.text
+ S.text := start_table_cell
+ this.brace_depth := *S.closes + 1 # will open at start of cell
+#write(&errout, "set brace depth for ", image(this))
+ }
+ tab(many(' \t\n'))
+## write(&errout, " past &, text = ", image(S.text), ", next = ",
+## image(&subject[&pos:0]))
+ return
+end
+@
+The double backslash is the end of a row, unless it's buried in braces
+or there's no table.
+We have to be careful about ignoring a square bracket, because if the
+[[\\]] is at the end of a line, we won't know until we see the newline
+that it's not a bracket, and we don't see the newline until we get the
+next text.
+We therefore must use a continuation-passing style for this ignore.
+<<*>>=
+procedure Cbackback(S, cs, cl)
+ local this
+ this := S.tables[1]
+ cs_ignore(S, cs, "[", Cbackback_continue, [S, this])
+end
+
+procedure Cbackback_continue(S, this)
+#if /(\this).brace_depth then write(&errout, image(this), " has null brace depth")
+ if /this | *S.closes > this.brace_depth then { # ordinary \\
+ S.text(S, "<br>")
+ } else { # row terminator
+## write(&errout, "ending row with ", image(&subject[&pos:0]))
+ emit_text(S, "") # be sure cell gets started, even if empty
+ <<take close-group actions>>
+ emit_text(S, "</td></tr>\n")
+ tab(many(' \t\n'))
+ if S.text ~=== start_table_cell then
+ this.cell_text := S.text
+ this.index := 1
+ this.alignment := this.alignments[this.index] | &null
+ this.width := 1
+ S.text := start_table_cell
+ this.brace_depth := *S.closes + 1 # about to open
+ }
+end
+@
+A horizontal line disappears if it's in a table.
+<<*>>=
+procedure Chline(S, cs, cl)
+ if \S.tables[1] then return
+ else emit_text(S, "<hr>")
+ return
+end
+@
+An [[\end{tabular}]] terminates the whole affair.
+If we're at the beginning of a row, things are easy.
+Otherwise, we terminate the current row first.
+<<*>>=
+procedure Ctabular_end(S, cs, cl)
+ local this
+ if S.text ~=== start_table_cell | S.tables[1].index > 1 then {# row in progress
+ emit_text(S, "") # be sure cell gets started, even if empty
+ <<take close-group actions>>
+ emit_text(S, "</td></tr>")
+ }
+ if S.text === start_table_cell then # abort it
+ S.text := S.tables[1].cell_text
+ emit_text(S, "</table>")
+ xxx := pop(S.tables)
+#write(&errout, "popped ", image(xxx))
+ return
+end
+@
+Finally, the setup of the table itself:
+<<*>>=
+procedure Ctabular(S, cs, cl)
+ cs_ignore(S, cs, cl, Ctabular_continue, [S])
+ return
+end
+
+procedure Ctabular_continue(S)
+ a := csarg() # alignment
+#write(&errout, "Alignment ", a)
+ emit_text(S, if upto('|', a) then "<table border>" else "<table>")
+ emit_text(S, "<!-- alignment is " || a || "-->")
+ a := alignments(a)
+ emit_text(S, "<!-- " || *a || " columns-->")
+ push(S.tables, table_info(1, a[1] | "l", 1, a, *S.closes+1, S.text))
+#write(&errout, "pushed ", image(S.tables[1]))
+ S.text := start_table_cell
+ optwhite()
+ return
+end
+@ Earlier, the initial value of [[S.tables[1].brace_depth]] was
+[[&null]], but when we had alignment of \verb+{c}+, it was never
+getting set, so I'm setting it on startup, even though I'm not sure if
+that's really right.
+<<*>>=
+procedure tabular(env, ignore)
+ begintab[env] := Ctabular
+ begincl[env] := ignore
+ endtab[env] := Ctabular_end
+ endcl[env] := ignore
+end
+@
+We figure alignments using the tricks in the {\LaTeX} book.
+<<*>>=
+procedure aligneq(a)
+ return " align=\"" || a || "\""
+end
+
+procedure valigneq(a)
+ return " valign=\"" || a || "\""
+end
+
+procedure alignments(s)
+ a := []
+ s ? {
+ while not pos(0) do
+ case move(1) of {
+ "l" | "X" | "Y" | "p" :
+ { put(a, aligneq("left") || valigneq("top")); skip_bracket() }
+ "c" : put(a, aligneq("center"))
+ "r" : put(a, aligneq("right"))
+ "m" : { put(a, aligneq("left") || valigneq("center")); skip_bracket() }
+ "b" : { put(a, aligneq("left") || valigneq("bottom")); skip_bracket() }
+ "@" | "<" | ">" | "!" : skip_bracket()
+ "|" : &null
+ default : &null # unrecognized...
+ }
+ }
+ return a
+end
+<<*>>=
+procedure skip_bracket()
+ if ="{" then {
+ n := 1
+ while n > 0 & not pos(0) do {
+ tab(upto('{}\\') | 0)
+ case move(1) of {
+ "{" : n +:= 1
+ "}" : n -:= 1
+ "\\" : move(1)
+ }
+ }
+ }
+ return
+end
+@
+[[\multicolumn]] changes the width and alignment of the current cell.
+[[\multispan]] changes only the width.
+<<*>>=
+procedure Cmulticolumn(S, cs, cl)
+ local this
+ this := S.tables[1]
+ n := integer(csarg()) | error("\\multicolumn or \\multispan not followed by integer")
+ if cs == "multicolumn" then a := alignments(csarg())
+# write(&errout, "\\", cs, " n = ", n, ", a = ", (\a)[1] | "???",
+# ", text = ", image(S.text))
+ if /this then return # \multicolumn without table?
+ this.width := n
+ this.alignment := (\a)[1]
+ return
+end
+
+procedure Cspan(S, cs, cl)
+ (\S.tables[1]).width +:= 1
+ return
+end
+@
+<<*>>=
+procedure Cnoalign(S, cs, cl)
+ apply_args(S, finish_noalign, [S], 1)
+ return
+end
+
+procedure finish_noalign(S, arg)
+ return if \S.ignoring then "" else
+ accumulate_text(S, "<br>" || convert(converter("V"), "{" || arg || "}") || "<br>")
+end
+@
+\subsection{Reading and converting auxiliary {\LaTeX} files}
+<<*>>=
+procedure auxfile(cs, ext, placeholder, header, trailer, ignore)
+ cstab[cs] := Cauxfile
+ csclosure[cs] := aux_cl(ext, placeholder, header, trailer, \ignore | "")
+end
+@
+[[Cauxfile]] succeeds if it finds a file, fails otherwise.
+<<*>>=
+record aux_cl(ext, placeholder, header, trailer, ignore)
+
+procedure Cauxfile(S, cs, cl)
+ local auxfile, T
+ if auxfile := open(basename(\curfile) || "." || cl.ext) then {
+ T := converter("V")
+ Cmakeatletter(T)
+ S.text(S, \cl.header)
+ while line := read(auxfile) do
+ S.text(S, convert(T, line || "\n"))
+ close(auxfile)
+ S.text(S, \cl.trailer)
+ } else {
+ S.text(S, \cl.placeholder)
+ }
+ cs_ignore(S, cs, cl.ignore)
+ if \auxfile then return
+end
+<<*>>=
+procedure basename(name)
+ reverse(name) ? {
+ tab(upto('.')) & ="."
+ return reverse(tab(0))
+ }
+end
+@
+\subsubsection{Table of contents}
+We can build a table of contents by reading the .toc file.
+Sadly, I haven't figured out how to get hot links yet.
+<<control-sequence assignments>>=
+cstab["contentsline"] := Ccontentsline
+<<*>>=
+procedure Ctableofcontents(S, cs, cl)
+ S.mode := "V"
+ Cauxfile(S, cs, cl)
+ set_toclevel(S)
+end
+@
+[[set_toclevel]] manages the starting and ending of lists.
+With no level argument, it resets the toc to the initial level.
+<<*>>=
+procedure set_toclevel(S, l)
+ static toclevel, initiallevel
+ if /initiallevel := \l then
+ S.text(S, "<ul compact>")
+ if /l := \initiallevel then
+ S.text(S, "</ul>")
+ if /l then return # never set a level
+ /toclevel := l
+ while toclevel < l do {
+ S.text(S, "<ul compact>")
+ toclevel +:= 1
+ }
+ while toclevel > l do {
+ S.text(S, "</ul>")
+ toclevel -:= 1
+ }
+ return
+end
+@
+Assume one table of contents per converted document.
+<<*>>=
+procedure Ccontentsline(S, cs, cl)
+ local type, level
+ static leveltab
+ initial { <<assign numbers of sections in leveltab>> }
+ l := \leveltab[csarg()] | fail
+ if l > \countertab["tocdepth"] then
+ cs_ignore(S, cs, "{{") # skip this one
+ else {
+ set_toclevel(S, l)
+ S.text(S, "<li>")
+ after_next_open(S, after_next_close, [S, cs_ignore, [S, cs, "{"]])
+ }
+end
+<<assign numbers of sections in leveltab>>=
+l := ["part", "chapter", "section", "subsection", "subsubsection",
+ "paragraph", "subparagraph"]
+leveltab := table()
+every i := 1 to *l do
+ leveltab[l[i]] := i - 2 # making section level 1
+@
+\subsubsection{Counters}
+<<*>>=
+global countertab
+
+procedure Csetcounter(S, cs, cl)
+ local counter
+ (counter := csarg(), countertab[counter] := integer(csarg())) |
+ cs_ignore(S, cs, "{{")
+end
+<<initialization>>=
+countertab := table()
+@
+\subsubsection{Accents}
+This info is taken from the HTML RFC, section entitled
+``ISO Latin~1 character entities.''
+<<*>>=
+global accent_name, accent_valid
+<<initialization>>=
+accent_name := table()
+accent_valid := table('')
+accent_name ["`"] := "grave"
+accent_valid["`"] := 'AEIOUaeiou'
+accent_name ["'"] := "acute"
+accent_valid["'"] := 'AEIOUYaeiouy'
+accent_name ["^"] := "circ"
+accent_valid["^"] := 'AEIOUaeiou'
+accent_name ["hat"] := "circ"
+accent_valid["hat"] := 'AEIOUaeiou'
+accent_name ["\""] := "uml"
+accent_valid["\""] := 'AEIOUaeiouy'
+accent_name ["~"] := "tilde"
+accent_valid["~"] := 'ANOano'
+accent_name ["="] := "bar"
+accent_name ["."] := "dot"
+accent_name ["u"] := "u"
+accent_name ["v"] := "v"
+accent_name ["H"] := "H"
+accent_name ["t"] := "t"
+accent_name ["c"] := "cedil"
+accent_valid["c"] := 'Cc'
+accent_name ["d"] := "underdot"
+accent_name ["b"] := "underbar"
+@
+Initialization calls [[accent]] to indicate that a control
+sequence represents an accent.
+In fact, [[accent]] is called on all keys of [[accent_name]].
+<<*>>=
+procedure accent(cs)
+ cstab[cs] := Caccent
+end
+
+procedure Caccent(S, cs, cl)
+ static warned
+ initial warned := table()
+ arg := csarg(S) | return
+ if arg == "\\i" then arg := "i"
+ if arg == "\\j" then arg := "j"
+ if *arg = 1 & any(accent_valid[cs], arg) then
+ S.text(S, "&" || arg || accent_name[cs] || ";")
+ else {
+ <<warn about [[cs]] with [[arg]]>>
+ S.text(S, arg)
+ }
+end
+<<warn about [[cs]] with [[arg]]>>=
+/warned[cs] := set()
+if not member(warned[cs], arg) then {
+ write(&errout, "Warning: Can't handle \\", cs, " with arg `", arg, "'")
+ insert(warned[cs], arg)
+}
+@
+\subsection{Font changes}
+A font change changes the font until the next close, when we need to emit
+the appropriate end tag.
+<<*>>=
+procedure fontchange(tex, html)
+ cstab[tex] := Cfontchange
+ csclosure[tex] := html
+end
+<<*>>=
+procedure Cfontchange(S, tex, html)
+ S.text(S, tag(html))
+ before_next_close(S, emit_text, [S, endtag(html)])
+end
+@
+\section{Implementations of declaratives}
+\label{imp-decl}
+
+\subsection{Ignoring stuff}
+There are several different kinds of things that can be ignored:
+ordinary arguments,
+balanced-brace arguments, optional arguments, assignments (which may
+include dimensions), stars, and parenthesized coordinates.
+We ignore a sequence of these things by supplying a template to
+[[ignore]], in which each character stands for something to be ignored.
+We've already seen examples of these things in Section~\ref{cs-decls}.
+
+We can ignore arguments of control sequences or environments.
+In either case, [[cs_ignore]] does the work.
+<<*>>=
+procedure ignore(cs, template)
+ /template := ""
+ cstab[cs] := cs_ignore
+ csclosure[cs] := template
+end
+
+procedure ignoreenv(env, template)
+ /template := ""
+ begintab[env] := cs_ignore
+ begincl[env] := template
+ endtab[env] := do_nothing
+end
+@
+Because ignoring may span many inputs, all [[cs_ignore]] does is set things
+up to call [[do_ignore]].
+The major setup is replacing [[S.text]] with a function that does nothing.
+Oh, and it converts an integer template
+into that many arguments, for historical reasons.
+<<*>>=
+procedure cs_ignore(S, cs, template, proc, args)
+ local saved_ignore
+ saved_ignore := S.ignoring
+ S.ignoring := 1
+ if type(template) == "integer" then template := repl("{", template)
+ return do_ignore(S, template, saved_ignore, proc, args)
+end
+@
+Some things are easily ignored (partly because we assume they don't
+span inputs). For others, we have special procedures.
+The brace-ignoring stuff uses the open and close hooks, because braces
+can be nested deeply.
+If non-null, [[proc]] is applied to [[args]] after everything is ignored.
+<<*>>=
+procedure do_ignore(S, template, saved_ignore, proc, args)
+ if *template > 0 then
+ if optwhite() & pos(0) then
+ after_next_newtext(S, do_ignore, [S, template, saved_ignore, proc, args])
+ else
+ case template[1] of {
+ "{" : { S.ignoring := 1
+ after_next_open(S, ignore_til_close,
+ [S, template[2:0], saved_ignore, proc, args])
+ }
+ "A" : { csarg(S) # had better be in one input
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ }
+ "[" : if optwhite() & ="[" then {
+ delay_newtext(S)
+ with_upto_bracket(S, "", ignore_bracket_plus,
+ [S, template[2:0], saved_ignore, proc, args])
+ } else
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ "C" : # a total cheat, means ``copy optional arg''
+ if optwhite() & ="[" then {
+ S.ignoring := &null
+ delay_newtext(S)
+ with_upto_bracket(S, "", copy_bracket_plus,
+ [S, template[2:0], saved_ignore, proc, args])
+ } else
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ "=" : { delay_newtext(S)
+ eat_assignment(S, do_ignore, [S, template[2:0], saved_ignore, proc,args])
+ }
+ "*" : { (="*", optwhite())
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ }
+ "(" : { (="(", tab(upto(')')), =")", optwhite())
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ }
+ }
+ else {
+ S.ignoring := saved_ignore
+ (\proc)!(\args)
+ }
+end
+
+procedure ignore_til_close(S, template, saved_ignore, proc, args)
+ before_next_close(S, do_ignore, [S, template, saved_ignore, proc, args])
+end
+@
+Finally, at the end of an ignored environment, do nothing.
+<<*>>=
+procedure do_nothing(S, cs, cl)
+ return
+end
+@
+\subsubsection{Parsing bracketed (optional) arguments}
+We may have to deal with optional arguments that are split across lines.
+We pass in a continuation for the bracket.
+This is a lot like gobbling to a newline, which we had to do with a comment.
+As in the other case, we do something stupid if the bracket is
+protected (e.g. by a backslash or comment char).
+<<*>>=
+procedure with_upto_bracket(S, bracketed_text, proc, args)
+ bracketed_text ||:= tab(upto(']') | 0)
+ if pos(0) then
+ before_next_newtext(S, with_upto_bracket, [S, bracketed_text, proc, args])
+ else {
+ ="]"
+ undelay_newtext(S)
+ (\proc)(S, bracketed_text, args)
+ }
+ return
+end
+@
+To ignore brackets:
+<<*>>=
+procedure ignore_bracket_plus(S, contents, args)
+ # contents are ignored
+ do_ignore!args
+end
+@ and to copy them
+<<*>>=
+procedure copy_bracket_plus(S, contents, args)
+ local should_ignore
+ should_ignore := args[3] | fail # saved_ignore arg to do_ignore
+ if /should_ignore then
+ S.text(S, convert(converter("H"), "{" || contents || "}"))
+ do_ignore!args
+end
+@
+\subsubsection{Ignoring assignments}
+Assignments are tricky because they might involve numbers, control
+sequences, dimensions, or even glue.
+We approximate the syntax from page 275 in the \TeX book.
+<<*>>=
+procedure eat_assignment(S, proc, args)
+ static decimal_chars, hex_chars, oct_chars
+ initial {
+ decimal_chars := &digits ++ '.,+-'
+ hex_chars := &digits ++ 'abcdefABCDEF'
+ oct_chars := '0124567'
+ }
+ optwhite()
+ ="=" # so what if we swallow multiple = signs
+ optwhite()
+ if pos(0) then {
+ before_next_newtext(S, eat_assignment, [S, proc, args])
+ return
+ } else if glue() then { # finished
+ } else if any(decimal_chars) then {
+ tab(many(decimal_chars))
+ optwhite()
+ if ="\\" then
+ tab(many(S.csletters)) | move(1)
+ # else assume assignment of the form \hangafter=2
+ } else if ="\"" then {
+ tab(many(hex_chars)) & optwhite()
+ } else if ="\'" then {
+ tab(many(oct_chars)) & optwhite()
+ } else if =("\\"|"`\\") then
+ tab(many(S.csletters)) | move(1)
+ undelay_newtext(S)
+ (\proc)!args
+end
+<<*>>=
+procedure dimen()
+ static decimal_chars
+ initial decimal_chars := &digits ++ '.,'
+ suspend (optwhite(),
+ if any('+-') then (move(1), optwhite()) else "",
+ tab(many(decimal_chars)), optwhite(),
+ (="true", optwhite()) | &null,
+ =("em"|"ex"|"pt"|"pc"|"in"|"bp"|"cm"|"mm"|"dd"|"cc"|"sp"|"mu"))
+end
+<<*>>=
+procedure glue()
+ suspend (dimen(),
+ (optwhite(), ="plus", dimen()) | "",
+ (optwhite(), ="minus", dimen()) | "")
+end
+@
+\subsection{Substitution}
+
+\subsubsection{Simple substitution for a single control sequence}
+
+Even simple substitution isn't so simple, because in addition to the
+HTML that we substitute for the {\TeX}, we can also supply a template
+of stuff to be ignored (like the optional argument to \verb+\\+).
+<<*>>=
+procedure substitution(tex, html, ignore_template)
+ # ignore mode for now
+ cstab[tex] := Cemit_ig
+ csclosure[tex] := emit_ig_cl(html, \ignore_template | "")
+end
+@
+The closure contains HTML to be written and a template to be ignored.
+<<*>>=
+record emit_ig_cl(html, template)
+
+procedure Cemit_ig(S, cs, cl)
+ emit_text(S, cl.html)
+ if *cl.template > 0 then
+ cs_ignore(S, cs, cl.template)
+end
+@
+\subsubsection{Substitution for active characters}
+<<*>>=
+procedure activesubst(char, html, ignore_template)
+ local S
+ # ignore mode for now
+ activetab[char] := Cemit_ig
+ activeclosure[char] := emit_ig_cl(html, \ignore_template | "")
+ S := \dynamic_add_hack | return
+ if upto(S.activechars, char) then return # already active
+ if S.activechars ++:= cset(char) then {
+ before_next_close(S, delete_active_char, [S, char])
+ } else impossible("ugh")
+ return
+end
+
+procedure delete_active_char(S, char)
+ S.activechars --:= char
+ return
+end
+@
+\subsubsection{Substitution for environments}
+The [[envblock]] procedure has two forms:
+\begin{itemize}
+\item
+{}[[envblock(]]{\it environment}, {\it tag}[[)]] simply uses
+begin- and end-{\it tag} in place of the environment.
+\item
+{}[[envblock(]]{\it environment}, {\it left}, {\it right}, {\it
+ignore}[[)]]
+puts the {\it left} text at the beginning of the environment, the {\it
+right} text at the end, plus at the beginning of the environment it
+ignores the arguments described by {\it ignore}.
+\end{itemize}
+It's easier to implement than to describe.
+<<*>>=
+procedure envblock(env, left, right, ignore_template)
+ /ignore_template := ""
+ begintab[env] := Cemit_ig
+ begincl[env] := emit_ig_cl(if /right then tag(left) else left, ignore_template)
+ endtab[env] := Cemit
+ endcl[env] := if /right then endtag(left) else right
+end
+@ [[Cemit]] emits text with nothing to ignore.
+<<*>>=
+procedure Cemit(S, cs, cl)
+ S.text(S, cl)
+end
+@
+\subsubsection{Substitution around arguments of control sequences}
+These substitutions place tags at the beginning and end of arguments
+to control sequences, instead of surrounding the contents of an
+environment.
+For example, they specify how to convert [[\section{...}]] to
+[[<h1>...</h1>]] and so forth.
+The calling convention is as for [[envblock]].
+<<*>>=
+record blockpair(left, right, ignore)
+
+procedure argblock(tex, html, right, ignore)
+ # called as is envblock
+ /ignore := ""
+ cstab[tex] := Cblock
+ csclosure[tex] :=
+ if /right then blockpair (tag(html), endtag(html), ignore)
+ else blockpair (html, right, ignore)
+end
+@ There is a fine point; control sequences labelled with [[argblockv]]
+should put the converter into vertical mode.
+<<*>>=
+procedure argblockv(tex, html, right, ignore)
+ argblock(tex, html, right, ignore)
+ cstab[tex] := CblockV
+end
+<<*>>=
+procedure Cblock(S, cs, cl, done_ignoring)
+ if /done_ignoring & *cl.ignore > 0 then {
+ cs_ignore(S, cs, cl.ignore, Cblock, [S, cs, cl, 1])
+ } else if pos(0) then {
+ after_next_newtext(S, do_cs, [S, cs, cl])
+ } else if match("{") then {
+ S.text(S, cl.left)
+ after_next_open(S, before_next_close, [S, emit_text, [S, cl.right]])
+ } else {
+# S.text(S, cl.left || csarg(S) || cl.right)
+ apply_args(S, Cblock_continue, [S, cl], 1)
+ }
+ return
+end
+
+procedure Cblock_continue(S, cl, title)
+ S.text (S, cl.left || title || cl.right)
+ return
+end
+<<*>>=
+procedure CblockV(S, cs, cl)
+ S.mode := "V"
+ Cblock(S, cs, cl)
+ return
+end
+@
+\subsubsection{Macro substitution}
+I'm taking the plunge and describing a ghastly macro language.
+Macros have arguments, a body, and an optional terminal mode.
+The final mode, if non-null, is the mode to which the conversion
+engine should be set.
+<<*>>=
+record macro_defn(name, arg_count, body, mode)
+@ The body is a list of items, where an item may be a raw argument, a
+converted argument, or a string.
+<<*>>=
+record raw_arg(number)
+record converted_arg(number, mode)
+@
+<<*>>=
+procedure expand_macro(S, macro, args)
+ every a := !macro.body do
+ case type(a) of {
+ "string" : emit_text(S, a)
+ "raw_arg" : emit_text(S, args[a.number]) | impossible("missing arg")
+ "converted_arg" : S.text(S, convert(S, "{" || args[a.number] || "}"))
+ }
+# poptrace()
+ return
+end
+#link pushtrace
+@
+Scan arguments and hope comments in arguments just work out. Ha ha.
+<<*>>=
+procedure do_macro(S, macro, args_seen, current_arg, brace_depth)
+ # invariant : we have an open brace
+# write(&errout, "scanning args for macro ", macro.name)
+# write(&errout, "seen ", *args_seen, " want ", macro.arg_count)
+ while *args_seen < macro.arg_count & not pos(0) do {
+ while *args_seen < macro.arg_count & brace_depth = 0 & not pos(0) do {
+# write(&errout, "seen ", *args_seen, " want ", macro.arg_count,
+# " current ", image(current_arg), " braces ", brace_depth)
+ tab(many(' \t\n'))
+ case c := move(1) of {
+ "\\" : put(args_seen, "\\" ||
+ if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1))
+ "{" : { current_arg := "" ; brace_depth := 1 }
+ "}" : { error("Insufficient arguments to macro ", macro.name) }
+ default : put(args_seen, c)
+ }
+ }
+ while brace_depth > 0 & not pos(0) do {
+# write(&errout, "seen ", *args_seen, " want ", macro.arg_count,
+# " current ", image(current_arg), " braces ", brace_depth)
+ current_arg ||:= tab(upto('\\{}') | 0)
+ case move(1) of {
+ "\\" : current_arg ||:= "\\" ||
+ if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1)
+ "{" : { current_arg ||:= "{" ; brace_depth +:= 1 }
+ "}" : { brace_depth -:= 1
+ if brace_depth > 0 then
+ current_arg ||:= "}"
+ else {
+ put(args_seen, current_arg)
+ current_arg := ""
+ }
+ }
+ }
+ }
+ }
+# write(&errout, "seen ", *args_seen, " want ", macro.arg_count,
+# " current ", image(current_arg), " braces ", brace_depth)
+ if *args_seen = macro.arg_count then {
+# write(&errout, "Arguments for macro ", macro.name, ":")
+# every write(&errout, "\t", image(!args_seen))
+ expand_macro(S, macro, args_seen)
+ undelay_newtext(S)
+ } else
+ before_next_newtext(S, do_macro, [S, macro, args_seen, current_arg, brace_depth])
+ return
+end
+@
+<<*>>=
+procedure Cmacro(S, cs, cl)
+# pushtrace("MACRO")
+ delay_newtext(S)
+# apply_args(S, closure(expand_macro, [cl]), cl.arg_count)
+ do_macro(S, cl, [], "", 0)
+ return
+end
+@
+Now, a {\TeX}-like macro facility in which [[#]] is used for converted
+parameters and [[#$]] for raw ones.
+<<*>>=
+procedure macro(name, arg_count, body, mode)
+ m := macro_defn(name, arg_count, parse_body(body), mode)
+ cstab[name] := Cmacro
+ csclosure[name] := m
+ return
+end
+
+procedure begin_macro(env, arg_count, body, mode)
+ m := macro_defn(env, arg_count, parse_body(body), mode)
+ begintab[env] := Cmacro
+ begincl[env] := m
+ return
+end
+
+procedure parse_body(body)
+ b := []
+ body ? {
+ put(b, tab(upto('#') | 0))
+ while ="#" do {
+ put(b, ="#" | (="$", raw_arg(argnum())) | converted_arg(argnum())) |
+ error("malformed macro arg #", tab(0))
+ put(b, tab(upto('#') | 0))
+ }
+ }
+ return b
+end
+
+procedure argnum()
+ if any(&digits) then return integer(move(1)) else fail
+end
+@
+And the dynamic version\ldots
+<<*>>=
+procedure l2h_macro(name, count, body[])
+ count := integer(count) |
+ return error("must give # of arguments to l2h macro ", name)
+ s := ""
+ every s ||:= " " || (1(b := !body, type(b) == "string"))
+ s := s[2:0] # strip leading space if any
+ return macro(name, count, s)
+end
+@
+<<*>>=
+procedure l2h_environment(env, count, body[])
+ count := integer(count) |
+ return error("must give # of arguments to l2h environment ", env)
+ s := ""
+ every s ||:= " " || (1(b := !body, type(b) == "string"))
+ s := s[2:0] # strip leading space if any
+ return begin_macro(env, count, s)
+end
+@
+\subsection{Table environments}
+For tables, we not only have an HTML tag, we also supply some text
+for the ampersand.
+[[args]] is a template describing the arguments to the environment,
+which are ignored.
+<<*>>=
+record table_closure(args, amp, open, close)
+
+procedure table_env(env, args, amp, open, close)
+ begintab[env] := Ctable
+ begincl[env] := table_closure(args, amp,
+ if /close then tag(\open) | &null else open,
+ if /close then endtag(\open) | &null else close)
+ endtab[env] := Ctable_end
+ endcl[env] := []
+end
+<<*>>=
+procedure Ctable(S, env, cl)
+ local amp
+## amp := S.ampersand
+## S.ampersand := cl.amp
+ S.text(S, \cl.open)
+ push(endcl[env], amp)
+ cs_ignore(S, env, cl.args)
+end
+
+procedure Ctable_end(S, env, cl)
+# S.ampersand := pop(cl)
+ S.text(S, \begincl[env].close)
+end
+@
+\subsection{Postscript}
+<<*>>=
+procedure Cepsfig(S, cs, cl)
+ apply_args(S, do_epsfig, [S], 1)
+end
+
+procedure do_epsfig(S, arg)
+ local args
+ args := []
+ arg ?
+ while not pos(0) do {
+ tab(many(' \t\n'))
+ put(args, eqsplit(tab(upto(',') | 0)))
+ }
+ if a := !args & a.name == ("file"|"figure") then
+ emit_text(S, "<a href=" || image(a.value) || "><b>[</b>PostScript figure " ||
+ a.value || "<b>]</b></a>")
+ else
+ emit_text(S, "<b>[</b>Ill-understood PostScript figure<b>]</b>")
+end
+
+record apair(name, value)
+
+procedure eqsplit(s)
+ p := apair()
+ s ? (p.name := tab(upto('=')), ="=", p.value := tab(0))
+ return p
+end
+@
+<<*>>=
+procedure Cincludegraphics(S, cs, cl)
+ local saved_ignore
+ saved_ignore := S.ignoring
+ S.ignoring := 1
+ do_ignore(S, "[", saved_ignore, apply_args, [S, do_includegraphics, [S], 1])
+end
+
+procedure do_includegraphics(S, arg)
+ local base, ext
+ if arg ? (base := tab(find(ext := ".ps" | ".eps" | ".epsi")), =ext, pos(0)) then
+ emit_text(S, "<a href=" || image(arg) || "><b>[</b>PostScript figure " ||
+ arg || "<b>]</b></a>")
+ else if arg ? (base := tab(find(ext := ".png" | ".gif" | ".jpg")), =ext, pos(0)) then
+ emit_text(S, "<img src=" || image(arg) || ">")
+ else
+ emit_text(S, "<b>[</b>Ill-understood graphics<b>]</b>")
+end
+@
+\subsection{Control-sequence assignment}
+This procedure is available to be used for dynamic assignment.
+One day we might use it to parse \verb+\let+ as well.
+<<*>>=
+procedure let(lhs, rhs)
+ cstab[lhs] := cstab[rhs]
+ csclosure[lhs] := csclosure[rhs]
+end
+
+procedure let_closure(lhs, cl[])
+ csclosure[lhs] := if *cl = 1 then cl[1] else cl
+end
+
+procedure letenv(lhs, rhs)
+ begintab[lhs] := begintab[rhs]
+ endtab[lhs] := endtab[rhs]
+ begincl[lhs] := begincl[rhs]
+ endcl[lhs] := endcl[rhs]
+end
+@
+\section{HTML formatting}
+\label{html-format}
+
+First, generic procedures used to create beginning and ending tags.
+<<*>>=
+procedure tag(html)
+ return "<" || html || ">"
+end
+
+procedure endtag(html)
+ return "</" || html || ">"
+end
+@
+Next, a gazillion formatting procedures.
+<<*>>=
+procedure Ccomment(S)
+ if *S.comment > 0 then {
+ S.text(S, "<!--")
+ S.comment ? {
+ while S.text(S, tab(find("--"))) do {
+ move(2)
+ S.text(S, "- - ")
+ }
+ S.text(S, tab(0))
+ }
+ S.text(S, "-->")
+ }
+ S.comment := ""
+ return
+end
+<<*>>=
+procedure Cparagraph(S)
+ S.text(S, "<p>")
+end
+<<*>>=
+procedure Cmath(S)
+ <<take open-group actions>>
+ S.text(S, "<i>")
+end
+
+procedure Cmath_end(S)
+ S.text(S, "</i>")
+ <<take close-group actions>>
+end
+<<*>>=
+procedure Cdisplaymath(S)
+ <<take open-group actions>>
+ S.text(S, "<blockquote><i>")
+end
+
+procedure Cdisplaymath_end(S)
+ S.text(S, "</i></blockquote>")
+ <<take close-group actions>>
+end
+<<*>>=
+procedure Cmakeatletter(S)
+ S.csletters ++:= '@'
+end
+
+procedure Cmakeatother(S)
+ S.csletters --:= '@'
+end
+@
+Approximate \verb+\kill+ by eliminating text.
+<<*>>=
+procedure Ckill(S, cs, cl)
+ S.the_text := ""
+end
+@
+\section{Support for adding control sequences dynamically}
+
+The idea is to use formal comments of the form:
+\begin{quote}
+\verb+% l2h function arg arg ...+
+\end{quote}
+These comments have the same effect as the procedure calls in
+the chunk [[<<control-sequence assignments>>]].
+@
+Our first step is to create a table with the names of the functions we
+recognize.
+Ordinarly this table would be distributed, but I created it after the
+fact with a little quick Unix pipeline.
+<<*>>=
+global csfunctions
+<<initialization>>=
+csfunctions := table()
+<<assign to dynamic-add table>>=
+csfunctions["argblock"] := argblock
+csfunctions["argblockv"] := argblockv
+csfunctions["envblock"] := envblock
+csfunctions["fontchange"] := fontchange
+csfunctions["ignore"] := ignore
+csfunctions["ignoreenv"] := ignoreenv
+csfunctions["let"] := let
+csfunctions["letenv"] := letenv
+csfunctions["listenv"] := listenv
+csfunctions["substitution"] := substitution
+csfunctions["activesubst"] := activesubst
+csfunctions["closure"] := let_closure
+csfunctions["let_closure"] := let_closure
+csfunctions["newcommand"] := l2h_macro
+csfunctions["macro"] := l2h_macro
+csfunctions["environment"] := l2h_environment
+csfunctions["tabular"] := tabular
+@
+Now, the tough issue is how to parse arguments. I'm going to try the
+following initial strategy: arguments are separated by spaces.
+To put a space within an argument, use \verb+#+. There is no way to
+put a \verb+#+ within an argument.
+<<*>>=
+global dynamic_add_hack
+procedure parse_dynamic_add(S)
+ if (optwhite(), =("l2h"|"sl2h"), skipwhite(),
+ p := tab(upto(' \t')), <<make [[p]] a good function or warn and [[fail]]>>,
+ skipwhite(), any(~'\n')) then {
+ a := []
+ while (any(~'\n'), l := tab(upto(' \t\n') | 0)) do {
+ put(a, if p === (l2h_macro|l2h_environment) then l else map(l, "#", " "))
+ skipwhite()
+ }
+ dynamic_add_hack := S
+ p!a
+ dynamic_add_hack := &null
+ return
+ }
+end
+<<make [[p]] a good function or warn and [[fail]]>>=
+((p := \csfunctions[p]) |
+{ dynamic_warn(p); fail })
+<<*>>=
+procedure dynamic_warn(p)
+ static badprocs
+ initial badprocs := set()
+ if not member(badprocs, p) then {
+ write(&errout, "Warning: % l2h ", p, " not recognized -- ignored")
+ insert(badprocs, p)
+ }
+end
+@
+\section{Miscellanous utilities}
+[[optwhite]] skips and returns optional white space.
+<<*>>=
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+@ [[skipwhite]] insists that there must be some white space.
+<<*>>=
+procedure skipwhite()
+ suspend tab(many(' \t'))
+end
+@
+\section{Main program for a noweb filter}
+First, this is how we use the converter as a noweb filter.
+<<l2h.icn>>=
+<<*>>
+procedure main(args)
+ local line
+ errstatus := 0
+ every arg := !args do
+ case arg of {
+ "-show-unknowns" : show_unknowns := 1
+ "-html-quotes" : html_quotes := 1
+ default : fatal("unknown arg ", image(arg))
+ }
+ while line := read() do
+ apply(filter, line)
+ warn_unknown(\unknown_set, "control sequences", "\\")
+ warn_unknown(\unknown_envs, "environments", "{", "}")
+ if errstatus > 0 then
+ write("@fatal l2h Error occurred in l2h conversion")
+ exit(errstatus)
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+@
+This is noweb filter machinery. I really ought to coordinate quoted text
+with the converter (so it always shows up in the right place),
+but so far I'm too lazy.
+<<l2h.icn>>=
+global curfile, curline
+
+procedure filter(name, arg)
+ static S, code
+ initial S := converter("V")
+### write(" mode ", S.mode)
+ case name of {
+ "begin" : {<<out>>; if match("code ", arg) then code := 1}
+ "end" : {if match("docs ", arg) then <<possible paragraph>>
+ <<out>>; code := &null; S.mode := "V"}
+ "quote" : { outtext("\0" ? convert(S)) }
+ "endquote" : { outtext("\1" ? convert(S)) }
+ "file" : {<<out>>; curfile := arg; curline := 1}
+ "line" : {<<out>>; curline := integer(arg)}
+ "defn" : { write("@", name, " ", convert_use_or_def(arg)) }
+ "use" : { write("@", name, " ", convert_use_or_def(arg)) }
+ "text" : {if \code then <<out>> else outtext(arg ? convert(S)) }
+ "nl" : {if \code then <<out>> else outtext("\n" ? convert(S)); curline +:= 1}
+ "fatal" : {<<out>>; exit(1)}
+ default : {<<out>>}
+ }
+ return
+end
+<<possible paragraph>>=
+if S.mode ~== "V" then write("@text <p>")
+@ A special function is needed to implement {\tt noweb}'s quoting
+convention within chunk names.
+<<l2h.icn>>=
+procedure convert_use_or_def(s)
+ r := ""
+ s ? {
+ while r ||:= quickconv(tab(find("[["))) do {
+ (r ||:= ="[[") | fatal("impossible missing [[")
+ (r ||:= tab(find("]]")) || tab(many(']'))) |
+ fatal("impossible missing ]] in ", image(s))
+ }
+ return r || quickconv(tab(0))
+ }
+end
+
+procedure quickconv(s)
+ static C
+ initial C := converter("H")
+ return 1(("{" || s || "}" ? convert(C)), reset(C))
+end
+<<out>>=
+write("@", name, (" " || \arg) | "")
+<<l2h.icn>>=
+procedure outtext(s)
+ s ?
+ while not pos(0) do
+ if ="\n" then write("@nl")
+ else if ="\0" then write("@quote")
+ else if ="\1" then write("@endquote")
+ else write("@text ", tab(upto('\n\0\1') | 0))
+ return
+end
+<<*>>=
+global errstatus
+procedure error(args[])
+ errstatus := 1
+ return write!([&errout, (\curfile || ":") | "line ", curline, ": "] ||| args)
+end
+@
+\section{Main program for a simple converter}
+<<sl2h.icn>>=
+<<*>>
+global curfile, curline
+
+procedure convert_file(f)
+ static S
+ initial S := converter("V")
+ curline := 0
+ while line := read(f) do {
+ curline +:= 1
+ writes(convert(S, line || "\n"))
+ }
+ return
+end
+
+procedure main(args)
+ local warn
+ warn := 1
+ errstatus := 0
+ every arg := !args do
+ if arg[1] == "-" then
+ case arg of {
+ "-show-unknowns" : show_unknowns := 1
+ "-nowarn" : warn := &null
+ "-html-quotes" : html_quotes := 1
+ "-" : { curfile := arg; convert_file(&input) }
+ default : write(&errout, "Warning: unrecognized option ", arg)
+ }
+ else if f := open(curfile <- arg) then
+ convert_file(f)
+ else
+ write(&errout, "Error: Can't open file ", arg)
+ if /curfile then
+ convert_file(&input)
+ if \warn then {
+ warn_unknown(\unknown_set, "control sequences", "\\")
+ warn_unknown(\unknown_envs, "environments", "{", "}")
+ }
+ exit(errstatus)
+end
+@
+<<*>>=
+procedure fatal(L[])
+ write!(["@fatal l2h "] ||| L)
+ write!([&errout, "noweb error in l2h: "] ||| L)
+ exit(1)
+end
+@
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: l2h.nw,v 1.24 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+@
+\section{Chunks}
+\nowebchunks
+
+\begin{multicols}{2}[\section{Index}]
+\nowebindex
+\end{multicols}
+@
+\end{document}
diff --git a/web/noweb/src/icon/lrtldefs.icn b/web/noweb/src/icon/lrtldefs.icn
new file mode 100644
index 0000000000..6faec732b7
--- /dev/null
+++ b/web/noweb/src/icon/lrtldefs.icn
@@ -0,0 +1,99 @@
+#line 3 "lrtldefs.nw"
+procedure main(args)
+ go()
+end
+#line 7 "lrtldefs.nw"
+procedure postpass(name, arg)
+ static kind, definers
+ initial { kind := "bogus"
+ definers := ["fun", "val", "structure", "signature",
+ "type", "rtlop"]
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if =(""|" "|" ") & =!definers & tab(many(' ')) then {
+ skiptyvars(); optwhite()
+ if ="[" then
+ while define_id()
+ else
+ define_id()
+ }
+ }
+ return
+end
+
+procedure define_id()
+ static id1, id2, reserved
+ initial { id1 := &letters ++ &digits ++ '\'_'
+ id2 := '!%&$+-/:<=>?@\\~^|#*`'
+ reserved := set()
+ every insert(reserved, !"*|:=#_" | "->" | "=>")
+ }
+ optwhite()
+ if id := tab(many(id1 | id2)) then {
+ member(reserved, id) | writedefn(id)
+ return id
+ }
+ fail
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+
+procedure skiptyvars()
+ suspend =("'"|"#") || tab(many(&letters ++ &digits ++ '\'_')) |
+ ="(" || bal(')', '(', ')') || =")"
+end
+
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+#line 55 "lrtldefs.nw"
+procedure rcsinfo ()
+ return "$Id: lrtldefs.nw,v 1.17 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+#line 1 "defns.nw"
+procedure go()
+ local line
+ while line := read() do {
+ apply(prepass, line)
+ write(line)
+ if match("@fatal ", line) then exit(1)
+ apply(postpass, line)
+ }
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+#line 18 "defns.nw"
+procedure writedefn(defn, locl)
+ static indextext
+ initial indextext := ""
+ if /defn then
+ *indextext > 0 &
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 23 "defns.nw"
+ else {
+ if *indextext + *defn > 65 then
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 25 "defns.nw"
+ write(if \locl then "@index localdefn " else "@index defn ", defn)
+ indextext ||:= " " || defn
+ }
+ return
+end
+#line 35 "defns.nw"
+procedure rcsinfo_too ()
+ return "$Id: defns.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/lrtldefs.nw b/web/noweb/src/icon/lrtldefs.nw
new file mode 100644
index 0000000000..a928f761ff
--- /dev/null
+++ b/web/noweb/src/icon/lrtldefs.nw
@@ -0,0 +1,60 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+\section{Finding definitions in $\lambda$-RTL}
+<<*>>=
+procedure main(args)
+ go()
+end
+<<*>>=
+procedure postpass(name, arg)
+ static kind, definers
+ initial { kind := "bogus"
+ definers := ["fun", "val", "structure", "signature",
+ "type", "rtlop"]
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if =(""|" "|" ") & =!definers & tab(many(' ')) then {
+ skiptyvars(); optwhite()
+ if ="[" then
+ while define_id()
+ else
+ define_id()
+ }
+ }
+ return
+end
+
+procedure define_id()
+ static id1, id2, reserved
+ initial { id1 := &letters ++ &digits ++ '\'_'
+ id2 := '!%&$+-/:<=>?@\\~^|#*`'
+ reserved := set()
+ every insert(reserved, !"*|:=#_" | "->" | "=>")
+ }
+ optwhite()
+ if id := tab(many(id1 | id2)) then {
+ member(reserved, id) | writedefn(id)
+ return id
+ }
+ fail
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+
+procedure skiptyvars()
+ suspend =("'"|"#") || tab(many(&letters ++ &digits ++ '\'_')) |
+ ="(" || bal(')', '(', ')') || =")"
+end
+
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: lrtldefs.nw,v 1.17 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+@
diff --git a/web/noweb/src/icon/mmixdefs.icn b/web/noweb/src/icon/mmixdefs.icn
new file mode 100644
index 0000000000..cd9bf7ffca
--- /dev/null
+++ b/web/noweb/src/icon/mmixdefs.icn
@@ -0,0 +1,71 @@
+#line 3 "mmixdefs.nw"
+procedure main(args)
+ go()
+end
+#line 7 "mmixdefs.nw"
+global idchars
+procedure postpass(name, arg)
+ static kind, lets
+ initial { idchars := &letters ++ &digits ++ '_:'
+ lets := &letters ++ '_'
+ kind := "bogus"
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if (any(lets), t := tab(many(idchars)), any('\t ')) then
+ writedefn(t)
+ }
+ return
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+#line 27 "mmixdefs.nw"
+procedure rcsinfo ()
+ return "$Id: mmixdefs.nw,v 1.15 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+#line 1 "defns.nw"
+procedure go()
+ local line
+ while line := read() do {
+ apply(prepass, line)
+ write(line)
+ if match("@fatal ", line) then exit(1)
+ apply(postpass, line)
+ }
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+#line 18 "defns.nw"
+procedure writedefn(defn, locl)
+ static indextext
+ initial indextext := ""
+ if /defn then
+ *indextext > 0 &
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 23 "defns.nw"
+ else {
+ if *indextext + *defn > 65 then
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 25 "defns.nw"
+ write(if \locl then "@index localdefn " else "@index defn ", defn)
+ indextext ||:= " " || defn
+ }
+ return
+end
+#line 35 "defns.nw"
+procedure rcsinfo_too ()
+ return "$Id: defns.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/mmixdefs.nw b/web/noweb/src/icon/mmixdefs.nw
new file mode 100644
index 0000000000..abb7ceda31
--- /dev/null
+++ b/web/noweb/src/icon/mmixdefs.nw
@@ -0,0 +1,32 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+\section{Finding definitions in MMIX}
+<<*>>=
+procedure main(args)
+ go()
+end
+<<*>>=
+global idchars
+procedure postpass(name, arg)
+ static kind, lets
+ initial { idchars := &letters ++ &digits ++ '_:'
+ lets := &letters ++ '_'
+ kind := "bogus"
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if (any(lets), t := tab(many(idchars)), any('\t ')) then
+ writedefn(t)
+ }
+ return
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: mmixdefs.nw,v 1.15 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+@
diff --git a/web/noweb/src/icon/noidx.icn b/web/noweb/src/icon/noidx.icn
new file mode 100644
index 0000000000..3a829eaa9c
--- /dev/null
+++ b/web/noweb/src/icon/noidx.icn
@@ -0,0 +1,465 @@
+#line 9 "noidx.nw"
+global lines # all the input lines
+global delay # non-null if markup should be delayed past the first chunk
+global anchordist # max distance before code chunk to place defining @xref label
+
+procedure main(args)
+ lines := []
+
+#line 38 "noidx.nw"
+curfile := "standard input?"
+lastbeginarg := "never any chunks?"
+#line 50 "noidx.nw"
+every allchunks | allidents := set()
+every indexlabels | defanchors | uses | anchorlabel | indexanchorlabel := table()
+#line 284 "noidx.nw"
+every chunkud | indexud := table();
+#line 16 "noidx.nw"
+ delay := &null
+
+#line 28 "noidx.nw"
+while case(a := get(args)) of {
+ "-delay" : delay := 1
+ "-docanchor" : anchordist := integer(get(args))
+ default : fatal("unknown argument ", image(a))
+}
+#line 18 "noidx.nw"
+ while put(lines, line := read()) do
+ apply(pass1, line)
+ every apply(pass2, !lines)
+
+#line 340 "noidx.nw"
+(if /wrote_trailers then {
+ wrote_trailers := 1
+ write("@nl")
+ write("@nl")
+ lognowebchunks()
+ lognowebindex()
+} else &null)
+#line 22 "noidx.nw"
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+#line 35 "noidx.nw"
+global curfile # unique id of the current @file
+global lastbeginarg # identifies last chunk (for -delay)
+#line 47 "noidx.nw"
+global allchunks, allidents
+global indexlabels, defanchors, uses, anchorlabel, indexanchorlabel
+#line 57 "noidx.nw"
+procedure pass1(name, arg)
+ static lastdefnlabel, thisusecount, lastanchorlabel, nonblank, textnonblank
+ initial nonblank := ~' \t'
+ case name of {
+ "file" : curfile := uniqueid(arg)
+ "begin" : { lastbeginarg := arg; textnonblank := &null }
+ "end" : if match("docs ", arg) & \anchordist & \textnonblank then
+ {
+#line 116 "noidx.nw"
+t := []; n := anchordist
+lastanchorlabel := newdocslabel()
+while lines[-1] ?
+ if n = 0 | ="@begin docs" then
+ { put(lines, "@xref label " || lastanchorlabel); lines |||:= t; break }
+ else
+ { if ="@nl" & pos(0) then n -:= 1; push(t, pull(lines)) }
+#line 64 "noidx.nw"
+ }
+ else
+ lastanchorlabel := &null
+ "text" : /textnonblank := upto(nonblank, arg)
+ "defn" : {
+ insert(allchunks, arg)
+ slipin("@xref label " || (lastdefnlabel := newdefnlabel(arg)))
+ /lastanchorlabel := lastdefnlabel
+ /anchorlabel[arg] := lastanchorlabel
+ addlabel(defanchors, arg, lastanchorlabel)
+ addud(chunkud, "defn", arg, lastanchorlabel)
+ thisusecount := 0
+ }
+ "use" :
+ if match ("code ", lastbeginarg) then {
+ insert(allchunks, arg)
+ slipin("@xref label " || lastdefnlabel || "-u" || (thisusecount +:= 1))
+ addlabel(uses, arg, lastanchorlabel)
+ addud(chunkud, "use", arg, lastanchorlabel)
+ } else {
+ /textnonblank := upto(nonblank, arg) # could appear in quoted code
+ }
+ "index" : {
+
+#line 234 "noidx.nw"
+{ arg ? { name := tab(upto(' ')|0); arg := if =" " then tab(0) else &null } }
+#line 88 "noidx.nw"
+ case name of {
+ "use" : { insert(allidents, arg)
+ addud(indexud, "use", arg, \lastanchorlabel)
+ }
+ "defn" | "localdefn" : {
+ insert(allidents, arg)
+ (l := \lastanchorlabel) |
+ slipin("@xref label " || (l := newdocslabel()))
+ addud(indexud, "defn", arg, l)
+ /indexanchorlabel[arg] := l
+ slipin("@xref ref " || l) # bug fix
+ }
+ }
+ }
+ }
+ return
+end
+#line 127 "noidx.nw"
+procedure slipin(s)
+ local last
+ last := pull(lines)
+ every put(lines, s | last)
+ return s
+end
+#line 134 "noidx.nw"
+procedure pass2(name, arg)
+ static thesedefns, theseuses
+ static thischunk # null for docs chunk, arg of @defn for code chunk
+ static defout # number of definitions emitted for each chunk
+ initial defout := table(0)
+ case name of {
+ "begin" : {
+ if \delay & lastbeginarg == arg then
+#line 340 "noidx.nw"
+(if /wrote_trailers then {
+ wrote_trailers := 1
+ write("@nl")
+ write("@nl")
+ lognowebchunks()
+ lognowebindex()
+} else &null)
+#line 142 "noidx.nw"
+
+#line 236 "noidx.nw"
+write("@", name, (" " || \arg) | "")
+#line 143 "noidx.nw"
+ every thesedefns | theseuses := set()
+ thischunk := &null
+ }
+ "defn" : { thischunk := arg;
+ write("@xref ref " || anchorlabel[arg])
+
+#line 236 "noidx.nw"
+write("@", name, (" " || \arg) | "")
+#line 148 "noidx.nw"
+
+
+#line 195 "noidx.nw"
+defout[thischunk] +:= 1
+write("@xref prevdef ", defanchors[thischunk][defout[thischunk] - 1]) # fail if first
+write("@xref nextdef ", defanchors[thischunk][defout[thischunk] + 1]) # faif if last
+if defout[thischunk] = 1 then {
+#line 221 "noidx.nw"
+if *defanchors[thischunk] > 1 then {
+ write("@xref begindefs")
+ every write("@xref defitem ", defanchors[thischunk][2 to *defanchors[thischunk]])
+ write("@xref enddefs")
+}
+if \uses[thischunk] then {
+ write("@xref beginuses")
+ every write("@xref useitem ", !uses[thischunk])
+ write("@xref enduses")
+} else
+ write("@xref notused ", thischunk)
+#line 198 "noidx.nw"
+ }
+#line 150 "noidx.nw"
+ }
+# must postpone index cross-reference to end of chunk because
+# the info is accumulated in [[thesdefns]] and [[theseuses]] on this pass
+ "end" : { if match("code", arg) then {
+#line 200 "noidx.nw"
+theseuses --:= thesedefns
+if *thesedefns > 0 then {
+ write("@index begindefs")
+ every i := !alphasort(thesedefns) do {
+ every u := !\indexud[i] do u ? if ="use " then write("@index isused ", tab(0))
+ write("@index defitem ", i)
+ }
+ write("@index enddefs")
+}
+if *theseuses > 0 then {
+ l := alphasort(theseuses)
+ write("@index beginuses")
+ every i := !alphasort(theseuses) do {
+ every d := !\indexud[i] do d ? if ="defn " then write("@index isdefined ", tab(0))
+ write("@index useitem ", i)
+ }
+ write("@index enduses")
+}
+# every write("@literal \\nwindexuse{", TeXliteral(ident := !l), "}",
+# "{", indexlabels[ident], "}{", thislabel, "}")
+#line 153 "noidx.nw"
+ }
+
+#line 236 "noidx.nw"
+write("@", name, (" " || \arg) | "")
+#line 154 "noidx.nw"
+
+ }
+ "use" : { write("@xref ref " || (\anchorlabel[arg] | "nw@notdef")) # was "???"
+
+#line 236 "noidx.nw"
+write("@", name, (" " || \arg) | "")
+#line 157 "noidx.nw"
+
+ }
+ "index" : {
+
+#line 234 "noidx.nw"
+{ arg ? { name := tab(upto(' ')|0); arg := if =" " then tab(0) else &null } }
+#line 161 "noidx.nw"
+ case name of {
+ "defn" | "localdefn" : {
+ insert(thesedefns, arg)
+ # no xref ref because of bug fix
+ }
+ "use" : { insert(theseuses, arg)
+ write("@xref ref ", \indexanchorlabel[arg])
+ }
+ }
+ name := "index " || name
+
+#line 236 "noidx.nw"
+write("@", name, (" " || \arg) | "")
+#line 172 "noidx.nw"
+ }
+ "text" : # grotesque hack! for chunks and index in HTML
+ if /thischunk then # docs mode
+ case arg of {
+ "<nowebchunks>" : lognowebchunks()
+ "<nowebindex>" : lognowebindex()
+ default :
+#line 236 "noidx.nw"
+write("@", name, (" " || \arg) | "")
+#line 179 "noidx.nw"
+ }
+ else
+#line 236 "noidx.nw"
+write("@", name, (" " || \arg) | "")
+#line 181 "noidx.nw"
+ "fatal" : {
+#line 236 "noidx.nw"
+write("@", name, (" " || \arg) | "")
+#line 181 "noidx.nw"
+ ; exit(1) }
+ "trailer" : {
+#line 340 "noidx.nw"
+(if /wrote_trailers then {
+ wrote_trailers := 1
+ write("@nl")
+ write("@nl")
+ lognowebchunks()
+ lognowebindex()
+} else &null)
+#line 183 "noidx.nw"
+
+#line 236 "noidx.nw"
+write("@", name, (" " || \arg) | "")
+#line 184 "noidx.nw"
+ }
+ default :
+#line 236 "noidx.nw"
+write("@", name, (" " || \arg) | "")
+#line 186 "noidx.nw"
+ }
+ return
+end
+#line 238 "noidx.nw"
+procedure lualistimage(l)
+ p := "{ "
+ s := ""
+ every i := 1 to *l do {
+ s ||:= p || "[" || i || "] = " || image(l[i])
+ p := ", "
+ }
+ return s || " }"
+end
+#line 255 "noidx.nw"
+procedure newdefnlabel(arg)
+ static defcounts
+ initial defcounts := table(0)
+ /defanchors[arg] := []
+ k := curfile || "-" || uniqueid(arg)
+ defcounts[k] +:= 1
+ return "NW" || k || "-" || alphacode(defcounts[k])
+end
+#line 264 "noidx.nw"
+procedure newdocslabel()
+ static count
+ initial count := 0
+ return "NWD" || curfile || "-" || alphacode(count +:= 1)
+end
+#line 270 "noidx.nw"
+procedure addlabel(tbl, arg, label)
+ /tbl[arg] := []
+ if tbl[arg][-1] == label then &null
+ else put(tbl[arg], label)
+ return label
+end
+#line 277 "noidx.nw"
+global chunkud, indexud
+procedure addud(udlist, name, arg, label)
+ /udlist[arg] := []
+ s := name || " " || label
+ return udlist[arg][-1] == s | put(udlist[arg], s)
+end
+#line 289 "noidx.nw"
+procedure strip_extra_uses(udlista)
+ local old, new, item
+ old := copy(udlista)
+ new := []
+ while item := get(old) do
+ item ?
+ if ="defn " then
+
+#line 305 "noidx.nw"
+{ new[-1] == item | put(new, item) }
+#line 297 "noidx.nw"
+ else if ="use " then
+ if "defn " || tab(0) == !(old|new) then
+ &null # write(&errout, "Stripped extra ", item)
+ else
+
+#line 305 "noidx.nw"
+{ new[-1] == item | put(new, item) }
+#line 302 "noidx.nw"
+ return new
+end
+#line 309 "noidx.nw"
+procedure uniqueid(name)
+ local key
+ static idtable, keycounts, badchars, badstars
+ initial { idtable := table() ; keycounts := table(0)
+ badchars := ~ (&letters ++ &digits ++ '!$()*+,./:;=?@|')
+ badstars := repl("*", *badchars)
+ }
+
+ if not member(idtable, name) then {
+ # key := make_key(map(name, badchars, badstars)) # deprecated
+ key := alphacode(crc(name))
+ keycounts[key] +:= 1
+ idtable[name] := key
+ if keycounts[key] > 1 then idtable[name] ||:= "." || alphacode(keycounts[key])
+ }
+ return idtable[name]
+end
+#line 330 "noidx.nw"
+procedure make_key(key, len)
+ static noslash
+ initial noslash := ~ '/'
+ key ? return make_key(3(tab(upto('/')), ="/", tab(many(noslash)), pos(0)), *key) |
+ key[1+:3] || alphacode(\len | *key) |
+ key || (alphacode(\len) | "")
+end
+#line 338 "noidx.nw"
+global wrote_trailers
+#line 350 "noidx.nw"
+procedure lognowebchunks(noheader)
+ static called
+ if \called then return
+ else called := 1
+
+ l := alphasort(allchunks)
+ write("@xref beginchunks")
+ while name := get(l) do {
+ write("@xref chunkbegin ", (\anchorlabel[name] | "nw@notdef"), " ", name)
+ every write("@xref chunk", !\chunkud[name])
+ write("@xref chunkend")
+ }
+ write("@xref endchunks")
+end
+#line 365 "noidx.nw"
+procedure lognowebindex()
+ static called
+ if \called then return
+ else called := 1
+
+ l := alphasort(allidents)
+ write("@index beginindex")
+ while name := get(l) do {
+ write("@index entrybegin ", (\indexanchorlabel[name] | "nw@notdef"), " ", name)
+ every write("@index entry", !strip_extra_uses(\indexud[name]))
+ write("@index entryend")
+ }
+ write("@index endindex")
+end
+#line 380 "noidx.nw"
+procedure alphasort(x)
+ t := table()
+ every s := !x do t[s] := sortkey(s)
+ t := sort(t, 2)
+ l := []
+ every put(l, (!t)[1])
+ return l
+end
+#line 405 "noidx.nw"
+procedure sortkey(s)
+ return map(s) || "\n" || s # relies on \n sorting lower than other chars
+end
+#line 409 "noidx.nw"
+procedure alphacode(n)
+ static codes
+ initial codes := &digits || &letters
+ return if n < 0 then
+ "-" || alphacode(-n)
+ else if n >= *codes then
+ alphacode(n / *codes) || alphacode(n % *codes)
+ else
+ codes[n+1]
+end
+#line 421 "noidx.nw"
+# /* 32-bit Cyclic Redundancy Code implemented by A. Appel 1986 */
+#
+# this works only if POLY is a prime polynomial in the field
+# of integers modulo 2, of order 32. Since the representation of this
+# won't fit in a 32-bit word, the high-order bit is implicit.
+# IT MUST ALSO BE THE CASE that the coefficients of orders 31 down to 25
+# are zero. Fortunately, we have a candidate, from
+# E. J. Watson, "Primitive Polynomials (Mod 2)", Math. Comp 16 (1962).
+# It is: x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + x^0
+#
+# Now we reverse the bits to get:
+# 111101010000000000000000000000001 in binary (but drop the last 1)
+# f 5 0 0 0 0 0 0 in hex
+# */
+
+procedure crc_table()
+ local POLY, sum
+ POLY := 16rf5000000
+ t := table()
+ every i := 0 to 255 do {
+ sum := 0
+ every j := 7 to 0 by -1 do
+ if iand(i, ishift(1, j)) ~= 0 then
+ sum := ixor(sum, ishift(POLY, -j))
+ t[i] := sum
+ }
+ return t
+end
+
+procedure crc(s)
+ local sum
+ static table
+ initial table := crc_table()
+ sum := 0
+ s ? while sum := ixor(ishift(sum, -8), table[iand(ixor(sum, ord(move(1))), 255)])
+ return sum
+end
+#line 460 "noidx.nw"
+procedure fatal(L[])
+ write!(["@fatal noidx "] ||| L)
+ write!([&errout, "noweb error in noidx: "] ||| L)
+ exit(1)
+end
+#line 466 "noidx.nw"
+procedure rcsinfo ()
+ return "$Id: noidx.nw,v 1.22 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/noidx.nw b/web/noweb/src/icon/noidx.nw
new file mode 100644
index 0000000000..62fd9176d1
--- /dev/null
+++ b/web/noweb/src/icon/noidx.nw
@@ -0,0 +1,479 @@
+\documentstyle[noweb]{article}
+\pagestyle{noweb}\noweboptions{shortxref}
+\begin{document}
+Missing ``{\tt @xref tag} {\it label tag},'' where {\it label} is the name of
+a label and {\it tag} is a chunk number, page number, sub-page number, or
+other identifying mark.
+@
+\section{Cross-reference and index support}
+<<*>>=
+global lines # all the input lines
+global delay # non-null if markup should be delayed past the first chunk
+global anchordist # max distance before code chunk to place defining @xref label
+
+procedure main(args)
+ lines := []
+ <<initialization>>
+ delay := &null
+ <<swallow [[args]]>>
+ while put(lines, line := read()) do
+ apply(pass1, line)
+ every apply(pass2, !lines)
+ <<write trailers if not already written>>
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+<<swallow [[args]]>>=
+while case(a := get(args)) of {
+ "-delay" : delay := 1
+ "-docanchor" : anchordist := integer(get(args))
+ default : fatal("unknown argument ", image(a))
+}
+@
+<<*>>=
+global curfile # unique id of the current @file
+global lastbeginarg # identifies last chunk (for -delay)
+<<initialization>>=
+curfile := "standard input?"
+lastbeginarg := "never any chunks?"
+@
+[[anchorlabel]] is the label that references to a code chunk refer to.
+The {\LaTeX} back end typically uses the chunk itself, but the HTML
+back end will use a spot in the preceding documentation chunk (if
+any), as requested by [[-docanchor]] (and non-null [[anchordist]])
+and recorded in [[anchorlabel]].
+<<*>>=
+global allchunks, allidents
+global indexlabels, defanchors, uses, anchorlabel, indexanchorlabel
+<<initialization>>=
+every allchunks | allidents := set()
+every indexlabels | defanchors | uses | anchorlabel | indexanchorlabel := table()
+@
+I set [[textnonblank]] non-null if some text line in the current chunk
+contains a non-blank character.
+This trick lets me avoid planting anchors in empty documentation chunks.
+<<*>>=
+procedure pass1(name, arg)
+ static lastdefnlabel, thisusecount, lastanchorlabel, nonblank, textnonblank
+ initial nonblank := ~' \t'
+ case name of {
+ "file" : curfile := uniqueid(arg)
+ "begin" : { lastbeginarg := arg; textnonblank := &null }
+ "end" : if match("docs ", arg) & \anchordist & \textnonblank then
+ {<<insert and set [[lastanchorlabel]]>>}
+ else
+ lastanchorlabel := &null
+ "text" : /textnonblank := upto(nonblank, arg)
+ "defn" : {
+ insert(allchunks, arg)
+ slipin("@xref label " || (lastdefnlabel := newdefnlabel(arg)))
+ /lastanchorlabel := lastdefnlabel
+ /anchorlabel[arg] := lastanchorlabel
+ addlabel(defanchors, arg, lastanchorlabel)
+ addud(chunkud, "defn", arg, lastanchorlabel)
+ thisusecount := 0
+ }
+ "use" :
+ if match ("code ", lastbeginarg) then {
+ insert(allchunks, arg)
+ slipin("@xref label " || lastdefnlabel || "-u" || (thisusecount +:= 1))
+ addlabel(uses, arg, lastanchorlabel)
+ addud(chunkud, "use", arg, lastanchorlabel)
+ } else {
+ /textnonblank := upto(nonblank, arg) # could appear in quoted code
+ }
+ "index" : {
+ <<shift [[name]] and [[arg]]>>
+ case name of {
+ "use" : { insert(allidents, arg)
+ addud(indexud, "use", arg, \lastanchorlabel)
+ }
+ "defn" | "localdefn" : {
+ insert(allidents, arg)
+ (l := \lastanchorlabel) |
+ slipin("@xref label " || (l := newdocslabel()))
+ addud(indexud, "defn", arg, l)
+ /indexanchorlabel[arg] := l
+ slipin("@xref ref " || l) # bug fix
+ }
+ }
+ }
+ }
+ return
+end
+@
+The bug fix\label{multi-def-bug}
+alluded to above occurs when there are multiple definitions of an identifier.
+In this case, we can't just use [[indexanchorlabel[id]]], because that refers only to
+the first definition. In the {\TeX} back end, that leads to bogus
+tags like \hbox{\it x \small\rm 7b 7b 7b} instead of \hbox{\it x
+\small\rm 7b 9 12a}; the first tag is repeated again and again.
+Because the tag for the current [[@defn]] is lost by the time pass~2
+rolls around, we have to slip it in on pass~1.
+@
+<<insert and set [[lastanchorlabel]]>>=
+t := []; n := anchordist
+lastanchorlabel := newdocslabel()
+while lines[-1] ?
+ if n = 0 | ="@begin docs" then
+ { put(lines, "@xref label " || lastanchorlabel); lines |||:= t; break }
+ else
+ { if ="@nl" & pos(0) then n -:= 1; push(t, pull(lines)) }
+@
+[[slipin]] sticks something into [[lines]] just before the current (last) line.
+It makes sense only on the first pass.
+<<*>>=
+procedure slipin(s)
+ local last
+ last := pull(lines)
+ every put(lines, s | last)
+ return s
+end
+<<*>>=
+procedure pass2(name, arg)
+ static thesedefns, theseuses
+ static thischunk # null for docs chunk, arg of @defn for code chunk
+ static defout # number of definitions emitted for each chunk
+ initial defout := table(0)
+ case name of {
+ "begin" : {
+ if \delay & lastbeginarg == arg then <<write trailers if not already written>>
+ <<copy [[name]] and [[arg]] to output>>
+ every thesedefns | theseuses := set()
+ thischunk := &null
+ }
+ "defn" : { thischunk := arg;
+ write("@xref ref " || anchorlabel[arg])
+ <<copy [[name]] and [[arg]] to output>>
+ <<write chunk cross-reference>>
+ }
+# must postpone index cross-reference to end of chunk because
+# the info is accumulated in [[thesdefns]] and [[theseuses]] on this pass
+ "end" : { if match("code", arg) then {<<write index cross-reference>>}
+ <<copy [[name]] and [[arg]] to output>>
+ }
+ "use" : { write("@xref ref " || (\anchorlabel[arg] | "nw@notdef")) # was "???"
+ <<copy [[name]] and [[arg]] to output>>
+ }
+ "index" : {
+ <<shift [[name]] and [[arg]]>>
+ case name of {
+ "defn" | "localdefn" : {
+ insert(thesedefns, arg)
+ # no xref ref because of bug fix
+ }
+ "use" : { insert(theseuses, arg)
+ write("@xref ref ", \indexanchorlabel[arg])
+ }
+ }
+ name := "index " || name
+ <<copy [[name]] and [[arg]] to output>>
+ }
+ "text" : # grotesque hack! for chunks and index in HTML
+ if /thischunk then # docs mode
+ case arg of {
+ "<nowebchunks>" : lognowebchunks()
+ "<nowebindex>" : lognowebindex()
+ default : <<copy [[name]] and [[arg]] to output>>
+ }
+ else <<copy [[name]] and [[arg]] to output>>
+ "fatal" : { <<copy [[name]] and [[arg]] to output>>; exit(1) }
+ "trailer" : { <<write trailers if not already written>>
+ <<copy [[name]] and [[arg]] to output>>
+ }
+ default : <<copy [[name]] and [[arg]] to output>>
+ }
+ return
+end
+@
+The case of the [[@index defn]] is the one case where we don't emit a
+reference, because the reference has to go in earlier. See
+page~\pageref{multi-def-bug} for an explanation.
+@
+<<write chunk cross-reference>>=
+defout[thischunk] +:= 1
+write("@xref prevdef ", defanchors[thischunk][defout[thischunk] - 1]) # fail if first
+write("@xref nextdef ", defanchors[thischunk][defout[thischunk] + 1]) # faif if last
+if defout[thischunk] = 1 then {<<write use and def summary for chunk cross-reference>>}
+<<write index cross-reference>>=
+theseuses --:= thesedefns
+if *thesedefns > 0 then {
+ write("@index begindefs")
+ every i := !alphasort(thesedefns) do {
+ every u := !\indexud[i] do u ? if ="use " then write("@index isused ", tab(0))
+ write("@index defitem ", i)
+ }
+ write("@index enddefs")
+}
+if *theseuses > 0 then {
+ l := alphasort(theseuses)
+ write("@index beginuses")
+ every i := !alphasort(theseuses) do {
+ every d := !\indexud[i] do d ? if ="defn " then write("@index isdefined ", tab(0))
+ write("@index useitem ", i)
+ }
+ write("@index enduses")
+}
+# every write("@literal \\nwindexuse{", TeXliteral(ident := !l), "}",
+# "{", indexlabels[ident], "}{", thislabel, "}")
+<<write use and def summary for chunk cross-reference>>=
+if *defanchors[thischunk] > 1 then {
+ write("@xref begindefs")
+ every write("@xref defitem ", defanchors[thischunk][2 to *defanchors[thischunk]])
+ write("@xref enddefs")
+}
+if \uses[thischunk] then {
+ write("@xref beginuses")
+ every write("@xref useitem ", !uses[thischunk])
+ write("@xref enduses")
+} else
+ write("@xref notused ", thischunk)
+@
+<<shift [[name]] and [[arg]]>>=
+{ arg ? { name := tab(upto(' ')|0); arg := if =" " then tab(0) else &null } }
+<<copy [[name]] and [[arg]] to output>>=
+write("@", name, (" " || \arg) | "")
+<<*>>=
+procedure lualistimage(l)
+ p := "{ "
+ s := ""
+ every i := 1 to *l do {
+ s ||:= p || "[" || i || "] = " || image(l[i])
+ p := ", "
+ }
+ return s || " }"
+end
+@
+The following code is a change first effective in version~2.10d.
+It ensures that labels are the same whether files are marked up one at
+a time or in a group.
+This change helps ``book page definition marks'' for the 152 text,
+which is processed one chapter at a time for weaving but several
+chapters in a group for tangling.
+<<*>>=
+procedure newdefnlabel(arg)
+ static defcounts
+ initial defcounts := table(0)
+ /defanchors[arg] := []
+ k := curfile || "-" || uniqueid(arg)
+ defcounts[k] +:= 1
+ return "NW" || k || "-" || alphacode(defcounts[k])
+end
+<<*>>=
+procedure newdocslabel()
+ static count
+ initial count := 0
+ return "NWD" || curfile || "-" || alphacode(count +:= 1)
+end
+<<*>>=
+procedure addlabel(tbl, arg, label)
+ /tbl[arg] := []
+ if tbl[arg][-1] == label then &null
+ else put(tbl[arg], label)
+ return label
+end
+<<*>>=
+global chunkud, indexud
+procedure addud(udlist, name, arg, label)
+ /udlist[arg] := []
+ s := name || " " || label
+ return udlist[arg][-1] == s | put(udlist[arg], s)
+end
+<<initialization>>=
+every chunkud | indexud := table();
+@
+Because it's silly to have both a use and a definition point to the same chunk,
+I strip out uses that list the same chunk as their definitions.
+<<*>>=
+procedure strip_extra_uses(udlista)
+ local old, new, item
+ old := copy(udlista)
+ new := []
+ while item := get(old) do
+ item ?
+ if ="defn " then
+ <<add item if needed>>
+ else if ="use " then
+ if "defn " || tab(0) == !(old|new) then
+ &null # write(&errout, "Stripped extra ", item)
+ else
+ <<add item if needed>>
+ return new
+end
+<<add item if needed>>=
+{ new[-1] == item | put(new, item) }
+@
+[[uniqueid]] eliminates both {\TeX} and HTML specials.
+<<*>>=
+procedure uniqueid(name)
+ local key
+ static idtable, keycounts, badchars, badstars
+ initial { idtable := table() ; keycounts := table(0)
+ badchars := ~ (&letters ++ &digits ++ '!$()*+,./:;=?@|')
+ badstars := repl("*", *badchars)
+ }
+
+ if not member(idtable, name) then {
+ # key := make_key(map(name, badchars, badstars)) # deprecated
+ key := alphacode(crc(name))
+ keycounts[key] +:= 1
+ idtable[name] := key
+ if keycounts[key] > 1 then idtable[name] ||:= "." || alphacode(keycounts[key])
+ }
+ return idtable[name]
+end
+@
+The original key routine used the FORTH heuristic on the basename:
+first three letters plus the length. This produced too many collisions.
+<<*>>=
+procedure make_key(key, len)
+ static noslash
+ initial noslash := ~ '/'
+ key ? return make_key(3(tab(upto('/')), ="/", tab(many(noslash)), pos(0)), *key) |
+ key[1+:3] || alphacode(\len | *key) |
+ key || (alphacode(\len) | "")
+end
+<<*>>=
+global wrote_trailers
+<<write trailers if not already written>>=
+(if /wrote_trailers then {
+ wrote_trailers := 1
+ write("@nl")
+ write("@nl")
+ lognowebchunks()
+ lognowebindex()
+} else &null)
+@
+Now, a special hack, so we can write this stuff in the right place on pass 2.
+<<*>>=
+procedure lognowebchunks(noheader)
+ static called
+ if \called then return
+ else called := 1
+
+ l := alphasort(allchunks)
+ write("@xref beginchunks")
+ while name := get(l) do {
+ write("@xref chunkbegin ", (\anchorlabel[name] | "nw@notdef"), " ", name)
+ every write("@xref chunk", !\chunkud[name])
+ write("@xref chunkend")
+ }
+ write("@xref endchunks")
+end
+<<*>>=
+procedure lognowebindex()
+ static called
+ if \called then return
+ else called := 1
+
+ l := alphasort(allidents)
+ write("@index beginindex")
+ while name := get(l) do {
+ write("@index entrybegin ", (\indexanchorlabel[name] | "nw@notdef"), " ", name)
+ every write("@index entry", !strip_extra_uses(\indexud[name]))
+ write("@index entryend")
+ }
+ write("@index endindex")
+end
+<<*>>=
+procedure alphasort(x)
+ t := table()
+ every s := !x do t[s] := sortkey(s)
+ t := sort(t, 2)
+ l := []
+ every put(l, (!t)[1])
+ return l
+end
+@
+I tried to ignore special characters when sorting.
+This turned out to be too clever by half.
+Sample: it would sort [[BALANCER_DEBUGGING]] before
+[[BALANCE_TRANSFORMATION]], because the underscore didn't count.
+<<old, evil code>>=
+procedure sortkey(s)
+ static keep
+ initial keep := &lcase ++ ' '
+ s := map(s)
+ r := ""
+ s ? while tab(upto(keep)) do r ||:= move(1)
+ return r || "\n" || s # relies on \n sorting lower than other chars
+end
+@ My solution is to move to a much simpler scheme in which the only
+thing we do is change case.
+<<*>>=
+procedure sortkey(s)
+ return map(s) || "\n" || s # relies on \n sorting lower than other chars
+end
+<<*>>=
+procedure alphacode(n)
+ static codes
+ initial codes := &digits || &letters
+ return if n < 0 then
+ "-" || alphacode(-n)
+ else if n >= *codes then
+ alphacode(n / *codes) || alphacode(n % *codes)
+ else
+ codes[n+1]
+end
+@
+<<*>>=
+# /* 32-bit Cyclic Redundancy Code implemented by A. Appel 1986 */
+#
+# this works only if POLY is a prime polynomial in the field
+# of integers modulo 2, of order 32. Since the representation of this
+# won't fit in a 32-bit word, the high-order bit is implicit.
+# IT MUST ALSO BE THE CASE that the coefficients of orders 31 down to 25
+# are zero. Fortunately, we have a candidate, from
+# E. J. Watson, "Primitive Polynomials (Mod 2)", Math. Comp 16 (1962).
+# It is: x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + x^0
+#
+# Now we reverse the bits to get:
+# 111101010000000000000000000000001 in binary (but drop the last 1)
+# f 5 0 0 0 0 0 0 in hex
+# */
+
+procedure crc_table()
+ local POLY, sum
+ POLY := 16rf5000000
+ t := table()
+ every i := 0 to 255 do {
+ sum := 0
+ every j := 7 to 0 by -1 do
+ if iand(i, ishift(1, j)) ~= 0 then
+ sum := ixor(sum, ishift(POLY, -j))
+ t[i] := sum
+ }
+ return t
+end
+
+procedure crc(s)
+ local sum
+ static table
+ initial table := crc_table()
+ sum := 0
+ s ? while sum := ixor(ishift(sum, -8), table[iand(ixor(sum, ord(move(1))), 255)])
+ return sum
+end
+@
+<<*>>=
+procedure fatal(L[])
+ write!(["@fatal noidx "] ||| L)
+ write!([&errout, "noweb error in noidx: "] ||| L)
+ exit(1)
+end
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: noidx.nw,v 1.22 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+@
+\section{List of chunks}
+\nowebchunks
+
+\twocolumn
+\section{Index}
+\nowebindex
+@
+\end{document}
diff --git a/web/noweb/src/icon/noindex.icn b/web/noweb/src/icon/noindex.icn
new file mode 100644
index 0000000000..3ba307170b
--- /dev/null
+++ b/web/noweb/src/icon/noindex.icn
@@ -0,0 +1,98 @@
+#line 6 "noindex.nw"
+procedure main(args)
+ if *args ~= 1 then
+ write(&errout, "Usage: noindex basename")
+ else {
+ in := get(args)
+ if in[-4:0] == ".tex" then in[-4:0] := ".aux"
+ else if not (in[-4:0] == ".aux") then in ||:= ".aux"
+ gobble(in, idx := [])
+ f := open(in[1:-4] || ".nwi", "w") | fatal("Cannot write ", in[1:-4] || ".nwi")
+ last := ""
+ every out := stripcount(!alphasort(idx)) do
+ write(f, last ~== out) & last := out
+ close(f)
+ }
+ return
+end
+#line 23 "noindex.nw"
+procedure gobble(name, idx)
+ static count
+ initial count := 0
+ in := open(name) |
+#line 40 "noindex.nw"
+{ write(&errout, "No file ", name, "."); return }
+#line 27 "noindex.nw"
+ while line := read(in) do
+ line ?
+ if ="\\@input{" & name := tab(upto('}')) & move(1) & pos(0) then
+ gobble(name, idx)
+ else if ="\\nwixadds{" then
+ put(idx, right(count +:= 1, 6, "0") || " " || tab(0))
+ return
+end
+#line 36 "noindex.nw"
+procedure stripcount(s)
+ s ? { tab(many(&digits)); tab(many(' ')); return "\\nwixaddsx{" || tab(0) }
+end
+#line 42 "noindex.nw"
+procedure alphasort(x)
+ t := table()
+ every s := !x do t[s] := sortkey(s)
+ t := sort(t, 2)
+ l := []
+ every put(l, (!t)[1])
+ return l
+end
+#line 51 "noindex.nw"
+procedure sortkey(s)
+ local count
+ map(s) ? {
+ count := tab(many(&digits))
+ tab(many(' '))
+ if ="c}" then return firstkey() || "\n" || count
+ else if ="i}" then return firstkey() || "\n" || count
+ else fatal("not chunk or index")
+ }
+end
+#line 62 "noindex.nw"
+procedure firstkey()
+ ="{{" | fatal("bad index or chunk format")
+ s := (remove_control_sequences() ? tab(bal('}', '{', '}') | 0))
+ return alphabet(s) || "\n" || s
+end
+#line 68 "noindex.nw"
+procedure alphabet(s)
+ static keep
+ initial keep := &lcase ++ ' \t'
+ r := ""
+ s ? {
+ while tab(upto(keep)) do
+ if tab(many(' \t')) then
+ r ||:= " "
+ else
+ r ||:= tab(many(&lcase)) | fatal("This can't happen")
+ }
+ r ? { tab(many(' ')) ; return tab(0) } # strip leading blanks
+end
+#line 82 "noindex.nw"
+procedure remove_control_sequences()
+ s := ""
+ while s ||:= tab(upto('\\')) do {
+ ="\\"
+ tab(many(&letters)) | move(1) # skip
+ tab(many(' \t'))
+ }
+ return s || tab(0)
+end
+#line 93 "noindex.nw"
+procedure fatal(L[])
+ write!(["@fatal noindex "] ||| L)
+ write!([&errout, "noweb error in noindex: "] ||| L)
+ exit(1)
+end
+#line 99 "noindex.nw"
+procedure rcsinfo ()
+ return "$Id: noindex.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/noindex.nw b/web/noweb/src/icon/noindex.nw
new file mode 100644
index 0000000000..cad4369b8a
--- /dev/null
+++ b/web/noweb/src/icon/noindex.nw
@@ -0,0 +1,106 @@
+This program is similar to [[makeindex]] in that it grovels through [[.aux]]
+files looking for index information, which it writes to a [[.nwi]] file.
+It's used when [[noweave -indexfrom]] is used on many files separately;
+it combines the separate indices into a single, correctly sorted index.
+That index file is read by [[\nowebindex*]].
+<<*>>=
+procedure main(args)
+ if *args ~= 1 then
+ write(&errout, "Usage: noindex basename")
+ else {
+ in := get(args)
+ if in[-4:0] == ".tex" then in[-4:0] := ".aux"
+ else if not (in[-4:0] == ".aux") then in ||:= ".aux"
+ gobble(in, idx := [])
+ f := open(in[1:-4] || ".nwi", "w") | fatal("Cannot write ", in[1:-4] || ".nwi")
+ last := ""
+ every out := stripcount(!alphasort(idx)) do
+ write(f, last ~== out) & last := out
+ close(f)
+ }
+ return
+end
+<<*>>=
+procedure gobble(name, idx)
+ static count
+ initial count := 0
+ in := open(name) | <<can't open; return>>
+ while line := read(in) do
+ line ?
+ if ="\\@input{" & name := tab(upto('}')) & move(1) & pos(0) then
+ gobble(name, idx)
+ else if ="\\nwixadds{" then
+ put(idx, right(count +:= 1, 6, "0") || " " || tab(0))
+ return
+end
+<<*>>=
+procedure stripcount(s)
+ s ? { tab(many(&digits)); tab(many(' ')); return "\\nwixaddsx{" || tab(0) }
+end
+<<can't open; return>>=
+{ write(&errout, "No file ", name, "."); return }
+<<*>>=
+procedure alphasort(x)
+ t := table()
+ every s := !x do t[s] := sortkey(s)
+ t := sort(t, 2)
+ l := []
+ every put(l, (!t)[1])
+ return l
+end
+<<*>>=
+procedure sortkey(s)
+ local count
+ map(s) ? {
+ count := tab(many(&digits))
+ tab(many(' '))
+ if ="c}" then return firstkey() || "\n" || count
+ else if ="i}" then return firstkey() || "\n" || count
+ else fatal("not chunk or index")
+ }
+end
+<<*>>=
+procedure firstkey()
+ ="{{" | fatal("bad index or chunk format")
+ s := (remove_control_sequences() ? tab(bal('}', '{', '}') | 0))
+ return alphabet(s) || "\n" || s
+end
+<<*>>=
+procedure alphabet(s)
+ static keep
+ initial keep := &lcase ++ ' \t'
+ r := ""
+ s ? {
+ while tab(upto(keep)) do
+ if tab(many(' \t')) then
+ r ||:= " "
+ else
+ r ||:= tab(many(&lcase)) | fatal("This can't happen")
+ }
+ r ? { tab(many(' ')) ; return tab(0) } # strip leading blanks
+end
+<<*>>=
+procedure remove_control_sequences()
+ s := ""
+ while s ||:= tab(upto('\\')) do {
+ ="\\"
+ tab(many(&letters)) | move(1) # skip
+ tab(many(' \t'))
+ }
+ return s || tab(0)
+end
+@
+<<*>>=
+procedure fatal(L[])
+ write!(["@fatal noindex "] ||| L)
+ write!([&errout, "noweb error in noindex: "] ||| L)
+ exit(1)
+end
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: noindex.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+@
+\section{Index}
+\nowebindex
diff --git a/web/noweb/src/icon/noxref.nw b/web/noweb/src/icon/noxref.nw
new file mode 100644
index 0000000000..4b0eaa1836
--- /dev/null
+++ b/web/noweb/src/icon/noxref.nw
@@ -0,0 +1,119 @@
+\section{Cross-reference for noweb/latex}
+<<*>>=
+global lines, defns, uses, names, firstdefnout
+
+procedure main(args)
+ lines := []
+ defns := table()
+ uses := table()
+ names := table()
+ while put(lines, line := read()) do
+ apply(pass1, line)
+ firstdefnout := set()
+ every apply(pass2, !lines)
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+<<*>>=
+procedure pass1(name, chunkname)
+ static curfile, defined
+ initial {curfile := "????"; defined := set()}
+ case name of {
+ "file" : curfile := modid(chunkname || (chunkname[4+:3] | chunkname[4:0] | ""))
+ "defn" | "use" : {
+ if name == "defn" then tbl := defns else tbl := uses
+ if name == "defn" & not member(defined, chunkname) then {
+ label := "sublabel"
+ insert(defined, chunkname)
+ } else
+ label := "label"
+ /tbl[chunkname] := []
+ id := map(name, &lcase, &ucase) || ":" || curfile || ":" ||
+ modid(chunkname) || "-" || (1+*tbl[chunkname])
+ put(tbl[chunkname], id)
+ put(lines, "@literal \\" || label || "{" || id || "}")
+ names[chunkname] := lettersonly(chunkname)
+ }
+ }
+ return
+end
+<<*>>=
+procedure modid(name)
+ local key
+ static idtable, keycounts
+ initial { idtable := table() ; keycounts := table(0) }
+
+ if not member(idtable, name) then {
+ key := map(name, " \\{}-[]`#%&~_^", "**************")
+ if *key > 6 then key := key[1:4] || key[0:-3]
+ keycounts[key] +:= 1
+ idtable[name] := key || if keycounts[key] > 1 then "-" || keycounts[key] else ""
+ }
+ return idtable[name]
+end
+<<*>>=
+global thischunk
+
+procedure pass2(name, arg)
+ case name of {
+ "defn" : {
+ thischunk := arg
+ write("@defn ", arg, "~{\\footnotesize\\Rm\\subpageref{", defns[arg][1], "}}")
+ }
+ "use" :
+ write("@use ", arg, "~{\\footnotesize\\Rm\\subpageref{", (\defns[arg])[1], "}}") |
+ write("@use ", arg, "~{\\footnotesize\\Rm (never defined)}")
+ "end" : {
+ if match("code", arg) & not member(firstdefnout, thischunk) then {
+ insert(firstdefnout, thischunk)
+ if *defns[thischunk] > 1 then {
+ writes("@literal \\alsodefined{")
+ every i := 2 to *defns[thischunk] do
+ writes("\\\\{", defns[thischunk][i], "}")
+ write("}")
+ }
+ if \uses[thischunk] then {
+ writes("@literal \\used{")
+ every i := 1 to *uses[thischunk] do
+ writes("\\\\{", uses[thischunk][i], "}")
+ write("}")
+ } else write("@literal \\notused{", escapeTeXspecials(thischunk), "}")
+ }
+ write("@", name, " ", arg)
+ }
+ "text" : if \arg == "\\nowebchunks" then nowebchunks()
+ else write("@text", (" " || \arg) | "")
+ default : write("@", name, (" " || \arg) | "")
+ }
+ return
+end
+<<*>>=
+procedure nowebchunks()
+ l := sort(names,2)
+ while name := get(l)[1] do {
+ write("@literal {")
+ write("@use ", name, "~{\\footnotesize\\Rm\\subpageref{", (\defns[name])[1], "}}") |
+ write("@use ", name, "~{\\footnotesize\\Rm (never defined)}")
+ write("@literal }")
+ if *l > 0 then write("@literal \\\\")
+ }
+end
+<<*>>=
+procedure lettersonly(s)
+ static keep
+ initial keep := &lcase ++ ' '
+ s := map(s)
+ r := ""
+ s ? while tab(upto(keep)) do r ||:= move(1)
+ return r
+end
+<<*>>=
+procedure escapeTeXspecials(name)
+ name ? {
+ s := ""
+ while s ||:= tab(upto('{}$&%#^_~\\')) do s ||:= "\\" || move(1)
+ return s || tab(0)
+ }
+end
diff --git a/web/noweb/src/icon/nwl2h.nw b/web/noweb/src/icon/nwl2h.nw
new file mode 100644
index 0000000000..3dbc2e58ed
--- /dev/null
+++ b/web/noweb/src/icon/nwl2h.nw
@@ -0,0 +1,79 @@
+<<*>>=
+global show_unknowns
+
+procedure main(args)
+ local line
+ every arg := !args do
+ case arg of {
+ "-show-unknowns" : show_unknowns := 1
+ default : write(&errout, "l2h filter: unknown arg ", image(arg))
+ }
+ while line := read() do
+ apply(filter, line)
+ warn_unknown(unknown_set, "control sequences", "\\")
+ warn_unknown(unknown_envs, "environments", "{", "}")
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+<<*>>=
+global curfile, curline
+
+procedure filter(name, arg)
+ static S, C, code
+ initial { S := converter("V"); C := converter("H") }
+ case name of {
+ "begin" : {<<out>>; if match("code ", arg) then code := 1}
+ "end" : {<<out>>; code := &null; S.mode := "V"}
+ "quote" : {<<out>>; code := 1; stop_skipping(S)}
+ "endquote" : {<<out>>; code := &null}
+ "file" : {<<out>>; curfile := arg; curline := 1}
+ "line" : {<<out>>; curline := integer(arg)}
+ "defn" : { write("@", name, " ", "{" || arg || "}" ? convert(C)); reset(C) }
+ "use" : { write("@", name, " ", "{" || arg || "}" ? convert(C)); reset(C) }
+ "text" : {if \code then <<out>> else outtext(arg ? convert(S))}
+ "nl" : {if \code then <<out>> else outtext("\n" ? convert(S)); curline +:= 1}
+ default : {<<out>>}
+ }
+ return
+end
+<<out>>=
+write("@", name, (" " || \arg) | "")
+<<*>>=
+procedure outtext(s)
+ s ?
+ while not pos(0) do
+ if ="\n" then write("@nl")
+ else write("@text ", tab(upto('\n') | 0))
+ return
+end
+<<*>>=
+procedure warn_unknown(s, type, mark, rmark)
+ if *s > 0 then {
+ pushout("Unknown " || type || ": ")
+ every pushout(((\mark | "")\1) || !sort(s) || ((\rmark | "")\1) || " ")
+ pushout("\n")
+ }
+end
+<<*>>=
+procedure pushout(s)
+ static col
+ initial col := 0
+ if find("\n", s) then
+ s ? {
+ pushout(tab(upto('\n')))
+ while ="\n" do {col := 0; write(&errout)}
+ pushout(tab(0))
+ }
+ else {
+ col +:= *s
+ if col >= 79 then {writes(&errout, "\n "); col := *s + 2}
+ writes(&errout, s)
+ }
+ return
+end
+<<*>>=
+procedure error(args[])
+ return write!([&errout, (\curfile || ", ") | "", "line ", curline, ": "] ||| args)
+end
diff --git a/web/noweb/src/icon/pascaldefs.icn b/web/noweb/src/icon/pascaldefs.icn
new file mode 100644
index 0000000000..ccdd434ca2
--- /dev/null
+++ b/web/noweb/src/icon/pascaldefs.icn
@@ -0,0 +1,96 @@
+#line 2 "pascaldefs.nw"
+global showlocal
+procedure main(args)
+ showlocal := !args == "-local"
+ go()
+end
+#line 8 "pascaldefs.nw"
+procedure postpass(name, arg)
+ static kind
+ initial { kind := "bogus" }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if (optwhite(), =("function "|"procedure "), not hasword(arg, "forward")) then{
+ tab(many(' '))
+ writedefn(tab(upto(' ():;')))
+ } else if (optwhite(), x := allupper(), optwhite(), ="=") then {
+ writedefn(x)
+ }
+ }
+ return
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+
+procedure words()
+ static alnum
+ initial alnum := &letters ++ &digits ++ '_'
+ suspend if any(alnum) then tab(many(alnum))
+ else if pos(0) then fail
+ else if tab(upto(alnum)) then words()
+end
+
+procedure hasword(s, w)
+ suspend (tab(0) ? words()) == w
+end
+
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+
+procedure allupper()
+ static uppers
+ initial uppers := &ucase ++ &digits ++ '_'
+ suspend tab(many(uppers))
+end
+
+
+procedure rcsinfo ()
+ return "$Id: pascaldefs.nw,v 1.17 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+#line 1 "defns.nw"
+procedure go()
+ local line
+ while line := read() do {
+ apply(prepass, line)
+ write(line)
+ if match("@fatal ", line) then exit(1)
+ apply(postpass, line)
+ }
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+#line 18 "defns.nw"
+procedure writedefn(defn, locl)
+ static indextext
+ initial indextext := ""
+ if /defn then
+ *indextext > 0 &
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 23 "defns.nw"
+ else {
+ if *indextext + *defn > 65 then
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 25 "defns.nw"
+ write(if \locl then "@index localdefn " else "@index defn ", defn)
+ indextext ||:= " " || defn
+ }
+ return
+end
+#line 35 "defns.nw"
+procedure rcsinfo_too ()
+ return "$Id: defns.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/pascaldefs.nw b/web/noweb/src/icon/pascaldefs.nw
new file mode 100644
index 0000000000..04637bc3bf
--- /dev/null
+++ b/web/noweb/src/icon/pascaldefs.nw
@@ -0,0 +1,55 @@
+\section{Finding Pascal definitions}
+<<*>>=
+global showlocal
+procedure main(args)
+ showlocal := !args == "-local"
+ go()
+end
+<<*>>=
+procedure postpass(name, arg)
+ static kind
+ initial { kind := "bogus" }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if (optwhite(), =("function "|"procedure "), not hasword(arg, "forward")) then{
+ tab(many(' '))
+ writedefn(tab(upto(' ():;')))
+ } else if (optwhite(), x := allupper(), optwhite(), ="=") then {
+ writedefn(x)
+ }
+ }
+ return
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+
+procedure words()
+ static alnum
+ initial alnum := &letters ++ &digits ++ '_'
+ suspend if any(alnum) then tab(many(alnum))
+ else if pos(0) then fail
+ else if tab(upto(alnum)) then words()
+end
+
+procedure hasword(s, w)
+ suspend (tab(0) ? words()) == w
+end
+
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+
+procedure allupper()
+ static uppers
+ initial uppers := &ucase ++ &digits ++ '_'
+ suspend tab(many(uppers))
+end
+
+
+procedure rcsinfo ()
+ return "$Id: pascaldefs.nw,v 1.17 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/pdcached.icn b/web/noweb/src/icon/pdcached.icn
new file mode 100644
index 0000000000..e24102bce3
--- /dev/null
+++ b/web/noweb/src/icon/pdcached.icn
@@ -0,0 +1,238 @@
+#line 5 "pdcached.nw"
+procedure main(args)
+ cachename := get(args) | stop("pdcached: no cache")
+ if args[1] == "-nearcode" then
+ nearcode := get(args)
+ cmd := get(args) | stop("pdcached: no command")
+
+ cmd := "sed '/^@begin docs /s/[0-9][0-9]*/0/' | unmarkup | " || cmd ||
+ " | markup | grep -v '^@file $'"
+
+ last := &null
+ loadcache(cachename)
+
+ while line := read() do
+ {## write("====> process ", image(line), "; last = ", type(last),
+ ## "(", *\last | "?", "), lastcode = ", image(lastcode))
+ if match("@begin code ", line) then {
+ if type(last) == "list" then
+ pipeout(last, cmd)
+ last := "code"
+ until match("@end code ", line) do {
+ write(line)
+ line := read()
+ }
+ write(line)
+#write("******until completed with ", line)
+ } else if match("@begin docs ", line) then {
+ l := [line]
+ until match("@end docs ", line) do
+ put(l, line := read())
+#write("******until completed with ", line)
+ put(l, line)
+ if /nearcode then {
+ pipeout(l, cmd)
+ last := &null
+ } else if last === "code" & notblank(l) then {
+ pipeout(l, cmd)
+ every write("@begin docs 0" | "@nl" | "@end docs 0")
+ last := &null
+ } else {
+ last := l
+ }
+ } else {
+ write(line)
+ }
+ }
+ savecache(cachename)
+ return
+end
+
+#line 55 "pdcached.nw"
+procedure pipeout(lines, cmd)
+ local cached
+ static tmp
+ initial { tmp := "/tmp/pdcached.out"
+ hitcount := misscount := 0
+ }
+ cached := find_in_cache(lines)
+ if /cached then {
+ misscount +:= 1
+ f := open(cmd || " > " || tmp, "wp")
+ every write(f, !lines)
+ close(f)
+ f := open(tmp, "r")
+ cached := []
+ while put(cached, read(f))
+ close(f)
+ adjustblanks(lines, cached)
+ save_in_cache(lines, cached)
+ } else {
+ adjustblanks(lines, cached)
+ hitcount +:= 1
+ }
+ every write(!cached)
+ return
+end
+#line 84 "pdcached.nw"
+procedure adjustblanks(in, out)
+ if &fail & find("Applying a primitive", !in) then {
+ write(&errout, "For ", image(in[1]), "/", image(out[1]), ", notblank(in) = ",
+ image(notblank(in)) | "<failed>",
+ "; blankstring(out[1]) = ", image(blankstring(out[1])) | "<failed>")
+ every i := 1 to *in do write(&errout, " in[", i, "] = ", image( in[i]))
+ every i := 1 to *out do write(&errout, "out[", i, "] = ", image(out[i]))
+ }
+ if notblank(in) then
+ if notblank(out) then
+ &null # this is OK, so do nothing
+ else
+ remove_initial_blanks(out)
+ else # input begins with blanks
+ if notblank(out) then
+ insert_initial_newline(out)
+ else
+ &null # this is OK, so do nothing
+ return
+end
+
+procedure blankstring(s)
+ s ? { tab(many(' \t')); return pos(0) }
+end
+#line 110 "pdcached.nw"
+global cache, hitcount, misscount
+
+procedure strip_chunk_number(s)
+ s ?
+ if =("@" || ("begin" | "end") || " " || ("docs" | "code") || " ") then
+ return tab(1)
+ else
+ return s
+end
+
+procedure find_in_cache(lines)
+ c := cache
+ every l := strip_chunk_number(!lines) do
+ c := \c[l] | return &null
+ return c[&null]
+end
+
+procedure save_in_cache(lines, cached)
+ c := cache
+ i := 1
+ while l := strip_chunk_number(lines[i]) do {
+ /c[l] := table()
+ c := c[l]
+ i := i + 1
+ }
+ c[&null] := cached
+ return
+end
+
+link xcode
+
+procedure loadcache(cachename)
+ cache := xdecode(c := open(cachename)) | table()
+ close(\c)
+ return
+end
+
+link numbers
+
+procedure savecache(cachename)
+ write(&errout, "Cache misses ",
+ frn(real(misscount) * 100.0 / real(misscount + hitcount), 0, 1), "% of ",
+ misscount+hitcount, " queries")
+ if misscount = 0 then return
+ system("lockfile " || cachename || ".lock")
+ xencoden(cache, cachename || ".new")
+ rename(cachename || ".new", cachename) | stop("Could not update cache")
+ remove(cachename || ".lock")
+ return # forget the other!
+
+ c := open(cachename || ".fast", "w") | stop("cannot open fast cache")
+ wval(c, cache)
+ close(c)
+end
+#line 165 "pdcached.nw"
+procedure readval(f)
+ local stack
+ stack := []
+ while l := read(f) do
+ l ? case move(1) of {
+ "s" : push(stack, tab(0))
+ "l" : push(stack, [])
+ "t" : push(stack, table())
+ "n" : push(stack, &null)
+ "a" : { v := pop(stack); put(stack[1], v) }
+ "k" : { v := pop(stack); k := pop(stack); stack[1][k] := v }
+ }
+ return stack[1]
+end
+
+procedure wval(f, v)
+ return case type(v) of {
+ "string" : write(f, "s", v)
+ "list" : wlis (f, v)
+ "table" : wtab (f, v)
+ "null" : write(f, "n")
+ default : stop("writing unknown type")
+ }
+end
+
+procedure wlis(f, l)
+ write(f, "l")
+ every v := !l do {
+ wval(f, v); write(f, "a")
+ }
+ return
+end
+
+procedure wtab(f, t)
+ write(f, "t")
+ every k := key(t) do {
+ wval(f, k); wval(f, t[k]); write(f, "k")
+ }
+ return
+end
+#line 208 "pdcached.nw"
+procedure notblank(l)
+ every x := !l do
+ x ?
+ if ="@nl" & pos(0) then
+ fail
+ else if ="@text " & { tab(many(' \t')); not(pos(0)) } then
+ return x
+end
+#line 217 "pdcached.nw"
+procedure remove_initial_blanks(l)
+ p := []
+ while c := get(l) do
+ c ?
+ if ="@nl" | (="@text " & { tab(many(' \t')); pos(0) }) then {
+ &null # skip this baby
+ } else if =("@text" | "@end docs") then {
+ while push(l, pop(p))
+ return l
+ } else {
+ push(p, c)
+ }
+ while push(l, pop(p))
+ return l
+end
+#line 233 "pdcached.nw"
+procedure insert_initial_newline(l)
+ p := []
+ while c := get(l) do
+ if match("@text "|"@end docs", c) then {
+ push(l, c)
+ push(l, "@nl")
+ while push(l, pop(p))
+ return l
+ } else {
+ push(p, c)
+ }
+ push(l, "@nl")
+ while push(l, pop(p))
+ return l
+end
diff --git a/web/noweb/src/icon/pdcached.nw b/web/noweb/src/icon/pdcached.nw
new file mode 100644
index 0000000000..b85d3ff9aa
--- /dev/null
+++ b/web/noweb/src/icon/pdcached.nw
@@ -0,0 +1,248 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+This code pipes documentation chunks through a command.
+If given option [[-nearcode]], it pipes only documentation chunks that
+are next to code chunks; it drops all other documentation chunks.
+<<*>>=
+procedure main(args)
+ cachename := get(args) | stop("pdcached: no cache")
+ if args[1] == "-nearcode" then
+ nearcode := get(args)
+ cmd := get(args) | stop("pdcached: no command")
+
+ cmd := "sed '/^@begin docs /s/[0-9][0-9]*/0/' | unmarkup | " || cmd ||
+ " | markup | grep -v '^@file $'"
+
+ last := &null
+ loadcache(cachename)
+
+ while line := read() do
+ {## write("====> process ", image(line), "; last = ", type(last),
+ ## "(", *\last | "?", "), lastcode = ", image(lastcode))
+ if match("@begin code ", line) then {
+ if type(last) == "list" then
+ pipeout(last, cmd)
+ last := "code"
+ until match("@end code ", line) do {
+ write(line)
+ line := read()
+ }
+ write(line)
+#write("******until completed with ", line)
+ } else if match("@begin docs ", line) then {
+ l := [line]
+ until match("@end docs ", line) do
+ put(l, line := read())
+#write("******until completed with ", line)
+ put(l, line)
+ if /nearcode then {
+ pipeout(l, cmd)
+ last := &null
+ } else if last === "code" & notblank(l) then {
+ pipeout(l, cmd)
+ every write("@begin docs 0" | "@nl" | "@end docs 0")
+ last := &null
+ } else {
+ last := l
+ }
+ } else {
+ write(line)
+ }
+ }
+ savecache(cachename)
+ return
+end
+
+<<*>>=
+procedure pipeout(lines, cmd)
+ local cached
+ static tmp
+ initial { tmp := "/tmp/pdcached.out"
+ hitcount := misscount := 0
+ }
+ cached := find_in_cache(lines)
+ if /cached then {
+ misscount +:= 1
+ f := open(cmd || " > " || tmp, "wp")
+ every write(f, !lines)
+ close(f)
+ f := open(tmp, "r")
+ cached := []
+ while put(cached, read(f))
+ close(f)
+ adjustblanks(lines, cached)
+ save_in_cache(lines, cached)
+ } else {
+ adjustblanks(lines, cached)
+ hitcount +:= 1
+ }
+ every write(!cached)
+ return
+end
+@
+Make sure if it begins blank before processing, it begins blank after
+processing.
+<<*>>=
+procedure adjustblanks(in, out)
+ if &fail & find("Applying a primitive", !in) then {
+ write(&errout, "For ", image(in[1]), "/", image(out[1]), ", notblank(in) = ",
+ image(notblank(in)) | "<failed>",
+ "; blankstring(out[1]) = ", image(blankstring(out[1])) | "<failed>")
+ every i := 1 to *in do write(&errout, " in[", i, "] = ", image( in[i]))
+ every i := 1 to *out do write(&errout, "out[", i, "] = ", image(out[i]))
+ }
+ if notblank(in) then
+ if notblank(out) then
+ &null # this is OK, so do nothing
+ else
+ remove_initial_blanks(out)
+ else # input begins with blanks
+ if notblank(out) then
+ insert_initial_newline(out)
+ else
+ &null # this is OK, so do nothing
+ return
+end
+
+procedure blankstring(s)
+ s ? { tab(many(' \t')); return pos(0) }
+end
+@
+<<*>>=
+global cache, hitcount, misscount
+
+procedure strip_chunk_number(s)
+ s ?
+ if =("@" || ("begin" | "end") || " " || ("docs" | "code") || " ") then
+ return tab(1)
+ else
+ return s
+end
+
+procedure find_in_cache(lines)
+ c := cache
+ every l := strip_chunk_number(!lines) do
+ c := \c[l] | return &null
+ return c[&null]
+end
+
+procedure save_in_cache(lines, cached)
+ c := cache
+ i := 1
+ while l := strip_chunk_number(lines[i]) do {
+ /c[l] := table()
+ c := c[l]
+ i := i + 1
+ }
+ c[&null] := cached
+ return
+end
+
+link xcode
+
+procedure loadcache(cachename)
+ cache := xdecode(c := open(cachename)) | table()
+ close(\c)
+ return
+end
+
+link numbers
+
+procedure savecache(cachename)
+ write(&errout, "Cache misses ",
+ frn(real(misscount) * 100.0 / real(misscount + hitcount), 0, 1), "% of ",
+ misscount+hitcount, " queries")
+ if misscount = 0 then return
+ system("lockfile " || cachename || ".lock")
+ xencoden(cache, cachename || ".new")
+ rename(cachename || ".new", cachename) | stop("Could not update cache")
+ remove(cachename || ".lock")
+ return # forget the other!
+
+ c := open(cachename || ".fast", "w") | stop("cannot open fast cache")
+ wval(c, cache)
+ close(c)
+end
+<<*>>=
+procedure readval(f)
+ local stack
+ stack := []
+ while l := read(f) do
+ l ? case move(1) of {
+ "s" : push(stack, tab(0))
+ "l" : push(stack, [])
+ "t" : push(stack, table())
+ "n" : push(stack, &null)
+ "a" : { v := pop(stack); put(stack[1], v) }
+ "k" : { v := pop(stack); k := pop(stack); stack[1][k] := v }
+ }
+ return stack[1]
+end
+
+procedure wval(f, v)
+ return case type(v) of {
+ "string" : write(f, "s", v)
+ "list" : wlis (f, v)
+ "table" : wtab (f, v)
+ "null" : write(f, "n")
+ default : stop("writing unknown type")
+ }
+end
+
+procedure wlis(f, l)
+ write(f, "l")
+ every v := !l do {
+ wval(f, v); write(f, "a")
+ }
+ return
+end
+
+procedure wtab(f, t)
+ write(f, "t")
+ every k := key(t) do {
+ wval(f, k); wval(f, t[k]); write(f, "k")
+ }
+ return
+end
+@
+Manipulating docs chunks.
+<<*>>=
+procedure notblank(l)
+ every x := !l do
+ x ?
+ if ="@nl" & pos(0) then
+ fail
+ else if ="@text " & { tab(many(' \t')); not(pos(0)) } then
+ return x
+end
+<<*>>=
+procedure remove_initial_blanks(l)
+ p := []
+ while c := get(l) do
+ c ?
+ if ="@nl" | (="@text " & { tab(many(' \t')); pos(0) }) then {
+ &null # skip this baby
+ } else if =("@text" | "@end docs") then {
+ while push(l, pop(p))
+ return l
+ } else {
+ push(p, c)
+ }
+ while push(l, pop(p))
+ return l
+end
+<<*>>=
+procedure insert_initial_newline(l)
+ p := []
+ while c := get(l) do
+ if match("@text "|"@end docs", c) then {
+ push(l, c)
+ push(l, "@nl")
+ while push(l, pop(p))
+ return l
+ } else {
+ push(p, c)
+ }
+ push(l, "@nl")
+ while push(l, pop(p))
+ return l
+end
diff --git a/web/noweb/src/icon/pipedocs.icn b/web/noweb/src/icon/pipedocs.icn
new file mode 100644
index 0000000000..fc86e7a03b
--- /dev/null
+++ b/web/noweb/src/icon/pipedocs.icn
@@ -0,0 +1,65 @@
+#line 5 "pipedocs.nw"
+procedure main(args)
+ if args[1] == "-nearcode" then
+ nearcode := get(args)
+ cmd := get(args) | stop("pipedocs: no command")
+
+ cmd := "sed '/^@begin docs /s/[0-9][0-9]*/0/' | unmarkup | " || cmd ||
+ " | awk ' NR == 1 && /^[ \t]*$/ {next}\n{print}\n' | markup | grep -v '^@file $'"
+
+ last := &null
+
+ while line := read() do
+ {## write("====> process ", image(line), "; last = ", type(last),
+ ## "(", *\last | "?", "), lastcode = ", image(lastcode))
+ if match("@begin code ", line) then {
+ if type(last) == "list" then
+ pipeout(last, cmd)
+ last := "code"
+ until match("@end code ", line) do {
+ write(line)
+ line := read()
+ }
+ write(line)
+#write("******until completed with ", line)
+ } else if match("@begin docs ", line) then {
+ l := [line]
+ until match("@end docs ", line) do
+ put(l, line := read())
+#write("******until completed with ", line)
+ put(l, line)
+ if /nearcode then {
+ pipeout(l, cmd)
+ last := &null
+ } else if last === "code" & notblank(l) then {
+ pipeout(l, cmd)
+ every write("@begin docs 0" | "@nl" | "@end docs 0")
+ last := &null
+ } else {
+ last := l
+ }
+ } else {
+ write(line)
+ }
+ }
+ return
+end
+
+#line 52 "pipedocs.nw"
+procedure pipeout(lines, cmd)
+ f := open(cmd, "wp")
+ every write(f, !lines)
+ return close(f)
+end
+
+#line 59 "pipedocs.nw"
+procedure notblank(l)
+ every x := !l do
+ x ?
+ if ="@nl" & pos(0) then
+ fail
+ else if ="@text " & { tab(many(' \t')); not(pos(0)) } then
+ return x
+end
+
+
diff --git a/web/noweb/src/icon/pipedocs.nw b/web/noweb/src/icon/pipedocs.nw
new file mode 100644
index 0000000000..bc2ac8df5d
--- /dev/null
+++ b/web/noweb/src/icon/pipedocs.nw
@@ -0,0 +1,69 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+This code pipes documentation chunks through a command.
+If given option [[-nearcode]], it pipes only documentation chunks that
+are next to code chunks; it drops all other documentation chunks.
+<<*>>=
+procedure main(args)
+ if args[1] == "-nearcode" then
+ nearcode := get(args)
+ cmd := get(args) | stop("pipedocs: no command")
+
+ cmd := "sed '/^@begin docs /s/[0-9][0-9]*/0/' | unmarkup | " || cmd ||
+ " | awk ' NR == 1 && /^[ \t]*$/ {next}\n{print}\n' | markup | grep -v '^@file $'"
+
+ last := &null
+
+ while line := read() do
+ {## write("====> process ", image(line), "; last = ", type(last),
+ ## "(", *\last | "?", "), lastcode = ", image(lastcode))
+ if match("@begin code ", line) then {
+ if type(last) == "list" then
+ pipeout(last, cmd)
+ last := "code"
+ until match("@end code ", line) do {
+ write(line)
+ line := read()
+ }
+ write(line)
+#write("******until completed with ", line)
+ } else if match("@begin docs ", line) then {
+ l := [line]
+ until match("@end docs ", line) do
+ put(l, line := read())
+#write("******until completed with ", line)
+ put(l, line)
+ if /nearcode then {
+ pipeout(l, cmd)
+ last := &null
+ } else if last === "code" & notblank(l) then {
+ pipeout(l, cmd)
+ every write("@begin docs 0" | "@nl" | "@end docs 0")
+ last := &null
+ } else {
+ last := l
+ }
+ } else {
+ write(line)
+ }
+ }
+ return
+end
+
+<<*>>=
+procedure pipeout(lines, cmd)
+ f := open(cmd, "wp")
+ every write(f, !lines)
+ return close(f)
+end
+
+<<*>>=
+procedure notblank(l)
+ every x := !l do
+ x ?
+ if ="@nl" & pos(0) then
+ fail
+ else if ="@text " & { tab(many(' \t')); not(pos(0)) } then
+ return x
+end
+
+
diff --git a/web/noweb/src/icon/promeladefs.icn b/web/noweb/src/icon/promeladefs.icn
new file mode 100644
index 0000000000..183e53d16b
--- /dev/null
+++ b/web/noweb/src/icon/promeladefs.icn
@@ -0,0 +1,97 @@
+#line 2 "promeladefs.nw"
+global showlocal
+procedure rcsinfo ()
+ return "$Id: promeladefs.nw,v 1.17 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+procedure main(args)
+ showlocal := !args == "-local"
+ go()
+end
+#line 12 "promeladefs.nw"
+procedure postpass(name, arg)
+ static kind, mtype
+ initial { kind := "bogus" }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if \mtype then
+ mtype := write_mtypes()
+ else if (optwhite(), =("proctype "|"chan ")) then {
+ tab(many(' '))
+ writedefn(tab(upto(' ():;')))
+ } else if (optwhite(), ="mtype", optwhite(), ="{") then
+ mtype := write_mtypes()
+ }
+ return
+end
+
+procedure write_mtypes()
+ static start, alnum
+ initial { start := &letters ++ '/,}'; alnum := &letters ++ &digits ++ '_' }
+ optwhite()
+ while any(start) do {
+ if ="/*" then tab(upto("*/") | 0)
+ else if ="," then &null
+ else if ="}" then return &null
+ else if any(alnum) then writedefn(tab(many(alnum)))
+ else if pos(0) then return 1
+ else if ="/" then return &null
+ else { write(&errout, "bad mtype ", tab(0)); return &null }
+ optwhite();
+ }
+ return if pos(0) then 1 else &null
+end
+
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+
+
+#line 1 "defns.nw"
+procedure go()
+ local line
+ while line := read() do {
+ apply(prepass, line)
+ write(line)
+ if match("@fatal ", line) then exit(1)
+ apply(postpass, line)
+ }
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+#line 18 "defns.nw"
+procedure writedefn(defn, locl)
+ static indextext
+ initial indextext := ""
+ if /defn then
+ *indextext > 0 &
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 23 "defns.nw"
+ else {
+ if *indextext + *defn > 65 then
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 25 "defns.nw"
+ write(if \locl then "@index localdefn " else "@index defn ", defn)
+ indextext ||:= " " || defn
+ }
+ return
+end
+#line 35 "defns.nw"
+procedure rcsinfo_too ()
+ return "$Id: defns.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/promeladefs.nw b/web/noweb/src/icon/promeladefs.nw
new file mode 100644
index 0000000000..cda5d81336
--- /dev/null
+++ b/web/noweb/src/icon/promeladefs.nw
@@ -0,0 +1,56 @@
+\section{Finding Promela definitions}
+<<*>>=
+global showlocal
+procedure rcsinfo ()
+ return "$Id: promeladefs.nw,v 1.17 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+procedure main(args)
+ showlocal := !args == "-local"
+ go()
+end
+<<*>>=
+procedure postpass(name, arg)
+ static kind, mtype
+ initial { kind := "bogus" }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if \mtype then
+ mtype := write_mtypes()
+ else if (optwhite(), =("proctype "|"chan ")) then {
+ tab(many(' '))
+ writedefn(tab(upto(' ():;')))
+ } else if (optwhite(), ="mtype", optwhite(), ="{") then
+ mtype := write_mtypes()
+ }
+ return
+end
+
+procedure write_mtypes()
+ static start, alnum
+ initial { start := &letters ++ '/,}'; alnum := &letters ++ &digits ++ '_' }
+ optwhite()
+ while any(start) do {
+ if ="/*" then tab(upto("*/") | 0)
+ else if ="," then &null
+ else if ="}" then return &null
+ else if any(alnum) then writedefn(tab(many(alnum)))
+ else if pos(0) then return 1
+ else if ="/" then return &null
+ else { write(&errout, "bad mtype ", tab(0)); return &null }
+ optwhite();
+ }
+ return if pos(0) then 1 else &null
+end
+
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+
+
diff --git a/web/noweb/src/icon/sl2h.icn b/web/noweb/src/icon/sl2h.icn
new file mode 100644
index 0000000000..22a571c534
--- /dev/null
+++ b/web/noweb/src/icon/sl2h.icn
@@ -0,0 +1,2167 @@
+#line 217 "l2h.nw"
+procedure star(cs)
+ suspend cs | (cs || "*")
+end
+#line 596 "l2h.nw"
+procedure asciiCharCode(S)
+ return emit_text(S, char(2(optwhite(), TeXnumber(), optwhite())))
+end
+procedure TeXnumber()
+ return integer(
+ (="'", "8r" || tab(many(&digits))) |
+ (="\"", "16r" || tab(many(&digits))) |
+ tab(many(&digits)))
+end
+#line 671 "l2h.nw"
+procedure convert(S, optstring)
+ static specials
+ initial {
+
+#line 819 "l2h.nw"
+activetab := table(unknown_cs)
+activeclosure := table()
+#line 969 "l2h.nw"
+cstab := table(unknown_cs)
+csclosure := table()
+#line 987 "l2h.nw"
+unknown_set := set()
+#line 1015 "l2h.nw"
+every begintab | endtab := table(unknown_env)
+every begincl | endcl := table()
+#line 1028 "l2h.nw"
+unknown_envs := set()
+#line 1381 "l2h.nw"
+liststack := []
+# write(&errout, "Initialized liststack")
+suspendstack := []
+#line 1961 "l2h.nw"
+countertab := table()
+#line 1969 "l2h.nw"
+accent_name := table()
+accent_valid := table('')
+accent_name ["`"] := "grave"
+accent_valid["`"] := 'AEIOUaeiou'
+accent_name ["'"] := "acute"
+accent_valid["'"] := 'AEIOUYaeiouy'
+accent_name ["^"] := "circ"
+accent_valid["^"] := 'AEIOUaeiou'
+accent_name ["hat"] := "circ"
+accent_valid["hat"] := 'AEIOUaeiou'
+accent_name ["\""] := "uml"
+accent_valid["\""] := 'AEIOUaeiouy'
+accent_name ["~"] := "tilde"
+accent_valid["~"] := 'ANOano'
+accent_name ["="] := "bar"
+accent_name ["."] := "dot"
+accent_name ["u"] := "u"
+accent_name ["v"] := "v"
+accent_name ["H"] := "H"
+accent_name ["t"] := "t"
+accent_name ["c"] := "cedil"
+accent_valid["c"] := 'Cc'
+accent_name ["d"] := "underdot"
+accent_name ["b"] := "underbar"
+#line 2675 "l2h.nw"
+csfunctions := table()
+#line 675 "l2h.nw"
+
+#line 114 "l2h.nw"
+substitution(",", " ")
+substitution(" ", " ")
+substitution("\n", "\n")
+substitution("\t", " ")
+ignore("raggedright")
+ignore("@")
+ignore("/") # no italic correction
+substitution("", "\n") # \<newline> treated as request for newline
+every c := !"$%#{}_" do
+ substitution(c, c)
+substitution("&", "&amp;")
+argblock("emph", "em")
+every argblock("footnote" | "footnotetext" | "thanks",
+ " <b>[</b>", "<b>]</b> ") # put footnotes in bold brackets
+substitution("today", &date)
+#line 132 "l2h.nw"
+ignore("textrm") # html can't switch to default font!
+argblock("textit", "i")
+argblock("textbf", "b")
+argblock("textsl", "i")
+ignore("textsc")
+argblock("texttt", "tt")
+ignore("textsf")
+ignore("boldmath")
+# \boldmath could be done by introducing S.mathfont, but I don't want to!
+#line 142 "l2h.nw"
+ignore("mathrm") # html can't switch to default font!
+argblock("mathit", "i")
+argblock("mathbf", "b")
+argblock("mathtt", "tt")
+ignore("mathsf")
+argblock("mathcal", "i")
+every ignore("scriptstyle"|"displaystyle"|"scriptscriptstyle")
+every ignore("mathord"|"mathbin"|"mathrel")
+#line 152 "l2h.nw"
+every ignore("tiny" | "scriptsize" | "footnotesize" | "small" | "normalsize" |
+ "large" | "Large" | "LARGE" | "huge" | "Huge")
+#line 160 "l2h.nw"
+every accent(key(accent_name))
+every ignore("dag" | "ddag")
+substitution("S", "&sect;")
+substitution("P", "&para;")
+substitution("copyright", "&copy;")
+substitution("pounds", "&pound;")
+substitution("o", "&oslash;")
+substitution("O", "&Oslash;")
+substitution("aa", "&aring;")
+substitution("AA", "&Aring;")
+substitution("ae", "&aelig;")
+substitution("AE", "&Aelig;")
+#line 175 "l2h.nw"
+argblockv("part", "h1", &null, "*[")
+argblockv("chapter", "h1", &null, "*[")
+argblockv("section", "h2", &null, "*[")
+argblockv("subsection", "h3", &null, "*[")
+argblockv("subsubsection", "h4", &null, "*[")
+argblockv("paragraph", "h5", &null, "*[")
+argblockv("subparagraph", "h6", &null, "*[")
+ignore("appendix")
+auxfile("tableofcontents", "toc",
+ "<p>\n<tableofcontents>\n<b>[Table of contents]</b>\n</tableofcontents>\n<p>",
+ "<h2>Table of Contents</h2>\n<tableofcontents>\n", "\n</tableofcontents>\n")
+cstab["tableofcontents"] := Ctableofcontents # override to call set_toclevel
+ignore("listoftables")
+ignore("listoffigures")
+ignore("addtocontents", "{{")
+ignoreenv("filecontents", "{")
+#line 198 "l2h.nw"
+cstab["("] := Cmath
+cstab[")"] := Cmath_end
+cstab["["] := Cdisplaymath
+cstab["]"] := Cdisplaymath_end
+ignoreenv("equation")
+every table_env(star("eqnarray"), 0, " ", "<blockquote><i>", "</i></blockquote>")
+ # also lame
+substitution("frac", "<b>frac</b>")
+substitution("sqrt", "<b>frac</b>")
+every substitution("ldots" | "cdots" | "vdots", "...")
+ignore("left")
+ignore("right")
+ignore("overline")
+substitution(":", " ")
+substitution(";", " ")
+ignore("!")
+#line 223 "l2h.nw"
+substitution("Diamond", "&lt;&gt;")
+substitution("langle", "&lt;")
+substitution("rangle", "&gt;")
+substitution("le", "&lt;=")
+substitution("ne", "!=")
+substitution("ge", "&gt;=")
+substitution("times", "&times;")
+substitution("divide", "&divide;")
+substitution("bmod", "</i>mod<i>") # better hook in with math
+substitution("equiv", "===")
+every x := "arccos" | "arcsin" | "arctan" | "arg" | "cos" | "cosh" |
+ "cot" | "coth" | "csc" | "deg" | "det" | "dim" | "exp" |
+ "gcd" | "hom" | "lim" | "liminf" | "limsup" | "ln" | "log" |
+ "max" | "min" | "sec" | "sin" | "sinh" | "sup" | "tan" | "tanh"
+do
+ substitution(x, "</i>" || x || "<i>")
+substitution("liminf", "</i>lim inf<i>")
+substitution("limsup", "</i>lim sup<i>")
+every x := "alpha" | "beta" | "gamma" | "delta" | "epsilon" | "zeta" | "eta" |
+ "theta" | "iota" | "kappa" | "lambda" | "nu" | "xi" | "pi" |
+ "rho" | "sigma" | "tau" | "upsilon" | "phi" | "chi" | "psi" | "omega" |
+ "in"
+do
+ substitution(x, "<b>" || x || "</b>")
+substitution("mu", "&micro;")
+every x := "Gamma" | "Delta" | "Theta" | "Lambda" | "Xi" | "Pi" | "Sigma" |
+ "Upsilon" | "Phi" | "Psi" | "Omega"
+do
+ substitution(x, "<b>" || x || "</b>")
+#line 255 "l2h.nw"
+substitution("lfloor", "</i>|_<i>")
+substitution("rfloor", "</i>_|<i>")
+substitution("leq", "&lt;=")
+substitution("geq", "&gt;=")
+substitution("ll", "&laquo;")
+substitution("gg", "&raquo;")
+substitution("Rightarrow", "==&gt;")
+substitution("rightarrow", "--&gt;")
+substitution("approx", "<u>~</u>")
+#line 268 "l2h.nw"
+envblock("quote", "blockquote")
+envblock("quotation", "blockquote")
+envblock("center", "blockquote")
+envblock("flushleft", "blockquote")
+envblock("flushright", "blockquote")
+envblock("verse", "blockquote")
+verbatim("verbatim", escape_HTML_specials, "pre")
+cstab["verb"] := Cverb
+cstab["verb*"] := Cverb
+csclosure["verb*"] := 1
+cstab["verbatiminput"] := Cverbatiminput
+csclosure["verbatiminput"] := verbatim_cl(escape_HTML_specials)
+#line 284 "l2h.nw"
+cstab["item"] := Citem
+csclosure["item"] := [item_cl("<li>", "", "<li>")]
+listenv("itemize", "ul")
+listenv("enumerate", "ol")
+listenv("description", "dl")
+#line 292 "l2h.nw"
+ignore("documentstyle", "[{")
+ignore("documentclass", "[{")
+ignore("usepackage", "[{")
+ignore("pagestyle", "{")
+ignore("thispagestyle", "{")
+ignore("pagenumbering", "{")
+ignore("newcounter", "{")
+ignore("global")
+ignore("etalchar") # used in the .bbl files: \newcommand{\etalchar}[1]{$^{#1}$}
+#line 307 "l2h.nw"
+argblockv("title", "h1")
+argblockv("author","address")
+argblockv("date", "b")
+substitution("maketitle", "<!--title goes here-->")
+ignoreenv("titlepage")
+envblock("abstract", "<h2>Abstract</h2><blockquote>", "</blockquote>")
+#line 322 "l2h.nw"
+cstab["label"] := Clabel
+cstab["ref"] := Cref
+cstab["pageref"] := Cref
+cstab["subpageref"] := Cref
+cstab["chunklabel"] := Clabel
+#line 332 "l2h.nw"
+ignore("bibliographystyle", "{")
+auxfile("bibliography", "bbl", "<b>[BibTeX bibliography]</b>", &null, &null, "{")
+envblock("thebibliography", "<h2>References</h2>", "", "{")
+every cstab["cite" | "citeN" | "opencite" | "openciteN" | "citeyear"] := Ccite
+cstab["bibitem"] := Cbibitem
+ignore("newblock")
+ignore("nocite", "{")
+#line 343 "l2h.nw"
+every ignore("input" | "include" | "includeonly", "{")
+# filecontents not done yet
+#line 348 "l2h.nw"
+cstab["\\"] := Cbackback
+substitution("linebreak", "<br>")
+ignore("-")
+ignoreenv("sloppypar")
+ignore("sloppy")
+#line 357 "l2h.nw"
+substitution("pagebreak", "<hr>")
+substitution("newpage", "<hr>")
+substitution("clearpage", "<hr>")
+ignore("enlargethispage", "*{")
+#line 364 "l2h.nw"
+ignore("mbox")
+ignore("makebox", "([[") # ( comes from picture area
+ignore("fbox")
+ignore("framebox", "[[") # could insert horizontal rules, but why?
+ignore("newsavebox", 1)
+ignore("sbox", 2)
+ignore("savebox", "{[[{")
+ignore("usebox", 1)
+envblock("minipage", "blockquote", &null, "[{")
+argblock("parbox", "blockquote", &null, "[{")
+#line 377 "l2h.nw"
+ignore("hspace", "*{")
+ignore("hfil")
+ignore("hfill")
+ignore("vspace", "*{")
+ignore("vfil")
+ignore("vfill")
+#line 386 "l2h.nw"
+ignore("newlength", "{")
+ignore("setlength", "{{")
+ignore("addtolength", "{{")
+#line 392 "l2h.nw"
+envblock("picture", "<b>[picture]</b>", "", "((")
+ignore("put", "({")
+ignore("multiput", "(({{")
+ignore("dashbox", "{([")
+ignore("line", "({")
+ignore("vector", "({")
+ignore("shortstack", "[")
+ignore("circle", "*{")
+ignore("oval", "([")
+ignore("frame")
+ignore("thinlines")
+ignore("thicklines")
+#line 408 "l2h.nw"
+every envblock(star("figure"), "<hr>", "<hr>", "[")
+every envblock(star("table"), "<hr>", "<hr>", "[")
+argblock("caption", "b") # captions in bold
+#line 415 "l2h.nw"
+envblock("tabbing", "blockquote")
+# \= is accent
+ignore(">")
+ignore("+")
+ignore("kill")
+#line 423 "l2h.nw"
+tabular("array", "[")
+tabular("tabular", "[")
+tabular("tabularx", "{[")
+tabular("tabular*", "{[")
+every cstab["multicolumn"|"multispan"] := Cmulticolumn
+cstab["span"] := Cspan
+cstab["noalign"] := Cnoalign
+cstab["hline"] := Chline
+cstab["toprule"] := Chline
+cstab["midrule"] := Chline
+cstab["bottomrule"] := Chline
+ignore("cline", "{")
+ignore("newcolumntype", "{{")
+#line 439 "l2h.nw"
+ignore("newcommand", "A[[{")
+ignore("renewcommand", "A[[{")
+ignore("providecommand", "A[[{")
+ignore("newenvironment", "{[{{")
+ignore("renewenvironment", "{[{{")
+ignore("newtheorem", "{{")
+#line 450 "l2h.nw"
+cstab["setcounter"] := Csetcounter
+ignore("addtocounter", "{{")
+#line 455 "l2h.nw"
+cstab["makeatletter"] := Cmakeatletter
+cstab["makeatother"] := Cmakeatother
+#line 460 "l2h.nw"
+every fontchange("tt" | "ttfamily", "tt")
+every fontchange("bf" | "bfseries", "b")
+every fontchange("it" | "itshape", "i")
+fontchange("sl", "i")
+fontchange("em", "em")
+ignore("rm") # html can't switch to default font!
+ignore("sf")
+ignore("sc")
+#line 470 "l2h.nw"
+ignore("rmfamily")
+ignore("normalfont")
+#line 473 "l2h.nw"
+ignoreenv("document")
+#line 475 "l2h.nw"
+substitution("LaTeX", "LaTeX")
+#line 477 "l2h.nw"
+ignore("numberline", "{")
+ignore("protect")
+ignore("onecolumn")
+ignore("twocolumn", "C")
+ignore("typeout", "[{")
+ignore("closedbib")
+#line 484 "l2h.nw"
+every ignore("leftmargini" | "leftmarginii" | "labelsep" | "fboxsep", "=")
+every ignore("tabcolsep", "=")
+every ignore("evensidemargin" | "marginparsep" | "marginparwidth" |
+ "oddsidemargin" | "textheight" | "textwidth" | "topmargin", "=")
+#line 489 "l2h.nw"
+ignore("DeclareMathVersion", "{")
+ignore("mathversion", "{")
+ignore("setpapersize", "{")
+ignore("setmarginsrb", "{{{{{{{{")
+ignore("marginparwidth", "=")
+ignore("marginparsep", "=")
+#line 498 "l2h.nw"
+ignoreenv("multicols", "{C")
+cstab["citeN"] := Ccite
+ignore("afterpage", "{")
+every cstab["psfig"|"epsfig"] := Cepsfig
+cstab["includegraphics"] := Cincludegraphics
+ignore("newcolumntype", "{{")
+#line 507 "l2h.nw"
+cstab["kill"] := Ckill
+#line 511 "l2h.nw"
+activesubst("~", "&nbsp;")
+argblock("centerline", "<br>", "<br>")
+substitution("cr", "<br>")
+substitution("hrule", "<hr>")
+substitution("vrule", "|")
+substitution("hrulefill", "------")
+ignore("hyphenation", "{")
+ignore("hbox")
+ignore("rlap")
+ignore("llap")
+ignore("vbox")
+ignore("vtop")
+ignore("hidewidth")
+ignore("message", "{")
+ignore("relax")
+ignore("null")
+ignore("offinterlineskip")
+ignore("omit")
+ignore("newdimen", "{")
+ignore("nobreak")
+#line 532 "l2h.nw"
+cstab["par"] := implicit_paragraph
+cstab["smallskip"] := implicit_paragraph
+cstab["medskip"] := implicit_paragraph
+cstab["bigskip"] := implicit_paragraph
+cstab["vskip"] := implicit_paragraph
+csclosure["vskip"] := "="
+#line 544 "l2h.nw"
+every ignore("begingroup" | "endgroup" | "bgroup" | "egroup")
+#line 546 "l2h.nw"
+cstab["newif"] := Cnewif
+cstab["iffalse"] := Ciffalse
+cstab["iftrue"] := Ciftrue
+cstab["ifhtml"] := Ciftrue # false in LaTeX, but true when converting!
+cstab["else"] := Celse
+cstab["fi"] := Cfi
+cstab["ifx"] := cstab["if"] := cstab["ifnum"] := Ciffalse
+#line 556 "l2h.nw"
+ignore("let", "A=")
+every ignore("hfuzz" | "parindent" | "parskip" | "baselineskip", "=")
+every ignore("hbadness" | "hsize" | "vsize" | "overfullrule" | "tabskip", "=")
+every ignore("extrarowheight" | "codemargin", "=")
+every ignore("looseness", "=")
+substitution("hskip", " ", "=")
+ignore("setbox", "{=")
+every ignore("box" | "unhbox" | "unvbox", "{")
+#line 565 "l2h.nw"
+ignore("unskip")
+ignore("hss")
+ignore("phantom", "{")
+every ignore("kern" | "lower" | "spacefactor", "=") # a cheat, but works
+every ignore("clubpenalty" | "widowpenalty", "=")
+#line 578 "l2h.nw"
+every ignore("expandafter" | "indent" | "noindent" | "leavevmode" | "strut")
+ignore("def", 1)
+#line 581 "l2h.nw"
+substitution("TeX", "TeX")
+substitution("BibTeX", "BibTeX")
+substitution("MF", "METAFONT")
+#line 594 "l2h.nw"
+cstab["char"] := asciiCharCode
+#line 608 "l2h.nw"
+macro("nwanchorto", 2, "<a href=\"#$1\">#2</a>")
+macro("nwanchorname", 2, "<a name=\"#$1\">#2</a>")
+ignore("nwaddbox", "{")
+verbatim("latexonly", do_nothing)
+verbatim("rawhtml", emit_text)
+#line 617 "l2h.nw"
+substitution("quad", " ")
+#line 624 "l2h.nw"
+ignore("noweboptions", 1)
+#line 630 "l2h.nw"
+substitution("nowebindex", "<nowebindex>")
+substitution("nowebchunks", "<nowebchunks>")
+ignore("nowebsize")
+#line 634 "l2h.nw"
+envblock("fields", "blockquote", &null, "[") # lame; could try to <tt> 1st col
+envblock("fields*", "blockquote", &null, "{") # lame; could try to <tt> 1st col
+ignore("citeauthoryear", "{{{")
+ignore("authoryear", "{{")
+substitution("bibrule", "--------")
+let("bibskip", "par")
+every cstab["anoncite"|"authorcite"] := Ccite
+#line 644 "l2h.nw"
+ignore("pssilent")
+ignore("psnoisy")
+#line 1012 "l2h.nw"
+cstab["begin"] := do_begin
+cstab["end"] := do_end
+#line 1385 "l2h.nw"
+cstab["suspend"] := Csuspend
+cstab["resume"] := Cresume
+#line 1603 "l2h.nw"
+cstab["uppercase"] := Cuppercase
+#line 1899 "l2h.nw"
+cstab["contentsline"] := Ccontentsline
+#line 676 "l2h.nw"
+
+#line 2677 "l2h.nw"
+csfunctions["argblock"] := argblock
+csfunctions["argblockv"] := argblockv
+csfunctions["envblock"] := envblock
+csfunctions["fontchange"] := fontchange
+csfunctions["ignore"] := ignore
+csfunctions["ignoreenv"] := ignoreenv
+csfunctions["let"] := let
+csfunctions["letenv"] := letenv
+csfunctions["listenv"] := listenv
+csfunctions["substitution"] := substitution
+csfunctions["activesubst"] := activesubst
+csfunctions["closure"] := let_closure
+csfunctions["let_closure"] := let_closure
+csfunctions["newcommand"] := l2h_macro
+csfunctions["macro"] := l2h_macro
+csfunctions["environment"] := l2h_environment
+csfunctions["tabular"] := tabular
+#line 677 "l2h.nw"
+ specials := '\\{}<>-\'`"%$&~\n\0\1'
+ }
+
+ if \optstring then return optstring ? convert(S)
+ else {
+
+#line 867 "l2h.nw"
+l := S.newtext
+S.newtext := []
+while c := get(l) do
+ c.proc!c.args
+#line 700 "l2h.nw"
+if S.mode == "V" & any(~'\\{}<>%\n\t ') then S.mode := "H"
+emit_text(S, tab(upto(specials) | 0))
+while not pos(0) do
+ if S.mode == "Q" then { # quoting
+ emit_text(S, tab(upto('\1') | 0))
+ if ="\1" then {
+ emit_text(S, "\1")
+ S.mode := S.quotemode
+ }
+ } else {
+ if any(S.activechars) then
+ do_activechar(S, move(1))
+ else
+ case move(1) of {
+ "\\" : {
+#line 941 "l2h.nw"
+cs := if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1)
+if /S.ignoring | cs == ("else"|"fi") | cstab[cs] === (Ciffalse|Ciftrue) then
+ do_cs(S, cs)
+else
+ &null # error("### Ignoring \\", cs)
+#line 714 "l2h.nw"
+ }
+ "{" : {
+#line 915 "l2h.nw"
+push(S.closes, []) # fresh set of closing tasks
+while c := get(S.open) do
+ c.proc!c.args
+#line 715 "l2h.nw"
+ }
+ "}" : {
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 716 "l2h.nw"
+ }
+ "%" : {
+#line 1066 "l2h.nw"
+parse_dynamic_add(S)
+delay_newtext(S)
+eat_comment(S)
+#line 717 "l2h.nw"
+ }
+ "\n" : {
+#line 1313 "l2h.nw"
+emit_text(S, "\n")
+if /S.ignoring then Cnewline(S)
+#line 718 "l2h.nw"
+ }
+ "$" : {
+#line 1301 "l2h.nw"
+if /S.ignoring then
+ if ="$" then
+ if S.mode == "M" then { Cdisplaymath_end(S); S.mode := "V" }
+ else { Cdisplaymath(S); S.mode := "M" }
+ else
+ if S.mode == "M" then { Cmath_end(S); S.mode := "H" }
+ else { Cmath(S); S.mode := "M" }
+#line 719 "l2h.nw"
+ }
+ "&" : ampersand(S)
+ "\0" : {S.quotemode := S.mode; S.mode := "Q"; emit_text(S, "\0")}
+ # remaining cases simply escape HTML specials
+ "<" : emit_text(S, "&lt;")
+ ">" : emit_text(S, "&gt;")
+ "\"" : emit_text(S, "&quot;")
+ "-" : {
+#line 735 "l2h.nw"
+if S.mode == "V" then S.mode := "H"
+if S.mode == "H" then
+ if ="--" then emit_text(S, "&mdash;")
+ else if ="-" then emit_text(S, "&ndash;")
+ else emit_text(S, "-")
+else
+ emit_text(S, "-")
+#line 726 "l2h.nw"
+ }
+ "`" : {
+#line 746 "l2h.nw"
+if S.mode == "V" then S.mode := "H"
+if \html_quotes & S.mode == "H" then
+ if ="`" then emit_text(S, "&ldquo;")
+ else emit_text(S, "&lsquo;")
+else
+ emit_text(S, "`")
+#line 727 "l2h.nw"
+ }
+ "'" : {
+#line 753 "l2h.nw"
+if S.mode == "V" then S.mode := "H"
+if \html_quotes & S.mode == "H" & ="'" then emit_text(S, "&rdquo;")
+else emit_text(S, "'")
+#line 728 "l2h.nw"
+ }
+ }
+ if S.mode == "V" & any(~'\\{}<>%\n\t ') then S.mode := "H"
+ emit_text(S, tab(upto(specials++S.activechars) | 0))
+ }
+return 1(. S.the_text, S.the_text := "") # what's been converted
+#line 683 "l2h.nw"
+ }
+end
+#line 744 "l2h.nw"
+global html_quotes # render quotes as HTML 4 entities
+#line 760 "l2h.nw"
+record state(mode, quotemode
+#line 788 "l2h.nw"
+, text, the_text
+#line 804 "l2h.nw"
+, ignoring
+#line 822 "l2h.nw"
+, activechars
+#line 844 "l2h.nw"
+, newtext
+#line 887 "l2h.nw"
+, delayed_newtext
+#line 897 "l2h.nw"
+, open, closes
+#line 949 "l2h.nw"
+, csletters
+#line 1082 "l2h.nw"
+, comment
+#line 1521 "l2h.nw"
+, ifstack
+#line 1628 "l2h.nw"
+, tables
+#line 760 "l2h.nw"
+ )
+ # mode is Q, H, V, or M
+ # quotemode is saved mode: H, V, or M
+#line 766 "l2h.nw"
+procedure converter(mode)
+ /mode := "V"
+ return state(mode, mode
+#line 790 "l2h.nw"
+, accumulate_text, ""
+#line 806 "l2h.nw"
+, &null
+#line 824 "l2h.nw"
+, '~'
+#line 846 "l2h.nw"
+, []
+#line 889 "l2h.nw"
+, []
+#line 899 "l2h.nw"
+, [], []
+#line 951 "l2h.nw"
+, &letters
+#line 1084 "l2h.nw"
+, ""
+#line 1523 "l2h.nw"
+, []
+#line 1630 "l2h.nw"
+, []
+#line 768 "l2h.nw"
+ )
+end
+#line 774 "l2h.nw"
+procedure reset(S)
+
+#line 792 "l2h.nw"
+S.text := accumulate_text
+S.the_text := ""
+#line 808 "l2h.nw"
+S.ignoring := &null
+#line 826 "l2h.nw"
+S.activechars := '~'
+#line 848 "l2h.nw"
+S.newtext := []
+#line 891 "l2h.nw"
+S.delayed_newtext := []
+#line 901 "l2h.nw"
+every S.open | S.closes := []
+#line 953 "l2h.nw"
+S.csletters := &letters
+#line 1086 "l2h.nw"
+S.comment := ""
+#line 1525 "l2h.nw"
+if *S.ifstack > 0 then S.ifstack := [] # keeps GC down
+#line 1632 "l2h.nw"
+S.tables := []
+#line 776 "l2h.nw"
+ return S
+end
+#line 783 "l2h.nw"
+procedure accumulate_text(S, text)
+ S.the_text ||:= text
+ return
+end
+#line 800 "l2h.nw"
+procedure emit_text(S, text)
+ return if \S.ignoring then "" else S.text(S, text)
+end
+#line 813 "l2h.nw"
+global activetab, activeclosure
+procedure do_activechar(S, c)
+ (activetab[c])(S, c, activeclosure[c])
+ return
+end
+#line 852 "l2h.nw"
+record closure(proc, args)
+#line 857 "l2h.nw"
+procedure before_next_newtext(S, proc, args)
+ push(S.newtext, closure(proc, args))
+end
+
+procedure after_next_newtext(S, proc, args)
+ put(S.newtext, closure(proc, args))
+end
+#line 876 "l2h.nw"
+procedure delay_newtext(S)
+ push(S.delayed_newtext, S.newtext)
+ S.newtext := []
+ return
+end
+
+procedure undelay_newtext(S)
+ S.newtext := \pop(S.delayed_newtext) |
+ {write(&errout, "This can't happen: no delayed_newtext"); &null[0]}
+end
+#line 903 "l2h.nw"
+procedure after_next_open(S, proc, args)
+ return put(S.open, closure(proc, args))
+end
+
+procedure before_next_close(S, proc, args)
+ return push(S.closes[1], closure(proc, args)) # lost at top level
+end
+
+procedure after_next_close(S, proc, args)
+ return put(S.closes[1], closure(proc, args)) # lost at top level
+end
+#line 960 "l2h.nw"
+global cstab, csclosure
+
+procedure do_cs(S, cs)
+ tab(many(' \t')) # skip white space following CS
+ if pos(0) | any('\n') then before_next_newtext(S, skipblanks, [S])
+ (cstab[cs])(S, cs, csclosure[cs])
+ return
+end
+#line 976 "l2h.nw"
+global show_unknowns
+procedure unknown_cs(S, cs, cl)
+# if S.text === ignore_text then return # a bit of a hack -- should no longer be needed
+ if \show_unknowns then S.text(S, "<b>\\" || cs || "</b>")
+ if not member(unknown_set, cs) then {
+ write(\unknown_file, "Warning: unknown control sequence \\", cs)
+ insert(unknown_set, cs)
+ }
+ return
+end
+#line 989 "l2h.nw"
+global cstab, csclosure, unknown_set
+#line 995 "l2h.nw"
+global begintab, endtab, begincl, endcl
+
+procedure do_begin(S, cs, cl)
+ (="{", env := tab(upto('}')), ="}") | error("botched \\begin{...}")
+
+#line 915 "l2h.nw"
+push(S.closes, []) # fresh set of closing tasks
+while c := get(S.open) do
+ c.proc!c.args
+#line 1000 "l2h.nw"
+ (begintab[env])(S, env, begincl[env])
+ return
+end
+
+procedure do_end(S, cs, cl)
+ (="{", env := tab(upto('}')), ="}") | error("botched \\end{...}")
+ # write(&errout, "calling ", image(endtab[env]), " for \\end{", env, "}")
+ (endtab[env])(S, env, endcl[env])
+
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 1009 "l2h.nw"
+ return
+end
+#line 1018 "l2h.nw"
+procedure unknown_env(S, env, cl)
+### if S.text === ignore_text then return # a bit of a hack # no longer needed
+ if \show_unknowns then S.text(S, "<b>{" || env || "}</b>")
+ if not member(unknown_envs, env) then {
+ write(\unknown_file, "Warning: unknown environment {", env, "}")
+ insert(unknown_envs, env)
+ }
+ return
+end
+#line 1030 "l2h.nw"
+global unknown_envs
+#line 1034 "l2h.nw"
+procedure warn_unknown(s, type, mark, rmark)
+ if *s > 0 then {
+ pushout("Unknown " || type || ": ")
+ every pushout(((\mark | "")\1) || !sort(s) || ((\rmark | "")\1) || " ")
+ pushout("\n")
+ }
+end
+#line 1042 "l2h.nw"
+procedure pushout(s)
+ static col
+ initial col := 0
+ if find("\n", s) then
+ s ? {
+ pushout(tab(upto('\n')))
+ while ="\n" do {col := 0; write(&errout)}
+ pushout(tab(0))
+ }
+ else {
+ col +:= *s
+ if col >= 79 then {writes(&errout, "\n "); col := *s + 2}
+ writes(&errout, s)
+ }
+ return
+end
+#line 1070 "l2h.nw"
+procedure eat_comment(S)
+ S.comment ||:= tab(upto('\n') | 0)
+ if pos(0) then
+ before_next_newtext(S, eat_comment, [S])
+ else {
+ undelay_newtext(S)
+ Ccomment(S)
+ S.comment := ""
+ }
+ return
+end
+#line 1106 "l2h.nw"
+record verbatim_cl(output, terminator, html, translate_blank)
+
+procedure verbatim(name, output, html)
+ begintab[name] := Cverbatim
+ begincl [name] := verbatim_cl(output, &null, html)
+ return
+end
+
+procedure Cverbatim(S, cs, cl)
+ if cl === begincl[cs] & /cl.terminator then
+ cl := begincl[cs] :=
+ verbatim_cl(cl.output, "\\end{" || cs || "}", cl.html, cl.translate_blank)
+ emit_text(S, tag(\cl.html))
+ delay_newtext(S)
+ do_verbatim(S, cl)
+ return
+end
+#line 1128 "l2h.nw"
+procedure do_verbatim(S, cl)
+ if cl.output(S, tab(find(cl.terminator)), cl) then {
+ =cl.terminator
+ emit_text(S, endtag(\cl.html))
+ undelay_newtext(S)
+ } else {
+ cl.output(S, tab(0), cl)
+ before_next_newtext(S, do_verbatim, [S, cl])
+ }
+ return
+end
+#line 1142 "l2h.nw"
+procedure escape_HTML_specials(S, s, cl)
+ s ? {
+ while emit_text(S, tab(upto('&<>" '))) do
+ case move(1) of {
+ "\"" : emit_text(S, "&quot;")
+ "&" : emit_text(S, "&amp;")
+ "<" : emit_text(S, "&lt;")
+ ">" : emit_text(S, "&gt;")
+ " " : emit_text(S, if \cl.translate_blank then "&middot;" else " ")
+ }
+ emit_text(S, tab(0))
+ }
+ return
+end
+#line 1160 "l2h.nw"
+procedure Cverb(S, cs, cl)
+ Cverbatim(S, cs, verbatim_cl(escape_HTML_specials, move(1), "tt", cl))
+ return
+end
+#line 1166 "l2h.nw"
+procedure Cverbatiminput(S, cs, cl)
+ local filename, f, line
+ if ="{" & filename := tab(upto('}')) & ="}" then {
+ f := \open(filename) | { emit_text(S, "<strong>Could not read file</strong> <tt>")
+ escape_HTML_specials(S, filename, cl)
+ emit_text(S, "</tt>")
+ return
+ }
+ emit_text(S, "\n<pre>\n")
+ while line := read(f) do {
+ escape_HTML_specials(S, line, cl)
+ emit_text(S, "\n")
+ }
+ emit_text(S, "</pre>\n")
+ close(f)
+ }
+ return
+end
+#line 1190 "l2h.nw"
+procedure csarg(S)
+ return 2(="{", tab(bal('}', '{', '}')), ="}") |
+ (optwhite(),
+ if ="\\" then
+ "\\" || (tab(many(S.csletters)) | move(1))
+ else
+ move(1))
+end
+#line 1225 "l2h.nw"
+procedure apply_args(S, p, as, args_wanted)
+ delay_newtext(S)
+ do_apply_args(S, closure(p, as), args_wanted, [], "", 0)
+ return
+end
+
+procedure do_apply_args(S, cl, wanted_count, args_seen, current_arg, brace_depth)
+ local open_comment
+ # invariant : we have an open brace
+# pushtrace("APPLY")
+ while *args_seen < wanted_count & not pos(0) do {
+ while *args_seen < wanted_count & brace_depth = 0 & not pos(0) do {
+ tab(many(' \t\n'))
+ case c := move(1) of {
+ "\\" : put(args_seen, "\\" ||
+ if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1))
+ "{" : { current_arg := "" ; brace_depth := 1 }
+ "}" : { error("Insufficient arguments to macro ", macro.name) }
+ "%" : if tab(upto('\n')) then ="\n" else open_comment := tab(0)
+ default : put(args_seen, c)
+ }
+ }
+ while brace_depth > 0 & not pos(0) do {
+ current_arg ||:= tab(upto('\\{}%') | 0)
+ case move(1) of {
+ "%" : if tab(upto('\n')) then ="\n" else open_comment := tab(0)
+ "\\" : current_arg ||:= "\\" ||
+ if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1)
+ "{" : { current_arg ||:= "{" ; brace_depth +:= 1 }
+ "}" : { brace_depth -:= 1
+ if brace_depth > 0 then
+ current_arg ||:= "}"
+ else {
+ put(args_seen, current_arg)
+ current_arg := ""
+ }
+ }
+ }
+ }
+ }
+ if *args_seen = wanted_count then {
+ undelay_newtext(S)
+ cl.proc ! (cl.args ||| args_seen)
+ } else if \open_comment then {
+ delay_newtext(S)
+ before_next_newtext(S, skip_comment_and_continue,
+ [S, closure(do_apply_args, [S, cl, wanted_count, args_seen,
+ current_arg, brace_depth])])
+ } else
+ before_next_newtext(S, do_apply_args, [S, cl, wanted_count, args_seen,
+ current_arg, brace_depth])
+# poptrace()
+ return
+end
+#line 1284 "l2h.nw"
+procedure skip_comment_and_continue(S, cl)
+ tab(upto('\n') | 0)
+ if pos(0) then
+ before_next_newtext(S, skip_comment_and_continue, [S, cl])
+ else {
+ ="\n"
+ undelay_newtext(S)
+# <take actions appropriate to new text>>
+ }
+ return
+end
+#line 1316 "l2h.nw"
+procedure Cnewline(S)
+ tab(many(' \t'))
+ if match("\n") then implicit_paragraph(S)
+ if pos(0) then before_next_newtext(S, Cnewline, [S])
+end
+#line 1325 "l2h.nw"
+procedure skipblanks(S)
+ tab(many(' \t'))
+ if ="\n" then Cnewline(S)
+ else if pos(0) then before_next_newtext(S, skipblanks, [S])
+end
+#line 1334 "l2h.nw"
+procedure implicit_paragraph(S, cs, cl)
+ if S.mode ~== "V" then {
+ S.mode := "V"
+ Cparagraph(S)
+ }
+ cs_ignore(S, cs, \cl)
+end
+#line 1347 "l2h.nw"
+procedure stop_skipping(S)
+ while S.newtext[1].proc === (Cnewline|skipblanks) do pop(S.newtext)
+end
+#line 1357 "l2h.nw"
+record item_cl(before, after, ifnone)
+
+procedure Citem(S, cs, cl)
+ if pos(0) then
+ after_next_newtext(S, Citem, [S, cs, cl])
+ else if ="[" then {
+ delay_newtext(S)
+ with_upto_bracket(S, "", convert_bracketed, cl)
+ } else {
+ skipblanks(S)
+ emit_text(S, cl[1].ifnone)
+ \liststack[1] := \liststack[1] + 1
+ }
+end
+#line 1372 "l2h.nw"
+procedure convert_bracketed(S, contents, cl)
+ emit_text(S, cl[1].before ||
+ convert(converter("H"), "{" || contents || "}") ||
+ cl[1].after)
+ optwhite()
+end
+#line 1379 "l2h.nw"
+global liststack, suspendstack
+#line 1388 "l2h.nw"
+procedure listenv(env, html)
+ begintab[env] := Clist
+ begincl[env] := html
+ endtab[env] := Clist_end
+ endcl[env] := html
+end
+
+procedure push_item_closure(cs)
+ push(csclosure["item"],
+ if cs == "description" then item_cl("<dt>", "<dd>", "<dt><dd>")
+ else item_cl("<li>", "--", "<li>"))
+end
+
+procedure Clist(S, cs, cl)
+ push(liststack, 1)
+ push_item_closure(cs)
+ emit_text(S, tag(cl))
+end
+
+procedure Cresume(S, cs, cl)
+ local n, env
+ (="{", env := tab(upto('}')), ="}") | error("botched \\resume{...}")
+ n := pop(suspendstack) | error("\\resume not balanced by corresponding \\suspend")
+ push(liststack, n)
+ push_item_closure(env)
+ if env == "enumerate" then
+ emit_text(S, tag(begincl[env] || " start=\"" || n || "\""))
+ else
+ emit_text(S, tag(begincl[env]))
+end
+
+procedure Clist_end(S, cs, cl)
+ emit_text(S, endtag(cl))
+ pop(csclosure["item"])
+ pop(liststack)
+end
+
+procedure Csuspend(S, cs, cl)
+ local env
+ (="{", env := tab(upto('}')), ="}") | error("botched \\suspend{...}")
+ emit_text(S, endtag(endcl[env]))
+ pop(csclosure["item"])
+ push(suspendstack, pop(liststack))
+end
+#line 1437 "l2h.nw"
+global labels_seen
+
+procedure Clabel(S, cs, cl)
+ initial /labels_seen := set()
+ insert(labels_seen, l := csarg(S)) | fail
+ emit_text(S, "<a name=\"" || l || "\"><b>[*]</b></a>")
+end
+
+procedure Cref(S, cs, cl)
+ local prefix, prefix_tag
+ initial /labels_seen := set()
+ prefix_tag := (\cl)[1] | ""
+ prefix := (\cl)[2] | ""
+ l := prefix || csarg(S) | fail
+ emit_text(S, prefix_tag || "<a href=\"#" || l || "\">[" ||
+ (if member(labels_seen, l) then "&lt;-" else "-&gt;") || "]</a>")
+end
+#line 1463 "l2h.nw"
+procedure Ccite(S, cs, cl, bracketed_text)
+ if ="[" then {
+ delay_newtext(S)
+ with_upto_bracket(S, "", do_cite, cl)
+ } else
+ do_cite(S, &null, cl)
+end
+
+procedure do_cite(S, commentary, cl)
+ local key
+ if \commentary then
+ optwhite()
+ if pos(0) then before_next_newtext(S, do_cite, [S, commentary, cl])
+ else {
+ key := csarg(S)
+ \commentary := convert(converter("H"), "{" || \commentary || "}")
+ emit_text(S, "<b>[cite&nbsp;")
+ key ? {
+ while k := tab(upto(",")) & ="," do
+ emit_text(S, "<a href=\"#NWcite-" || k || "\">" || k || "</a>, ")
+ if k := tab(0) then
+ emit_text(S, "<a href=\"#NWcite-" || k || "\">" || k || "</a>")
+ }
+ emit_text(S, ", <i>" || \commentary || "</i>")
+ emit_text(S, "]</b>")
+ }
+end
+#line 1491 "l2h.nw"
+procedure Cbibitem(S, cs, cl)
+ local label, key
+ static counter
+ initial counter := 0
+ if ="[" then {
+ delay_newtext(S)
+ with_upto_bracket(S, "", finish_bibitem, [])
+ } else {
+ label := "<b>[" || (counter +:= 1) || "]</b>"
+ apply_args(S, do_bibitem_key, [S, label], 1)
+ }
+end
+
+procedure do_bibitem_key(S, label, key)
+ return emit_text(S, "<a name=\"NWcite-" || key || "\">" || label || "</a> ")
+end
+
+procedure finish_bibitem(S, contents, args)
+ local key, label
+ optwhite()
+ label := convert(converter("H"), "{" || contents || "}")
+ key := apply_args(S, do_bibitem_key, [S, label], 1)
+end
+#line 1529 "l2h.nw"
+record ifrec(on_else, on_fi)
+#line 1538 "l2h.nw"
+procedure Ciffalse(S, cs, cl)
+#error("### \\", cs, " -> false (S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)}, ")")
+ push(S.ifstack, ifrec(S.ignoring, S.ignoring))
+ S.ignoring := 1
+end
+
+procedure Ciftrue(S, cs, cl)
+#error("### \\", cs, " -> true (S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)}, ")")
+ push(S.ifstack, ifrec(1, S.ignoring))
+end
+
+procedure Celse(S, cs, cl)
+ S.ignoring := S.ifstack[1].on_else
+#error("### \\else -> S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)})
+end
+
+procedure Cfi(S, cs, cl)
+ S.ignoring := S.ifstack[1].on_fi
+#error("### \\fi -> S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)})
+ pop(S.ifstack)
+end
+#line 1563 "l2h.nw"
+procedure Cnewif(S, cs, cl)
+ local newif, newcs
+ tab(many(' \t\n'))
+ if pos(0) then
+ after_next_newtext(S, Cnewif, [S, cs, cl])
+ else {
+ newif := csarg(S)
+ newif ?
+ if ="\\if" & newcs := tab(many(S.csletters)) & pos(0) then {
+
+#line 1580 "l2h.nw"
+cstab[newcs || "false"] := Csetif
+cstab[newcs || "true"] := Csetif
+cstab["if" || newcs] := Ciffalse
+#line 1573 "l2h.nw"
+ } else
+ error("\\newif argument botch: " || newif)
+ }
+end
+#line 1584 "l2h.nw"
+procedure Csetif(S, cs, cl)
+ local base, tag
+ if cs ? (base := tab(find("true"|"false")), tag := =("true"|"false"), pos(0)) then {
+ cstab["if" || base] := if tag == "true" then Ciftrue else Ciffalse
+ } else {
+ error("This can't happen --- setif botch (not urgent)")
+ }
+end
+#line 1598 "l2h.nw"
+procedure Cuppercase(S, cs, cl)
+ l := map(csarg(S), &lcase, &ucase) | fail
+ emit_text(S, l)
+end
+#line 1613 "l2h.nw"
+record table_info(index, # number of this cell in the row
+ alignment, # the alignment of this cell
+ width, # how many columns this cell will span
+ alignments, # default alignments for this table
+ brace_depth, # size of S.closes after start of cell
+ cell_text) # value of S.text to use to scan this cell
+#line 1637 "l2h.nw"
+procedure start_table_cell(S, text)
+ local this, attributes
+
+ text ? {
+ tab(many(' \t\n'))
+ if pos(0) then return
+ }
+# write(&errout, "starting cell with ", image(text))
+
+ this := S.tables[1] | fatal("starting cell with no current table")
+ S.text := this.cell_text
+
+if /(\this).brace_depth then write(&errout, "starting table cell, ", image(this), " has null brace depth")
+ # use this to start the current cell
+ if this.index = 1 then emit_text(S, "<tr>")
+ attributes := \this.alignment | aligneq("top")
+ if this.width > 1 then attributes ||:= " colspan=" || this.width
+ emit_text(S, "<td" || attributes || ">")
+
+ # now update state for the next cell
+ this.index +:= this.width # advance to next cell
+ this.alignment := this.alignments[this.index] | &null
+ this.width := 1
+ # can't set cell_text until we hit &
+
+
+#line 915 "l2h.nw"
+push(S.closes, []) # fresh set of closing tasks
+while c := get(S.open) do
+ c.proc!c.args
+#line 1663 "l2h.nw"
+ emit_text(S, text)
+ return
+end
+#line 1670 "l2h.nw"
+procedure ampersand(S)
+ local this
+ this := S.tables[1]
+
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 1674 "l2h.nw"
+ if /this then
+ emit_text(S, " --- ")
+ else {
+ emit_text(S, "") # be sure cell gets started, even if empty
+ emit_text(S, "</td>")
+ if S.text ~=== start_table_cell then
+ this.cell_text := S.text
+ S.text := start_table_cell
+ this.brace_depth := *S.closes + 1 # will open at start of cell
+#write(&errout, "set brace depth for ", image(this))
+ }
+ tab(many(' \t\n'))
+## write(&errout, " past &, text = ", image(S.text), ", next = ",
+## image(&subject[&pos:0]))
+ return
+end
+#line 1699 "l2h.nw"
+procedure Cbackback(S, cs, cl)
+ local this
+ this := S.tables[1]
+ cs_ignore(S, cs, "[", Cbackback_continue, [S, this])
+end
+
+procedure Cbackback_continue(S, this)
+#if /(\this).brace_depth then write(&errout, image(this), " has null brace depth")
+ if /this | *S.closes > this.brace_depth then { # ordinary \\
+ S.text(S, "<br>")
+ } else { # row terminator
+## write(&errout, "ending row with ", image(&subject[&pos:0]))
+ emit_text(S, "") # be sure cell gets started, even if empty
+
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 1713 "l2h.nw"
+ emit_text(S, "</td></tr>\n")
+ tab(many(' \t\n'))
+ if S.text ~=== start_table_cell then
+ this.cell_text := S.text
+ this.index := 1
+ this.alignment := this.alignments[this.index] | &null
+ this.width := 1
+ S.text := start_table_cell
+ this.brace_depth := *S.closes + 1 # about to open
+ }
+end
+#line 1727 "l2h.nw"
+procedure Chline(S, cs, cl)
+ if \S.tables[1] then return
+ else emit_text(S, "<hr>")
+ return
+end
+#line 1737 "l2h.nw"
+procedure Ctabular_end(S, cs, cl)
+ local this
+ if S.text ~=== start_table_cell | S.tables[1].index > 1 then {# row in progress
+ emit_text(S, "") # be sure cell gets started, even if empty
+
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 1742 "l2h.nw"
+ emit_text(S, "</td></tr>")
+ }
+ if S.text === start_table_cell then # abort it
+ S.text := S.tables[1].cell_text
+ emit_text(S, "</table>")
+ xxx := pop(S.tables)
+#write(&errout, "popped ", image(xxx))
+ return
+end
+#line 1754 "l2h.nw"
+procedure Ctabular(S, cs, cl)
+ cs_ignore(S, cs, cl, Ctabular_continue, [S])
+ return
+end
+
+procedure Ctabular_continue(S)
+ a := csarg() # alignment
+#write(&errout, "Alignment ", a)
+ emit_text(S, if upto('|', a) then "<table border>" else "<table>")
+ emit_text(S, "<!-- alignment is " || a || "-->")
+ a := alignments(a)
+ emit_text(S, "<!-- " || *a || " columns-->")
+ push(S.tables, table_info(1, a[1] | "l", 1, a, *S.closes+1, S.text))
+#write(&errout, "pushed ", image(S.tables[1]))
+ S.text := start_table_cell
+ optwhite()
+ return
+end
+#line 1777 "l2h.nw"
+procedure tabular(env, ignore)
+ begintab[env] := Ctabular
+ begincl[env] := ignore
+ endtab[env] := Ctabular_end
+ endcl[env] := ignore
+end
+#line 1786 "l2h.nw"
+procedure aligneq(a)
+ return " align=\"" || a || "\""
+end
+
+procedure valigneq(a)
+ return " valign=\"" || a || "\""
+end
+
+procedure alignments(s)
+ a := []
+ s ? {
+ while not pos(0) do
+ case move(1) of {
+ "l" | "X" | "Y" | "p" :
+ { put(a, aligneq("left") || valigneq("top")); skip_bracket() }
+ "c" : put(a, aligneq("center"))
+ "r" : put(a, aligneq("right"))
+ "m" : { put(a, aligneq("left") || valigneq("center")); skip_bracket() }
+ "b" : { put(a, aligneq("left") || valigneq("bottom")); skip_bracket() }
+ "@" | "<" | ">" | "!" : skip_bracket()
+ "|" : &null
+ default : &null # unrecognized...
+ }
+ }
+ return a
+end
+#line 1813 "l2h.nw"
+procedure skip_bracket()
+ if ="{" then {
+ n := 1
+ while n > 0 & not pos(0) do {
+ tab(upto('{}\\') | 0)
+ case move(1) of {
+ "{" : n +:= 1
+ "}" : n -:= 1
+ "\\" : move(1)
+ }
+ }
+ }
+ return
+end
+#line 1831 "l2h.nw"
+procedure Cmulticolumn(S, cs, cl)
+ local this
+ this := S.tables[1]
+ n := integer(csarg()) | error("\\multicolumn or \\multispan not followed by integer")
+ if cs == "multicolumn" then a := alignments(csarg())
+# write(&errout, "\\", cs, " n = ", n, ", a = ", (\a)[1] | "???",
+# ", text = ", image(S.text))
+ if /this then return # \multicolumn without table?
+ this.width := n
+ this.alignment := (\a)[1]
+ return
+end
+
+procedure Cspan(S, cs, cl)
+ (\S.tables[1]).width +:= 1
+ return
+end
+#line 1850 "l2h.nw"
+procedure Cnoalign(S, cs, cl)
+ apply_args(S, finish_noalign, [S], 1)
+ return
+end
+
+procedure finish_noalign(S, arg)
+ return if \S.ignoring then "" else
+ accumulate_text(S, "<br>" || convert(converter("V"), "{" || arg || "}") || "<br>")
+end
+#line 1862 "l2h.nw"
+procedure auxfile(cs, ext, placeholder, header, trailer, ignore)
+ cstab[cs] := Cauxfile
+ csclosure[cs] := aux_cl(ext, placeholder, header, trailer, \ignore | "")
+end
+#line 1869 "l2h.nw"
+record aux_cl(ext, placeholder, header, trailer, ignore)
+
+procedure Cauxfile(S, cs, cl)
+ local auxfile, T
+ if auxfile := open(basename(\curfile) || "." || cl.ext) then {
+ T := converter("V")
+ Cmakeatletter(T)
+ S.text(S, \cl.header)
+ while line := read(auxfile) do
+ S.text(S, convert(T, line || "\n"))
+ close(auxfile)
+ S.text(S, \cl.trailer)
+ } else {
+ S.text(S, \cl.placeholder)
+ }
+ cs_ignore(S, cs, cl.ignore)
+ if \auxfile then return
+end
+#line 1888 "l2h.nw"
+procedure basename(name)
+ reverse(name) ? {
+ tab(upto('.')) & ="."
+ return reverse(tab(0))
+ }
+end
+#line 1901 "l2h.nw"
+procedure Ctableofcontents(S, cs, cl)
+ S.mode := "V"
+ Cauxfile(S, cs, cl)
+ set_toclevel(S)
+end
+#line 1910 "l2h.nw"
+procedure set_toclevel(S, l)
+ static toclevel, initiallevel
+ if /initiallevel := \l then
+ S.text(S, "<ul compact>")
+ if /l := \initiallevel then
+ S.text(S, "</ul>")
+ if /l then return # never set a level
+ /toclevel := l
+ while toclevel < l do {
+ S.text(S, "<ul compact>")
+ toclevel +:= 1
+ }
+ while toclevel > l do {
+ S.text(S, "</ul>")
+ toclevel -:= 1
+ }
+ return
+end
+#line 1931 "l2h.nw"
+procedure Ccontentsline(S, cs, cl)
+ local type, level
+ static leveltab
+ initial {
+#line 1945 "l2h.nw"
+l := ["part", "chapter", "section", "subsection", "subsubsection",
+ "paragraph", "subparagraph"]
+leveltab := table()
+every i := 1 to *l do
+ leveltab[l[i]] := i - 2 # making section level 1
+#line 1934 "l2h.nw"
+ }
+ l := \leveltab[csarg()] | fail
+ if l > \countertab["tocdepth"] then
+ cs_ignore(S, cs, "{{") # skip this one
+ else {
+ set_toclevel(S, l)
+ S.text(S, "<li>")
+ after_next_open(S, after_next_close, [S, cs_ignore, [S, cs, "{"]])
+ }
+end
+#line 1953 "l2h.nw"
+global countertab
+
+procedure Csetcounter(S, cs, cl)
+ local counter
+ (counter := csarg(), countertab[counter] := integer(csarg())) |
+ cs_ignore(S, cs, "{{")
+end
+#line 1967 "l2h.nw"
+global accent_name, accent_valid
+#line 1998 "l2h.nw"
+procedure accent(cs)
+ cstab[cs] := Caccent
+end
+
+procedure Caccent(S, cs, cl)
+ static warned
+ initial warned := table()
+ arg := csarg(S) | return
+ if arg == "\\i" then arg := "i"
+ if arg == "\\j" then arg := "j"
+ if *arg = 1 & any(accent_valid[cs], arg) then
+ S.text(S, "&" || arg || accent_name[cs] || ";")
+ else {
+
+#line 2016 "l2h.nw"
+/warned[cs] := set()
+if not member(warned[cs], arg) then {
+ write(&errout, "Warning: Can't handle \\", cs, " with arg `", arg, "'")
+ insert(warned[cs], arg)
+}
+#line 2012 "l2h.nw"
+ S.text(S, arg)
+ }
+end
+#line 2026 "l2h.nw"
+procedure fontchange(tex, html)
+ cstab[tex] := Cfontchange
+ csclosure[tex] := html
+end
+#line 2031 "l2h.nw"
+procedure Cfontchange(S, tex, html)
+ S.text(S, tag(html))
+ before_next_close(S, emit_text, [S, endtag(html)])
+end
+#line 2051 "l2h.nw"
+procedure ignore(cs, template)
+ /template := ""
+ cstab[cs] := cs_ignore
+ csclosure[cs] := template
+end
+
+procedure ignoreenv(env, template)
+ /template := ""
+ begintab[env] := cs_ignore
+ begincl[env] := template
+ endtab[env] := do_nothing
+end
+#line 2070 "l2h.nw"
+procedure cs_ignore(S, cs, template, proc, args)
+ local saved_ignore
+ saved_ignore := S.ignoring
+ S.ignoring := 1
+ if type(template) == "integer" then template := repl("{", template)
+ return do_ignore(S, template, saved_ignore, proc, args)
+end
+#line 2084 "l2h.nw"
+procedure do_ignore(S, template, saved_ignore, proc, args)
+ if *template > 0 then
+ if optwhite() & pos(0) then
+ after_next_newtext(S, do_ignore, [S, template, saved_ignore, proc, args])
+ else
+ case template[1] of {
+ "{" : { S.ignoring := 1
+ after_next_open(S, ignore_til_close,
+ [S, template[2:0], saved_ignore, proc, args])
+ }
+ "A" : { csarg(S) # had better be in one input
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ }
+ "[" : if optwhite() & ="[" then {
+ delay_newtext(S)
+ with_upto_bracket(S, "", ignore_bracket_plus,
+ [S, template[2:0], saved_ignore, proc, args])
+ } else
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ "C" : # a total cheat, means ``copy optional arg''
+ if optwhite() & ="[" then {
+ S.ignoring := &null
+ delay_newtext(S)
+ with_upto_bracket(S, "", copy_bracket_plus,
+ [S, template[2:0], saved_ignore, proc, args])
+ } else
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ "=" : { delay_newtext(S)
+ eat_assignment(S, do_ignore, [S, template[2:0], saved_ignore, proc,args])
+ }
+ "*" : { (="*", optwhite())
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ }
+ "(" : { (="(", tab(upto(')')), =")", optwhite())
+ do_ignore(S, template[2:0], saved_ignore, proc, args)
+ }
+ }
+ else {
+ S.ignoring := saved_ignore
+ (\proc)!(\args)
+ }
+end
+
+procedure ignore_til_close(S, template, saved_ignore, proc, args)
+ before_next_close(S, do_ignore, [S, template, saved_ignore, proc, args])
+end
+#line 2133 "l2h.nw"
+procedure do_nothing(S, cs, cl)
+ return
+end
+#line 2144 "l2h.nw"
+procedure with_upto_bracket(S, bracketed_text, proc, args)
+ bracketed_text ||:= tab(upto(']') | 0)
+ if pos(0) then
+ before_next_newtext(S, with_upto_bracket, [S, bracketed_text, proc, args])
+ else {
+ ="]"
+ undelay_newtext(S)
+ (\proc)(S, bracketed_text, args)
+ }
+ return
+end
+#line 2158 "l2h.nw"
+procedure ignore_bracket_plus(S, contents, args)
+ # contents are ignored
+ do_ignore!args
+end
+#line 2164 "l2h.nw"
+procedure copy_bracket_plus(S, contents, args)
+ local should_ignore
+ should_ignore := args[3] | fail # saved_ignore arg to do_ignore
+ if /should_ignore then
+ S.text(S, convert(converter("H"), "{" || contents || "}"))
+ do_ignore!args
+end
+#line 2177 "l2h.nw"
+procedure eat_assignment(S, proc, args)
+ static decimal_chars, hex_chars, oct_chars
+ initial {
+ decimal_chars := &digits ++ '.,+-'
+ hex_chars := &digits ++ 'abcdefABCDEF'
+ oct_chars := '0124567'
+ }
+ optwhite()
+ ="=" # so what if we swallow multiple = signs
+ optwhite()
+ if pos(0) then {
+ before_next_newtext(S, eat_assignment, [S, proc, args])
+ return
+ } else if glue() then { # finished
+ } else if any(decimal_chars) then {
+ tab(many(decimal_chars))
+ optwhite()
+ if ="\\" then
+ tab(many(S.csletters)) | move(1)
+ # else assume assignment of the form \hangafter=2
+ } else if ="\"" then {
+ tab(many(hex_chars)) & optwhite()
+ } else if ="\'" then {
+ tab(many(oct_chars)) & optwhite()
+ } else if =("\\"|"`\\") then
+ tab(many(S.csletters)) | move(1)
+ undelay_newtext(S)
+ (\proc)!args
+end
+#line 2207 "l2h.nw"
+procedure dimen()
+ static decimal_chars
+ initial decimal_chars := &digits ++ '.,'
+ suspend (optwhite(),
+ if any('+-') then (move(1), optwhite()) else "",
+ tab(many(decimal_chars)), optwhite(),
+ (="true", optwhite()) | &null,
+ =("em"|"ex"|"pt"|"pc"|"in"|"bp"|"cm"|"mm"|"dd"|"cc"|"sp"|"mu"))
+end
+#line 2217 "l2h.nw"
+procedure glue()
+ suspend (dimen(),
+ (optwhite(), ="plus", dimen()) | "",
+ (optwhite(), ="minus", dimen()) | "")
+end
+#line 2231 "l2h.nw"
+procedure substitution(tex, html, ignore_template)
+ # ignore mode for now
+ cstab[tex] := Cemit_ig
+ csclosure[tex] := emit_ig_cl(html, \ignore_template | "")
+end
+#line 2239 "l2h.nw"
+record emit_ig_cl(html, template)
+
+procedure Cemit_ig(S, cs, cl)
+ emit_text(S, cl.html)
+ if *cl.template > 0 then
+ cs_ignore(S, cs, cl.template)
+end
+#line 2249 "l2h.nw"
+procedure activesubst(char, html, ignore_template)
+ local S
+ # ignore mode for now
+ activetab[char] := Cemit_ig
+ activeclosure[char] := emit_ig_cl(html, \ignore_template | "")
+ S := \dynamic_add_hack | return
+ if upto(S.activechars, char) then return # already active
+ if S.activechars ++:= cset(char) then {
+ before_next_close(S, delete_active_char, [S, char])
+ } else impossible("ugh")
+ return
+end
+
+procedure delete_active_char(S, char)
+ S.activechars --:= char
+ return
+end
+#line 2282 "l2h.nw"
+procedure envblock(env, left, right, ignore_template)
+ /ignore_template := ""
+ begintab[env] := Cemit_ig
+ begincl[env] := emit_ig_cl(if /right then tag(left) else left, ignore_template)
+ endtab[env] := Cemit
+ endcl[env] := if /right then endtag(left) else right
+end
+#line 2291 "l2h.nw"
+procedure Cemit(S, cs, cl)
+ S.text(S, cl)
+end
+#line 2303 "l2h.nw"
+record blockpair(left, right, ignore)
+
+procedure argblock(tex, html, right, ignore)
+ # called as is envblock
+ /ignore := ""
+ cstab[tex] := Cblock
+ csclosure[tex] :=
+ if /right then blockpair (tag(html), endtag(html), ignore)
+ else blockpair (html, right, ignore)
+end
+#line 2316 "l2h.nw"
+procedure argblockv(tex, html, right, ignore)
+ argblock(tex, html, right, ignore)
+ cstab[tex] := CblockV
+end
+#line 2321 "l2h.nw"
+procedure Cblock(S, cs, cl, done_ignoring)
+ if /done_ignoring & *cl.ignore > 0 then {
+ cs_ignore(S, cs, cl.ignore, Cblock, [S, cs, cl, 1])
+ } else if pos(0) then {
+ after_next_newtext(S, do_cs, [S, cs, cl])
+ } else if match("{") then {
+ S.text(S, cl.left)
+ after_next_open(S, before_next_close, [S, emit_text, [S, cl.right]])
+ } else {
+# S.text(S, cl.left || csarg(S) || cl.right)
+ apply_args(S, Cblock_continue, [S, cl], 1)
+ }
+ return
+end
+
+procedure Cblock_continue(S, cl, title)
+ S.text (S, cl.left || title || cl.right)
+ return
+end
+#line 2341 "l2h.nw"
+procedure CblockV(S, cs, cl)
+ S.mode := "V"
+ Cblock(S, cs, cl)
+ return
+end
+#line 2353 "l2h.nw"
+record macro_defn(name, arg_count, body, mode)
+#line 2357 "l2h.nw"
+record raw_arg(number)
+record converted_arg(number, mode)
+#line 2361 "l2h.nw"
+procedure expand_macro(S, macro, args)
+ every a := !macro.body do
+ case type(a) of {
+ "string" : emit_text(S, a)
+ "raw_arg" : emit_text(S, args[a.number]) | impossible("missing arg")
+ "converted_arg" : S.text(S, convert(S, "{" || args[a.number] || "}"))
+ }
+# poptrace()
+ return
+end
+#link pushtrace
+#line 2375 "l2h.nw"
+procedure do_macro(S, macro, args_seen, current_arg, brace_depth)
+ # invariant : we have an open brace
+# write(&errout, "scanning args for macro ", macro.name)
+# write(&errout, "seen ", *args_seen, " want ", macro.arg_count)
+ while *args_seen < macro.arg_count & not pos(0) do {
+ while *args_seen < macro.arg_count & brace_depth = 0 & not pos(0) do {
+# write(&errout, "seen ", *args_seen, " want ", macro.arg_count,
+# " current ", image(current_arg), " braces ", brace_depth)
+ tab(many(' \t\n'))
+ case c := move(1) of {
+ "\\" : put(args_seen, "\\" ||
+ if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1))
+ "{" : { current_arg := "" ; brace_depth := 1 }
+ "}" : { error("Insufficient arguments to macro ", macro.name) }
+ default : put(args_seen, c)
+ }
+ }
+ while brace_depth > 0 & not pos(0) do {
+# write(&errout, "seen ", *args_seen, " want ", macro.arg_count,
+# " current ", image(current_arg), " braces ", brace_depth)
+ current_arg ||:= tab(upto('\\{}') | 0)
+ case move(1) of {
+ "\\" : current_arg ||:= "\\" ||
+ if pos(0) then ""
+ else if any(S.csletters) then tab(many(S.csletters))
+ else move(1)
+ "{" : { current_arg ||:= "{" ; brace_depth +:= 1 }
+ "}" : { brace_depth -:= 1
+ if brace_depth > 0 then
+ current_arg ||:= "}"
+ else {
+ put(args_seen, current_arg)
+ current_arg := ""
+ }
+ }
+ }
+ }
+ }
+# write(&errout, "seen ", *args_seen, " want ", macro.arg_count,
+# " current ", image(current_arg), " braces ", brace_depth)
+ if *args_seen = macro.arg_count then {
+# write(&errout, "Arguments for macro ", macro.name, ":")
+# every write(&errout, "\t", image(!args_seen))
+ expand_macro(S, macro, args_seen)
+ undelay_newtext(S)
+ } else
+ before_next_newtext(S, do_macro, [S, macro, args_seen, current_arg, brace_depth])
+ return
+end
+#line 2428 "l2h.nw"
+procedure Cmacro(S, cs, cl)
+# pushtrace("MACRO")
+ delay_newtext(S)
+# apply_args(S, closure(expand_macro, [cl]), cl.arg_count)
+ do_macro(S, cl, [], "", 0)
+ return
+end
+#line 2439 "l2h.nw"
+procedure macro(name, arg_count, body, mode)
+ m := macro_defn(name, arg_count, parse_body(body), mode)
+ cstab[name] := Cmacro
+ csclosure[name] := m
+ return
+end
+
+procedure begin_macro(env, arg_count, body, mode)
+ m := macro_defn(env, arg_count, parse_body(body), mode)
+ begintab[env] := Cmacro
+ begincl[env] := m
+ return
+end
+
+procedure parse_body(body)
+ b := []
+ body ? {
+ put(b, tab(upto('#') | 0))
+ while ="#" do {
+ put(b, ="#" | (="$", raw_arg(argnum())) | converted_arg(argnum())) |
+ error("malformed macro arg #", tab(0))
+ put(b, tab(upto('#') | 0))
+ }
+ }
+ return b
+end
+
+procedure argnum()
+ if any(&digits) then return integer(move(1)) else fail
+end
+#line 2472 "l2h.nw"
+procedure l2h_macro(name, count, body[])
+ count := integer(count) |
+ return error("must give # of arguments to l2h macro ", name)
+ s := ""
+ every s ||:= " " || (1(b := !body, type(b) == "string"))
+ s := s[2:0] # strip leading space if any
+ return macro(name, count, s)
+end
+#line 2482 "l2h.nw"
+procedure l2h_environment(env, count, body[])
+ count := integer(count) |
+ return error("must give # of arguments to l2h environment ", env)
+ s := ""
+ every s ||:= " " || (1(b := !body, type(b) == "string"))
+ s := s[2:0] # strip leading space if any
+ return begin_macro(env, count, s)
+end
+#line 2497 "l2h.nw"
+record table_closure(args, amp, open, close)
+
+procedure table_env(env, args, amp, open, close)
+ begintab[env] := Ctable
+ begincl[env] := table_closure(args, amp,
+ if /close then tag(\open) | &null else open,
+ if /close then endtag(\open) | &null else close)
+ endtab[env] := Ctable_end
+ endcl[env] := []
+end
+#line 2508 "l2h.nw"
+procedure Ctable(S, env, cl)
+ local amp
+## amp := S.ampersand
+## S.ampersand := cl.amp
+ S.text(S, \cl.open)
+ push(endcl[env], amp)
+ cs_ignore(S, env, cl.args)
+end
+
+procedure Ctable_end(S, env, cl)
+# S.ampersand := pop(cl)
+ S.text(S, \begincl[env].close)
+end
+#line 2524 "l2h.nw"
+procedure Cepsfig(S, cs, cl)
+ apply_args(S, do_epsfig, [S], 1)
+end
+
+procedure do_epsfig(S, arg)
+ local args
+ args := []
+ arg ?
+ while not pos(0) do {
+ tab(many(' \t\n'))
+ put(args, eqsplit(tab(upto(',') | 0)))
+ }
+ if a := !args & a.name == ("file"|"figure") then
+ emit_text(S, "<a href=" || image(a.value) || "><b>[</b>PostScript figure " ||
+ a.value || "<b>]</b></a>")
+ else
+ emit_text(S, "<b>[</b>Ill-understood PostScript figure<b>]</b>")
+end
+
+record apair(name, value)
+
+procedure eqsplit(s)
+ p := apair()
+ s ? (p.name := tab(upto('=')), ="=", p.value := tab(0))
+ return p
+end
+#line 2552 "l2h.nw"
+procedure Cincludegraphics(S, cs, cl)
+ local saved_ignore
+ saved_ignore := S.ignoring
+ S.ignoring := 1
+ do_ignore(S, "[", saved_ignore, apply_args, [S, do_includegraphics, [S], 1])
+end
+
+procedure do_includegraphics(S, arg)
+ local base, ext
+ if arg ? (base := tab(find(ext := ".ps" | ".eps" | ".epsi")), =ext, pos(0)) then
+ emit_text(S, "<a href=" || image(arg) || "><b>[</b>PostScript figure " ||
+ arg || "<b>]</b></a>")
+ else if arg ? (base := tab(find(ext := ".png" | ".gif" | ".jpg")), =ext, pos(0)) then
+ emit_text(S, "<img src=" || image(arg) || ">")
+ else
+ emit_text(S, "<b>[</b>Ill-understood graphics<b>]</b>")
+end
+#line 2574 "l2h.nw"
+procedure let(lhs, rhs)
+ cstab[lhs] := cstab[rhs]
+ csclosure[lhs] := csclosure[rhs]
+end
+
+procedure let_closure(lhs, cl[])
+ csclosure[lhs] := if *cl = 1 then cl[1] else cl
+end
+
+procedure letenv(lhs, rhs)
+ begintab[lhs] := begintab[rhs]
+ endtab[lhs] := endtab[rhs]
+ begincl[lhs] := begincl[rhs]
+ endcl[lhs] := endcl[rhs]
+end
+#line 2595 "l2h.nw"
+procedure tag(html)
+ return "<" || html || ">"
+end
+
+procedure endtag(html)
+ return "</" || html || ">"
+end
+#line 2605 "l2h.nw"
+procedure Ccomment(S)
+ if *S.comment > 0 then {
+ S.text(S, "<!--")
+ S.comment ? {
+ while S.text(S, tab(find("--"))) do {
+ move(2)
+ S.text(S, "- - ")
+ }
+ S.text(S, tab(0))
+ }
+ S.text(S, "-->")
+ }
+ S.comment := ""
+ return
+end
+#line 2621 "l2h.nw"
+procedure Cparagraph(S)
+ S.text(S, "<p>")
+end
+#line 2625 "l2h.nw"
+procedure Cmath(S)
+
+#line 915 "l2h.nw"
+push(S.closes, []) # fresh set of closing tasks
+while c := get(S.open) do
+ c.proc!c.args
+#line 2627 "l2h.nw"
+ S.text(S, "<i>")
+end
+
+procedure Cmath_end(S)
+ S.text(S, "</i>")
+
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 2633 "l2h.nw"
+end
+#line 2635 "l2h.nw"
+procedure Cdisplaymath(S)
+
+#line 915 "l2h.nw"
+push(S.closes, []) # fresh set of closing tasks
+while c := get(S.open) do
+ c.proc!c.args
+#line 2637 "l2h.nw"
+ S.text(S, "<blockquote><i>")
+end
+
+procedure Cdisplaymath_end(S)
+ S.text(S, "</i></blockquote>")
+
+#line 919 "l2h.nw"
+while c := get(S.closes[1]) do
+ c.proc!c.args
+pop(S.closes)
+#line 2643 "l2h.nw"
+end
+#line 2645 "l2h.nw"
+procedure Cmakeatletter(S)
+ S.csletters ++:= '@'
+end
+
+procedure Cmakeatother(S)
+ S.csletters --:= '@'
+end
+#line 2655 "l2h.nw"
+procedure Ckill(S, cs, cl)
+ S.the_text := ""
+end
+#line 2673 "l2h.nw"
+global csfunctions
+#line 2700 "l2h.nw"
+global dynamic_add_hack
+procedure parse_dynamic_add(S)
+ if (optwhite(), =("l2h"|"sl2h"), skipwhite(),
+ p := tab(upto(' \t')),
+#line 2717 "l2h.nw"
+((p := \csfunctions[p]) |
+{ dynamic_warn(p); fail })
+#line 2703 "l2h.nw"
+ ,
+ skipwhite(), any(~'\n')) then {
+ a := []
+ while (any(~'\n'), l := tab(upto(' \t\n') | 0)) do {
+ put(a, if p === (l2h_macro|l2h_environment) then l else map(l, "#", " "))
+ skipwhite()
+ }
+ dynamic_add_hack := S
+ p!a
+ dynamic_add_hack := &null
+ return
+ }
+end
+#line 2720 "l2h.nw"
+procedure dynamic_warn(p)
+ static badprocs
+ initial badprocs := set()
+ if not member(badprocs, p) then {
+ write(&errout, "Warning: % l2h ", p, " not recognized -- ignored")
+ insert(badprocs, p)
+ }
+end
+#line 2732 "l2h.nw"
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+#line 2737 "l2h.nw"
+procedure skipwhite()
+ suspend tab(many(' \t'))
+end
+#line 2829 "l2h.nw"
+global errstatus
+procedure error(args[])
+ errstatus := 1
+ return write!([&errout, (\curfile || ":") | "line ", curline, ": "] ||| args)
+end
+#line 2878 "l2h.nw"
+procedure fatal(L[])
+ write!(["@fatal l2h "] ||| L)
+ write!([&errout, "noweb error in l2h: "] ||| L)
+ exit(1)
+end
+#line 2885 "l2h.nw"
+procedure rcsinfo ()
+ return "$Id: l2h.nw,v 1.24 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+#line 2838 "l2h.nw"
+global curfile, curline
+
+procedure convert_file(f)
+ static S
+ initial S := converter("V")
+ curline := 0
+ while line := read(f) do {
+ curline +:= 1
+ writes(convert(S, line || "\n"))
+ }
+ return
+end
+
+procedure main(args)
+ local warn
+ warn := 1
+ errstatus := 0
+ every arg := !args do
+ if arg[1] == "-" then
+ case arg of {
+ "-show-unknowns" : show_unknowns := 1
+ "-nowarn" : warn := &null
+ "-html-quotes" : html_quotes := 1
+ "-" : { curfile := arg; convert_file(&input) }
+ default : write(&errout, "Warning: unrecognized option ", arg)
+ }
+ else if f := open(curfile <- arg) then
+ convert_file(f)
+ else
+ write(&errout, "Error: Can't open file ", arg)
+ if /curfile then
+ convert_file(&input)
+ if \warn then {
+ warn_unknown(\unknown_set, "control sequences", "\\")
+ warn_unknown(\unknown_envs, "environments", "{", "}")
+ }
+ exit(errstatus)
+end
diff --git a/web/noweb/src/icon/smldefs.icn b/web/noweb/src/icon/smldefs.icn
new file mode 100644
index 0000000000..43f29ab1b1
--- /dev/null
+++ b/web/noweb/src/icon/smldefs.icn
@@ -0,0 +1,84 @@
+#line 3 "smldefs.nw"
+procedure rcsinfo ()
+ return "$Id: smldefs.nw,v 1.19 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+procedure main(args)
+ go()
+end
+#line 11 "smldefs.nw"
+procedure postpass(name, arg)
+ static kind, definers, id1, id2, reserved
+ initial { kind := "bogus"
+ definers := ["fun", "val", "structure", "signature", "and", "functor",
+ "type", "eqtype", "datatype", "withtype", "exception"]
+ id1 := &letters ++ &digits ++ '\'_'
+ id2 := '!%&$+-/:<=>?@\\~^|#*`'
+ reserved := set()
+ every insert(reserved, !"*|:=#_" | "->" | "=>")
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if =(""|" "|" ") & =!definers & tab(many(' ')) then {
+ skiptyvars(); optwhite()
+ writedefn(1(id := tab(many(id1 | id2)), not member(reserved, id)))
+ }
+ }
+ return
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+
+procedure skiptyvars()
+ suspend ="'" || tab(many(&letters ++ &digits ++ '\'_')) |
+ ="(" || tab(bal(')', '(', ')')) || =")"
+end
+
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+#line 1 "defns.nw"
+procedure go()
+ local line
+ while line := read() do {
+ apply(prepass, line)
+ write(line)
+ if match("@fatal ", line) then exit(1)
+ apply(postpass, line)
+ }
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+#line 18 "defns.nw"
+procedure writedefn(defn, locl)
+ static indextext
+ initial indextext := ""
+ if /defn then
+ *indextext > 0 &
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 23 "defns.nw"
+ else {
+ if *indextext + *defn > 65 then
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 25 "defns.nw"
+ write(if \locl then "@index localdefn " else "@index defn ", defn)
+ indextext ||:= " " || defn
+ }
+ return
+end
+#line 35 "defns.nw"
+procedure rcsinfo_too ()
+ return "$Id: defns.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/smldefs.nw b/web/noweb/src/icon/smldefs.nw
new file mode 100644
index 0000000000..1a715ced4a
--- /dev/null
+++ b/web/noweb/src/icon/smldefs.nw
@@ -0,0 +1,44 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+\section{Finding definitions in Standard ML}
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: smldefs.nw,v 1.19 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+procedure main(args)
+ go()
+end
+<<*>>=
+procedure postpass(name, arg)
+ static kind, definers, id1, id2, reserved
+ initial { kind := "bogus"
+ definers := ["fun", "val", "structure", "signature", "and", "functor",
+ "type", "eqtype", "datatype", "withtype", "exception"]
+ id1 := &letters ++ &digits ++ '\'_'
+ id2 := '!%&$+-/:<=>?@\\~^|#*`'
+ reserved := set()
+ every insert(reserved, !"*|:=#_" | "->" | "=>")
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if =(""|" "|" ") & =!definers & tab(many(' ')) then {
+ skiptyvars(); optwhite()
+ writedefn(1(id := tab(many(id1 | id2)), not member(reserved, id)))
+ }
+ }
+ return
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+
+procedure skiptyvars()
+ suspend ="'" || tab(many(&letters ++ &digits ++ '\'_')) |
+ ="(" || tab(bal(')', '(', ')')) || =")"
+end
+
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
diff --git a/web/noweb/src/icon/texdefs.icn b/web/noweb/src/icon/texdefs.icn
new file mode 100644
index 0000000000..13ddd4b12a
--- /dev/null
+++ b/web/noweb/src/icon/texdefs.icn
@@ -0,0 +1,73 @@
+#line 2 "texdefs.nw"
+procedure rcsinfo ()
+ return "$Id: texdefs.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+procedure main(args)
+ go()
+end
+#line 10 "texdefs.nw"
+procedure postpass(name, arg)
+ static kind, idchars, definers, newcommand
+ initial { kind := "bogus"; idchars := &letters ++ '@'
+ definers := ["def", "newdimen", "newif", "newcount", "newwrite",
+ "newbox", "global\\def", "long\\def", "gdef" ]
+ newcommand := ["newcommand", "renewcommand"]
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ? {
+ if =("\\" || !definers || "\\") then
+ writedefn("\\" || (tab(many(idchars)) | move(1)))
+ else if =("\\" || !newcommand || "{") then
+ writedefn(tab(upto('}')))
+ }
+ }
+ return
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+#line 1 "defns.nw"
+procedure go()
+ local line
+ while line := read() do {
+ apply(prepass, line)
+ write(line)
+ if match("@fatal ", line) then exit(1)
+ apply(postpass, line)
+ }
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+#line 18 "defns.nw"
+procedure writedefn(defn, locl)
+ static indextext
+ initial indextext := ""
+ if /defn then
+ *indextext > 0 &
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 23 "defns.nw"
+ else {
+ if *indextext + *defn > 65 then
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 25 "defns.nw"
+ write(if \locl then "@index localdefn " else "@index defn ", defn)
+ indextext ||:= " " || defn
+ }
+ return
+end
+#line 35 "defns.nw"
+procedure rcsinfo_too ()
+ return "$Id: defns.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/texdefs.nw b/web/noweb/src/icon/texdefs.nw
new file mode 100644
index 0000000000..c530120662
--- /dev/null
+++ b/web/noweb/src/icon/texdefs.nw
@@ -0,0 +1,32 @@
+\section{Finding {\TeX} definitions}
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: texdefs.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+procedure main(args)
+ go()
+end
+<<*>>=
+procedure postpass(name, arg)
+ static kind, idchars, definers, newcommand
+ initial { kind := "bogus"; idchars := &letters ++ '@'
+ definers := ["def", "newdimen", "newif", "newcount", "newwrite",
+ "newbox", "global\\def", "long\\def", "gdef" ]
+ newcommand := ["newcommand", "renewcommand"]
+ }
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ? {
+ if =("\\" || !definers || "\\") then
+ writedefn("\\" || (tab(many(idchars)) | move(1)))
+ else if =("\\" || !newcommand || "{") then
+ writedefn(tab(upto('}')))
+ }
+ }
+ return
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
diff --git a/web/noweb/src/icon/tohtml.icn b/web/noweb/src/icon/tohtml.icn
new file mode 100644
index 0000000000..dfea222088
--- /dev/null
+++ b/web/noweb/src/icon/tohtml.icn
@@ -0,0 +1,489 @@
+#line 10 "tohtml.nw"
+# Copyright 1994 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+#line 19 "tohtml.nw"
+# Don't try to understand this file! Look at icon/tohtml.nw in the noweb source!
+
+global braw, eraw
+procedure main(args)
+ local delay, raw, where, localindex, noindex, shortxref
+
+#line 218 "tohtml.nw"
+useitemstab := table()
+defns := table("")
+defns_above := set() # keep track of defining chunks we've seen
+#line 25 "tohtml.nw"
+ every braw | eraw := ""
+ delay := !args == "-delay"
+ noindex := !args == "-noindex"
+ shortxref := if !args == "-longxref" then &null else 1
+ localindex := (/noindex, !args == "-localindex") # produce local identifier xref?
+ raw := !args == "-raw"
+ if \raw then {braw := "\\begin{rawhtml}"; eraw := "\\end{rawhtml}"}
+ if !args == "-no-gen-comment" then &null
+ else
+ write(braw, "<!-- this file was generated automatically by noweave;",
+ " better not edit it-->", eraw)
+ while inputline := read() do inputline ? {
+
+#line 90 "tohtml.nw"
+if ="@text " then { text +:= *(line := tab(0))
+ if \code then
+ writes((
+#line 98 "tohtml.nw"
+2(line ? {tab(many(' \t')); not pos(0)},
+ linkto(\lastindexref, escapeSpecials(line)),
+ lastindexref := &null)
+#line 92 "tohtml.nw"
+ ) | escapeSpecials(line))
+ else if \quoting then
+ writes((
+#line 123 "tohtml.nw"
+2(line ? {tab(many(' \t')); not pos(0)},
+ linklabelto(lastxreflabel, lastindexref, escapeSpecials(line), "bare"),
+ lastxreflabel := lastindexref := &null)
+#line 94 "tohtml.nw"
+ ) | escapeSpecials(line))
+ else
+ writes((
+#line 107 "tohtml.nw"
+1(line ? skip_white_tags() ||
+ linklabel(\lastxreflabel, skip_chars()) || tab(0),
+ insert(defns_above, \lastxreflabel),
+ lastxreflabel := &null)
+#line 96 "tohtml.nw"
+ ) | line) } else
+#line 207 "tohtml.nw"
+if ="@nl" & pos(0) then {
+#line 292 "tohtml.nw"
+if \shortxref & (\pendinguses | \pendingprev | \pendingnext | \notused) then {
+
+#line 297 "tohtml.nw"
+if \pendinguses & *\useitems > 0 then {
+ writes(" <b>(")
+ every i := 1 to *\useitems do {
+ usedir := if member(defns_above, useitems[i]) then "&lt;-U" else "U-&gt;"
+ writes(if i > 1 then " " else "", linkto(useitems[i], usedir))
+ }
+ writes(")</b>")
+}
+if \pendingprev | \pendingnext then {
+ writes(" <b>[")
+ writes(linkto(\pendingprev, "&lt;-"))
+ writes("D")
+ writes(linkto(\pendingnext, "-&gt;"))
+ writes("]</b>")
+}
+#line 294 "tohtml.nw"
+ pendinguses := pendingprev := pendingnext := notused := &null
+}
+#line 208 "tohtml.nw"
+ write() } else
+#line 62 "tohtml.nw"
+if ="@begin code " then { code := 1 ; thischunk := &null
+
+#line 350 "tohtml.nw"
+useitems := []
+notused := &null
+#line 64 "tohtml.nw"
+ writes(braw, "<pre>"); ecode := "</pre>" } else
+if ="@end code " then {
+#line 313 "tohtml.nw"
+if /shortxref then {
+ useitems := useitemstab[\thischunk]
+ if \pendingprev | \pendingnext | (\pendinguses, (*\useitems > 0 | \notused)) then {
+
+#line 356 "tohtml.nw"
+if ecode == "</pre>" then {
+ writes("</pre><blockquote>")
+ ecode := "</blockquote>"
+}
+#line 317 "tohtml.nw"
+
+#line 342 "tohtml.nw"
+useprefix := "Used "
+every i := 1 to *\useitems do {
+ usedir := if member(defns_above, useitems[i]) then "above" else "below"
+ usesuffix := if *\useitems > 1 then " (" || i || ")" else ""
+ writes(useprefix, linkto(useitems[i], usedir || usesuffix))
+ useprefix := ", "
+}
+#line 318 "tohtml.nw"
+ useitemstab[\thischunk]
+ if *\useitems > 0 & (\pendingprev | \pendingnext) then
+ writes("; ")
+ p := if *\useitems > 0 then "previous" else "Previous"
+ n := if *\useitems > 0 then "next" else "Next"
+ if \pendingprev then
+ if \pendingnext then
+ writes(linkto(pendingprev, p), " and ",
+ linkto(pendingnext, "next"), " definitions")
+ else
+ writes(linkto(pendingprev, p), " definition")
+ else
+ if \pendingnext then
+ writes(linkto(pendingnext, n), " definition")
+ if \pendingprev | \pendingnext | *\useitems > 0 then
+ writes(".")
+ if \notused then
+ writes("<br>\nThis code is written to a file (or else not used).")
+ write("<p>")
+ pendinguses := pendingprev := pendingnext := useitems := notused := &null
+ }
+} else
+ &null
+#line 66 "tohtml.nw"
+ code := nil ; previscode := 1
+ writes(ecode, eraw) } else
+#line 210 "tohtml.nw"
+if ="@defn " then { writechunk(lastxreflabel, lastxrefref, "dfn",
+ thischunk := tab(0), defns[thischunk] || "=")
+ insert(defns_above, \lastxreflabel)
+ useitems := \useitemstab[thischunk]
+ pendinguses := 1
+
+#line 274 "tohtml.nw"
+every lastxreflabel | lastxrefref := &null
+#line 216 "tohtml.nw"
+ defns[thischunk] := "+" } else
+#line 74 "tohtml.nw"
+if ="@begin docs " then { if \previscode then writes(if /raw then "<p>" else "\\par")
+ previscode := &null
+ text := 0 } else
+#line 82 "tohtml.nw"
+if ="@end docs " then { write(linklabel(\lastxreflabel, "*"))
+ lastxreflabel := &null } else
+#line 222 "tohtml.nw"
+if ="@use " then { writechunk(lastxreflabel, lastxrefref, "i", tab(0))
+
+#line 274 "tohtml.nw"
+every lastxreflabel | lastxrefref := &null
+#line 223 "tohtml.nw"
+ } else
+#line 251 "tohtml.nw"
+if ="@xref " then {
+ if fun := tab(upto(' ')) then {move(1); arg := tab(0)}
+ else { fun := tab(0); arg := &null }
+ case fun of {
+
+#line 265 "tohtml.nw"
+"label" : {
+#line 276 "tohtml.nw"
+warn_unused_xref("label", \lastxreflabel)
+#line 265 "tohtml.nw"
+ ; lastxreflabel := arg }
+"ref" : {
+#line 278 "tohtml.nw"
+warn_unused_xref("ref", \lastxrefref)
+#line 266 "tohtml.nw"
+ ; lastxrefref := arg }
+"prevdef" : pendingprev := arg
+"nextdef" : pendingnext := arg
+"beginuses" : useitems := []
+"useitem" : put(useitems, arg)
+"enduses" : useitemstab[\thischunk] := useitems
+"notused" : notused := arg
+#line 364 "tohtml.nw"
+"begindefs" | "defitem" | "enddefs" : &null
+#line 367 "tohtml.nw"
+"beginchunks" : { write(braw, "<ul>") }
+"chunkbegin" : { writes("<li>"); comma := ": "; count := 0
+ arg ? { ref := tab(upto(' ')); =" "; name := tab(0) }
+ writechunk(&null, ref, "i", name) }
+"chunkuse" : { writes(comma, linkto(arg, "U" || (count +:= 1))); comma := ", " }
+"chunkdefn" : { writes(comma, linkto(arg, "D" || (count +:= 1))); comma := ", " }
+"chunkend" : write()
+"endchunks" : write("</ul>", eraw)
+#line 255 "tohtml.nw"
+
+ default : (\arg|"") ? warn_unknown("xref " || fun)
+ }
+} else
+#line 385 "tohtml.nw"
+if ="@index " then {
+ if /noindex then {
+ if fun := tab(upto(' ')) then {move(1); arg := tab(0)}
+ else { fun := tab(0); arg := &null }
+ case fun of {
+
+#line 376 "tohtml.nw"
+"beginindex" : { write(braw, "<ul>") }
+"entrybegin" : { writes("<li>"); comma := ": "; count := 0
+ arg ? { ref := tab(upto(' ')); =" "; name := tab(0) }
+ writes(linklabelto("NWI-" || escapeSpecials(name), ref, name, "b")) }
+"entryuse" : { writes(comma, linkto(arg, "U" || (count +:= 1))); comma := ", " }
+"entrydefn" : { writes(comma, linkto(arg, "D" || (count +:= 1))); comma := ", " }
+"entryend" : write()
+"endindex" : write("</ul>", eraw)
+#line 400 "tohtml.nw"
+"use" : { lastindexref := lastxrefref; lastxrefref := &null }
+"defn" : {
+#line 274 "tohtml.nw"
+every lastxreflabel | lastxrefref := &null
+#line 401 "tohtml.nw"
+ }
+"localdefn" : {
+#line 274 "tohtml.nw"
+every lastxreflabel | lastxrefref := &null
+#line 402 "tohtml.nw"
+ }
+"nl" : &null # do nothing -- no hope of keeping line numbering
+#line 408 "tohtml.nw"
+"begindefs" : if \localindex then {
+
+#line 313 "tohtml.nw"
+if /shortxref then {
+ useitems := useitemstab[\thischunk]
+ if \pendingprev | \pendingnext | (\pendinguses, (*\useitems > 0 | \notused)) then {
+
+#line 356 "tohtml.nw"
+if ecode == "</pre>" then {
+ writes("</pre><blockquote>")
+ ecode := "</blockquote>"
+}
+#line 317 "tohtml.nw"
+
+#line 342 "tohtml.nw"
+useprefix := "Used "
+every i := 1 to *\useitems do {
+ usedir := if member(defns_above, useitems[i]) then "above" else "below"
+ usesuffix := if *\useitems > 1 then " (" || i || ")" else ""
+ writes(useprefix, linkto(useitems[i], usedir || usesuffix))
+ useprefix := ", "
+}
+#line 318 "tohtml.nw"
+ useitemstab[\thischunk]
+ if *\useitems > 0 & (\pendingprev | \pendingnext) then
+ writes("; ")
+ p := if *\useitems > 0 then "previous" else "Previous"
+ n := if *\useitems > 0 then "next" else "Next"
+ if \pendingprev then
+ if \pendingnext then
+ writes(linkto(pendingprev, p), " and ",
+ linkto(pendingnext, "next"), " definitions")
+ else
+ writes(linkto(pendingprev, p), " definition")
+ else
+ if \pendingnext then
+ writes(linkto(pendingnext, n), " definition")
+ if \pendingprev | \pendingnext | *\useitems > 0 then
+ writes(".")
+ if \notused then
+ writes("<br>\nThis code is written to a file (or else not used).")
+ write("<p>")
+ pendinguses := pendingprev := pendingnext := useitems := notused := &null
+ }
+} else
+ &null
+#line 410 "tohtml.nw"
+ if /uglyindex | /shortxref then {
+
+#line 356 "tohtml.nw"
+if ecode == "</pre>" then {
+ writes("</pre><blockquote>")
+ ecode := "</blockquote>"
+}
+#line 412 "tohtml.nw"
+ writes("Defines ")
+ } else {
+ writes("<hr><b>[</b>")
+ }
+ comma := ""
+ }
+"isused" : &null
+"defitem" : if \localindex then {
+ writes(comma, linkto("NWI-" || escapeSpecials(arg),
+ sgmlwrap("code", escapeSpecials(arg))))
+ comma := if /uglyindex | /shortxref then ", " else "<b>,</b> "
+ }
+"enddefs" : if \localindex then
+ write(if /uglyindex | /shortxref then " (links are to index).<p>"
+ else "<b>]</b>")
+"beginuses" | "isdefined" | "useitem" | "enduses" : &null # use local links
+#line 390 "tohtml.nw"
+
+ default : (\arg|"") ? warn_unknown("index " || fun)
+ }
+ }
+ # don't get any warnings if not doing indexing
+} else
+#line 237 "tohtml.nw"
+if ="@quote" & pos(0) then { quoting := 1 ; writes(braw, "<code>") } else
+if ="@endquote" & pos(0) then { quoting := nil ; writes("</code>", eraw) } else
+#line 240 "tohtml.nw"
+if ="@file " then { filename := tab(0);
+#line 274 "tohtml.nw"
+every lastxreflabel | lastxrefref := &null
+#line 240 "tohtml.nw"
+ } else
+if ="@literal " then { writes(tab(0)) } else
+if ="@header html " then {
+#line 246 "tohtml.nw"
+writes("<html><head><title>", tab(0), "</title></head><body>")
+#line 242 "tohtml.nw"
+ } else
+if ="@trailer html" & pos(0) then {
+#line 248 "tohtml.nw"
+write("</body></html>")
+#line 243 "tohtml.nw"
+ } else
+#line 51 "tohtml.nw"
+if match("@fatal ") then { # follows last else
+ exit(1)
+} else if ="@" then
+ warn_unknown(1(tab(upto(' ')|0), pos(0) | move(1)))
+else
+ fatal("Botched line in noweb pipeline: ", tab(0))
+#line 38 "tohtml.nw"
+ }
+ write()
+end
+#line 131 "tohtml.nw"
+procedure skip_white_tags()
+ suspend thewhite() ||
+ ((="<" || thewhite() || (="/" || thewhite() | "") ||
+ (tab(many(&letters)) | ="!--") ||
+ tab(upto(">")) || =">" || skip_white_tags() |
+ "") \ 1)
+end
+#line 139 "tohtml.nw"
+procedure skip_chars()
+ if not any('<') & upto('<') then
+ suspend tab(upto('<'))
+ else if any('&') & upto(';') then
+ suspend (tab(upto(';')) || =";")
+ else if (any('<') & upto('>')) | any(' \t') then
+ (write(&errout, "broken skip_chars, report to nr@eecs.harvard.edu: ", image(tab(0))),
+ &fail)
+ else if any('<') then
+ (write(&errout, "warning: can't find end of HTML tag: ", image(tab(0)),
+ "\n\tquoted code embedded in comment?"), &fail)
+ else if pos(0) then
+ fail
+ else
+ suspend tab(0)
+end
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+procedure thewhite()
+ return optwhite() \ 1
+end
+#line 162 "tohtml.nw"
+procedure skip_tags_and_char(count)
+ local tag
+ /count := 0
+ if any('&') & upto(';') then
+ suspend(tab(upto(';')) || =";")
+ else if any('<') then
+ suspend ="<" || (tab(many(' \t')) | "") ||
+ (="/" | (tag := tab(many(&letters)))) ||
+ tab(upto(">")) || =">" ||
+ (if map(tag) == "a" then
+ tab(upto("<")) || ="<" || optwhite() || ="/" || optwhite() ||
+ (("A"|"a") == tab(many(&letters))) || optwhite || =">"
+ else "") ||
+ skip_tags_and_char(count+1)
+ else
+ suspend (tab(many(' \t')) | "") ||
+ ((move(1) | if count > 0 then "")\1) # succeed at end if count > 0
+
+end
+#line 228 "tohtml.nw"
+procedure writechunk(label, ref, tag, name, suffix)
+ /suffix := ""
+ writes(linklabelto(label, ref,
+ sgmlwrap(tag, "&lt;" || convquotes(name) || "&gt;" || suffix),
+ "bare"))
+ return
+end
+#line 280 "tohtml.nw"
+procedure warn_unused_xref(tag, label)
+ static warned
+ initial warned := set()
+ if not member(warned, tag) then {
+ insert(warned, tag)
+ write(&errout, "Warning: internal inconsistency in noweb (not urgent)---")
+ write(&errout, "\tnever used @xref ", tag, " ", label)
+ }
+ return
+end
+#line 436 "tohtml.nw"
+procedure linklabelto(label, ref, contents, bare)
+ local s
+ s := if \bare then "" else braw
+ s ||:= if \label | \ref then "<a" else ""
+ s ||:= " name=" || image(\label)
+ s ||:= " href=" || image("#" || \ref)
+ s ||:= if \label | \ref then ">" else ""
+ s ||:= if \bare then "" else eraw
+ s ||:= contents
+ s ||:= if \bare then "" else braw
+ s ||:= if \label | \ref then "</a>" else ""
+ s ||:= if \bare then "" else eraw
+ return s
+end
+#line 453 "tohtml.nw"
+procedure linklabel(label, contents, bare)
+ return linklabelto(label, &null, contents, bare)
+end
+
+procedure linkto(ref, contents)
+ return linklabelto(&null, ref, contents, "bare")
+end
+#line 467 "tohtml.nw"
+procedure sgmlwrap(tag, s)
+ return "<" || tag || ">" || s || "</" || tag || ">"
+end
+#line 475 "tohtml.nw"
+procedure escapeSpecials (l)
+ static escapes, specials
+ initial {escapes := table();
+ escapes["&"] := "&amp;"
+ escapes["<"] := "&lt;"
+ escapes[">"] := "&gt;"
+ escapes["\""] := "&quot;"
+ specials := ''
+ every specials ++:= key(escapes)
+ }
+ s := ""
+ l ? {
+ while s ||:= tab(upto(specials)) do
+ s ||:= escapes[move(1)]
+ return s || tab(0)
+ }
+end
+#line 496 "tohtml.nw"
+procedure convquotes(s)
+ r := ""
+ s ? { # don't call escapeSpecials on s; it destroys internal markup
+ while r ||:= tab(find("[[")) do {
+ ="[[" | fatal("impossible missing [[")
+ r ||:= "<code>" || tab(find("]]"))
+ r ||:= tab(many(']')-2)
+ ="]]" | fatal("impossible missing ]] in ", image(s))
+ r ||:= "</code>"
+ }
+ return r || tab(0)
+ }
+end
+#line 511 "tohtml.nw"
+procedure warn_unknown(tag)
+ static warned
+ initial warned := set()
+ if not member(warned, tag) then {
+ write(&errout, "Warning: unrecognized escape @", tag, " ", tab(0))
+ insert(warned, tag)
+ }
+ return
+end
+#line 522 "tohtml.nw"
+procedure fatal(L[])
+ write!([&errout, "noweb error in tohtml: "] ||| L)
+ exit(1)
+end
+#line 529 "tohtml.nw"
+procedure rcsinfo ()
+ return "$Id: tohtml.nw,v 1.22 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/tohtml.nw b/web/noweb/src/icon/tohtml.nw
new file mode 100644
index 0000000000..9eb904836c
--- /dev/null
+++ b/web/noweb/src/icon/tohtml.nw
@@ -0,0 +1,534 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+\documentstyle[noweb]{article}
+\pagestyle{noweb}
+\begin{document}
+@
+\section{Converting {\tt noweb} markup to {\tt HTML}}
+This copyright applies both to the {\tt noweb} source and to the
+generated code.
+Thanks to Bill Trost for getting me started with an early version.
+<<copyright notice>>=
+# Copyright 1994 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+@
+The [[-raw]] option brackets HTML with [[\begin{rawhtml}]] and
+[[\end{rawhtml}]]; the purpose is to embed HTML in a {\LaTeX}
+document before converting the document with {\tt latex2html}.
+[[braw]] and [[eraw]] hold those delimiters (or else empty strings).
+<<*>>=
+<<copyright notice>>
+# Don't try to understand this file! Look at icon/tohtml.nw in the noweb source!
+
+global braw, eraw
+procedure main(args)
+ local delay, raw, where, localindex, noindex, shortxref
+ <<initialization>>
+ every braw | eraw := ""
+ delay := !args == "-delay"
+ noindex := !args == "-noindex"
+ shortxref := if !args == "-longxref" then &null else 1
+ localindex := (/noindex, !args == "-localindex") # produce local identifier xref?
+ raw := !args == "-raw"
+ if \raw then {braw := "\\begin{rawhtml}"; eraw := "\\end{rawhtml}"}
+ if !args == "-no-gen-comment" then &null
+ else
+ write(braw, "<!-- this file was generated automatically by noweave;",
+ " better not edit it-->", eraw)
+ while inputline := read() do inputline ? {
+ <<scan and convert>>
+ }
+ write()
+end
+<<scan and convert>>=
+<<@text>>
+<<@nl>>
+<<code chunks>>
+<<@defn>>
+<<docs chunks>>
+<<@use>>
+<<@xref>>
+<<@index>>
+<<others>>
+if match("@fatal ") then { # follows last else
+ exit(1)
+} else if ="@" then
+ warn_unknown(1(tab(upto(' ')|0), pos(0) | move(1)))
+else
+ fatal("Botched line in noweb pipeline: ", tab(0))
+@
+[[ecode]] is the marker used at the end of the current code chunk.
+If there is no cross-reference stuff at the end, we just use [[</pre>]];
+otherwise we terminate whatever environment is used for the cross-reference stuff.
+<<code chunks>>=
+if ="@begin code " then { code := 1 ; thischunk := &null
+ <<reset cross-reference info>>
+ writes(braw, "<pre>"); ecode := "</pre>" } else
+if ="@end code " then { <<dump pending cross-reference info (long form)>>
+ code := nil ; previscode := 1
+ writes(ecode, eraw) } else
+@ We maintain [[thischunk]] null until we've seen [[@defn]].
+
+We want to try to avoid emitting paragraph elements when the
+preceding chunk is a code chunk, as tracked by [[previscode]].
+Also, if we do slip in a paragraph, we may use the {\LaTeX} style.
+<<docs chunks>>=
+if ="@begin docs " then { if \previscode then writes(if /raw then "<p>" else "\\par")
+ previscode := &null
+ text := 0 } else
+@
+Sometimes it happens that a document-chunk anchor is put in a document chunk that
+contains no text. In that case, we put in a phony anchor at the end of the chunk so
+we won't lose the cross-reference.
+<<docs chunks>>=
+if ="@end docs " then { write(linklabel(\lastxreflabel, "*"))
+ lastxreflabel := &null } else
+@
+Normally, if there's a pending anchor, we put it on the first available text line.
+There's a bit of a fine point that crops up if the very first piece of text
+is quoted code. In that case we have to attach both the label for the
+{\it docs} anchor and the ref for the {\it index} anchor.
+<<@text>>=
+if ="@text " then { text +:= *(line := tab(0))
+ if \code then
+ writes((<<index anchor>>) | escapeSpecials(line))
+ else if \quoting then
+ writes((<<index and docs anchor>>) | escapeSpecials(line))
+ else
+ writes((<<docs anchor>>) | line) } else
+<<index anchor>>=
+2(line ? {tab(many(' \t')); not pos(0)},
+ linkto(\lastindexref, escapeSpecials(line)),
+ lastindexref := &null)
+@
+We anchor on the first nonblank character of the line, unless that's
+an SGML tag, in which case we have to
+skip past.
+None of this crap would be necessary if HTML could anchor to empty text.
+<<docs anchor>>=
+1(line ? skip_white_tags() ||
+ linklabel(\lastxreflabel, skip_chars()) || tab(0),
+ insert(defns_above, \lastxreflabel),
+ lastxreflabel := &null)
+<<old docs anchor>>=
+2(line ? {tab(many(' \t')); not pos(0)},
+ line ? linklabel(\lastxreflabel,
+ (tab(many(' \t')) | "") ||
+ (skip_tags_and_char() | "*")) ||
+ tab(0),
+ insert(defns_above, \lastxreflabel),
+ lastxreflabel := &null)
+@
+An indexed identifier is not empty and contains no tags, so we don't
+have to worry.
+<<index and docs anchor>>=
+2(line ? {tab(many(' \t')); not pos(0)},
+ linklabelto(lastxreflabel, lastindexref, escapeSpecials(line), "bare"),
+ lastxreflabel := lastindexref := &null)
+@
+Skip as many tags as possible.
+Argument is number of tags already skipped; if nonzero, we're willing to succeed
+at the end of the string.
+<<*>>=
+procedure skip_white_tags()
+ suspend thewhite() ||
+ ((="<" || thewhite() || (="/" || thewhite() | "") ||
+ (tab(many(&letters)) | ="!--") ||
+ tab(upto(">")) || =">" || skip_white_tags() |
+ "") \ 1)
+end
+<<*>>=
+procedure skip_chars()
+ if not any('<') & upto('<') then
+ suspend tab(upto('<'))
+ else if any('&') & upto(';') then
+ suspend (tab(upto(';')) || =";")
+ else if (any('<') & upto('>')) | any(' \t') then
+ (write(&errout, "broken skip_chars, report to nr@eecs.harvard.edu: ", image(tab(0))),
+ &fail)
+ else if any('<') then
+ (write(&errout, "warning: can't find end of HTML tag: ", image(tab(0)),
+ "\n\tquoted code embedded in comment?"), &fail)
+ else if pos(0) then
+ fail
+ else
+ suspend tab(0)
+end
+procedure optwhite()
+ suspend tab(many(' \t')) | ""
+end
+procedure thewhite()
+ return optwhite() \ 1
+end
+<<*>>=
+procedure skip_tags_and_char(count)
+ local tag
+ /count := 0
+ if any('&') & upto(';') then
+ suspend(tab(upto(';')) || =";")
+ else if any('<') then
+ suspend ="<" || (tab(many(' \t')) | "") ||
+ (="/" | (tag := tab(many(&letters)))) ||
+ tab(upto(">")) || =">" ||
+ (if map(tag) == "a" then
+ tab(upto("<")) || ="<" || optwhite() || ="/" || optwhite() ||
+ (("A"|"a") == tab(many(&letters))) || optwhite || =">"
+ else "") ||
+ skip_tags_and_char(count+1)
+ else
+ suspend (tab(many(' \t')) | "") ||
+ ((move(1) | if count > 0 then "")\1) # succeed at end if count > 0
+
+end
+@
+The preceding scheme sometimes wraps an anchor around a tag.
+If that turns out to be bad, we could try the following alternative:
+<<funky new docs anchor>>=
+2(line ? {tab(many(' \t')); not pos(0)},
+ line ? scan_initial_tags() ||
+ linklabel(\lastxreflabel,
+ (tab(many(' \t')) | "") || (scan_past_char() | "*")) ||
+ tab(0),
+ insert(defns_above, \lastxreflabel),
+ lastxreflabel := &null)
+<<procedures to support new docs anchor>>=
+procedure scan_initial_tags()
+ suspend (="<" || (tab(many(' \t')) | "") ||
+ (="/" | (tag := tab(many(&letters)), map(tag) ~== "a", tag)) ||
+ tab(upto(">")) || =">" || scan_initial_tags()) |
+ ""
+end
+
+procedure scan_past_char()
+ if any('&') & upto(';') then
+ suspend(tab(upto(';')) || =";")
+ else
+ suspend (tab(many(' \t')) | "") || tab(any(~'<'))
+end
+<<@nl>>=
+if ="@nl" & pos(0) then { <<show definitions and uses on definition line---once>>
+ write() } else
+<<@defn>>=
+if ="@defn " then { writechunk(lastxreflabel, lastxrefref, "dfn",
+ thischunk := tab(0), defns[thischunk] || "=")
+ insert(defns_above, \lastxreflabel)
+ useitems := \useitemstab[thischunk]
+ pendinguses := 1
+ <<clear [[lastxref*]]>>
+ defns[thischunk] := "+" } else
+<<initialization>>=
+useitemstab := table()
+defns := table("")
+defns_above := set() # keep track of defining chunks we've seen
+<<@use>>=
+if ="@use " then { writechunk(lastxreflabel, lastxrefref, "i", tab(0))
+ <<clear [[lastxref*]]>> } else
+@
+Writing a chunk involves creating an anchor for it.
+The anchor is ``bare'' because it's always in an HTML-containing place.
+<<*>>=
+procedure writechunk(label, ref, tag, name, suffix)
+ /suffix := ""
+ writes(linklabelto(label, ref,
+ sgmlwrap(tag, "&lt;" || convquotes(name) || "&gt;" || suffix),
+ "bare"))
+ return
+end
+@
+<<others>>=
+if ="@quote" & pos(0) then { quoting := 1 ; writes(braw, "<code>") } else
+if ="@endquote" & pos(0) then { quoting := nil ; writes("</code>", eraw) } else
+<<others>>=
+if ="@file " then { filename := tab(0); <<clear [[lastxref*]]>> } else
+if ="@literal " then { writes(tab(0)) } else
+if ="@header html " then { <<write HTML header>> } else
+if ="@trailer html" & pos(0) then { <<write HTML trailer>> } else
+@
+<<write HTML header>>=
+writes("<html><head><title>", tab(0), "</title></head><body>")
+<<write HTML trailer>>=
+write("</body></html>")
+@
+<<@xref>>=
+if ="@xref " then {
+ if fun := tab(upto(' ')) then {move(1); arg := tab(0)}
+ else { fun := tab(0); arg := &null }
+ case fun of {
+ <<cases for @xref>>
+ default : (\arg|"") ? warn_unknown("xref " || fun)
+ }
+} else
+@
+[[useitemstab]] seems to exist to enable us to repeat the
+uses for each chunk, even though the [[noidx]] filter only provides them once.
+I think it may prove better to provide use information for each instance
+of a chunk.
+<<cases for @xref>>=
+"label" : { <<warn if unused [[lastxreflabel]]>>; lastxreflabel := arg }
+"ref" : { <<warn if unused [[lastxrefref]]>>; lastxrefref := arg }
+"prevdef" : pendingprev := arg
+"nextdef" : pendingnext := arg
+"beginuses" : useitems := []
+"useitem" : put(useitems, arg)
+"enduses" : useitemstab[\thischunk] := useitems
+"notused" : notused := arg
+<<clear [[lastxref*]]>>=
+every lastxreflabel | lastxrefref := &null
+<<warn if unused [[lastxreflabel]]>>=
+warn_unused_xref("label", \lastxreflabel)
+<<warn if unused [[lastxrefref]]>>=
+warn_unused_xref("ref", \lastxrefref)
+<<*>>=
+procedure warn_unused_xref(tag, label)
+ static warned
+ initial warned := set()
+ if not member(warned, tag) then {
+ insert(warned, tag)
+ write(&errout, "Warning: internal inconsistency in noweb (not urgent)---")
+ write(&errout, "\tnever used @xref ", tag, " ", label)
+ }
+ return
+end
+@
+<<show definitions and uses on definition line---once>>=
+if \shortxref & (\pendinguses | \pendingprev | \pendingnext | \notused) then {
+ <<write out definition-line markup>>
+ pendinguses := pendingprev := pendingnext := notused := &null
+}
+<<write out definition-line markup>>=
+if \pendinguses & *\useitems > 0 then {
+ writes(" <b>(")
+ every i := 1 to *\useitems do {
+ usedir := if member(defns_above, useitems[i]) then "&lt;-U" else "U-&gt;"
+ writes(if i > 1 then " " else "", linkto(useitems[i], usedir))
+ }
+ writes(")</b>")
+}
+if \pendingprev | \pendingnext then {
+ writes(" <b>[")
+ writes(linkto(\pendingprev, "&lt;-"))
+ writes("D")
+ writes(linkto(\pendingnext, "-&gt;"))
+ writes("]</b>")
+}
+<<dump pending cross-reference info (long form)>>=
+if /shortxref then {
+ useitems := useitemstab[\thischunk]
+ if \pendingprev | \pendingnext | (\pendinguses, (*\useitems > 0 | \notused)) then {
+ <<code-to-blockquote>>
+ <<write out uses with links>>
+ useitemstab[\thischunk]
+ if *\useitems > 0 & (\pendingprev | \pendingnext) then
+ writes("; ")
+ p := if *\useitems > 0 then "previous" else "Previous"
+ n := if *\useitems > 0 then "next" else "Next"
+ if \pendingprev then
+ if \pendingnext then
+ writes(linkto(pendingprev, p), " and ",
+ linkto(pendingnext, "next"), " definitions")
+ else
+ writes(linkto(pendingprev, p), " definition")
+ else
+ if \pendingnext then
+ writes(linkto(pendingnext, n), " definition")
+ if \pendingprev | \pendingnext | *\useitems > 0 then
+ writes(".")
+ if \notused then
+ writes("<br>\nThis code is written to a file (or else not used).")
+ write("<p>")
+ pendinguses := pendingprev := pendingnext := useitems := notused := &null
+ }
+} else
+ &null
+<<write out uses with links>>=
+useprefix := "Used "
+every i := 1 to *\useitems do {
+ usedir := if member(defns_above, useitems[i]) then "above" else "below"
+ usesuffix := if *\useitems > 1 then " (" || i || ")" else ""
+ writes(useprefix, linkto(useitems[i], usedir || usesuffix))
+ useprefix := ", "
+}
+<<reset cross-reference info>>=
+useitems := []
+notused := &null
+@
+The hack here is to put the supplementary information in a blockquote area
+after the code.
+<<code-to-blockquote>>=
+if ecode == "</pre>" then {
+ writes("</pre><blockquote>")
+ ecode := "</blockquote>"
+}
+@
+The HTML back end ignores [[@xref begindefs]], [[@xref defitem]], and
+[[@xref enddefs]]; it uses the [[nextdef]] and [[prevdef]] links instead.
+<<cases for @xref>>=
+"begindefs" | "defitem" | "enddefs" : &null
+@
+<<cases for @xref>>=
+"beginchunks" : { write(braw, "<ul>") }
+"chunkbegin" : { writes("<li>"); comma := ": "; count := 0
+ arg ? { ref := tab(upto(' ')); =" "; name := tab(0) }
+ writechunk(&null, ref, "i", name) }
+"chunkuse" : { writes(comma, linkto(arg, "U" || (count +:= 1))); comma := ", " }
+"chunkdefn" : { writes(comma, linkto(arg, "D" || (count +:= 1))); comma := ", " }
+"chunkend" : write()
+"endchunks" : write("</ul>", eraw)
+<<cases for @index>>=
+"beginindex" : { write(braw, "<ul>") }
+"entrybegin" : { writes("<li>"); comma := ": "; count := 0
+ arg ? { ref := tab(upto(' ')); =" "; name := tab(0) }
+ writes(linklabelto("NWI-" || escapeSpecials(name), ref, name, "b")) }
+"entryuse" : { writes(comma, linkto(arg, "U" || (count +:= 1))); comma := ", " }
+"entrydefn" : { writes(comma, linkto(arg, "D" || (count +:= 1))); comma := ", " }
+"entryend" : write()
+"endindex" : write("</ul>", eraw)
+<<@index>>=
+if ="@index " then {
+ if /noindex then {
+ if fun := tab(upto(' ')) then {move(1); arg := tab(0)}
+ else { fun := tab(0); arg := &null }
+ case fun of {
+ <<cases for @index>>
+ default : (\arg|"") ? warn_unknown("index " || fun)
+ }
+ }
+ # don't get any warnings if not doing indexing
+} else
+@
+The local identifier cross-reference doesn't show each use; it just shows
+the identifiers that are defined, with links to the full index.
+<<cases for @index>>=
+"use" : { lastindexref := lastxrefref; lastxrefref := &null }
+"defn" : { <<clear [[lastxref*]]>> }
+"localdefn" : { <<clear [[lastxref*]]>> }
+"nl" : &null # do nothing -- no hope of keeping line numbering
+@
+I tried an abbreviated index format at the end of the chunk, but it looks
+so bad that I've punted on it (for now). Hence the [[\uglyindex]].
+<<cases for @index>>=
+"begindefs" : if \localindex then {
+ <<dump pending cross-reference info (long form)>>
+ if /uglyindex | /shortxref then {
+ <<code-to-blockquote>>
+ writes("Defines ")
+ } else {
+ writes("<hr><b>[</b>")
+ }
+ comma := ""
+ }
+"isused" : &null
+"defitem" : if \localindex then {
+ writes(comma, linkto("NWI-" || escapeSpecials(arg),
+ sgmlwrap("code", escapeSpecials(arg))))
+ comma := if /uglyindex | /shortxref then ", " else "<b>,</b> "
+ }
+"enddefs" : if \localindex then
+ write(if /uglyindex | /shortxref then " (links are to index).<p>"
+ else "<b>]</b>")
+"beginuses" | "isdefined" | "useitem" | "enduses" : &null # use local links
+@
+\subsection{Support functions}
+Here's all our anchor support goo.
+Unless the anchor is deemed ``bare,'' the beginning and ending tags
+are protected with [[braw]] and [[eraw]].
+This step is necessary to make \verb=noweave -latex+html= work without
+trapping {\LaTeX} markup in a \texttt{rawhtml} environment.
+<<*>>=
+procedure linklabelto(label, ref, contents, bare)
+ local s
+ s := if \bare then "" else braw
+ s ||:= if \label | \ref then "<a" else ""
+ s ||:= " name=" || image(\label)
+ s ||:= " href=" || image("#" || \ref)
+ s ||:= if \label | \ref then ">" else ""
+ s ||:= if \bare then "" else eraw
+ s ||:= contents
+ s ||:= if \bare then "" else braw
+ s ||:= if \label | \ref then "</a>" else ""
+ s ||:= if \bare then "" else eraw
+ return s
+end
+@
+Here are two abbreviations.
+<<*>>=
+procedure linklabel(label, contents, bare)
+ return linklabelto(label, &null, contents, bare)
+end
+
+procedure linkto(ref, contents)
+ return linklabelto(&null, ref, contents, "bare")
+end
+@ [[linkto]] is always used ``bare,'' and I've decided that the
+inconsistency in calling conversions is worth the savings from not
+having to write a meaningless argument everywhere.
+Reasonable people could disagree.
+@
+Another support function is used for wrapping tags around text:
+<<*>>=
+procedure sgmlwrap(tag, s)
+ return "<" || tag || ">" || s || "</" || tag || ">"
+end
+@
+Lucky for us, {\tt HTML} has few special characters. Unlucky for us,
+we have to deal with each one seperately. Nothing much to whine
+about, really.
+<<*>>=
+procedure escapeSpecials (l)
+ static escapes, specials
+ initial {escapes := table();
+ escapes["&"] := "&amp;"
+ escapes["<"] := "&lt;"
+ escapes[">"] := "&gt;"
+ escapes["\""] := "&quot;"
+ specials := ''
+ every specials ++:= key(escapes)
+ }
+ s := ""
+ l ? {
+ while s ||:= tab(upto(specials)) do
+ s ||:= escapes[move(1)]
+ return s || tab(0)
+ }
+end
+@
+A special function is used to implement {\tt noweb}'s quoting
+convention within chunk names.
+<<*>>=
+procedure convquotes(s)
+ r := ""
+ s ? { # don't call escapeSpecials on s; it destroys internal markup
+ while r ||:= tab(find("[[")) do {
+ ="[[" | fatal("impossible missing [[")
+ r ||:= "<code>" || tab(find("]]"))
+ r ||:= tab(many(']')-2)
+ ="]]" | fatal("impossible missing ]] in ", image(s))
+ r ||:= "</code>"
+ }
+ return r || tab(0)
+ }
+end
+@
+<<*>>=
+procedure warn_unknown(tag)
+ static warned
+ initial warned := set()
+ if not member(warned, tag) then {
+ write(&errout, "Warning: unrecognized escape @", tag, " ", tab(0))
+ insert(warned, tag)
+ }
+ return
+end
+@
+<<*>>=
+procedure fatal(L[])
+ write!([&errout, "noweb error in tohtml: "] ||| L)
+ exit(1)
+end
+@
+\end{document}
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: tohtml.nw,v 1.22 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+@
diff --git a/web/noweb/src/icon/totex.icn b/web/noweb/src/icon/totex.icn
new file mode 100644
index 0000000000..353f695656
--- /dev/null
+++ b/web/noweb/src/icon/totex.icn
@@ -0,0 +1,456 @@
+#line 5 "totex.nw"
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+#line 11 "totex.nw"
+procedure rcsinfo ()
+ return "$Id: totex.nw,v 1.21 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+global headercomment, realwrite
+procedure main(args)
+ local delay, name
+
+#line 46 "totex.nw"
+text := 1
+#line 135 "totex.nw"
+useitemstab := table()
+#line 149 "totex.nw"
+defns := table("")
+#line 336 "totex.nw"
+TeXspecials := '\\{}$&#^_ ~%'
+#line 19 "totex.nw"
+ delay := !args == "-delay"
+ noindex := !args == "-noindex"
+ if !args == "-no-gen-comment" then &null
+ else {realwrite := write; write := firstwrite}
+ while inputline := read() do inputline ? {
+
+#line 82 "totex.nw"
+if ="@text " then { text +:= *(line := tab(0))
+ writes(if \quoting then
+#line 88 "totex.nw"
+if /noindex & \lastindexref then
+ "\\nwlinkedidentq{" || TeXliteral(line) || "}{" || lastindexref || "}"
+else
+ TeXliteral(line)
+#line 84 "totex.nw"
+ else if \code then
+#line 93 "totex.nw"
+if /noindex & \lastindexref then
+ "\\nwlinkedidentc{" || escape(line, '{}\\') || "}{" || lastindexref || "}"
+else
+ escape(line, '{}\\')
+
+#line 85 "totex.nw"
+ else line)
+ lastindexref := &null } else
+#line 99 "totex.nw"
+if ="@nl" & pos(0) then { if /code then {
+#line 115 "totex.nw"
+if text = 0 then writes("\\nwdocspar")
+text := 1
+#line 99 "totex.nw"
+ }
+ if \quoting then writes("\\nwnewline")
+
+#line 201 "totex.nw"
+if \pendinguses | \pendingprev | \pendingnext then {
+ writes("\\nwstartdeflinemarkup")
+
+#line 208 "totex.nw"
+if \pendinguses then {
+ dumpitems(useitems, "nwusesondefline")
+}
+if \pendingprev | \pendingnext then {
+ writes("\\nwprevnextdefs{", \pendingprev | "\\relax", "}{",
+ \pendingnext | "\\relax", "}")
+}
+#line 204 "totex.nw"
+ writes("\\nwenddeflinemarkup")
+ pendinguses := pendingprev := pendingnext := &null
+}
+#line 102 "totex.nw"
+ write() } else
+#line 71 "totex.nw"
+if ="@begin code " then { code := 1 ; writes("\\nwbegincode{", tab(0), "}")
+
+#line 177 "totex.nw"
+every defitems | useitems := []
+notused := &null
+#line 72 "totex.nw"
+ } else
+if ="@end code " then {
+#line 184 "totex.nw"
+dumpitems(defitems, "nwalsodefined")
+dumpitems(useitems, "nwused")
+writes("\\nwnotused{", \notused, "}")
+#line 177 "totex.nw"
+every defitems | useitems := []
+notused := &null
+#line 74 "totex.nw"
+ code := &null ; writes("\\nwendcode{}")
+ lastdefnlabel := pendingprev := pendingnext := &null } else
+#line 122 "totex.nw"
+if ="@defn " then { writes("\\sublabel{", \lastxreflabel, "}")
+ writes("\\nwmargintag{", label2tag(\lastxreflabel), "}")
+ writes("\\moddef{", convquotes(thischunk := tab(0)),
+ ("~" || label2tag(\lastxrefref)) | "",
+ "}\\", defns[thischunk], "endmoddef")
+ useitems := \useitemstab[thischunk]
+ pendinguses := 1
+ lastdefnlabel := lastxreflabel
+
+#line 216 "totex.nw"
+every lastxreflabel | lastxrefref := &null
+#line 131 "totex.nw"
+ defns[thischunk] := "plus" } else
+#line 77 "totex.nw"
+if ="@begin docs " then { if \delay & match(0) then
+#line 110 "totex.nw"
+&null
+#line 77 "totex.nw"
+
+ else {text := 0; writes("\\nwbegindocs{",tab(0),"}")} } else
+if ="@end docs " then { if \delay & match(0) then
+#line 112 "totex.nw"
+{ writes("\\nwfilename{", filename, "}"); delay := &null }
+#line 79 "totex.nw"
+
+ else writes("\\nwenddocs{}") } else
+#line 137 "totex.nw"
+if ="@use " then { writes("\\LA{}", convquotes(name := tab(0)),
+ ("~" || label2tag(\lastxrefref)) | "",
+ "\\RA{}")
+
+#line 216 "totex.nw"
+every lastxreflabel | lastxrefref := &null
+#line 140 "totex.nw"
+ } else
+#line 175 "totex.nw"
+if ="@xref " then {
+#line 189 "totex.nw"
+if ="label " then { lastxreflabel := tab(0) } else
+if ="ref " then { lastxrefref := tab(0) } else
+if ="begindefs" & pos(0) then { } else
+if ="defitem " then { put(defitems, tab(0)) } else
+if ="enddefs" & pos(0) then { } else
+if ="beginuses" & pos(0) then { useitems := [] } else
+if ="useitem " then { put(useitems, tab(0)) } else
+if ="enduses" & pos(0) then { useitemstab[thischunk] := useitems } else
+if ="notused " then { notused := tab(0) } else
+if ="nextdef " then { pendingnext := tab(0) } else
+if ="prevdef " then { pendingprev := tab(0) } else
+#line 294 "totex.nw"
+if ="beginchunks" & pos(0) then { } else
+if ="chunkbegin " then { label := tab(upto(' ')); =" "
+ writes("\\nwixlogsorted{c}{{", convquotes(tab(0)),
+ "}{", label, "}{") } else
+if ="chunkuse " then { writes("\\nwixu{", tab(0), "}") } else
+if ="chunkdefn " then { writes("\\nwixd{", tab(0), "}") } else
+if ="chunkend" & pos(0) then { write("}}%") } else
+if ="endchunks" & pos(0) then { } else
+#line 175 "totex.nw"
+
+#line 218 "totex.nw"
+warn_unknown("xref " || tab(upto(' \t') | 0))
+#line 175 "totex.nw"
+ } else
+#line 232 "totex.nw"
+if ="@index " then {
+#line 240 "totex.nw"
+if ="nl" & pos(0) then { write(if \code then "\\eatline" else "%")}else
+if =("defn "|"localdefn ") then
+#line 244 "totex.nw"
+/noindex &
+#line 241 "totex.nw"
+ {
+#line 253 "totex.nw"
+writes("\\nosublabel{", \lastxreflabel, "}")
+writes("\\nwindexdefn{\\nwixident{", TeXliteral(name := tab(0)), "}}{", indexlabel(name), "}{",
+ \lastxrefref, "}")
+#line 216 "totex.nw"
+every lastxreflabel | lastxrefref := &null
+#line 241 "totex.nw"
+ } else
+if ="use " then
+#line 244 "totex.nw"
+/noindex &
+#line 242 "totex.nw"
+ {
+#line 261 "totex.nw"
+if /code & /quoting then {
+ writes("\\protect\\nosublabel{", \lastxreflabel, "}")
+ writes("\\protect\\nwindexuse{\\nwixident{", TeXliteral(name := tab(0)), "}}{",
+ indexlabel(name), "}{", \lastxrefref, "}")
+}
+lastindexref := lastxrefref
+#line 216 "totex.nw"
+every lastxreflabel | lastxrefref := &null
+#line 242 "totex.nw"
+ } else
+#line 272 "totex.nw"
+if ="begindefs" & pos(0) then
+#line 244 "totex.nw"
+/noindex &
+#line 272 "totex.nw"
+ {
+#line 184 "totex.nw"
+dumpitems(defitems, "nwalsodefined")
+dumpitems(useitems, "nwused")
+writes("\\nwnotused{", \notused, "}")
+#line 177 "totex.nw"
+every defitems | useitems := []
+notused := &null
+#line 273 "totex.nw"
+ writes("\\nwidentdefs{") } else
+if ="isused " then
+#line 244 "totex.nw"
+/noindex &
+#line 274 "totex.nw"
+ { "handled by latex" } else
+if ="defitem " then
+#line 244 "totex.nw"
+/noindex &
+#line 275 "totex.nw"
+ { i := tab(0);
+#line 284 "totex.nw"
+writes("\\\\{{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}}")
+#line 275 "totex.nw"
+ } else
+if ="enddefs" & pos(0) then
+#line 244 "totex.nw"
+/noindex &
+#line 276 "totex.nw"
+ { writes("}") } else
+if ="beginuses" & pos(0) then
+#line 244 "totex.nw"
+/noindex &
+#line 277 "totex.nw"
+ {
+#line 184 "totex.nw"
+dumpitems(defitems, "nwalsodefined")
+dumpitems(useitems, "nwused")
+writes("\\nwnotused{", \notused, "}")
+#line 177 "totex.nw"
+every defitems | useitems := []
+notused := &null
+#line 278 "totex.nw"
+ writes("\\nwidentuses{"); ulist := [] } else
+if ="isdefined " then
+#line 244 "totex.nw"
+/noindex &
+#line 279 "totex.nw"
+ { "latex finds the definitions" } else
+if ="useitem " then
+#line 244 "totex.nw"
+/noindex &
+#line 280 "totex.nw"
+ { i := tab(0);
+#line 284 "totex.nw"
+writes("\\\\{{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}}")
+#line 280 "totex.nw"
+
+ put(ulist, i); } else
+if ="enduses" & pos(0) then
+#line 244 "totex.nw"
+/noindex &
+#line 282 "totex.nw"
+ { writes("}");
+#line 286 "totex.nw"
+every i := !ulist do
+ writes("\\nwindexuse{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}{", \lastdefnlabel, "}")
+#line 282 "totex.nw"
+ } else
+#line 303 "totex.nw"
+if ="beginindex" & pos(0) then
+#line 244 "totex.nw"
+/noindex &
+#line 303 "totex.nw"
+ { } else
+if ="entrybegin " then
+#line 244 "totex.nw"
+/noindex &
+#line 304 "totex.nw"
+ { label := tab(upto(' ')); =" "; name := tab(0)
+ write("\\nwixlogsorted{i}{{\\nwixident{", TeXliteral(name),
+ "}}{", indexlabel(name), "}}%") } else
+if ="entryuse " then
+#line 244 "totex.nw"
+/noindex &
+#line 307 "totex.nw"
+ { "handled by latex" } else
+if ="entrydefn " then
+#line 244 "totex.nw"
+/noindex &
+#line 308 "totex.nw"
+ { "handled by latex" } else
+if ="entryend" & pos(0) then
+#line 244 "totex.nw"
+/noindex &
+#line 309 "totex.nw"
+ { } else
+if ="endindex" & pos(0) then
+#line 244 "totex.nw"
+/noindex &
+#line 310 "totex.nw"
+ { } else
+#line 232 "totex.nw"
+
+#line 234 "totex.nw"
+warn_unknown("index " || tab(upto(' \t') | 0))
+#line 232 "totex.nw"
+ } else
+#line 153 "totex.nw"
+if ="@quote" & pos(0) then { quoting := 1 ; writes("{\\Tt{}") } else
+if ="@endquote" & pos(0) then { quoting := &null ; writes("\\nwendquote}") } else
+if ="@file " then { filename := tab(0);
+#line 216 "totex.nw"
+every lastxreflabel | lastxrefref := &null
+#line 156 "totex.nw"
+ \delay | writes("\\nwfilename{", filename, "}")
+ } else
+if ="@line " then { } else
+if ="@literal " then { writes(tab(0)) } else
+if ="@header latex " then {
+#line 165 "totex.nw"
+writes("\\documentclass{article}\\usepackage{noweb}\\pagestyle{noweb}\\noweboptions{", tab(0),
+ "}\\begin{document}")
+#line 160 "totex.nw"
+ } else
+if ="@header tex " then { writes("\\input nwmac ") } else
+if ="@trailer latex" & pos(0) then { write("\\end{document}") } else
+if ="@trailer tex" & pos(0) then { write("\\bye") } else
+#line 61 "totex.nw"
+if ="@fatal " then { # follows last else
+ # write(&errout, "Noweb error in stage ", tab(upto(' ')), ":", tab(0))
+ exit(1)
+} else if ="@" then
+ warn_unknown(1(tab(upto(' ')|0), pos(0) | move(1)))
+else
+ write(&errout, "Botched line in noweb pipeline: ", tab(0))
+#line 25 "totex.nw"
+ }
+ write()
+end
+#line 142 "totex.nw"
+procedure label2tag(label)
+ return "{\\nwtagstyle{}\\subpageref{" || label || "}}"
+end
+#line 220 "totex.nw"
+procedure dumpitems(items, cs)
+ if *\items > 0 then {
+ writes("\\", cs, "{")
+ every writes("\\\\{", !items, "}")
+ writes("}")
+ return
+ } else
+ fail
+end
+#line 316 "totex.nw"
+procedure firstwrite(L[])
+ write := realwrite
+ put(L,
+ "% ===> this file was generated automatically by noweave --- better not edit it")
+ return write!L
+end
+#line 325 "totex.nw"
+procedure escape(line, chars, prefix)
+ /prefix := "\\"
+ line ? {
+ s := ""
+ while s ||:= tab(upto(chars)) do s ||:= prefix || move(1)
+ return s || tab(0)
+ }
+end
+#line 334 "totex.nw"
+global TeXspecials
+#line 357 "totex.nw"
+procedure TeXliteral(arg)
+ static nospace, code
+ initial { codes := ["\\", "nwbackslash",
+ "{", "nwlbrace",
+ "}", "nwrbrace",
+ "$", "$",
+ "&", "&",
+ "#", "#",
+ "^", "char94",
+ "_", "_",
+ "%", "%",
+ "~", "char126"]
+ code := table()
+ while (c := get(codes), n := get(codes)) do code[c] := string(n)
+ if c := !TeXspecials & c ~== " " & not member(code, c) then
+ fatal("internal error, character-code mismatch, report a bug!")
+ }
+ s := ""
+ arg ? {
+ while s ||:= tab(upto(TeXspecials)) do {
+ c := move(1)
+ if member(code, c) then
+ s ||:= "{\\" || code[c] || "}"
+ else
+ s ||:= "\\" || c
+ }
+ return s || tab(0)
+ }
+end
+#line 390 "totex.nw"
+procedure convquotes(s)
+ r := ""
+ s ? {
+ while r ||:= tab(find("[[")) do {
+ ="[[" | fatal("impossible missing [[")
+ r ||:= "\\code{}" || TeXliteral(tab(find("]]")))
+ r ||:= tab(many(']')-2)
+ ="]]" | fatal("impossible missing ]]")
+ r ||:= "\\edoc{}"
+ }
+ return r || tab(0)
+ }
+end
+#line 404 "totex.nw"
+procedure warn_unknown(tag)
+ static warned
+ initial warned := set()
+ if not member(warned, tag) then {
+ write(&errout, "Warning: unrecognized escape @", tag, " ", tab(0))
+ insert(warned, tag)
+ }
+ return
+end
+#line 416 "totex.nw"
+procedure indexlabel(ident)
+ static badset, trans
+ initial {
+
+#line 430 "totex.nw"
+trans := table()
+trans[" "] := "sp" # space
+trans["#"] := "has" # hash
+trans["$"] := "do" # dollar
+trans["%"] := "pe" # percent
+trans["&"] := "am" # ampersand
+trans[","] := "com" # commad
+trans[":"] := "col" # colon
+trans["\\"] := "bs" # backslash
+trans["^"] := "hat" # hat
+trans["_"] := "un" # underscore
+trans["{"] := "lb" # left brace
+trans["}"] := "rb" # right brace
+trans["~"] := "ti" # tilde
+#line 420 "totex.nw"
+ badset := ''
+ every badset ++:= key(trans)
+ }
+ ident ? {
+ s := ""
+ while s ||:= tab(upto(badset)) do s ||:= ":" || trans[move(1)]
+ return s || tab(0)
+ }
+end
+#line 445 "totex.nw"
+procedure fatal(L[])
+ write!([&errout, "noweb error in tohtml: "] ||| L)
+ exit(1)
+end
+
diff --git a/web/noweb/src/icon/totex.nw b/web/noweb/src/icon/totex.nw
new file mode 100644
index 0000000000..0b3200aae7
--- /dev/null
+++ b/web/noweb/src/icon/totex.nw
@@ -0,0 +1,450 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+\section{Converting {\tt noweb} markup to {\TeX} markup (Icon version)}
+The copyright applies both to the {\tt noweb} source and to the
+generated shell script.
+<<copyright notice>>=
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+@
+Here's the organization of the source:
+<<*>>=
+<<copyright notice>>
+procedure rcsinfo ()
+ return "$Id: totex.nw,v 1.21 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+global headercomment, realwrite
+procedure main(args)
+ local delay, name
+ <<initialization>>
+ delay := !args == "-delay"
+ noindex := !args == "-noindex"
+ if !args == "-no-gen-comment" then &null
+ else {realwrite := write; write := firstwrite}
+ while inputline := read() do inputline ? {
+ <<scan and convert>>
+ }
+ write()
+end
+@ The markup carefully adds no newlines not already present in the input,
+so that the line numbers of the {\TeX} file will be the same as the
+numbers of the corresponding {\tt noweb} file.
+The variables are:
+\begin{description}
+\item[\tt code] Nonnull if converting a code chunk.
+\item[\tt quoting] Nonnull if quoting code in documentation.
+\item[\tt text] Number of characters written since start of
+ documentation chunk.
+\end{description}
+[[text]] is used to write [[\nwdocspar]] if a newline appears at the
+beginning of a documentation chunk without any intervening text.
+This subtle trick preserves new-paragraph semantics without requiring
+the insertion of a blank line that would throw off the line count.
+The special control sequences makes a page break at that spot especially likely,
+so that small documentation chunks will appear on the some page as the code
+chunks they precede.
+<<initialization>>=
+text := 1
+@ %def text
+
+Ordering helps improve speed, so I write things in a funny order.
+This whole code is a giant [[if ... then ... else if ...]].
+<<scan and convert>>=
+<<@text>>
+<<@nl>>
+<<code chunks>>
+<<@defn>>
+<<docs chunks>>
+<<@use>>
+<<@xref>>
+<<@index>>
+<<others>>
+if ="@fatal " then { # follows last else
+ # write(&errout, "Noweb error in stage ", tab(upto(' ')), ":", tab(0))
+ exit(1)
+} else if ="@" then
+ warn_unknown(1(tab(upto(' ')|0), pos(0) | move(1)))
+else
+ write(&errout, "Botched line in noweb pipeline: ", tab(0))
+@
+\subsection{Basic text and chunk boundaries}
+<<code chunks>>=
+if ="@begin code " then { code := 1 ; writes("\\nwbegincode{", tab(0), "}")
+ <<reset cross-reference info>> } else
+if ="@end code " then { <<dump pending cross-reference info>>
+ code := &null ; writes("\\nwendcode{}")
+ lastdefnlabel := pendingprev := pendingnext := &null } else
+<<docs chunks>>=
+if ="@begin docs " then { if \delay & match(0) then <<delay for [[@begin docs]]>>
+ else {text := 0; writes("\\nwbegindocs{",tab(0),"}")} } else
+if ="@end docs " then { if \delay & match(0) then <<delay for [[@end docs]]>>
+ else writes("\\nwenddocs{}") } else
+<<@text>>=
+if ="@text " then { text +:= *(line := tab(0))
+ writes(if \quoting then <<possibly indexed quoted [[line]]>>
+ else if \code then <<possibly indexed code [[line]]>>
+ else line)
+ lastindexref := &null } else
+<<possibly indexed quoted [[line]]>>=
+if /noindex & \lastindexref then
+ "\\nwlinkedidentq{" || TeXliteral(line) || "}{" || lastindexref || "}"
+else
+ TeXliteral(line)
+<<possibly indexed code [[line]]>>=
+if /noindex & \lastindexref then
+ "\\nwlinkedidentc{" || escape(line, '{}\\') || "}{" || lastindexref || "}"
+else
+ escape(line, '{}\\')
+
+<<@nl>>=
+if ="@nl" & pos(0) then { if /code then {<<print [[\nwdocspar]] if no [[text]]>>}
+ if \quoting then writes("\\nwnewline")
+ <<show definitions and uses on definition line---once>>
+ write() } else
+@
+Delaying markup is handled by special patterns for the first document chunk.
+Because several {\tt noweb} files can be marked up at once, there can be
+several document chunks numbered 0.
+The later ones are given no special treatment by the simple expedient of
+turning [[delay]] off after the first one.
+<<delay for [[@begin docs]]>>=
+&null
+<<delay for [[@end docs]]>>=
+{ writes("\\nwfilename{", filename, "}"); delay := &null }
+@
+<<print [[\nwdocspar]] if no [[text]]>>=
+if text = 0 then writes("\\nwdocspar")
+text := 1
+@
+\subsection{Chunk definitions and uses, with possible cross-reference}
+Here we start to see the cross-reference markup, driven by [[lastxreflabel]]
+and [[lastxrefref]].
+<<@defn>>=
+if ="@defn " then { writes("\\sublabel{", \lastxreflabel, "}")
+ writes("\\nwmargintag{", label2tag(\lastxreflabel), "}")
+ writes("\\moddef{", convquotes(thischunk := tab(0)),
+ ("~" || label2tag(\lastxrefref)) | "",
+ "}\\", defns[thischunk], "endmoddef")
+ useitems := \useitemstab[thischunk]
+ pendinguses := 1
+ lastdefnlabel := lastxreflabel
+ <<clear [[lastxref*]]>>
+ defns[thischunk] := "plus" } else
+@ [[useitemstab]] enables us to show uses even on later instances of a chunk,
+although the index filter only provides uses with the first chunk.
+<<initialization>>=
+useitemstab := table()
+<<@use>>=
+if ="@use " then { writes("\\LA{}", convquotes(name := tab(0)),
+ ("~" || label2tag(\lastxrefref)) | "",
+ "\\RA{}")
+ <<clear [[lastxref*]]>> } else
+<<*>>=
+procedure label2tag(label)
+ return "{\\nwtagstyle{}\\subpageref{" || label || "}}"
+end
+@
+[[defns]] serves only to give the proper distinction between
+[[\endmoddef]] and [[\plusendmoddef]].
+<<initialization>>=
+defns := table("")
+@
+\subsection{Quoting, headers, trailers, \& miscellany}
+<<others>>=
+if ="@quote" & pos(0) then { quoting := 1 ; writes("{\\Tt{}") } else
+if ="@endquote" & pos(0) then { quoting := &null ; writes("\\nwendquote}") } else
+if ="@file " then { filename := tab(0); <<clear [[lastxref*]]>>
+ \delay | writes("\\nwfilename{", filename, "}")
+ } else
+if ="@line " then { } else
+if ="@literal " then { writes(tab(0)) } else
+if ="@header latex " then { <<write {\LaTeX} header>> } else
+if ="@header tex " then { writes("\\input nwmac ") } else
+if ="@trailer latex" & pos(0) then { write("\\end{document}") } else
+if ="@trailer tex" & pos(0) then { write("\\bye") } else
+<<write {\LaTeX} header>>=
+writes("\\documentclass{article}\\usepackage{noweb}\\pagestyle{noweb}\\noweboptions{", tab(0),
+ "}\\begin{document}")
+@
+\subsection{Cross-reference and index support}
+
+\subsubsection{Chunk cross-reference}
+We begin with basic cross-reference [[@xref label]] and [[@xref ref]],
+then show the chunk cross-reference that comes at the end of a code chunk.
+The {\LaTeX} back end ignores [[@xref nextdef]] and [[@xref prevdef]].
+<<@xref>>=
+if ="@xref " then { <<@xref tests>> <<bad @xref>> } else
+<<reset cross-reference info>>=
+every defitems | useitems := []
+notused := &null
+@
+By resetting the cross-reference info after dumping,
+we make it possible to dump both before index stuff and before
+end of chunk, without having to do any checking.
+<<dump pending cross-reference info>>=
+dumpitems(defitems, "nwalsodefined")
+dumpitems(useitems, "nwused")
+writes("\\nwnotused{", \notused, "}")
+<<reset cross-reference info>>
+<<@xref tests>>=
+if ="label " then { lastxreflabel := tab(0) } else
+if ="ref " then { lastxrefref := tab(0) } else
+if ="begindefs" & pos(0) then { } else
+if ="defitem " then { put(defitems, tab(0)) } else
+if ="enddefs" & pos(0) then { } else
+if ="beginuses" & pos(0) then { useitems := [] } else
+if ="useitem " then { put(useitems, tab(0)) } else
+if ="enduses" & pos(0) then { useitemstab[thischunk] := useitems } else
+if ="notused " then { notused := tab(0) } else
+if ="nextdef " then { pendingnext := tab(0) } else
+if ="prevdef " then { pendingprev := tab(0) } else
+<<show definitions and uses on definition line---once>>=
+if \pendinguses | \pendingprev | \pendingnext then {
+ writes("\\nwstartdeflinemarkup")
+ <<write out definition-line markup>>
+ writes("\\nwenddeflinemarkup")
+ pendinguses := pendingprev := pendingnext := &null
+}
+<<write out definition-line markup>>=
+if \pendinguses then {
+ dumpitems(useitems, "nwusesondefline")
+}
+if \pendingprev | \pendingnext then {
+ writes("\\nwprevnextdefs{", \pendingprev | "\\relax", "}{",
+ \pendingnext | "\\relax", "}")
+}
+<<clear [[lastxref*]]>>=
+every lastxreflabel | lastxrefref := &null
+<<bad @xref>>=
+warn_unknown("xref " || tab(upto(' \t') | 0))
+<<*>>=
+procedure dumpitems(items, cs)
+ if *\items > 0 then {
+ writes("\\", cs, "{")
+ every writes("\\\\{", !items, "}")
+ writes("}")
+ return
+ } else
+ fail
+end
+@
+\subsubsection{Identifier cross-reference, i.e.\ index}
+<<@index>>=
+if ="@index " then { <<@index tests>> <<bad @index>> } else
+<<bad @index>>=
+warn_unknown("index " || tab(upto(' \t') | 0))
+@
+This first round of stuff just handles the basics: definitions, uses, and newlines.
+Unless it's OK to show the index (by \LA{}SI\RA), we handle nothing but
+\hbox{[[@index nl]]}.
+<<@index tests>>=
+if ="nl" & pos(0) then { write(if \code then "\\eatline" else "%")}else
+if =("defn "|"localdefn ") then <<SI>> { <<handle index defn>> } else
+if ="use " then <<SI>> { <<handle index use>> } else
+<<SI>>=
+/noindex &
+@
+Nothing is involved in handling definitions and uses unless there are cross-reference
+labels pending.
+An index definition or use has its own [[@xref label]] only if it's in documentation;
+if it's in code, we use the anchor label of the definition.
+(You don't have to know that to understand what happens here, but I thought you
+might like to.)
+<<handle index defn>>=
+writes("\\nosublabel{", \lastxreflabel, "}")
+writes("\\nwindexdefn{\\nwixident{", TeXliteral(name := tab(0)), "}}{", indexlabel(name), "}{",
+ \lastxrefref, "}")
+<<clear [[lastxref*]]>>
+@
+The {\LaTeX} back end ignores uses in code; they get bundled up by a previous filter
+(the cross-referencer) and handled elsewhere.
+<<handle index use>>=
+if /code & /quoting then {
+ writes("\\protect\\nosublabel{", \lastxreflabel, "}")
+ writes("\\protect\\nwindexuse{\\nwixident{", TeXliteral(name := tab(0)), "}}{",
+ indexlabel(name), "}{", \lastxrefref, "}")
+}
+lastindexref := lastxrefref
+<<clear [[lastxref*]]>>
+@
+Here's the local identifier cross-reference that appears at the end of a code chunk.
+We guard everything with \LA{}SI\RA, as before.
+<<@index tests>>=
+if ="begindefs" & pos(0) then <<SI>> { <<dump pending cross-reference info>>
+ writes("\\nwidentdefs{") } else
+if ="isused " then <<SI>> { "handled by latex" } else
+if ="defitem " then <<SI>> { i := tab(0); <<write [[i]] with [[\\]]>> } else
+if ="enddefs" & pos(0) then <<SI>> { writes("}") } else
+if ="beginuses" & pos(0) then <<SI>> { <<dump pending cross-reference info>>
+ writes("\\nwidentuses{"); ulist := [] } else
+if ="isdefined " then <<SI>> { "latex finds the definitions" } else
+if ="useitem " then <<SI>> { i := tab(0); <<write [[i]] with [[\\]]>>
+ put(ulist, i); } else
+if ="enduses" & pos(0) then <<SI>> { writes("}"); <<write [[ulist]]>> } else
+<<write [[i]] with [[\\]]>>=
+writes("\\\\{{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}}")
+<<write [[ulist]]>>=
+every i := !ulist do
+ writes("\\nwindexuse{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}{", \lastdefnlabel, "}")
+@
+\subsubsection{The list of chunks and the index}
+The treatments of the list of chunks and the index are similar.
+Both use [[\nwixlogsorted]], which writes magic goo into the {\tt .aux} file.
+The real cross-referencing is done by the underlying {\LaTeX} code.
+<<@xref tests>>=
+if ="beginchunks" & pos(0) then { } else
+if ="chunkbegin " then { label := tab(upto(' ')); =" "
+ writes("\\nwixlogsorted{c}{{", convquotes(tab(0)),
+ "}{", label, "}{") } else
+if ="chunkuse " then { writes("\\nwixu{", tab(0), "}") } else
+if ="chunkdefn " then { writes("\\nwixd{", tab(0), "}") } else
+if ="chunkend" & pos(0) then { write("}}%") } else
+if ="endchunks" & pos(0) then { } else
+<<@index tests>>=
+if ="beginindex" & pos(0) then <<SI>> { } else
+if ="entrybegin " then <<SI>> { label := tab(upto(' ')); =" "; name := tab(0)
+ write("\\nwixlogsorted{i}{{\\nwixident{", TeXliteral(name),
+ "}}{", indexlabel(name), "}}%") } else
+if ="entryuse " then <<SI>> { "handled by latex" } else
+if ="entrydefn " then <<SI>> { "handled by latex" } else
+if ="entryend" & pos(0) then <<SI>> { } else
+if ="endindex" & pos(0) then <<SI>> { } else
+@
+\subsection{HEader comments}
+This godawful hack slips in a comment without messing up our line
+numbers.
+<<*>>=
+procedure firstwrite(L[])
+ write := realwrite
+ put(L,
+ "% ===> this file was generated automatically by noweave --- better not edit it")
+ return write!L
+end
+@
+\subsection{Utility procedures}
+<<*>>=
+procedure escape(line, chars, prefix)
+ /prefix := "\\"
+ line ? {
+ s := ""
+ while s ||:= tab(upto(chars)) do s ||:= prefix || move(1)
+ return s || tab(0)
+ }
+end
+<<*>>=
+global TeXspecials
+<<initialization>>=
+TeXspecials := '\\{}$&#^_ ~%'
+@
+I can't use [[\\char`\%]] and similar sequences with latex2e, because
+[[`]] is an active character that suppresses ligatures. So I got TeX to print out the
+actual character codes for me.
+This string ([['\\{}$&#^_ ~%']]) should serve as a test.
+
+Unfortunately, the character codes for these characters are not the
+same across fonts. While this is not a problem when everything is in
+a typewriter font, it can cause major strangenesses when another font
+is used (Icon, for example, is often typeset in a sans-serif font).
+Codes for `[[$]]', `[[&]]', `[[#]]', `[[^]]', `[[_]]', `[[~]]' and
+`[[%]]' use
+font-independent macros. Since there is no font-independent way to
+typeset `[[\]]', `[[{]]' and `[[}]]',\footnote{Although both plain
+\TeX\ and \LaTeX\ provide `[[\{]]' and `[[\}]], plain \TeX\ only
+allows their use in math mode.}
+we generate special macros defined in \verb"noweb.sty" and
+\verb"nwmac.tex". The default definitions are geared to typewriter
+fonts, but they can be redefined as necessary.
+<<*>>=
+procedure TeXliteral(arg)
+ static nospace, code
+ initial { codes := ["\\", "nwbackslash",
+ "{", "nwlbrace",
+ "}", "nwrbrace",
+ "$", "$",
+ "&", "&",
+ "#", "#",
+ "^", "char94",
+ "_", "_",
+ "%", "%",
+ "~", "char126"]
+ code := table()
+ while (c := get(codes), n := get(codes)) do code[c] := string(n)
+ if c := !TeXspecials & c ~== " " & not member(code, c) then
+ fatal("internal error, character-code mismatch, report a bug!")
+ }
+ s := ""
+ arg ? {
+ while s ||:= tab(upto(TeXspecials)) do {
+ c := move(1)
+ if member(code, c) then
+ s ||:= "{\\" || code[c] || "}"
+ else
+ s ||:= "\\" || c
+ }
+ return s || tab(0)
+ }
+end
+@
+A special function is used to implement {\tt noweb}'s quoting
+convention within chunk names.
+<<*>>=
+procedure convquotes(s)
+ r := ""
+ s ? {
+ while r ||:= tab(find("[[")) do {
+ ="[[" | fatal("impossible missing [[")
+ r ||:= "\\code{}" || TeXliteral(tab(find("]]")))
+ r ||:= tab(many(']')-2)
+ ="]]" | fatal("impossible missing ]]")
+ r ||:= "\\edoc{}"
+ }
+ return r || tab(0)
+ }
+end
+<<*>>=
+procedure warn_unknown(tag)
+ static warned
+ initial warned := set()
+ if not member(warned, tag) then {
+ write(&errout, "Warning: unrecognized escape @", tag, " ", tab(0))
+ insert(warned, tag)
+ }
+ return
+end
+@
+This gets special characters out of the labels used by identifiers.
+<<*>>=
+procedure indexlabel(ident)
+ static badset, trans
+ initial {
+ <<initialize [[trans]]>>
+ badset := ''
+ every badset ++:= key(trans)
+ }
+ ident ? {
+ s := ""
+ while s ||:= tab(upto(badset)) do s ||:= ":" || trans[move(1)]
+ return s || tab(0)
+ }
+end
+<<initialize [[trans]]>>=
+trans := table()
+trans[" "] := "sp" # space
+trans["#"] := "has" # hash
+trans["$"] := "do" # dollar
+trans["%"] := "pe" # percent
+trans["&"] := "am" # ampersand
+trans[","] := "com" # commad
+trans[":"] := "col" # colon
+trans["\\"] := "bs" # backslash
+trans["^"] := "hat" # hat
+trans["_"] := "un" # underscore
+trans["{"] := "lb" # left brace
+trans["}"] := "rb" # right brace
+trans["~"] := "ti" # tilde
+<<*>>=
+procedure fatal(L[])
+ write!([&errout, "noweb error in tohtml: "] ||| L)
+ exit(1)
+end
+
diff --git a/web/noweb/src/icon/xchunks.icn b/web/noweb/src/icon/xchunks.icn
new file mode 100644
index 0000000000..cf1a74b20e
--- /dev/null
+++ b/web/noweb/src/icon/xchunks.icn
@@ -0,0 +1,142 @@
+#line 31 "xchunks.nw"
+record chunk(lines, type)
+ # lines is all the lines of the chunk
+ # type is "code" or "docs" or "unknown"
+
+procedure main(args)
+ local merge, summary
+ while args[1][1] == "-" do
+ case args[1] of {
+ "-merge" : merge := get(args)
+ "-summary" : { get(args); summary := " (summary)" }
+ default : break
+ }
+ *args > 0 | stop("xchunks needs an external database")
+
+
+#line 136 "xchunks.nw"
+db := "markup"
+every db ||:= " " || !args
+db := open(db, "rp") | stop("cannot pipe from ", image(db))
+
+#line 47 "xchunks.nw"
+ dbchunks := readchunks(db)
+ defns := defnstable(dbchunks)
+ # defns maps name to list of code chunks defining that name
+ if \merge then
+ every merge_chunks(!defns)
+ if \summary then
+ every add_defn_string(!defns, summary)
+
+ thisdoc := readchunks(&input)
+ every c := !thisdoc do
+ if c.type ~== "code" | notEmpty(c) | /defns[chunkName(c)] then
+ every write(!c.lines)
+ else {
+ write("@crc_prefix on")
+ every write(!(!defns[chunkName(c)]).lines)
+ write("@crc_prefix off")
+ }
+end
+#line 69 "xchunks.nw"
+procedure readchunks(infile)
+ local chunks, c
+ local file, lnum, lines, startline
+ chunks := []
+ lnum := 1
+ while line := read(infile) do
+ line ?
+ if ="@file " then {
+ file := tab(0)
+ lnum := 1
+ } else if ="@line " then {
+ lnum := integer(tab(0))
+ } else if ="@begin " then {
+ lines := []
+ put(lines, "@file " || \file)
+ put(lines, "@line " || lnum)
+ put(lines, line)
+ startline := line
+ c := chunk(lines, tab(upto(' ')|0))
+ line := read(infile) | stop("unmatched ", startline)
+ while line ? not ="@end " do {
+ put(c.lines, line)
+ line := read(infile) | stop("unmatched ", startline)
+ line ?
+ if ="@file " then { file := tab(0); lnum := 1 }
+ else if ="@line " then { lnum := integer(tab(0)) }
+ else if =("@nl"|"@index nl") & pos(0) then { lnum := lnum + 1 }
+ }
+ put(c.lines, line)
+ put(chunks, c)
+ } else {
+ put(chunks, chunk([line], "unknown"))
+ line ?
+ if ="@file " then { file := tab(0); lnum := 1 }
+ else if ="@line " then { lnum := integer(tab(0)) }
+ else if =("@nl"|"@index nl") & pos(0) then { lnum := lnum + 1 }
+ }
+ return chunks
+end
+#line 111 "xchunks.nw"
+procedure defnstable(chunks)
+ t := table()
+ every c := !chunks & c.type == "code" do {
+ /t[chunkName(c)] := []
+ put(t[chunkName(c)], c)
+ }
+ return t
+end
+#line 124 "xchunks.nw"
+procedure chunkName(c)
+ return (!c.lines ? (="@defn " & tab(0))) | stop("no @defn in code chunk")
+end
+
+procedure notEmpty(c)
+ static nonwhite
+ initial nonwhite := ~' \t'
+ return !c.lines ? ="@use " | (="@text ", upto(nonwhite))
+end
+#line 142 "xchunks.nw"
+procedure merge_chunks(chunks)
+ while *chunks > 1 do {
+ c := get(chunks)
+ strip_code_tail(c)
+ strip_code_head(chunks[1])
+ every put(c.lines, !chunks[1].lines)
+ chunks[1] := c
+ }
+ return chunks
+end
+#line 154 "xchunks.nw"
+procedure strip_code_tail(c)
+ if c.lines[-1] ? match("@end code") then
+ pull(c.lines)
+ else
+ stop("Unexpected line")
+ return c
+end
+
+procedure strip_code_head(c)
+ local pfx
+ pfx := []
+ if match("@begin code", c.lines[1]) then
+ get(c.lines)
+ else
+ stop("bad line " || c.lines[1])
+ while not match("@defn ", c.lines[1]) do
+ push(pfx, get(c.lines))
+ get(c.lines) | stop("this can't happen")
+ while c.lines[1] ~== "@nl" do
+ push(pfx, get(c.lines))
+ get(c.lines) | stop("this can't happen")
+ every push(c.lines, !pfx)
+ return c
+end
+#line 180 "xchunks.nw"
+procedure add_defn_string(chunks, s)
+ every c := !chunks & i := 1 to *c.lines do
+ if match("@defn ", c.lines[i]) then
+ c.lines[i] ||:= s
+ return chunks
+end
diff --git a/web/noweb/src/icon/xchunks.nw b/web/noweb/src/icon/xchunks.nw
new file mode 100644
index 0000000000..b3ef8fd98d
--- /dev/null
+++ b/web/noweb/src/icon/xchunks.nw
@@ -0,0 +1,186 @@
+% -*- mode: Noweb; noweb-code-mode: icon-mode -*-
+
+\section{Getting chunks from an external ``dictionary''}
+
+Mike Smith wants to do an unweblike thing: keep his code and
+documentation in separate source files.
+I~think he wants to do this so he can enable the \emph{same} code
+chunks to appear in \emph{multiple} documents, with guaranteed
+consistency, but I~suppose the reasons don't matter.
+In any case, he wants syntax for referring to a code chunk from an
+external database, and for displaying the definition(s) of that chunk
+exactly where he specifies.
+
+I~suggested solving the problem with a Noweb filter.
+He can refer to chunks using the approved source syntax:
+\texttt{[{}[<{}<}\emph{chunk name}\texttt{>{}>]{}]}.
+To pull in the definitions from the external database, I suggested he
+provide an empty definition.
+Since such a definition can be written in one line (two lines if the
+definition is followed by a documentation chunk), he can pull in many
+definitions concisely.
+
+This program is the noweb filter that does the job.
+Named ``\texttt{xchunks},'' short for ``external chunks,'' it pulls in
+definitions from an external database.
+The external database is itself simply a list of Noweb files.
+It's a bit more liberal than defined above; a chunk is considered
+empty if its definition contains at most whitespace.
+
+A late-breaking bug: we need to resynchronize line numbers.
+<<*>>=
+record chunk(lines, type)
+ # lines is all the lines of the chunk
+ # type is "code" or "docs" or "unknown"
+
+procedure main(args)
+ local merge, summary
+ while args[1][1] == "-" do
+ case args[1] of {
+ "-merge" : merge := get(args)
+ "-summary" : { get(args); summary := " (summary)" }
+ default : break
+ }
+ *args > 0 | stop("xchunks needs an external database")
+
+ <<let [[db]] be an open file giving the database pipeline from [[args]]>>
+
+ dbchunks := readchunks(db)
+ defns := defnstable(dbchunks)
+ # defns maps name to list of code chunks defining that name
+ if \merge then
+ every merge_chunks(!defns)
+ if \summary then
+ every add_defn_string(!defns, summary)
+
+ thisdoc := readchunks(&input)
+ every c := !thisdoc do
+ if c.type ~== "code" | notEmpty(c) | /defns[chunkName(c)] then
+ every write(!c.lines)
+ else {
+ write("@crc_prefix on")
+ every write(!(!defns[chunkName(c)]).lines)
+ write("@crc_prefix off")
+ }
+end
+@
+Reading chunks is fairly straightforward; we look for begin and end.
+The loop logic is a little less pleasant than I would like.
+<<*>>=
+procedure readchunks(infile)
+ local chunks, c
+ local file, lnum, lines, startline
+ chunks := []
+ lnum := 1
+ while line := read(infile) do
+ line ?
+ if ="@file " then {
+ file := tab(0)
+ lnum := 1
+ } else if ="@line " then {
+ lnum := integer(tab(0))
+ } else if ="@begin " then {
+ lines := []
+ put(lines, "@file " || \file)
+ put(lines, "@line " || lnum)
+ put(lines, line)
+ startline := line
+ c := chunk(lines, tab(upto(' ')|0))
+ line := read(infile) | stop("unmatched ", startline)
+ while line ? not ="@end " do {
+ put(c.lines, line)
+ line := read(infile) | stop("unmatched ", startline)
+ line ?
+ if ="@file " then { file := tab(0); lnum := 1 }
+ else if ="@line " then { lnum := integer(tab(0)) }
+ else if =("@nl"|"@index nl") & pos(0) then { lnum := lnum + 1 }
+ }
+ put(c.lines, line)
+ put(chunks, c)
+ } else {
+ put(chunks, chunk([line], "unknown"))
+ line ?
+ if ="@file " then { file := tab(0); lnum := 1 }
+ else if ="@line " then { lnum := integer(tab(0)) }
+ else if =("@nl"|"@index nl") & pos(0) then { lnum := lnum + 1 }
+ }
+ return chunks
+end
+@
+Building the definitions table is easy.
+<<*>>=
+procedure defnstable(chunks)
+ t := table()
+ every c := !chunks & c.type == "code" do {
+ /t[chunkName(c)] := []
+ put(t[chunkName(c)], c)
+ }
+ return t
+end
+@
+The basic functions [[chunkName]] and [[notEmpty]] require search.
+You could imagine caching these, but since they're called twice and at
+most once per chunk, respectively, I doubt it's worth it.
+<<*>>=
+procedure chunkName(c)
+ return (!c.lines ? (="@defn " & tab(0))) | stop("no @defn in code chunk")
+end
+
+procedure notEmpty(c)
+ static nonwhite
+ initial nonwhite := ~' \t'
+ return !c.lines ? ="@use " | (="@text ", upto(nonwhite))
+end
+@
+Finally, here's how we get the database.
+<<let [[db]] be an open file giving the database pipeline from [[args]]>>=
+db := "markup"
+every db ||:= " " || !args
+db := open(db, "rp") | stop("cannot pipe from ", image(db))
+@
+To merge adjacent definitions, we strip leading and trailing markup.
+<<*>>=
+procedure merge_chunks(chunks)
+ while *chunks > 1 do {
+ c := get(chunks)
+ strip_code_tail(c)
+ strip_code_head(chunks[1])
+ every put(c.lines, !chunks[1].lines)
+ chunks[1] := c
+ }
+ return chunks
+end
+@
+<<*>>=
+procedure strip_code_tail(c)
+ if c.lines[-1] ? match("@end code") then
+ pull(c.lines)
+ else
+ stop("Unexpected line")
+ return c
+end
+
+procedure strip_code_head(c)
+ local pfx
+ pfx := []
+ if match("@begin code", c.lines[1]) then
+ get(c.lines)
+ else
+ stop("bad line " || c.lines[1])
+ while not match("@defn ", c.lines[1]) do
+ push(pfx, get(c.lines))
+ get(c.lines) | stop("this can't happen")
+ while c.lines[1] ~== "@nl" do
+ push(pfx, get(c.lines))
+ get(c.lines) | stop("this can't happen")
+ every push(c.lines, !pfx)
+ return c
+end
+@
+<<*>>=
+procedure add_defn_string(chunks, s)
+ every c := !chunks & i := 1 to *c.lines do
+ if match("@defn ", c.lines[i]) then
+ c.lines[i] ||:= s
+ return chunks
+end
diff --git a/web/noweb/src/icon/yaccdefs.icn b/web/noweb/src/icon/yaccdefs.icn
new file mode 100644
index 0000000000..e0313651e8
--- /dev/null
+++ b/web/noweb/src/icon/yaccdefs.icn
@@ -0,0 +1,67 @@
+#line 2 "yaccdefs.nw"
+procedure rcsinfo ()
+ return "$Id: yaccdefs.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+procedure main(args)
+ go()
+end
+
+procedure postpass(name, arg)
+ static kind
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if id := tab(many(&letters)) then {
+ tab(many(' \t'))
+ if =":" & any(&letters ++ ' ([{') then writedefn(id)
+ }
+ }
+ return
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
+#line 1 "defns.nw"
+procedure go()
+ local line
+ while line := read() do {
+ apply(prepass, line)
+ write(line)
+ if match("@fatal ", line) then exit(1)
+ apply(postpass, line)
+ }
+end
+
+procedure apply(pass, line)
+ line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null))
+end
+#line 18 "defns.nw"
+procedure writedefn(defn, locl)
+ static indextext
+ initial indextext := ""
+ if /defn then
+ *indextext > 0 &
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 23 "defns.nw"
+ else {
+ if *indextext + *defn > 65 then
+#line 31 "defns.nw"
+{ # write("@index nl") # don't!
+ indextext := ""
+}
+#line 25 "defns.nw"
+ write(if \locl then "@index localdefn " else "@index defn ", defn)
+ indextext ||:= " " || defn
+ }
+ return
+end
+#line 35 "defns.nw"
+procedure rcsinfo_too ()
+ return "$Id: defns.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
diff --git a/web/noweb/src/icon/yaccdefs.nw b/web/noweb/src/icon/yaccdefs.nw
new file mode 100644
index 0000000000..596090cff5
--- /dev/null
+++ b/web/noweb/src/icon/yaccdefs.nw
@@ -0,0 +1,26 @@
+\section{Finding {\tt yacc} definitions}
+<<*>>=
+procedure rcsinfo ()
+ return "$Id: yaccdefs.nw,v 1.18 2008/10/06 01:03:05 nr Exp nr $" ||
+ "$Name: v2_12 $"
+end
+procedure main(args)
+ go()
+end
+
+procedure postpass(name, arg)
+ static kind
+ case name of {
+ "begin" : arg ? kind := tab(upto(' ')|0)
+ "text" : if kind == "code" then arg ?
+ if id := tab(many(&letters)) then {
+ tab(many(' \t'))
+ if =":" & any(&letters ++ ' ([{') then writedefn(id)
+ }
+ }
+ return
+end
+
+procedure prepass(name, arg)
+ if name == "end" then writedefn(&null) # force newline
+end
diff --git a/web/noweb/src/lib/Makefile b/web/noweb/src/lib/Makefile
new file mode 100644
index 0000000000..47cb6f40fe
--- /dev/null
+++ b/web/noweb/src/lib/Makefile
@@ -0,0 +1,38 @@
+# Copyright 1993 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+
+LIB=/dev/null
+SHELL=/bin/sh
+CINAME=
+CIMSG=
+RCSFILES=emptydefn toascii.nw unmarkup Makefile nwmtime pipedocs h2a btdefn
+
+all: toascii
+ chmod +x unmarkup emptydefn toascii nwmtime pipedocs h2a btdefn
+
+install: all
+ cp unmarkup emptydefn nwmtime btdefn $(LIB)
+ sed 's@|LIBDIR|@$(LIB)@g' pipedocs > $(LIB)/pipedocs
+ sed 's@|LIBDIR|@$(LIB)@g' toascii > $(LIB)/toascii
+ sed 's@|LIBDIR|@$(LIB)@g' h2a > $(LIB)/h2a
+ chmod +x $(LIB)/pipedocs $(LIB)/toascii $(LIB)/h2a
+
+uninstall:
+ for i in unmarkup emptydefn toascii nwmtime h2a btdefn; do rm -f $(LIB)/$$i; done
+ rm -f $(LIB)/pipedocs
+
+checkin:
+ ci -l $(CINAME) $(CIMSG) $(RCSFILES)
+
+source: toascii
+touch: toascii
+ touch toascii
+boot:
+ touch toascii
+
+toascii: toascii.nw
+ notangle -Rtoascii toascii.nw > toascii
+
+clean: ; rm -f *.log *.blg *.dvi *.toc *.aux *.tex *~
+clobber: clean
+ rm -f toascii
diff --git a/web/noweb/src/lib/btdefn b/web/noweb/src/lib/btdefn
new file mode 100755
index 0000000000..a7b2d1678d
--- /dev/null
+++ b/web/noweb/src/lib/btdefn
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# turn backticks into definitions
+
+nawk '
+/^@begin code / { code = 1 }
+/^@end code / { code = 0 }
+code && /^@text .*".*`.*"/ { print; next }
+code && /^@text .*`/ {
+ while (i = match($0, /`[a-zA-Z_][a-zA-Z0-9_]*/)) {
+ id = substr($0, i+1, RLENGTH-1)
+ sub(/`[a-zA-Z_][a-zA-Z0-9_]*/, id)
+ print "@index defn " id
+ }
+}
+{print}'
diff --git a/web/noweb/src/lib/emptydefn b/web/noweb/src/lib/emptydefn
new file mode 100755
index 0000000000..29499b147b
--- /dev/null
+++ b/web/noweb/src/lib/emptydefn
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+# notangle filter that makes the definition of an empty chunk <<>>=
+# stand for a continuation of the previous chunk definition.
+
+nawk 'BEGIN { lastdefn = "@defn " }
+/^@defn $/ { print lastdefn; next }
+/^@defn / { lastdefn = $0 }
+{ print }' "$@"
diff --git a/web/noweb/src/lib/h2a b/web/noweb/src/lib/h2a
new file mode 100755
index 0000000000..9aec5dc416
--- /dev/null
+++ b/web/noweb/src/lib/h2a
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+LIB=|LIBDIR|
+opts="-nolist"
+
+case $1 in
+ -[0-9]*) opts="$opts -width=`expr 0 - $1`" ; shift ;;
+esac
+
+html=$($LIB/nwmktemp) || { echo "$0: Cannot create temporary file" >&2; exit 1; }
+trap 'rm -f $html; exit 1' 1 2 15 # clean up files
+
+awk '
+/^ *$/ { if (NR == 1) { print ; next } }
+{ print > "'"$html"'" }'
+if [ -r $html ]; then lynx -dump $opts $html | sed '1d'; fi
+rm -f $html
diff --git a/web/noweb/src/lib/noxref.nw b/web/noweb/src/lib/noxref.nw
new file mode 100644
index 0000000000..3eec706bc7
--- /dev/null
+++ b/web/noweb/src/lib/noxref.nw
@@ -0,0 +1,215 @@
+\section{Cross-referencing tool}
+This filter adds labels and cross-references to chunk definitions and uses,
+and it converts the line [[\nowebchunks]] into an alphabetical list of chunks.
+
+Following the lead of J. G. Krom, I make it possible to generate the
+file [[noxref]] for the Unix environment, and the files [[noxref.bat]]
+and [[noxref.awk]] for the MS-DOS environment.
+
+<<*>>=
+#!/bin/sh
+nawk '<<cross-reference awk program>>'
+<<noxref.awk>>=
+<<cross-reference awk program>>
+<<noxref.bat>>=
+@echo off
+REM The NOWEB environment variable must be set to the directory
+REM where NOXREF.AWK is. It must end in '/' or '\' as required
+REM by the AWK interpreter in use.
+awk -f %NOWEB%noxref.awk
+@
+The function [[modid]] turns a chunk name into a unique key acceptable
+for use as a {\LaTeX} label.
+The first step maps the name into a 6-character key; the second step
+appends an integer (from [[keycounts]]) used to distinguish different
+chunk names that map to the same key.
+[[idtable]] is used to cache the results so the computation is
+performed just once per chunk name.
+<<function definitions>>=
+function modid(name, key) {
+ if (idtable[name] == "") {
+ key = name
+ gsub(/[\[\]\\{} `#%&~_^-]/, "*", key) # ditch special chars
+ if (length(key) > 6) key = substr(key,1,3) substr(key, length(key)-2, 3)
+ keycounts[key] = keycounts[key] + 1
+ if (keycounts[key] > 1)
+ idtable[name] = key "-" keycounts[key]
+ else
+ idtable[name] = key
+ }
+ return idtable[name]
+}
+<<initialization>>=
+idtable[0] = 0 ; keycounts[0] = 0
+@
+The complete program runs in two passes.
+The first pass saves all the input and builds up list of definitions
+and uses.
+The second pass writes out all the lines with suitable
+cross-referencing markup.
+The first pass saves information in the following tables, which are
+indexed by chunk name.
+\begin{itemize}
+\item[\tt defns] Lists labels of all defining instances.
+\item[\tt firstdef] Label of the first defining instance.
+\item[\tt dcounts] Counts the number of defining instances.
+\item[\tt uses] Lists labels of all uses.
+\item[\tt dcounts] Counts the number of uses.
+\end{itemize}
+<<initialization>>=
+defns[0] = 0 ; firstdef[0] = 0 ; dcounts[0] = 0 ; uses[0] = 0 ; ucounts[0] = 0
+@ The first pass logs both definitions ([[which == "DEFN"]]) and uses
+([[which == "USE"]]) by calling [[logname]].
+<<function definitions>>=
+function logname(which, tbl, counts, name, id, label) {
+ counts[name] = counts[name] + 1
+ id = which ":" curfile ":" modid(name) "-" counts[name]
+ tbl[name] = tbl[name] id " "
+ if (which == "DEFN" && counts[name] == 1) label = "sublabel"
+ else label = "label"
+ lines[nextline++] = "@literal \\" label "{" id "}"
+ if (which == "DEFN" && firstdef[name] == "") firstdef[name] = id
+}
+@
+The structure of the full program, showing both passes, is:
+<<cross-reference awk program>>=
+<<function definitions>>
+BEGIN { <<initialization>> }
+{ lines[nextline++] = $0 }
+/^@defn / { logname("DEFN", defns, dcounts, substr($0, 7)) }
+/^@use / { logname("USE", uses, ucounts, substr($0, 6)) }
+/^@file / { curfile = modid(substr($0, 7) substr($0, 10, 3)) }
+END { <<write out the program with cross-reference info>> }
+@
+The second pass just copies lines to its output, except for
+definitions, uses and the [[\nowebchunks]] control sequence.
+It also puts a bunch of cross-reference information at the end of each
+code chunk.
+<<write out the program with cross-reference info>>=
+for (i=0; i < nextline; i++) {
+ name = substr(lines[i], 2)
+ if (index(name, " ")) {
+ name = substr(name, 1, index(name, " ")-1)
+ arg = substr(lines[i], length(name)+3)
+ } else {
+ arg = ""
+ }
+ if (name == "defn") {
+ thischunk = arg
+ <<emit definition>>
+ } else if (name == "use") {
+ <<emit use>>
+ } else if (name == "begin") {
+ chunktype = substr(arg, 1, 4)
+ print lines[i]
+ } else if (name == "quote") {
+ quote = 1
+ print lines[i]
+ } else if (name == "endquote") {
+ quote = 0
+ print lines[i]
+ } else if (name == "end") {
+ if (chunktype == "code") {
+ <<emit cross-reference info for [[thischunk]]>>
+ }
+ print lines[i]
+ } else if (name == "text" && arg == "\\nowebchunks" && chunktype == "docs" && quote == 0) {
+ <<emit sorted list of chunks>>
+ } else {
+ print lines[i]
+ }
+ delete lines[i]
+}
+@
+\maybreak{1in}
+<<emit definition>>=
+printf "@defn %s~{\\footnotesize\\Rm\\subpageref{%s}}\n", arg, firstdef[arg]
+<<emit use>>=
+if (firstdef[arg] != "")
+ printf "@use %s~{\\footnotesize\\Rm\\subpageref{%s}}\n", arg, firstdef[arg]
+else
+ printf "@use %s~{\\footnotesize\\Rm (never defined)}\n", arg
+@
+Cross reference information is emitted only at the first definition of each
+chunk, as tracked by [[firstdefnout]].
+<<initialization>>=
+firstdefnout[0] = 0
+<<emit cross-reference info for [[thischunk]]>>=
+if (firstdefnout[thischunk] == 0) {
+ firstdefnout[thischunk] = 1
+ n = split(defns[thischunk], a)
+ if (n > 1) {
+ printf "@literal \\nwalsodefined{"
+ for (j = 2; j <= n; j++)
+ printf "\\\\{%s}", a[j]
+ printf "}\n"
+ }
+ if (uses[thischunk] != "") {
+ printf "@literal \\nwused{"
+ n = split(uses[thischunk], a)
+ for (j = 1; j <= n; j++)
+ printf "\\\\{%s}", a[j]
+ printf "}\n"
+ } else
+ printf "@literal \\nwnotused{%s}\n", escapeTeXspecials(thischunk)
+}
+@ \subsection{Sorting}
+Each chunk name is mapped to a sorting key.
+Ideally such a key would contain only lower-case letters and spaces,
+and it would discount \TeX{} control sequences, and more.
+Such computations are so excruciating in awk that I content myself
+with eliminating nonletters.
+<<function definitions>>=
+function sortkey(name, s) {
+ s = name
+ gsub(/[^a-zA-Z ]/, "", s)
+ return s
+}
+@ I maintain a two parallel lists, one containing sort keys and the other
+containing chunk names.
+<<function definitions>>=
+function insertchunk(name, i, tmp) {
+ sortcount = sortcount + 1
+ sortnames[sortcount] = name
+ sortkeys[sortcount] = sortkey(name)
+ i = sortcount
+ while (i > 1 && (sortkeys[i] < sortkeys[i-1] ||
+ sortkeys[i] == sortkeys[i-1] && sortnames[i] < sortnames[i-1])) {
+ tmp = sortkeys [i]; sortkeys [i] = sortkeys [i-1]; sortkeys [i-1] = tmp
+ tmp = sortnames[i]; sortnames[i] = sortnames[i-1]; sortnames[i-1] = tmp
+ i = i - 1
+ }
+}
+@
+That's enough machinery to do the job.
+<<emit sorted list of chunks>>=
+if (sortcount == 0) {
+ <<insert all chunk names into [[sortnames]]>>
+}
+for (j = 1; j <= sortcount; j++) {
+ if (firstdef[sortnames[j]] != "")
+ print "@use " sortnames[j] "~{\\footnotesize\\Rm\\subpageref{" firstdef[sortnames[j]] "}}"
+ else
+ print "@use " sortnames[j] "~{\\footnotesize\\Rm (never defined)}"
+ if (j < sortcount)
+ print "@literal \\\\"
+}
+<<insert all chunk names into [[sortnames]]>>=
+delete defns[0]
+for (c in defns) insertchunk(c)
+delete uses[0]
+for (c in uses) if (!(c in defns)) insertchunk(c)
+@
+<<function definitions>>=
+function escapeTeXspecials(name, l, r) {
+ r = name
+ l = ""
+ while (match(r, /[{}$%&#^_~\\]/) > 0) {
+ l = l substr(r, 1, RSTART-1) "\\" substr(r, RSTART, 1)
+ r = substr(r, RSTART+1)
+ }
+ return l r
+}
+@
+\subsection{List of chunk names}
+\nowebchunks
diff --git a/web/noweb/src/lib/noxref.sh b/web/noweb/src/lib/noxref.sh
new file mode 100644
index 0000000000..da09c46a55
--- /dev/null
+++ b/web/noweb/src/lib/noxref.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+nawk 'BEGIN { defns[0] = 0 ; uses[0] = 0 ; dcounts[0] = 0 ; firstdef[0] = 0;
+ ucounts[0] = 0 ; idtable[0] = 0 ; keycounts[0] = 0 ; firstdefnout[0] = 0;
+ filetable[0] = 0 }
+{ lines[nextline++] = $0 }
+/^@defn / { logname("DEFN", defns, dcounts, substr($0, 7)) }
+/^@use / { logname("USE", uses, ucounts, substr($0, 6)) }
+/^@file / { curfile = modid(substr($0, 7)) }
+
+function logname(which, tbl, counts, name, id) {
+ counts[name] = counts[name] + 1
+ id = which curfile "-" modid(name) "-" counts[name]
+ tbl[name] = tbl[name] id " "
+ lines[nextline++] = "@literal \\label{" id "}"
+ if (which == "DEFN" && firstdef[name] == "") firstdef[name] = id
+}
+
+function modid(name, key) {
+ if (idtable[name] == "") {
+ key = name
+ gsub(/[\[\]\\{} -]/, "*", key)
+ if (length(key) > 6) key = substr(key,1,3) substr(key, length(key)-2, 3)
+ keycounts[key] = keycounts[key] + 1
+ idtable[name] = key "-" keycounts[key]
+ }
+ return idtable[name]
+}
+
+END {
+ for (i=0; i < nextline; i++) {
+ name = substr(lines[i], 2)
+ name = substr(name, 1, index(name, " ")-1)
+ arg = substr(lines[i], length(name)+3)
+ if (name == "defn") {
+ thischunk = arg
+ printf "@defn %s~{\\footnotesize\\rm\\pageref{%s}}\n", arg, firstdef[arg]
+ } else if (name == "use") {
+ if (firstdef[arg] != "")
+ printf "@use %s~{\\footnotesize\\rm\\pageref{%s}}\n", arg, firstdef[arg]
+ else
+ printf "@use %s~{\\footnotesize\\rm (never defined)}\n", arg
+ } else if (name == "end") {
+ if (substr(arg, 1, 4) == "code" && firstdefnout[thischunk] == 0) {
+ firstdefnout[thischunk] = 1
+ n = split(defns[thischunk], a)
+ if (n > 1) {
+ printf "@literal \\alsodefined{"
+ for (j = 2; j <= n; j++)
+ printf "\\\\{%s}", a[j]
+ printf "}\n@nl\n"
+ }
+ if (uses[thischunk] != "") {
+ printf "@literal \\used{"
+ n = split(uses[thischunk], a)
+ for (j = 1; j <= n; j++)
+ printf "\\\\{%s}", a[j]
+ printf "}\n@nl\n"
+ } else
+ printf "@literal \\notused\n@nl\n"
+ }
+ print lines[i]
+ } else
+ print lines[i]
+ }
+}'
diff --git a/web/noweb/src/lib/nwmtime b/web/noweb/src/lib/nwmtime
new file mode 100755
index 0000000000..0d65b8a4b6
--- /dev/null
+++ b/web/noweb/src/lib/nwmtime
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# nwmtime -- emit defn of modification time of first file
+#
+
+eval 'exec perl -S $0 ${1+"$@"}'
+ if $running_under_some_shell;
+
+$first = 1;
+while(<>) {
+ print;
+ if ($first && /\@file\s*(\S+)/) {
+ $mtime_file = $1;
+ $first = 0;
+ }
+}
+
+if (!$first) {
+ my $filename = $mtime_file;
+ my $mtime;
+
+ # localtime if you really want local time...
+ $mtime = gmtime((stat $filename)[9]);
+ print <<EOF;
+\@begin code 000
+\@defn modification time of first \@file
+\@nl
+\@text $mtime
+\@nl
+\@end code 000
+EOF
+}
diff --git a/web/noweb/src/lib/pipedocs b/web/noweb/src/lib/pipedocs
new file mode 100755
index 0000000000..4205475a4f
--- /dev/null
+++ b/web/noweb/src/lib/pipedocs
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+
+nawk '
+BEGIN {
+ rcsid = "$I$"
+ rcsname = "$Name $"
+ cmd = "sed '"'"'/^@begin docs /s/[0-9][0-9]*/0/'"'"' | |LIBDIR|/unmarkup | '"$*"' | |LIBDIR|/markup | grep -v '"'"'^@file $'"'"'"
+}
+/^@begin docs / { piping = 1 }
+{ if (piping)
+ print | cmd
+ else
+ print
+}
+/^@end docs / {
+ piping = 0
+ close(cmd)
+}'
+
+
diff --git a/web/noweb/src/lib/toascii b/web/noweb/src/lib/toascii
new file mode 100755
index 0000000000..7df1ee32fb
--- /dev/null
+++ b/web/noweb/src/lib/toascii
@@ -0,0 +1,131 @@
+#!/bin/sh
+delay=0 noindex=0
+for i do
+ case $i in
+ -delay) delay=1 ;;
+ -noindex) noindex=1 ;;
+ *) echo "This can't happen -- $i passed to toascii" 1>&2 ; exit 1 ;;
+ esac
+done
+awkfile=$(mktemp)
+textfile=$(mktemp)
+tagsfile=$(mktemp)
+export awkfile textfile tagsfile
+trap 'rm -f $awkfile $textfile $tagsfile' 0 1 2 10 14 15
+nawk 'BEGIN { textfile=ENVIRON["textfile"]
+ tagsfile=ENVIRON["tagsfile"] }
+ /^@begin code/ { ++secno }
+ /^@xref label/ { print $3, secno >tagsfile }
+ /^@((begin|end) (docs|code))/ { print >textfile }
+ /^@(text|nl|defn|use)/ { print >textfile }
+ /^@xref (ref|notused)/ { print >textfile }
+ /^@xref (begin|end)(defs|uses)/ { print >textfile }
+ /^@xref (def|use)item/ { print >textfile}
+ /^@xref ((begin|end)chunks)|(chunk(begin|use|defn|end))/ { print >textfile }
+ /^@index (begin|end)(defs|uses)/ { print >textfile }
+ /^@index (is(us|defin)ed)|((def|use)item)/ { print >textfile }
+ /^@index ((begin|end)index)|(entry(begin|use|defn|end))/ { print >textfile }'
+nawk 'BEGIN {
+ textfile = ENVIRON["textfile"]
+ tagsfile = ENVIRON["tagsfile"]
+ tfmt="detex | fmt -79"
+ cfmt="expand -4 | fold -75 | sed \"s/^/ /\""
+ xfmt="fold -75 | sed \"s/^/ /\""
+ zfmt="cat"
+ while (getline <tagsfile > 0)
+ tag[$1] = $2
+ close(tagsfile)
+ }
+ /^@begin docs/ { out = tfmt }
+ /^@end docs/ { close(out) }
+ /^@begin code/ { out = cfmt; code = 1; ++secno }
+ /^@end code/ { endcode(); close(out); printf "\n" }
+ /^@text/ { printf "%s", substr($0, 7) | out }
+ /^@nl/ { # printf "(->%s)", formatname(out) | out ;
+ printf "\n" | out }
+ /^@xref ref/ { lastxrefref = tag[substr($0, 11)] }
+ /^@defn/ { name = convquote(substr($0, 7))
+ printf "\n### %d ### %s%s=",
+ secno, chunkname(name, lastxrefref), defn[name]
+ defn[name] = "+" }
+ /^@use/ { name = convquote(substr($0, 6))
+ printf "%s", chunkname(name, lastxrefref) | out }
+ /^@xref begindefs/ { endcode()
+ printf "This definition continued in" | out }
+ /^@xref beginuses/ { endcode()
+ printf "This code used in" | out }
+ /^@xref notused/ { endcode()
+ print "This code not used in this document." | out }
+ /^@xref (def|use)item/ { addlist(tag[$3]) }
+ /^@xref end(defs|uses)/ { printlist() }
+ $0 ~ /^@index begindefs/ && !noindex {
+ endcode()
+ print "Defines:" | out }
+
+ $0 ~ /^@index isused/ && !noindex {
+ if (tag[$3] != lastxrefref) addlist(tag[$3]) }
+
+ $0 ~ /^@index defitem/ && !noindex {
+ printf " %s,", $3 | out
+ if (nlist == 0) printf " not used in this document.\n" | out
+ else { printf " used in" | out; printlist() } }
+ $0 ~ /^@index beginuses/ && !noindex { endcode(); printf "Uses" | out }
+ $0 ~ /^@index isdefined/ && !noindex { lastuse = tag[$3] }
+ $0 ~ /^@index useitem/ && !noindex { addlist(sprintf("%s %s", $3, lastuse)) }
+ $0 ~ /^@index enduses/ && !noindex { printlist() }
+ /^@xref beginchunks/ { close(out); out = zfmt
+ print "List of code chunks\n" | out }
+ /^@xref chunkbegin/ { name = convquote(substr($0, length($3) + 19))
+ printf "%s\n", chunkname(name, tag[$3]) | out }
+ /^@xref chunkuse/ { addlist(tag[$3]) }
+ /^@xref chunkdefn/ { }
+ /^@xref chunkend/ { if (nlist == 0)
+ print " Not used in this document." | out
+ else { printf " Used in" | out; printlist() } }
+ /^@xref endchunks/ { }
+ $0 ~ /^@index beginindex/ && !noindex { print "\nList of identifiers (defini" \
+ "tion in parentheses)\n" | out }
+ $0 ~ /^@index entrybegin/ && !noindex { name = substr($0, length($3 + 19))
+ lastdefn = tag[$3]
+ printf "%s: ", $4 | out }
+ $0 ~ /^@index entryuse/ && !noindex { addlist(tag[$3]) }
+ $0 ~ /^@index entrydefn/ && !noindex { }
+ $0 ~ /^@index entryend/ && !noindex { for (i = 1; i <= nlist; i++)
+ if (list[i] == lastdefn)
+ sub(/.*/, "(&)", list[i])
+ if (nlist == 0)
+ print "Not used." | out
+ else printlist() }
+ $0 ~ /^@index endindex/ && !noindex { }
+ /^@fatal / { exit 1 }
+ END {
+ close(out)
+ }
+ function endcode() {
+ if (code == 1) {
+ code = 0
+ close(out)
+ out = xfmt
+ printf "\n" | out } }
+ function addlist(s, i) {
+ for (i = 1; i <= nlist; i++)
+ if (s == list[i]) return
+ list[++nlist] = s }
+
+ function printlist( i) {
+ if (nlist == 1) printf " %s.\n", list[1] | out
+ else if (nlist == 2) printf " %s and %s.\n", list[1], list[2] | out
+ else {
+ for (i = 1; i < nlist; i++)
+ printf " %s,", list[i] | out
+ printf " and %s.\n", list[nlist] | out }
+ for (i in list) delete list[i]
+ nlist = 0 }
+ function convquote(s) { gsub(/\[\[|\]\]/, "", s); return s }
+ function chunkname(name, number) {
+ if (number == 0)
+ return sprintf("<%s>", name)
+ else
+ return sprintf("<%s %d>", name, number)
+ }' noindex=$noindex $textfile
+exit $?
diff --git a/web/noweb/src/lib/toascii.nw b/web/noweb/src/lib/toascii.nw
new file mode 100644
index 0000000000..c76a7fd2ff
--- /dev/null
+++ b/web/noweb/src/lib/toascii.nw
@@ -0,0 +1,262 @@
+[[Toascii]] is a [[noweb]] back end for formatting text as a plain ascii file.
+It was written by Phil Bewig (pbewig@netcom.com) on March 31, 1995, and
+contributed to Norman Ramsey's [[noweb]] literate programming system.
+@
+The main program is shown below. Option [[-delay]] is processed, for
+compatibility with other back ends, but ignored; since the initial document
+chunk used with [[-delay]] normally contains only [[TeX]] formatting commands
+in limbo, and since those commands will be deleted before formatting, there is
+no need to handle [[-delay]].
+<<toascii>>=
+#!/bin/sh
+delay=0 noindex=0
+for i do
+ case $i in
+ -delay) delay=1 ;;
+ -noindex) noindex=1 ;;
+ *) echo "This can't happen -- $i passed to toascii" 1>&2 ; exit 1 ;;
+ esac
+done
+<<arrange temporary files>>
+<<invoke first pass using parameter>>
+<<invoke second pass using parameter>>
+exit $?
+@ %def delay noindex
+[[Toascii]] uses two temporary files, one for storing the text between passes
+and one for communicating the conversion of labels to tags. The files are
+named here, and disposal of the file on exit from [[toascii]] is arranged.
+Also arranged here is a temporary file for storage of the awk program on an
+ugly system, as discussed below.
+<<arrange temporary files>>=
+awkfile=$(mktemp)
+textfile=$(mktemp)
+tagsfile=$(mktemp)
+export awkfile textfile tagsfile
+trap 'rm -f $awkfile $textfile $tagsfile' 0 1 2 10 14 15
+@ %def textfile tagsfile awkfile
+The actual formatting of the text, code, and index entries is done by various
+unix text processing commands in pipelines. There are four formatting pipes:
+tfmt, which formats text, cfmt, which formats code, xfmt, which formats index
+entries within the running text, and zfmt, which formats the lists of chunks
+and identifiers at the end of the text. The formatters established below are
+only suggestions, and may be modified to suit local taste (and the presence of
+various text processing commands on the local machine!); in particular, [[c]]
+programmers may want to format code with cb or indent. The sed patterns below
+insert four blank spaces at the beginning of the line.
+<<initialize formatters>>=
+tfmt="detex | fmt -79"
+cfmt="expand -4 | fold -75 | sed \"s/^/ /\""
+xfmt="fold -75 | sed \"s/^/ /\""
+zfmt="cat"
+@ %def tfmt cfmt xfmt zfmt
+Forgiving systems allow the awk program to be specified as a parameter to the
+awk interpreter; ugly systems require that it be placed in a temporary file.
+The chunks below implement both options.
+<<invoke first pass using parameter>>=
+nawk '<<first pass>>'
+<<invoke second pass using parameter>>=
+nawk '<<second pass>>' noindex=$noindex $textfile
+<<invoke first pass using file>>=
+cat > $awkfile << 'EOF'
+<<first pass>>
+EOF
+nawk -f $awkfile
+<<invoke second pass using file>>=
+cat > $awkfile << 'EOF'
+<<second pass>>
+EOF
+nawk -f $awkfile noindex=$noindex $textfile
+@
+The first pass is responsible for extracting [[label]]s and assigning them
+section numbers, which are used for cross-referencing in the second pass. The
+first pass also removes from the input file those lines which are not used by
+the second pass.
+<<first pass>>=
+BEGIN { textfile=ENVIRON["textfile"]
+ tagsfile=ENVIRON["tagsfile"] }
+/^@begin code/ { ++secno }
+/^@xref label/ { print $3, secno >tagsfile }
+/^@((begin|end) (docs|code))/ { print >textfile }
+/^@(text|nl|defn|use)/ { print >textfile }
+/^@xref (ref|notused)/ { print >textfile }
+/^@xref (begin|end)(defs|uses)/ { print >textfile }
+/^@xref (def|use)item/ { print >textfile}
+/^@xref ((begin|end)chunks)|(chunk(begin|use|defn|end))/ { print >textfile }
+/^@index (begin|end)(defs|uses)/ { print >textfile }
+/^@index (is(us|defin)ed)|((def|use)item)/ { print >textfile }
+/^@index ((begin|end)index)|(entry(begin|use|defn|end))/ { print >textfile }
+@
+The second pass performs formatting. After looking up the temp file names and
+formatters in the environment and reading the [[tagsfile]] created in the first
+pass, the second pass processes each input command in the body of the awk
+[[pattern-action]] processing loop.
+<<second pass>>=
+BEGIN {
+ textfile = ENVIRON["textfile"]
+ tagsfile = ENVIRON["tagsfile"]
+ <<initialize formatters>>
+ while (getline <tagsfile > 0)
+ tag[$1] = $2
+ close(tagsfile)
+}
+<<process [[noweb]] commands>>
+/^@fatal / { exit 1 }
+END {
+ close(out)
+}
+<<functions>>
+@ %def tag
+The rest of the program consists of a series of awk [[pattern-action]]
+statements which each process a particular type of [[noweb]] pipeline command.
+They are discussed in related groups, and all collected in a single chunk. We
+begin with the commands that process the text of the document and code chunks.
+The basic strategy is always write text to [[out]] and open and close various
+pipes as needed. Variable [[code]] is true only within code chunks, and
+[[secno]] numbers the sections as they appear. Function [[endcode()]] closes
+the code pipeline at the end of a code section or whenever the first indexing
+command appears.
+<<process [[noweb]] commands>>=
+/^@begin docs/ { out = tfmt }
+/^@end docs/ { close(out) }
+/^@begin code/ { out = cfmt; code = 1; ++secno }
+/^@end code/ { endcode(); close(out); printf "\n" }
+/^@text/ { printf "%s", substr($0, 7) | out }
+/^@nl/ { # printf "(->%s)", formatname(out) | out ;
+ printf "\n" | out }
+@ %def out secno code
+<<functions>>=
+function endcode() {
+ if (code == 1) {
+ code = 0
+ close(out)
+ out = xfmt
+ printf "\n" | out } }
+@ %def endcode
+Definitions and uses of code chunks are handled below. Variable [[defn[name]]]
+is set to a plus sign after a definition is printed, so that continuations of
+the definition are properly identified. Variable [[lastxrefref]] is the tag
+associated with the most-recently-seen cross-reference label, and refers to the
+section number of the original definition of the code chunk. Definition lines
+are printed directly, without passing through any of the formatters defined
+above.
+<<process [[noweb]] commands>>=
+/^@xref ref/ { lastxrefref = tag[substr($0, 11)] }
+/^@defn/ { name = convquote(substr($0, 7))
+ printf "\n### %d ### %s%s=",
+ secno, chunkname(name, lastxrefref), defn[name]
+ defn[name] = "+" }
+/^@use/ { name = convquote(substr($0, 6))
+ printf "%s", chunkname(name, lastxrefref) | out }
+@ %def lastxref name defn
+There are three messages related to the definition and use of code chunks which
+may appear in the output: "This definition continued in ...", "This code used
+in ...", and "This code not used in this document." These messages are printed
+by the following code.
+<<process [[noweb]] commands>>=
+/^@xref begindefs/ { endcode()
+ printf "This definition continued in" | out }
+/^@xref beginuses/ { endcode()
+ printf "This code used in" | out }
+/^@xref notused/ { endcode()
+ print "This code not used in this document." | out }
+/^@xref (def|use)item/ { addlist(tag[$3]) }
+/^@xref end(defs|uses)/ { printlist() }
+@
+Processing of the [[noweb]] commands which produce the identifier definition
+message "Defines: ... used in ..." is performed by the following code. The
+[[if]] in [[@index isused]] prevents index definitions from pointing to
+themselves.
+<<process [[noweb]] commands>>=
+$0 ~ /^@index begindefs/ && !noindex {
+ endcode()
+ print "Defines:" | out }
+
+$0 ~ /^@index isused/ && !noindex {
+ if (tag[$3] != lastxrefref) addlist(tag[$3]) }
+
+$0 ~ /^@index defitem/ && !noindex {
+ printf " %s,", $3 | out
+ if (nlist == 0) printf " not used in this document.\n" | out
+ else { printf " used in" | out; printlist() } }
+@
+Processing of the [[noweb]] commands which produce the identifier usage message
+"Uses ..." is performed by the following code.
+<<process [[noweb]] commands>>=
+$0 ~ /^@index beginuses/ && !noindex { endcode(); printf "Uses" | out }
+$0 ~ /^@index isdefined/ && !noindex { lastuse = tag[$3] }
+$0 ~ /^@index useitem/ && !noindex { addlist(sprintf("%s %s", $3, lastuse)) }
+$0 ~ /^@index enduses/ && !noindex { printlist() }
+@ %def lastuse
+The [[noweb]] commands which print the list of chunks at the end of the
+document are processed by the following code.
+<<process [[noweb]] commands>>=
+/^@xref beginchunks/ { close(out); out = zfmt
+ print "List of code chunks\n" | out }
+/^@xref chunkbegin/ { name = convquote(substr($0, length($3) + 19))
+ printf "%s\n", chunkname(name, tag[$3]) | out }
+/^@xref chunkuse/ { addlist(tag[$3]) }
+/^@xref chunkdefn/ { }
+/^@xref chunkend/ { if (nlist == 0)
+ print " Not used in this document." | out
+ else { printf " Used in" | out; printlist() } }
+/^@xref endchunks/ { }
+@
+The [[noweb]] commands which print the list of identifiers at the end of the
+document are processed by the following code.
+<<process [[noweb]] commands>>=
+$0 ~ /^@index beginindex/ && !noindex { print "\nList of identifiers (defini" \
+ "tion in parentheses)\n" | out }
+$0 ~ /^@index entrybegin/ && !noindex { name = substr($0, length($3 + 19))
+ lastdefn = tag[$3]
+ printf "%s: ", $4 | out }
+$0 ~ /^@index entryuse/ && !noindex { addlist(tag[$3]) }
+$0 ~ /^@index entrydefn/ && !noindex { }
+$0 ~ /^@index entryend/ && !noindex { for (i = 1; i <= nlist; i++)
+ if (list[i] == lastdefn)
+ sub(/.*/, "(&)", list[i])
+ if (nlist == 0)
+ print "Not used." | out
+ else printlist() }
+$0 ~ /^@index endindex/ && !noindex { }
+@
+Several of the cross-reference and indexing commands use the [[addlist(s)]] and
+[[printlist()]] functions to manage the printing of lists of code sections and
+variable names: [[addlist(s)]] adds string [[s]] to a queued [[list]] waiting
+to be printed and [[printlist()]] prints the [[list]], appropriately formatted
+with commas. These two functions are described below.
+<<functions>>=
+function addlist(s, i) {
+ for (i = 1; i <= nlist; i++)
+ if (s == list[i]) return
+ list[++nlist] = s }
+
+function printlist( i) {
+ if (nlist == 1) printf " %s.\n", list[1] | out
+ else if (nlist == 2) printf " %s and %s.\n", list[1], list[2] | out
+ else {
+ for (i = 1; i < nlist; i++)
+ printf " %s,", list[i] | out
+ printf " and %s.\n", list[nlist] | out }
+ for (i in list) delete list[i]
+ nlist = 0 }
+@ %def list nlist addlist printlist
+Chunk names which appear in definitions and uses of chunks consist of text
+which may contain quoted code embedded between double square brackets. Quoted
+code in text chunks are handled by the [[@quote ... @endquote]] mechanism, but
+quoted code in chunk names must be handled explicitly by the back end. The
+function below does what is needed.
+<<functions>>=
+function convquote(s) { gsub(/\[\[|\]\]/, "", s); return s }
+@ %def convquote
+
+<<functions>>=
+function chunkname(name, number) {
+ if (number == 0)
+ return sprintf("<%s>", name)
+ else
+ return sprintf("<%s %d>", name, number)
+}
+@ %def chunkname
+@
+<nowebchunks>
+<nowebindex>
diff --git a/web/noweb/src/lib/unmarkup b/web/noweb/src/lib/unmarkup
new file mode 100755
index 0000000000..761fc14897
--- /dev/null
+++ b/web/noweb/src/lib/unmarkup
@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+
+nawk '
+BEGIN {
+ rcsid = "$Id: unmarkup,v 1.20 2008/10/06 01:03:05 nr Exp $"
+ rcsname = "$Name: $"
+ firstdoc = 1
+}
+/^@begin docs / { if (!firstdoc) printf "@ "; firstdoc = 0 }
+/^@begin code / { code = 1 }
+/^@end [cd]o[dc][es] / {
+ code = 0
+ if (dangling_text) printf "\n"
+ dangling_text = 0
+ printf "%s", deflines
+ if (defline != "") printf "%s\n", defline
+ deflines = "" ; defline = ""
+ }
+/^@defn / { printf "<<%s>>=", substr($0,7) }
+/^@text $/ {next}
+/^@text / {
+ gsub("<<", "@<<");
+ gsub(">>", "@>>");
+ if (!(code || quoting)) {
+ gsub(/\[\[/, "@[[");
+ gsub(/\]\]/, "@]]");
+ }
+ printf "%s", substr($0,7)
+ dangling_text = 1
+}
+/^@quote$/ { printf("[["); dangling_text = 1; quoting = 1 }
+/^@endquote$/ { printf("]]"); dangling_text = 1; quoting = 0 }
+/^@nl$/ { printf "\n"; dangling_text = 0}
+
+/^@index defn / {
+ if (defline == "") defline = "@ %def"
+ defline = defline " " substr($0, 13)
+}
+/^@index nl$/ {
+ deflines = deflines defline "\n"
+ defline = ""
+}
+/^@use / { printf "<<%s>>", substr($0,6)
+ dangling_text = 1
+ }' "$@" | sed 's/^@ $/@/'
diff --git a/web/noweb/src/limake b/web/noweb/src/limake
new file mode 100755
index 0000000000..150840afc9
--- /dev/null
+++ b/web/noweb/src/limake
@@ -0,0 +1,3 @@
+#!/bin/sh
+if [ $# -eq 0 ]; then set all install; fi # "$@" breaks make for empty args
+/usr/bin/make CC="gcc -ansi -pedantic -O -Wall -Werror" LIBSRC=icon BIN=/usr/local/noweb/bin LIB=/usr/local/noweb/lib MAN=/usr/local/noweb/man TEXINPUTS=/usr/share/texmf/tex/plain/misc ELISP=$HOME/emacs "$@"
diff --git a/web/noweb/src/nwmake b/web/noweb/src/nwmake
new file mode 100644
index 0000000000..eb9e71ea61
--- /dev/null
+++ b/web/noweb/src/nwmake
@@ -0,0 +1,3 @@
+#!/bin/sh
+if [ $# -eq 0 ]; then set iconlib all install; fi # "$@" breaks make for empty args
+/bin/make CC="lcc -A -A" BIN=/usr/local/bin LIB=/usr/local/lib/noweb MAN=/usr/local/man TEXINPUTS=/usr/local/lib/tex/inputs "$@"
diff --git a/web/noweb/src/rhmake b/web/noweb/src/rhmake
new file mode 100755
index 0000000000..4694987aff
--- /dev/null
+++ b/web/noweb/src/rhmake
@@ -0,0 +1,3 @@
+#!/bin/sh
+if [ $# -eq 0 ]; then set all install; fi # "$@" breaks make for empty args
+/usr/bin/make CC="lcc -A" LIBSRC=icon BIN=/usr/local/noweb/bin LIB=/usr/local/noweb/lib MAN=/usr/local/noweb/man TEXINPUTS=/usr/share/texmf/tex/latex/local ELISP=$HOME/emacs "$@"
diff --git a/web/noweb/src/shell/Makefile b/web/noweb/src/shell/Makefile
new file mode 100644
index 0000000000..e28d7b5659
--- /dev/null
+++ b/web/noweb/src/shell/Makefile
@@ -0,0 +1,35 @@
+# Copyright 1993 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+SHELL=/bin/sh
+LIB=/usr/public/pkg/noweb/lib
+
+EXEC=noweave noweb notangle noroff toroff
+SRCS=$(EXEC) tmac.w
+RCSFILES=noweave.nw notangle.nw noweb.nw noroff.nw noroots nocount Makefile
+CINAME=
+CIMSG=
+
+all: $(SRCS)
+source: $(SRCS)
+touch: $(SRCS)
+ touch $(SRCS)
+boot:
+ touch $(SRCS)
+
+checkin:
+ ci -l $(CINAME) $(CIMSG) $(RCSFILES)
+
+noweave: noweave.nw
+ notangle -Rnoweave noweave.nw > noweave
+
+notangle: notangle.nw
+ notangle -Rnotangle notangle.nw > notangle
+
+noweb: noweb.nw
+ notangle -Rnoweb noweb.nw > noweb
+
+noroff toroff tmac.w: roff.nw
+ noweb -t roff.nw
+
+clean: ; rm -f *.log *.blg *.dvi *.toc *.aux *.tex *~ *.nwt roff.mm
+clobber: clean ; rm -f $(SRCS)
diff --git a/web/noweb/src/shell/cpif b/web/noweb/src/shell/cpif
new file mode 100644
index 0000000000..d304e204f5
--- /dev/null
+++ b/web/noweb/src/shell/cpif
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# cpif [ -eq -ne ] file...
+# copy standard input to each of the named files
+# if new * old is true or old doesn't exist;
+# * defaults to -ne
+
+PATH=/bin:/usr/bin
+LIB=|LIBDIR|
+
+# set -x
+op=-ne
+case "$1" in
+-eq|-ne) op=$1; shift ;;
+-*) echo 'Usage: '`basename $0`' [ -eq -ne ] file...' 1>&2; exit 2
+esac
+case $# in
+0) echo 'Usage: '`basename $0`' [ -eq -ne ] file...' 1>&2; exit 2
+esac
+
+new=$($LIB/nwmktemp)
+trap 'rm -f $new; exit 1' 1 2 15 # clean up files
+
+cat >$new
+for i
+do
+ cmp -s $new $i
+ case $op$? in
+ -eq0|-ne1|*2) cp $new $i || { rm -f $new; exit 1; }
+ esac
+done
+rm -f $new
diff --git a/web/noweb/src/shell/detangle b/web/noweb/src/shell/detangle
new file mode 100644
index 0000000000..741afd4654
--- /dev/null
+++ b/web/noweb/src/shell/detangle
@@ -0,0 +1,73 @@
+#!/bin/sh
+#
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+# set -x
+LIB=|LIBDIR|
+markup=$LIB/markup opt= arg= filters=
+width=72 subst='gsub("\\*/", "* /", s)' format='/* %%-%ds */'
+
+while [ $# -gt 0 ]; do
+ case $1 in
+ -ml|-m3) format='(* %%-%ds *)' ; subst='gsub("\\*\\)", "* )", s)' ;;
+ -awk|-icn|-icon) format='# %%-%ds' ; subst=' ' ;;
+ -lisp|-scm) format=';;; %%-%ds' ; subst=' ' ;;
+ -c++) format='// %%-%ds' ; subst=' ' ;;
+ -c) format='/* %%-%ds */' subst='gsub("\\*/", "* /", s)' ;;
+ -pascal) format='{ %%-%ds }' ; subst='gsub("[{}]", "-", s)' ;;
+ -f77) format='C %%-%ds' ; subst=' ' ;;
+ -f90) format='! %%-%ds' ; subst=' ' ;;
+ -tex) format='%%%% %%-%ds' ; subst=' ' ;;
+ -L*) ;; # deliberately ignore requests for #line
+ -w[0-9][0-9]*) width=`echo $1 | sed 's/^-w//'` ;;
+ -filter) filters=" | $filters $2 " ; shift ;;
+ -markup) markup="$2" ; shift ;;
+ -) arg="$arg '$1'" ;;
+ -*) opt="$opt '$1'" ;;
+ *) arg="$arg '$1'" ;;
+ esac
+ shift
+done
+
+PATH="$PATH:$LIB" eval "$markup $arg $filters" |
+nawk 'BEGIN { line = 0; capture = 0; aftercode=0
+ format=sprintf("'"$format"'",'"$width"') }
+
+function comment(s) {
+ '"$subst"'
+ return sprintf(format,s)
+}
+
+function grab(s) {
+ if (capture==0) print
+ else holding[line] = holding[line] s
+}
+
+/^@end doc/ { capture = 0; holding[++line] = "" ; next }
+/^@begin doc/ { capture = 1; next }
+
+/^@end code/ { aftercode = 1; seenchars = 0; next }
+
+/^@text [ ]*$/ { grab(substr($0,7)); next}
+/^@text / { grab(substr($0,7)); seenchars = 1; next}
+/^@quote$/ { grab("[[") ; next}
+/^@endquote$/ { grab("]]") ; next}
+
+/^@nl$/ { if (aftercode != 0) {
+ if (seenchars == 0) {
+ if (capture !=0 ) {
+ holding[++line] = ""
+ } else if (defn_pending != 0) {
+ print "@nl"
+ for (i=0; i<=line && holding[i] ~ /^ *$/; i++) i=i
+ for (; i<=line; i++) printf "@text %s\n@nl\n", comment(holding[i])
+ line = 0; holding[0] = ""
+ defn_pending = 0
+ } else print
+ next
+ }
+
+/^@defn / { holding[line] = holding[line] "<"substr($0,7)">=" # (line should be blank)
+ print ; defn_pending = 1 ; next }
+{ print }' |
+eval "$LIB/nt $opt"
diff --git a/web/noweb/src/shell/htmltoc b/web/noweb/src/shell/htmltoc
new file mode 100755
index 0000000000..db2606e6a0
--- /dev/null
+++ b/web/noweb/src/shell/htmltoc
@@ -0,0 +1,66 @@
+eval 'exec perl -S $0 ${1+"$@"}'
+ if 0;
+
+$sentinel = "<tableofcontents>";
+$sentinel_end = "</tableofcontents>";
+
+while (<>) {
+ push(@file, $_) unless (/^$sentinel/ .. /^$sentinel_end/);
+ push(@file, $_) if (/^$sentinel/ || /^$sentinel_end/);
+}
+
+$intro = -1;
+
+$outerlevel = 1;
+
+$curlevel = $outerlevel;
+foreach $i (0..$#file) {
+
+ if ($file[$i] =~ m|$sentinel|) {$intro = $i;}
+
+ next unless $file[$i] =~ m|<[hH]([23])>\s*((.*\S)*)\s*</[hH]\1>|;
+ $nowlevel = $1;
+ $label = $heading = $2;
+
+ while ($nowlevel > $curlevel) {
+ push(@toc, "<ul compact>\n");
+ $curlevel++;
+ }
+ while ($nowlevel < $curlevel) {
+ push(@toc, "</ul>\n");
+ $curlevel--;
+ }
+ if ($file[$i] =~ m/name="([^"]+)"/i) {
+ $label = $1;
+ $heading =~ s/name="/href="#/i;
+ push(@toc, "<li>$heading\n");
+ } else {
+ $label =~ s/\W//g;
+ $label =~ tr/A-Z/a-z/;
+ $label = substr($label, 0, 6) . "00";
+ $label++ while (defined $labels{$label});
+# $file[$i] =~ s|\Q$heading\E|<a name="$label">$&</a>|;
+ $file[$i] =~ s|$heading|<a name="$label">$&</a>|;
+ push(@toc, qq{<li><a href="#$label">$heading</a>\n});
+ }
+ $labels{$label}++;
+}
+$nowlevel = $outerlevel;
+while ($nowlevel > $curlevel) {
+ push(@toc, "<ul compact>\n");
+ $curlevel++;
+}
+while ($nowlevel < $curlevel) {
+ push(@toc, "</ul>\n");
+ $curlevel--;
+}
+
+if ($intro >= 0) {
+ print @file[0..$intro];
+ print @toc;
+ print @file[$intro+1 .. $#file];
+} else {
+ print @file;
+}
+
+
diff --git a/web/noweb/src/shell/luddite b/web/noweb/src/shell/luddite
new file mode 100644
index 0000000000..5a38673946
--- /dev/null
+++ b/web/noweb/src/shell/luddite
@@ -0,0 +1,46 @@
+#!/bin/sh
+# set -x
+LIB=+LIBDIR+
+opt= arg=
+comment='function comment(s) {
+ gsub("\\*/", "* /", s)
+ return sprintf("/* %-72s */",s)
+}'
+
+for i do
+ case $i in
+ -ml|-m3) comment='function comment(s) {
+ gsub("\\*\\)", "* )", s)
+ return sprintf("(* %-72s *)",s)
+}' ;;
+ -awk) comment='function comment(s) {
+
+ return sprintf("# %s",s)
+}' ;;
+ -c) comment='function comment(s) {
+ gsub("\\*/", "* /", s)
+ return sprintf("/* %-72s */",s)
+}' ;;
+ -L*) ;; # deliberately ignore requests for #line
+ -*) opt="$opt '$i'" ;;
+ *) arg="$arg '$i'" ;;
+ esac
+done
+
+eval "$LIB/markup $arg" | expand |
+nawk 'BEGIN { line = 0; capture = 0 }
+'"$comment"'
+
+/^@end doc/ { capture = 0; holding[line++] = "" ; next }
+/^@begin doc/ { capture = 1; next }
+
+capture == 1 { holding[line++] = comment($0); next }
+
+/@name / { print
+ print comment("<"substr($0,7)">=") # may want to omit this line
+ for (i=0; i<line; i++) print holding[i]
+ line = 0
+ next
+}
+{ print }' |
+eval "$LIB/nt $opt"
diff --git a/web/noweb/src/shell/nocount b/web/noweb/src/shell/nocount
new file mode 100755
index 0000000000..6ca632a089
--- /dev/null
+++ b/web/noweb/src/shell/nocount
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+LIB=|LIBDIR|
+
+$LIB/markup "$@" | nawk '
+BEGIN { bogus = "this is total bogosity"; codecount[bogus] = -1; docscount[bogus] = -1 }
+/^@file / { thisfile = $2 ; files[thisfile] = 0 }
+/^@begin code/ { code = 1 }
+/^@begin docs/ { code = 0 }
+/^@nl/ {
+ if (code == 0)
+ docscount[thisfile]++
+ else
+ codecount[thisfile]++
+}
+END {
+ printf " Code Docs Both File\n"
+ for (file in files) {
+ printf "%5d %5d %5d %s\n", codecount[file], docscount[file], codecount[file]+docscount[file], file
+ totalcode += codecount[file]
+ totaldocs += docscount[file]
+ }
+ printf "%5d %5d %5d %s\n", totalcode, totaldocs, totalcode+totaldocs, "Total"
+}'
diff --git a/web/noweb/src/shell/nodefs b/web/noweb/src/shell/nodefs
new file mode 100644
index 0000000000..5396e105db
--- /dev/null
+++ b/web/noweb/src/shell/nodefs
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# Copyright 1993 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+LIB=|LIBDIR|
+case $1 in
+ -auto|-autodefs)
+ newfilter="$LIB/autodefs.$2" ; shift ; shift
+ $LIB/markup "$@" | $newfilter | sed -n 's/^@index defn //p'
+ ;;
+ -showauto|-showautodefs)
+ foundautodefs=
+ for i in $LIB/autodefs.*; do
+ if [ -r $i ]; then
+ echo "This `basename $0` supports -autodefs $i" |
+ sed "s@$LIB/autodefs\.@@" 1>&2
+ foundautodefs=$i
+ fi
+ done
+ if [ -z "$foundautodefs" ]; then
+ echo "This `basename $0` does not support -autodefs"
+ fi
+ ;;
+ *)
+ $LIB/markup "$@" | sed -n 's/^@index defn //p'
+ ;;
+esac
+exit $?
diff --git a/web/noweb/src/shell/nonu b/web/noweb/src/shell/nonu
new file mode 100755
index 0000000000..612dadede9
--- /dev/null
+++ b/web/noweb/src/shell/nonu
@@ -0,0 +1,41 @@
+#!/bin/sh
+LIB=/usr/public/pkg/noweb/lib
+# attempt to convert nuweb to noweb using sam
+
+tmp=$($LIB/nwmktemp)
+trap '/bin/rm -f $tmp; exit 1' 1 2 15 # clean up files
+cp $1 $tmp || exit 1
+
+notat='([^@]|\n)'
+white='[ \n]'
+sam -d $tmp << EOF
+,x/\@\@/c/{{{the magic at sign}}}/
+,x/<</c/{{{double left brackets}}}/
+,x/>>/c/{{{double right brackets}}}/
+,x/@m/c/\\nowebchunks/
+,x/@u/c/\\nowebindex/
+,x/\@[oO][^@]*$/x/ -[dit][a-zA-Z]*/v/..../d
+,x/\@[dDoO|}]/i/\n/
+,x/\n\n\@[dDoO|}]/s/\n\n/\n/
+,x/\@[dDoO]${notat}*\@{/s/\n/ /g
+,x/\@[dDoO]${notat}*\@{/{
+s/\@[dDoO] */<</
+s/\@{/>>=\n/
+}
+,s/\@</<</g
+,s/\@>/>>/g
+,x/<<[^>]*(>[^>][^>]*)*>>/s/[ ][ ]*/ /g
+,x/<< | >>/s/ //
+,x/\@\|$notat*\@}/x/\n/a/@ %def /
+,x/\@ %def \@}/c/@ /
+,x/\@\|/c/@ %def /
+,s/\@}/@ /g
+,x/\n\@ %def.*\n\@ *\n/x/\n\@ *\n/c/\n/
+,x/^\@ %def.*$/s/[ ]+/ /g
+,x/{{{the magic at sign}}}/c/@/
+,x/{{{double left brackets}}}/c/@<</
+,x/{{{double right brackets}}}/c/@>>/
+w
+EOF
+$LIB/markup $tmp | $LIB/disambiguate | $LIB/unmarkup
+rm $tmp
diff --git a/web/noweb/src/shell/noroff b/web/noweb/src/shell/noroff
new file mode 100644
index 0000000000..fbe2b2a86a
--- /dev/null
+++ b/web/noweb/src/shell/noroff
@@ -0,0 +1,98 @@
+#!/bin/sh
+#
+# noroff -- run troff using tags file trick
+
+ROFF="groff"
+AWK=nawk
+macrodir=|LIBDIR|
+LIB=|LIBDIR|
+
+opts=
+
+if [ $# -eq 0 ]; then
+ echo "Usage: noroff [groff-arguments] files" 1>&2
+ exit 1
+fi
+
+while [ $# -gt 0 ]
+do
+ case $1 in
+ -*) opts="$opts $1"
+ shift
+ ;;
+ *) # end of options
+ break;
+ ;;
+ esac
+done
+
+if [ "$opts" = "" ]
+then
+ # no options, default to -mm
+ # groff already defaults to -Tps
+ opts="-mm"
+fi
+# otherwise assume user passed in all the arguments they want
+
+base="`basename $1 | sed '/\./s/\.[^.]*$//'`"
+tagsfile="$base.nwt"
+(echo ".so $macrodir/tmac.w"
+if [ -r "$tagsfile" ]; then
+ tagstemp=$($LIB/nwmktemp) || { echo "$0: Cannot create temporary file" >&2; exit 1; }
+ cp $tagsfile $tagstemp
+ $AWK '{
+ if (sub(/^###TAG### / , "")) tags[$1] = $2
+ else if (sub(/^###BEGINCHUNKS###/, "")) printf ".de CLIST\n.CLISTBEGIN\n"
+ else if (sub(/^###CHUNKBEGIN### /, "")) { name = convquote($0)
+ chunkuse = chunkdefn = "" }
+ else if (sub(/^###CHUNKUSE### / , "")) chunkuse = chunkuse " " tag($0)
+ else if (sub(/^###CHUNKDEFN### / , "")) chunkdefn = chunkdefn " " tag($0)
+ else if (sub(/^###CHUNKEND###/ , ""))
+ printf ".CITEM \"%s\" \"%s\" \"%s\"\n", name, chunkdefn, chunkuse
+ else if (sub(/^###ENDCHUNKS###/ , "")) printf ".CLISTEND\n..\n"
+ else if (sub(/^###BEGININDEX###/ , "")) printf ".de ILIST\n.ILISTBEGIN\n"
+ else if (sub(/^###ENTRYBEGIN### /, "")) { name = convquote($0)
+ entryuse = entrydefn = "" }
+ else if (sub(/^###ENTRYUSE### / , "")) entryuse = entryuse " " tag($0)
+ else if (sub(/^###ENTRYDEFN### / , "")) entrydefn = entrydefn " " tag($0)
+ else if (sub(/^###ENTRYEND###/ , "")) {
+ for (i = 1; i <= split(entrydefn, entryarray); i++)
+ sub(entryarray[i], "\\*[BEGINDEFN]&\\*[ENDDEFN]", entryuse)
+ printf ".IITEM \"%s\" \"%s\"\n", name, entryuse }
+ else if (sub(/^###ENDINDEX###/ , "")) printf ".ILISTEND\n..\n"
+ }
+ function convquote(s, out, front, mid, tail) {
+ gsub(/\[\[/, "\\*[BEGINCONVQUOTE]", s)
+ # gsub(/\]\]/, "\\*[ENDCONVQUOTE]", s)
+ out = ""
+ mid = "\\*[ENDCONVQUOTE]"
+ while (match(s, /\]\]+/) != 0) {
+ # RLENGTH is length of match, want to remove last two chars
+ # RSTART is where sequence of ]s begins
+ tail = substr(s, RSTART + RLENGTH)
+ if (RLENGTH == 2) # easy
+ front = substr(s, 1, RSTART - 1)
+ else
+ front = substr(s, 1, RSTART - 1 + RLENGTH - 2)
+ out = out front mid
+ s = tail
+ }
+ out = out s
+ return out }
+ # my test program for the revised function - ADR
+ # BEGIN { str = "abc[[foo[i]]]]]]]]junk"
+ # print str
+ # print convquote(str)
+ # str2 = "nothing here"
+ # print str2
+ # print convquote(str2)
+ # str3 = "abc[[foo[i]]]]]]]]junk[[bar[i]]more stuff[[baz]]"
+ # print str3
+ # print convquote(str3)
+ # }
+ function tag(s) { if (s in tags) return tags[s]; else return "???" }' $tagstemp
+ rm -f $tagstemp
+ fi
+ cat "$@") |
+($ROFF $opts 2>$tagsfile)
+sed '/^###[A-Z][A-Z]*###/d' $tagsfile >&2
diff --git a/web/noweb/src/shell/noroots b/web/noweb/src/shell/noroots
new file mode 100644
index 0000000000..0dcf6c06b5
--- /dev/null
+++ b/web/noweb/src/shell/noroots
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+# set -x
+LIB=|LIBDIR|
+$LIB/markup "$@" | nawk '
+/^@quote$/,/^@endquote$/ { next }
+/^@defn / { chunk=substr($0,7) ; defined[chunk]=1 }
+/^@use / { chunk=substr($0,6) ; used[chunk]=1 }
+END {
+ for (chunk in defined) {
+ if (defined[chunk]==1 && used[chunk]==0) printf "<<%s>>\n", chunk
+ }
+}'
diff --git a/web/noweb/src/shell/notangle b/web/noweb/src/shell/notangle
new file mode 100644
index 0000000000..ba3174e4be
--- /dev/null
+++ b/web/noweb/src/shell/notangle
@@ -0,0 +1,27 @@
+#!/bin/sh
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+# $Id: notangle.nw,v 1.2 1997/09/13 20:29:56 nr Exp $
+# $Name: $
+LIB=|LIBDIR|
+markup=$LIB/markup opt= arg= markopt= filters=
+while [ $# -gt 0 ]; do
+ case $1 in
+ -ml|-m3|-awk|-icn|-icon|-pascal|-c|-c++|-f77|-f90|-tex|-w[0-9][0-9]*) ;;
+ # deliberately ignore nountangle args
+ -t) ;; # this is default
+ -t*) markopt="$markopt -t" ; opt="$opt '$1'" ;;
+ # copy tabs at markup, use width given in notangle
+ -filter) filters="$filters $2 | " ; shift ;;
+ -markup) markup="$2" ; shift ;;
+ -) arg="$arg '$1'" ;;
+ -L*) opt="$opt -t '$1'" ; markopt="$markopt -t" ;;
+ -*) opt="$opt '$1'" ;;
+ *) arg="$arg '$1'" ;;
+ esac
+ shift
+done
+PATH="$PATH:$LIB"
+export PATH
+eval "$markup $markopt $arg | $filters $LIB/nt $opt "'; rc=$?'
+exit $rc
diff --git a/web/noweb/src/shell/notangle.nw b/web/noweb/src/shell/notangle.nw
new file mode 100644
index 0000000000..0cfa484344
--- /dev/null
+++ b/web/noweb/src/shell/notangle.nw
@@ -0,0 +1,30 @@
+<<copyright notice>>=
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+<<notangle>>=
+#!/bin/sh
+<<copyright notice>>
+# $Id: notangle.nw,v 1.2 1997/09/13 20:29:56 nr Exp $
+# $Name: $
+LIB=|LIBDIR|
+markup=$LIB/markup opt= arg= markopt= filters=
+while [ $# -gt 0 ]; do
+ case $1 in
+ -ml|-m3|-awk|-icn|-icon|-pascal|-c|-c++|-f77|-f90|-tex|-w[0-9][0-9]*) ;;
+ # deliberately ignore nountangle args
+ -t) ;; # this is default
+ -t*) markopt="$markopt -t" ; opt="$opt '$1'" ;;
+ # copy tabs at markup, use width given in notangle
+ -filter) filters="$filters $2 | " ; shift ;;
+ -markup) markup="$2" ; shift ;;
+ -) arg="$arg '$1'" ;;
+ -L*) opt="$opt -t '$1'" ; markopt="$markopt -t" ;;
+ -*) opt="$opt '$1'" ;;
+ *) arg="$arg '$1'" ;;
+ esac
+ shift
+done
+PATH="$PATH:$LIB"
+export PATH
+eval "$markup $markopt $arg | $filters $LIB/nt $opt "'; rc=$?'
+exit $rc
diff --git a/web/noweb/src/shell/nountangle b/web/noweb/src/shell/nountangle
new file mode 100644
index 0000000000..4853c33262
--- /dev/null
+++ b/web/noweb/src/shell/nountangle
@@ -0,0 +1,69 @@
+#!/bin/sh
+#
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+# set -x
+LIB=|LIBDIR|
+markup=$LIB/markup opt= arg= filters=
+width=72 subst='gsub("\\*/", "* /", s)' format='/* %%-%ds */'
+
+while [ $# -gt 0 ]; do
+ case $1 in
+ -ml|-m3) format='(* %%-%ds *)' ;
+ subst='gsub("\\*\\)", "* )", s); gsub("\\(\\*", "( *", s)' ;;
+ -awk|-icn|-icon) format='# %%-%ds' ; subst=' ' ;;
+ -lisp|-scm) format=';;; %%-%ds' ; subst=' ' ;;
+ -matlab) format='%%%% %%-%ds' ; subst=' ' ;;
+ -c++) format='// %%-%ds' ; subst=' ' ;;
+ -c) format='/* %%-%ds */' subst='gsub("\\*/", "* /", s)' ;;
+ -pascal) format='{ %%-%ds }' ; subst='gsub("[{}]", "-", s)' ;;
+ -f77) format='C %%-%ds' ; subst=' ' ;;
+ -f90) format='! %%-%ds' ; subst=' ' ;;
+ -tex) format='%%%% %%-%ds' ; subst=' ' ;;
+ -L*) ;; # deliberately ignore requests for #line
+ -w[0-9][0-9]*) width=`echo $1 | sed 's/^-w//'` ;;
+ -filter) filters=" $filters | $2 " ; shift ;;
+ -markup) markup="$2" ; shift ;;
+ -) arg="$arg '$1'" ;;
+ -*) opt="$opt '$1'" ;;
+ *) arg="$arg '$1'" ;;
+ esac
+ shift
+done
+
+PATH="$PATH:$LIB" eval "$markup $arg $filters" |
+nawk 'BEGIN { line = 0; capture = 0; format=sprintf("'"$format"'",'"$width"') }
+
+function comment(s) {
+ '"$subst"'
+ return sprintf(format,s)
+}
+
+function grab(s) {
+ if (capture==0) print
+ else holding[line] = holding[line] s
+}
+
+/^@end doc/ { capture = 0; holding[++line] = "" ; next }
+/^@begin doc/ { capture = 1; next }
+
+/^@text / { grab(substr($0,7)); next}
+/^@quote$/ { grab("[[") ; next}
+/^@endquote$/ { grab("]]") ; next}
+
+/^@nl$/ { if (capture !=0 ) {
+ holding[++line] = ""
+ } else if (defn_pending != 0) {
+ print "@nl"
+ for (i=0; i<=line && holding[i] ~ /^ *$/; i++) i=i
+ for (; i<=line; i++) printf "@text %s\n@nl\n", comment(holding[i])
+ line = 0; holding[0] = ""
+ defn_pending = 0
+ } else print
+ next
+ }
+
+/^@defn / { holding[line] = holding[line] "<"substr($0,7)">=" # (line should be blank)
+ print ; defn_pending = 1 ; next }
+{ print }' |
+eval "$LIB/nt $opt"
diff --git a/web/noweb/src/shell/noweave b/web/noweb/src/shell/noweave
new file mode 100644
index 0000000000..dad8b023c5
--- /dev/null
+++ b/web/noweb/src/shell/noweave
@@ -0,0 +1,292 @@
+#!/bin/sh
+# Copyright 1991-1997 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+# $Id: noweave.nw,v 1.7 2008/10/06 01:03:24 nr Exp $
+LIB=|LIBDIR|
+markup=$LIB/markup backend=$LIB/totex
+wrapper= delay= args= markopts= noweboptions= autodefs= verbose= shortxref=
+noquote="-noquote" docanchor= noindex="-noindex"
+filtera= filterb= filterc= filterd= filtere= filterf= filterg=
+# following supported by change in totex back end
+noquote=
+using_index= using_xref=
+pass2setcmd="set ignore"
+for i do
+ pass2setcmd="$pass2setcmd '$i'"
+done
+arg=
+while [ $# -gt 0 ]; do
+ case $1 in
+ -latex) if [ "$wrapper" != "none" ]; then wrapper=latex; fi ;;
+ -tex) wrapper=tex ;;
+ -html) if [ "$wrapper" != "none" ]; then wrapper=html; fi;
+ backend="$LIB/tohtml -localindex"
+ noquote=""; docanchor="-docanchor 10" ;;
+ -latex+html) if [ "$wrapper" != "none" ]; then wrapper=latex; fi;
+ backend="$LIB/tohtml -localindex -raw"
+ noquote=""; docanchor="-docanchor 10" ;;
+ -ascii) wrapper=none
+ backend="$LIB/toascii" ;;
+ -troff) wrapper=mm
+ backend="$LIB/toroff" ;;
+ -n) wrapper=none ;;
+ -backend) backend="$2" ; shift ;;
+ -markup) markup="$2" ; shift ;;
+ -filter) shift ;;
+ -x) using_xref=1 ;;
+ -index) noindex= ; using_index=1 ;;
+ -indexfrom) shift; noindex= ; using_index=1 ;;
+ -autodefs) newfilter="$LIB/autodefs.$2"
+ if [ -r $newfilter ]; then if [ -z "$filtera" ]; then
+ filtera="$newfilter"
+ elif [ -z "$filterb" ]; then
+ filterb="$newfilter"
+ elif [ -z "$filterc" ]; then
+ filterc="$newfilter"
+ elif [ -z "$filterd" ]; then
+ filterd="$newfilter"
+ elif [ -z "$filtere" ]; then
+ filtere="$newfilter"
+ elif [ -z "$filterf" ]; then
+ filterf="$newfilter"
+ elif [ -z "$filterg" ]; then
+ filterg="$newfilter"
+ else
+ echo "$0: ran out of filters" 1>&2
+ exit 1
+ fi
+ else echo "$0: don't know how to find definitions for '$2'" 1>&2; exit 1
+ fi
+ shift
+ ;;
+ -showautodefs) foundautodefs=
+ for i in $LIB/autodefs.*; do
+ if [ -r $i ]; then
+ echo "This `basename $0` supports -autodefs $i" |
+ sed "s@$LIB/autodefs\.@@" 1>&2
+ foundautodefs=$i
+ fi
+ done
+ if [ -z "$foundautodefs" ]; then
+ echo "This `basename $0` does not support -autodefs"
+ fi; exit 1 ;;
+ -option) newopt="$2"; shift
+ if [ "X$newopt" = "Xshortxref" ]; then shortxref="-shortxref"; fi
+ if [ "X$newopt" = "Xlongxref" ]; then shortxref="-longxref"; fi
+ if [ -z "$noweboptions" ] ; then noweboptions="$newopt"
+ else noweboptions="$noweboptions,$newopt"
+ fi ;;
+ # -nodelay) delay= ;;
+ -delay) delay="-delay" ; wrapper=none ;;
+ -t*) markopts="$markopts $1" ;;
+ -v) echo 'RCS version name $Name: $' 1>&2
+ echo 'RCS id $Id: noweave.nw,v 1.7 2008/10/06 01:03:24 nr Exp $' 1>&2
+ verbose=1 ;;
+ -) arg="$arg $1" ;;
+ -*) echo "$0: Unrecognized option '$1'" 1>&2 ; echo "Usage: $0 [options] [files]" 1>&2
+ echo "Options recognized are:" 1>&2
+ echo "-latex Emit LaTeX with headers and trailers (default)." 1>&2
+ echo "-tex Emit plain TeX with headers and trailers." 1>&2
+ echo "-html Emit HTML with headers and trailers." 1>&2
+ echo "-latex+html Assume LaTeX in documentation, but use HTML in code." 1>&2
+ # echo "-ascii Emit ASCII." 1>&2
+ echo "-troff Emit troff (actually GNU groff)." 1>&2
+ echo " -n Don't use any header or trailer." 1>&2
+ echo "-markup frontend Parse input with frontend (e.g., numarkup)." 1>&2
+ echo "-x Use the default cross-referencer (needs LaTeX or HTML)." 1>&2
+ echo "-index Create index using identifiers defined in input files." 1>&2
+ echo "-indexfrom defs Create index of identifers listed in file defs." 1>&2
+ echo "-filter cmd Filter through 'cmd' before weaving; cmd could prettyprint" 1>&2
+ echo " or perform other functions." 1>&2
+ echo "-autodefs lang Source is in language 'lang'; find definitions automatically." 1>&2
+ echo "-showautodefs List languages that can be used with -autodefs" 1>&2
+ echo '-option opt Add \noweboptions{opt} to header (latex only)' 1>&2
+ echo "-delay Delay markup until after first documentation chunk." 1>&2
+ echo "-tk Expand tab stops every k columns" 1>&2
+ echo "-t Copy tabs to the output" 1>&2
+ echo "-v Print pipeline and RCS info on standard error" 1>&2; exit 1 ;;
+ *) arg="$arg $1" ;;
+ esac
+ shift
+done
+if [ -n "$using_xref" -a -n "$using_index" ]; then
+ echo "$0: you may not use -x with -index or -indexfrom (drop the -x)" 1>&2
+ exit 1
+fi
+if [ -z "$wrapper" ]; then wrapper=latex; fi
+eval $pass2setcmd
+shift
+while [ $# -gt 0 ]; do
+ case $1 in
+ -filter)
+ newfilter="$2" ; shift ; if [ -z "$filtera" ]; then
+ filtera="$newfilter"
+ elif [ -z "$filterb" ]; then
+ filterb="$newfilter"
+ elif [ -z "$filterc" ]; then
+ filterc="$newfilter"
+ elif [ -z "$filterd" ]; then
+ filterd="$newfilter"
+ elif [ -z "$filtere" ]; then
+ filtere="$newfilter"
+ elif [ -z "$filterf" ]; then
+ filterf="$newfilter"
+ elif [ -z "$filterg" ]; then
+ filterg="$newfilter"
+ else
+ echo "$0: ran out of filters" 1>&2
+ exit 1
+ fi ;;
+ -x) newfilter="$LIB/noidx $docanchor $delay"; if [ -z "$filtera" ]; then
+ filtera="$newfilter"
+ elif [ -z "$filterb" ]; then
+ filterb="$newfilter"
+ elif [ -z "$filterc" ]; then
+ filterc="$newfilter"
+ elif [ -z "$filterd" ]; then
+ filterd="$newfilter"
+ elif [ -z "$filtere" ]; then
+ filtere="$newfilter"
+ elif [ -z "$filterf" ]; then
+ filterf="$newfilter"
+ elif [ -z "$filterg" ]; then
+ filterg="$newfilter"
+ else
+ echo "$0: ran out of filters" 1>&2
+ exit 1
+ fi ;;
+ -index)
+ newfilter="$LIB/finduses $noquote" ; if [ -z "$filtera" ]; then
+ filtera="$newfilter"
+ elif [ -z "$filterb" ]; then
+ filterb="$newfilter"
+ elif [ -z "$filterc" ]; then
+ filterc="$newfilter"
+ elif [ -z "$filterd" ]; then
+ filterd="$newfilter"
+ elif [ -z "$filtere" ]; then
+ filtere="$newfilter"
+ elif [ -z "$filterf" ]; then
+ filterf="$newfilter"
+ elif [ -z "$filterg" ]; then
+ filterg="$newfilter"
+ else
+ echo "$0: ran out of filters" 1>&2
+ exit 1
+ fi
+ newfilter="$LIB/noidx $docanchor $delay"; if [ -z "$filtera" ]; then
+ filtera="$newfilter"
+ elif [ -z "$filterb" ]; then
+ filterb="$newfilter"
+ elif [ -z "$filterc" ]; then
+ filterc="$newfilter"
+ elif [ -z "$filterd" ]; then
+ filterd="$newfilter"
+ elif [ -z "$filtere" ]; then
+ filtere="$newfilter"
+ elif [ -z "$filterf" ]; then
+ filterf="$newfilter"
+ elif [ -z "$filterg" ]; then
+ filterg="$newfilter"
+ else
+ echo "$0: ran out of filters" 1>&2
+ exit 1
+ fi ;;
+ -indexfrom)
+ newfilter="$LIB/finduses $noquote $2"; if [ -z "$filtera" ]; then
+ filtera="$newfilter"
+ elif [ -z "$filterb" ]; then
+ filterb="$newfilter"
+ elif [ -z "$filterc" ]; then
+ filterc="$newfilter"
+ elif [ -z "$filterd" ]; then
+ filterd="$newfilter"
+ elif [ -z "$filtere" ]; then
+ filtere="$newfilter"
+ elif [ -z "$filterf" ]; then
+ filterf="$newfilter"
+ elif [ -z "$filterg" ]; then
+ filterg="$newfilter"
+ else
+ echo "$0: ran out of filters" 1>&2
+ exit 1
+ fi
+ newfilter="$LIB/noidx $docanchor $delay"; if [ -z "$filtera" ]; then
+ filtera="$newfilter"
+ elif [ -z "$filterb" ]; then
+ filterb="$newfilter"
+ elif [ -z "$filterc" ]; then
+ filterc="$newfilter"
+ elif [ -z "$filterd" ]; then
+ filterd="$newfilter"
+ elif [ -z "$filtere" ]; then
+ filtere="$newfilter"
+ elif [ -z "$filterf" ]; then
+ filterf="$newfilter"
+ elif [ -z "$filterg" ]; then
+ filterg="$newfilter"
+ else
+ echo "$0: ran out of filters" 1>&2
+ exit 1
+ fi
+ shift ;;
+ esac
+ shift
+done
+(
+header=
+case $wrapper in
+ none) ;;
+ latex) header="@header $wrapper $noweboptions"
+ trailer="@trailer $wrapper" ;;
+ *) header="@header $wrapper$arg"
+ trailer="@trailer $wrapper" ;;
+esac
+if [ -n "$header" ]; then echo "$header"; fi
+PATH="$PATH:$LIB"
+export PATH
+if [ -n "$verbose" ]; then
+ if [ -n "$header" -o -n "$trailer" ]; then
+ parenpfx="("
+ if [ -n "$header" ]; then echo "(echo $header" 1>&2; parenpfx=" "; fi
+ echo "$parenpfx$markup" $markopts $arg 1>&2
+ if [ -n "$trailer" ]; then echo " echo $trailer" 1>&2; fi
+ echo ") |" 1>&2
+ else
+ echo $markup $markopts $arg '|' 1>&2
+ fi
+ if [ -n "$filtera" ]; then echo $filtera '|' 1>&2; fi
+ if [ -n "$filterb" ]; then echo $filterb '|' 1>&2; fi
+ if [ -n "$filterc" ]; then echo $filterc '|' 1>&2; fi
+ if [ -n "$filterd" ]; then echo $filterd '|' 1>&2; fi
+ if [ -n "$filtere" ]; then echo $filtere '|' 1>&2; fi
+ if [ -n "$filterf" ]; then echo $filterf '|' 1>&2; fi
+ if [ -n "$filterg" ]; then echo $filterg '|' 1>&2; fi
+fi
+if [ -n "$verbose" ]; then echo $backend $noindex $delay $shortxref 1>&2; fi
+if [ -z "$filtera" ]; then
+ $markup $markopts $arg
+elif [ -z "$filterb" ]; then
+ $markup $markopts $arg | eval $filtera
+elif [ -z "$filterc" ]; then
+ $markup $markopts $arg | eval $filtera | eval $filterb
+elif [ -z "$filterd" ]; then
+ $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc
+elif [ -z "$filtere" ]; then
+ $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc |
+ eval $filterd
+elif [ -z "$filterf" ]; then
+ $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc |
+ eval $filterd | eval $filtere
+elif [ -z "$filterg" ]; then
+ $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc |
+ eval $filterd | eval $filtere | eval $filterf
+else
+ $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc |
+ eval $filterd | eval $filtere | eval $filterf |
+ eval $filterg
+fi
+if [ -n "$trailer" ]; then echo $trailer; fi
+) |
+ $backend $noindex $delay $shortxref
+exit $?
diff --git a/web/noweb/src/shell/noweave.hpux b/web/noweb/src/shell/noweave.hpux
new file mode 100644
index 0000000000..1314af4675
--- /dev/null
+++ b/web/noweb/src/shell/noweave.hpux
@@ -0,0 +1,63 @@
+#!/bin/sh
+#
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+# options: -l == use LaTeX -x == generate LaTeX cross-reference goo
+
+# fix for backlash for HP-UX contributed by Gary Leavens.
+
+LIB=|LIBDIR|
+latex=0 tex=1 xref=0
+args=
+markopts=
+
+for i do
+ case $i in
+ -l) latex=1 ; tex=0 ;;
+ -n) latex=0 ; tex=0 ;;
+ -x) xref=1 ; if [ $tex -eq 1 ]; then tex=0 ; latex=1; fi ;;
+ -t*) markopts="$markopts $i" ;;
+ -*) echo "$0: Unrecognized argument '$i'" 1>&2 ; exit ;;
+ *) arg="$arg $i" ;;
+ esac
+done
+
+if [ $tex -eq 1 ]; then echo '\\\c' ; echo input nwmac; fi
+if [ $latex -eq 1 ]; then
+ echo '\\\c'; echo "documentstyle[noweb]{article}";
+ echo '\\\c' ; echo 'begin{document}'
+fi
+
+if [ $xref -eq 0 ]; then
+ $LIB/markup $markopts $arg
+else
+ $LIB/markup $markopts $arg | $LIB/noxref
+fi | nawk '
+BEGIN { code=0 ; quoting=0 }
+/^@begin code/ { code=1 ; printf "\\begincode{%s}\n", substr($0, 13) }
+/^@begin docs/ { printf "\\begindocs{%s}\n", substr($0, 13) }
+/^@end code/ { code=0 ; printf "\\endcode\n" }
+/^@end docs/ { printf "\\enddocs\n" }
+/^@text / { line = substr($0, 7)
+ if (code || quoting) {
+ gsub("\\\\", "\\\\", line)
+ gsub("{", "\\{", line) ; gsub("}", "\\}", line)
+ }
+ printf "%s", line
+ }
+/^@nl$/ { printf "\n" }
+/^@defn / { gsub("\\[\\[", "\\code{}") ; gsub("\\]\\]", "\\edoc{}")
+ printf "\\moddef{%s}\\%sendmoddef", substr($0, 7), defns[substr($0, 7)]
+ defns[substr($0, 7)] = "plus"
+ }
+/^@use / { gsub("\\[\\[", "\\code{}") ; gsub("\\]\\]", "\\edoc{}")
+ printf "\\LA{}%s\\RA{}", substr($0, 6)
+ }
+/^@quote$/ { quoting = 1 ; printf "\\code{}" }
+/^@endquote$/ { quoting = 0 ; printf "\\edoc{}" }
+/^@file / { printf "\\filename{%s}\n", substr($0, 7) }
+/^@literal / { printf "%s", substr($0, 10) }'
+status=$?
+if [ $tex -eq 1 ]; then echo '\\\c' ; echo bye; fi
+if [ $latex -eq 1 ]; then echo '\\\c'; echo 'end{document}' ; fi
+exit $status
diff --git a/web/noweb/src/shell/noweave.nr b/web/noweb/src/shell/noweave.nr
new file mode 100644
index 0000000000..ba67721748
--- /dev/null
+++ b/web/noweb/src/shell/noweave.nr
@@ -0,0 +1,77 @@
+#!/bin/sh
+#
+# Copyright 1991, 1992, 1993 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+# options: -l == use LaTeX -x == generate LaTeX cross-reference goo
+
+LIB=|LIBDIR|
+latex=0 tex=1 xref=0
+args=
+markopts=
+
+for i do
+ case $i in
+ -l) latex=1 ; tex=0 ;;
+ -n) latex=0 ; tex=0 ;;
+ -x) xref=1 ; if [ $tex -eq 1 ]; then tex=0 ; latex=1; fi ;;
+ -t*) markopts="$markopts $i" ;;
+ -*) echo "$0: Unrecognized argument '$i'" 1>&2 ; exit ;;
+ *) arg="$arg $i" ;;
+ esac
+done
+
+if [ $tex -eq 1 ]; then echo -n \\ ; echo input nwmac; fi
+if [ $latex -eq 1 ]; then
+ echo -n \\; echo "documentstyle[noweb]{article}";
+ for i in oddsidemargin evensidemargin; do
+ echo -n \\; echo -n "advance" ; echo -n \\ ; echo "$i -0.4in"
+ done
+ echo -n \\ ; echo 'begin{document}'
+fi
+
+if [ $xref -eq 0 ]; then
+ $LIB/markup $markopts $arg
+else
+ $LIB/markup $markopts $arg | $LIB/noxref
+fi | nawk '
+BEGIN { code=0 ; quoting=0 }
+/^@begin code/ { code=1 ; printf "\\begincode{%s}\n", substr($0, 13) }
+/^@begin docs/ { printf "\\begindocs{%s}\n", substr($0, 13) }
+/^@end code/ { code=0 ; printf "\\endcode\n" }
+/^@end docs/ { printf "\\enddocs\n" }
+/^@text / { line = substr($0, 7)
+ if (code || quoting) {
+ gsub("\\\\", "\\\\", line)
+ gsub("{", "\\{", line) ; gsub("}", "\\}", line)
+ }
+ printf "%s", line
+ }
+/^@nl$/ { printf "\n" }
+/^@defn / { name = substr($0, 7)
+ printf "\\moddef{%s}\\%sendmoddef", convquotes(name), defns[name]
+ defns[name] = "plus"
+ }
+/^@use / { printf "\\LA{}%s\\RA{}", convquotes(substr($0, 6)) }
+/^@quote$/ { quoting = 1 ; printf "\\code{}" }
+/^@endquote$/ { quoting = 0 ; printf "\\edoc{}" }
+/^@file / { printf "\\filename{%s}\n", substr($0, 7) }
+/^@literal / { printf "%s", substr($0, 10) }
+function convquotes(s, r, i) {
+ r = ""
+ while (i = index(s, "[[")) {
+ r = r substr(s, 1, i-1) "\\code{}"
+ s = substr(s, i+2)
+ if (i = match(s, "\\]\\]+")) {
+ r = r substr(s, 1, i-1+RLENGTH-2) "\\edoc{}"
+ s = substr(s, i+RLENGTH)
+ } else {
+ r = r s "\\edoc{}"
+ s = ""
+ }
+ }
+ return r s
+}'
+status=$?
+if [ $tex -eq 1 ]; then echo -n \\ ; echo bye; fi
+if [ $latex -eq 1 ]; then echo -n \\; echo 'end{document}' ; fi
+exit $status
diff --git a/web/noweb/src/shell/noweave.nw b/web/noweb/src/shell/noweave.nw
new file mode 100644
index 0000000000..d2e9cb0dbe
--- /dev/null
+++ b/web/noweb/src/shell/noweave.nw
@@ -0,0 +1,564 @@
+\section{Weaving a {\tt noweb} file into a \TeX file}
+The copyright applies both to the {\tt noweb} source and to the
+generated shell script.
+<<copyright notice>>=
+# Copyright 1991-1997 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+# $Id: noweave.nw,v 1.7 2008/10/06 01:03:24 nr Exp $
+@
+Here's the organization of the source:
+<<noweave>>=
+#!/bin/sh
+<<copyright notice>>
+<<initialization>>
+<<scan options and arguments>>
+<<emit markup on standard output>> |
+ $backend $noindex $delay $shortxref
+exit $?
+<<if verbose, show back end>>=
+if [ -n "$verbose" ]; then echo $backend $noindex $delay $shortxref 1>&2; fi
+@
+The first item of initialization is to locate the {\tt noweb} library.
+<<initialization>>=
+LIB=|LIBDIR|
+@
+<<initialization>>=
+markup=$LIB/markup backend=$LIB/totex
+wrapper= delay= args= markopts= noweboptions= autodefs= verbose= shortxref=
+noquote="-noquote" docanchor= noindex="-noindex"
+filtera= filterb= filterc= filterd= filtere= filterf= filterg=
+# following supported by change in totex back end
+noquote=
+@
+I make two passes over the arguments so as not to require that options
+be given in a certain order
+<<scan options and arguments>>=
+pass2setcmd="set ignore"
+for i do
+ pass2setcmd="$pass2setcmd '$i'"
+done
+arg=
+while [ $# -gt 0 ]; do
+ case $1 in
+ <<first pass {\tt noweave} options>>
+ -) arg="$arg $1" ;;
+ -*) echo "$0: Unrecognized option '$1'" 1>&2 ; <<show usage>>; exit 1 ;;
+ *) arg="$arg $1" ;;
+ esac
+ shift
+done
+<<insist first-pass options are self-consistent>>
+if [ -z "$wrapper" ]; then wrapper=latex; fi
+eval $pass2setcmd
+shift
+while [ $# -gt 0 ]; do
+ case $1 in
+ <<second pass {\tt noweave} options>>
+ esac
+ shift
+done
+<<old scan options and arguments>>=
+pass2args="$*"
+while [ $# -gt 0 ]; do
+ case $1 in
+ <<first pass {\tt noweave} options>>
+ -*) echo "$0: Unrecognized option '$1'" 1>&2 ; <<show usage>>; exit 1 ;;
+ *) arg="$arg $1" ;;
+ esac
+ shift
+done
+if [ -z "$wrapper" ]; then wrapper=latex; fi
+if [ -n "$pass2args" ]; then
+ set ignoreme $pass2args
+ shift
+ while [ $# -gt 0 ]; do
+ case $1 in
+ <<second pass {\tt noweave} options>>
+ esac
+ shift
+ done
+fi
+<<add [[$newopt]] to [[noweboptions]]>>=
+if [ -z "$noweboptions" ] ; then noweboptions="$newopt"
+else noweboptions="$noweboptions,$newopt"
+fi
+<<first pass {\tt noweave} options>>=
+-latex) if [ "$wrapper" != "none" ]; then wrapper=latex; fi ;;
+-tex) wrapper=tex ;;
+-html) if [ "$wrapper" != "none" ]; then wrapper=html; fi;
+ backend="$LIB/tohtml -localindex"
+ noquote=""; docanchor="-docanchor 10" ;;
+-latex+html) if [ "$wrapper" != "none" ]; then wrapper=latex; fi;
+ backend="$LIB/tohtml -localindex -raw"
+ noquote=""; docanchor="-docanchor 10" ;;
+-ascii) wrapper=none
+ backend="$LIB/toascii" ;;
+-troff) wrapper=mm
+ backend="$LIB/toroff" ;;
+-n) wrapper=none ;;
+-backend) backend="$2" ; shift ;;
+-markup) markup="$2" ; shift ;;
+@
+Note some versions of echo break on [[echo "-n..."]], echoing nothing
+at all. The leading space is claimed to prevent this problem.
+<<option printout for usage>>=
+echo "-latex Emit LaTeX with headers and trailers (default)." 1>&2
+echo "-tex Emit plain TeX with headers and trailers." 1>&2
+echo "-html Emit HTML with headers and trailers." 1>&2
+echo "-latex+html Assume LaTeX in documentation, but use HTML in code." 1>&2
+# echo "-ascii Emit ASCII." 1>&2
+echo "-troff Emit troff (actually GNU groff)." 1>&2
+echo " -n Don't use any header or trailer." 1>&2
+echo "-markup frontend Parse input with frontend (e.g., numarkup)." 1>&2
+@ \iffalse
+<<noweave man page option table>>=
+.TP
+.B \-latex
+Emit LaTeX, including wrapper in
+.B article
+style with the
+.B noweb
+package and page style. (Default)
+.TP
+.B \-tex
+Emit plain TeX, including wrapper with
+.B nwmac
+macros.
+.TP
+.B \-html
+Emit HTML, using HTML wrapper.
+The output is uninteresting without \fB-index\fP or \fB-x\fP.
+The tags \fB<nowebchunks>\fP and \fB<nowebindex>\fP, on lines by themselves,
+produce a list of chunks and an index of identifiers, respectively.
+If these tags are not present, the list and index are placed at the end of the file.
+.TP
+.B \-latex+html
+Assume documentation chunks are LaTeX, but generate HTML for code chunks,
+suitably marked so conversion with
+.I latex2html(1)
+yields reasonable output.
+A LaTeX wrapper is implied, but can be turned off with \fB-n\fP.
+.I Use of this option is
+.B deprecated;
+use
+.B \-html
+with
+.B "\-filter l2h"
+instead.
+<<noweave man page option table>>=
+.TP
+.B \-troff
+Emit
+.IR troff (1)
+markup (with no wrapper).
+The result should be processed with
+.IR noroff (1).
+Bug reports for
+.B \-troff
+to Arnold Robbins
+.B <arnold@skeeve.com>.
+<<bogus noweave man page option table>>=
+.TP
+.B \-ascii
+Emit ASCII (with no wrapper).
+Bug reports for
+.B \-ascii
+to Phil Bewig
+.B <pbewig@netcom.com>.
+<<noweave man page option table>>=
+.TP
+.B \-n
+Don't use any wrapper (header or trailer).
+This option is useful when \fInoweave\fP's output will be
+a part of a larger document.
+See also
+.B \-delay.
+@ \fi
+A common bug seems to be using both [[-x]] and [[-index]] on the same
+command line, so I complain about it.
+<<insist first-pass options are self-consistent>>=
+if [ -n "$using_xref" -a -n "$using_index" ]; then
+ echo "$0: you may not use -x with -index or -indexfrom (drop the -x)" 1>&2
+ exit 1
+fi
+<<initialization>>=
+using_index= using_xref=
+@
+<<first pass {\tt noweave} options>>=
+-filter) shift ;;
+-x) using_xref=1 ;;
+-index) noindex= ; using_index=1 ;;
+-indexfrom) shift; noindex= ; using_index=1 ;;
+<<second pass {\tt noweave} options>>=
+-filter)
+ newfilter="$2" ; shift ; <<add [[$newfilter]] (could overflow)>> ;;
+-x) newfilter="$LIB/noidx $docanchor $delay"; <<add [[$newfilter]] (could overflow)>> ;;
+-index)
+ newfilter="$LIB/finduses $noquote" ; <<add [[$newfilter]] (could overflow)>>
+ newfilter="$LIB/noidx $docanchor $delay"; <<add [[$newfilter]] (could overflow)>> ;;
+-indexfrom)
+ newfilter="$LIB/finduses $noquote $2"; <<add [[$newfilter]] (could overflow)>>
+ newfilter="$LIB/noidx $docanchor $delay"; <<add [[$newfilter]] (could overflow)>>
+ shift ;;
+<<option printout for usage>>=
+echo "-x Use the default cross-referencer (needs LaTeX or HTML)." 1>&2
+echo "-index Create index using identifiers defined in input files." 1>&2
+echo "-indexfrom defs Create index of identifers listed in file defs." 1>&2
+echo "-filter cmd Filter through 'cmd' before weaving; cmd could prettyprint" 1>&2
+echo " or perform other functions." 1>&2
+@ \iffalse
+<<noweave man page indexing options>>=
+.TP
+.B \-x
+For
+.I LaTeX,
+add a page number to each chunk name identifying the location of that
+chunk's definition, and emit cross-reference information relating definitions and uses.
+For
+.I HTML,
+create hypertext links between uses and definitions of chunks.
+When
+.B noweave -x
+is used with
+.I LaTeX,
+the control sequence
+.B "\\\\nowebchunks"
+expands to a sorted list of all code chunks.
+.TP
+.B \-index
+Build cross-reference information (or hypertext links) for defined identifiers.
+Definitions are those found in the input files by
+.B \-autodefs
+.I language
+or by
+.BR \-filter btdefn.
+Requires
+.I LaTeX
+or
+.I HTML.
+.B \-index
+implies
+.B \-x;
+including both will generate strange-looking output.
+.I noweave
+does not generate
+cross-references to identifiers that appear in quoted code (\fB@[[\fP...\fB@]]\fP),
+but it does generate hypertext links.
+When
+.B noweave -index
+is used with
+.I LaTeX,
+the control sequence
+.B "\\\\nowebindex"
+expands to an index of identifiers.
+.TP
+.B \-indexfrom \fIindex\fP
+Like
+.B \-index,
+but the identifiers to be indexed are taken from file \fIindex\fP.
+See
+.I noindex(1).
+<<noweave man page option table>>=
+.TP
+.B \-filter \fIcmd\fP
+Filters the
+.I noweb
+source through
+.I cmd
+after converting it to tool form and before converting to
+.I TeX.
+.I noweave
+looks for
+.I cmd
+first on the user's
+.B PATH,
+then in
+.B |LIBDIR|.
+Such filters
+can be used to add features to
+.I noweave;
+for an example, see
+.B |LIBDIR|/noxref.krom.
+.I Noweave
+supports up to four filters; one can get more by shell trickery,
+for example, \fB-filter "icon.filter | noidx"\fP.
+The \fB-autodefs\fP,
+\fB-x\fP, \fB-index\fP, and \fB-indexfrom\fP options are implemented as filters.
+Filters are executed with the shell's
+.B eval
+command, so
+.I cmd
+should be quoted accordingly.
+<<description of -markup option>>
+@ \fi
+Note that it would be appropriate to look for autodefs
+using [[[ -x $newfilter ]]],
+but that stupid DEC Ultrix doesn't support [[test -x]], so the best I can
+do in a portable way is [[test -r]].
+<<first pass {\tt noweave} options>>=
+-autodefs) newfilter="$LIB/autodefs.$2"
+ if [ -r $newfilter ]; then <<add [[$newfilter]] (could overflow)>>
+ else echo "$0: don't know how to find definitions for '$2'" 1>&2; exit 1
+ fi
+ shift
+ ;;
+-showautodefs) <<print all legal [[-autodefs]] or complain>>; exit 1 ;;
+<<option printout for usage>>=
+echo "-autodefs lang Source is in language 'lang'; find definitions automatically." 1>&2
+echo "-showautodefs List languages that can be used with -autodefs" 1>&2
+@ \iffalse
+<<noweave man page indexing options>>=
+.TP
+.B \-autodefs \fIlang\fP
+Discover identifier definitions automatically.
+Code in chunks must be in language \fIlang\fP.
+Permissible \fIlang\fPs vary but may include
+.B tex
+or
+.B icon.
+Useless without
+.B \-index,
+which it must precede.
+.TP
+.B \-showautodefs
+Show values of \fIlang\fP usable with \fB-autodefs\fP.
+@ \fi
+Same note as above regarding [[test -x]] vs [[test -r]].
+<<print all legal [[-autodefs]] or complain>>=
+foundautodefs=
+for i in $LIB/autodefs.*; do
+ if [ -r $i ]; then
+ echo "This `basename $0` supports -autodefs $i" |
+ sed "s@$LIB/autodefs\.@@" 1>&2
+ foundautodefs=$i
+ fi
+done
+if [ -z "$foundautodefs" ]; then
+ echo "This `basename $0` does not support -autodefs"
+fi
+@
+Here's an embarrassing hack --- if we spot \verb+-option shortxref+
+or \verb+-option longxref+ on the
+command line, we pass something suitable to the back end, in case we're doing
+HTML.
+<<first pass {\tt noweave} options>>=
+-option) newopt="$2"; shift
+ if [ "X$newopt" = "Xshortxref" ]; then shortxref="-shortxref"; fi
+ if [ "X$newopt" = "Xlongxref" ]; then shortxref="-longxref"; fi
+ <<add [[$newopt]] to [[noweboptions]]>> ;;
+<<option printout for usage>>=
+echo '-option opt Add \noweboptions{opt} to header (latex only)' 1>&2
+@ \iffalse
+<<noweave man page option table>>=
+.TP
+.B \-option \fIopt\fP
+Adds \fB\enoweboptions{\fP\fIopt\fP\fB}\fP to the
+.I LaTeX
+header.
+See
+.I nowebstyle(1)
+for values of
+.I opt.
+Normally useful only with the
+.B \-latex
+option, but
+.B "\-option longxref"
+works black magic with
+.B \-html.
+@ \fi
+<<first pass {\tt noweave} options>>=
+# -nodelay) delay= ;;
+-delay) delay="-delay" ; wrapper=none ;;
+<<option printout for usage>>=
+echo "-delay Delay markup until after first documentation chunk." 1>&2
+@ \iffalse
+<<noweave man page option table>>=
+.TP
+.B \-delay
+By default,
+.I noweave
+puts file-name and other information into the output before the first chunk
+of the program.
+.B \-delay
+delays that information until after the first documentation chunk, making
+act a little bit like the
+.I WEB
+``limbo.''
+The option is typically used to enable a user to put a specialized
+.I LaTeX
+.B "\\\\documentclass"
+command and other preamble material in the first documentation chunk (i.e.,
+.I before
+the first @ sign).
+This option also forces trailing cross-referencing information to be emitted
+just before the final chunk, instead of at the end of the document;
+the final chunk is expected to contain
+.B "\\\\end{document}."
+The
+.B \-delay
+option implies the
+.B \-n
+option.
+@ \fi
+% .TP
+% .B \-nodelay
+% Don't delay, put file-name and other information right after header. (Default)
+% @ \fi
+<<first pass {\tt noweave} options>>=
+-t*) markopts="$markopts $1" ;;
+<<option printout for usage>>=
+echo "-tk Expand tab stops every k columns" 1>&2
+echo "-t Copy tabs to the output" 1>&2
+@ \iffalse
+<<noweave man page option table>>=
+.TP
+.B \-t\fIk\fP
+Expand tabs with stops every \fIk\fP columns.
+(Default is to expand every 8 columns.)
+.TP
+.B \-t
+Copy tabs to the output.
+@ \fi
+<<first pass {\tt noweave} options>>=
+-v) echo 'RCS version name $Name: $' 1>&2
+ echo 'RCS id $Id: noweave.nw,v 1.7 2008/10/06 01:03:24 nr Exp $' 1>&2
+ verbose=1 ;;
+<<option printout for usage>>=
+echo "-v Print pipeline and RCS info on standard error" 1>&2
+@ \iffalse
+<<noweave man page option table>>=
+.TP
+.B \-v
+Print the pipeline and RCS info on standard error.
+@ \fi
+\iffalse
+<<man page: WEAVING section>>=
+Output from \fInoweave\fP can
+be used in \fITeX\fP documents that
+.B "\\\\input nwmac,"
+in \fILaTeX\fP documents that use the
+.B noweb
+package (see \fInowebstyle(1)\fP),
+and in \fIHTML\fP documents to be browsed with
+.I Mosaic(1).
+.I Noweave
+treats code chunks somewhat like
+.I LaTeX list environments.
+If the ``\fB@ \fP'' that terminates a code chunk is followed immediately by text,
+that text follows the code chunk without a paragraph break.
+If the rest of the line is blank,
+.I noweave
+puts
+.I TeX
+into ``vertical mode,'' and later text starts a fresh, indented paragraph.
+.PP
+No page breaks occur in the middle of code chunks unless necessary to avoid
+an overfull vbox.
+The documentation chunk immediately preceding a code chunk appears on
+the same page as that code chunk unless doing so would violate the previous rule.
+.PP
+.I Noweave
+inserts no extra newlines in its \fITeX\fP output, so the line numbers given
+in
+.I TeX
+error messages are the same as those in the input file.
+.PP
+.I noweave
+has
+options that dictate choice of
+formatter
+and that support different formatting idioms and tools.
+Basic options are described here; options related to index
+and cross-reference information are described in the
+INDEXING AND CROSS-REFERENCE section.
+<<noweave man page option table>>
+@
+<<man page: INDEXING AND CROSS-REFERENCE section>>=
+
+@ \fi
+<<add [[$newfilter]] (could overflow)>>=
+if [ -z "$filtera" ]; then
+ filtera="$newfilter"
+elif [ -z "$filterb" ]; then
+ filterb="$newfilter"
+elif [ -z "$filterc" ]; then
+ filterc="$newfilter"
+elif [ -z "$filterd" ]; then
+ filterd="$newfilter"
+elif [ -z "$filtere" ]; then
+ filtere="$newfilter"
+elif [ -z "$filterf" ]; then
+ filterf="$newfilter"
+elif [ -z "$filterg" ]; then
+ filterg="$newfilter"
+else
+ echo "$0: ran out of filters" 1>&2
+ exit 1
+fi
+<<show usage>>=
+echo "Usage: $0 [options] [files]" 1>&2
+echo "Options recognized are:" 1>&2
+<<option printout for usage>>
+@
+To avoid inserting any extra newlines into the output,
+I use [[@literal]]to insert headers and trailers.
+The altered [[PATH]] provides a convenience to people who want to
+use simple names to refer to filters in [[$LIB]].
+<<emit markup on standard output>>=
+(
+header=
+case $wrapper in
+ none) ;;
+ latex) header="@header $wrapper $noweboptions"
+ trailer="@trailer $wrapper" ;;
+ *) header="@header $wrapper$arg"
+ trailer="@trailer $wrapper" ;;
+esac
+if [ -n "$header" ]; then echo "$header"; fi
+PATH="$PATH:$LIB"
+export PATH
+<<if verbose, make noise about pipeline>>
+<<if verbose, show back end>>
+if [ -z "$filtera" ]; then
+ $markup $markopts $arg
+elif [ -z "$filterb" ]; then
+ $markup $markopts $arg | eval $filtera
+elif [ -z "$filterc" ]; then
+ $markup $markopts $arg | eval $filtera | eval $filterb
+elif [ -z "$filterd" ]; then
+ $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc
+elif [ -z "$filtere" ]; then
+ $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc |
+ eval $filterd
+elif [ -z "$filterf" ]; then
+ $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc |
+ eval $filterd | eval $filtere
+elif [ -z "$filterg" ]; then
+ $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc |
+ eval $filterd | eval $filtere | eval $filterf
+else
+ $markup $markopts $arg | eval $filtera | eval $filterb | eval $filterc |
+ eval $filterd | eval $filtere | eval $filterf |
+ eval $filterg
+fi
+if [ -n "$trailer" ]; then echo $trailer; fi
+)
+<<if verbose, make noise about pipeline>>=
+if [ -n "$verbose" ]; then
+ if [ -n "$header" -o -n "$trailer" ]; then
+ parenpfx="("
+ if [ -n "$header" ]; then echo "(echo $header" 1>&2; parenpfx=" "; fi
+ echo "$parenpfx$markup" $markopts $arg 1>&2
+ if [ -n "$trailer" ]; then echo " echo $trailer" 1>&2; fi
+ echo ") |" 1>&2
+ else
+ echo $markup $markopts $arg '|' 1>&2
+ fi
+ if [ -n "$filtera" ]; then echo $filtera '|' 1>&2; fi
+ if [ -n "$filterb" ]; then echo $filterb '|' 1>&2; fi
+ if [ -n "$filterc" ]; then echo $filterc '|' 1>&2; fi
+ if [ -n "$filterd" ]; then echo $filterd '|' 1>&2; fi
+ if [ -n "$filtere" ]; then echo $filtere '|' 1>&2; fi
+ if [ -n "$filterf" ]; then echo $filterf '|' 1>&2; fi
+ if [ -n "$filterg" ]; then echo $filterg '|' 1>&2; fi
+fi
diff --git a/web/noweb/src/shell/noweave.sgi b/web/noweb/src/shell/noweave.sgi
new file mode 100644
index 0000000000..49988461a1
--- /dev/null
+++ b/web/noweb/src/shell/noweave.sgi
@@ -0,0 +1,74 @@
+#!/bin/sh
+#
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+# options: -l == use LaTeX -x == generate LaTeX cross-reference goo
+
+LIB=|LIBDIR|
+latex=0 tex=1 xref=0
+args=
+markopts=
+
+for i do
+ case $i in
+ -l) latex=1 ; tex=0 ;;
+ -n) latex=0 ; tex=0 ;;
+ -x) xref=1 ; if [ $tex -eq 1 ]; then tex=0 ; latex=1; fi ;;
+ -t*) markopts="$markopts $i" ;;
+ -*) echo "$0: Unrecognized argument '$i'" 1>&2 ; exit ;;
+ *) arg="$arg $i" ;;
+ esac
+done
+
+if [ $tex -eq 1 ]; then echo "\\input nwmac"; fi
+if [ $latex -eq 1 ]; then
+ echo "\\documentstyle[noweb]{article}";
+ echo '\\begin{document}'
+fi
+
+if [ $xref -eq 0 ]; then
+ $LIB/markup $markopts $arg
+else
+ $LIB/markup $markopts $arg | $LIB/noxref
+fi | nawk '
+BEGIN { code=0 ; quoting=0 }
+/^@begin code/ { code=1 ; printf "\\begincode{%s}\n", substr($0, 13) }
+/^@begin docs/ { printf "\\begindocs{%s}\n", substr($0, 13) }
+/^@end code/ { code=0 ; printf "\\endcode\n" }
+/^@end docs/ { printf "\\enddocs\n" }
+/^@text / { line = substr($0, 7)
+ if (code || quoting) {
+ gsub("\\\\", "\\\\", line)
+ gsub("{", "\\{", line) ; gsub("}", "\\}", line)
+ }
+ printf "%s", line
+ }
+/^@nl$/ { printf "\n" }
+/^@defn / { name = substr($0, 7)
+ printf "\\moddef{%s}\\%sendmoddef", convquotes(name), defns[name]
+ defns[name] = "plus"
+ }
+/^@use / { printf "\\LA{}%s\\RA{}", convquotes(substr($0, 6)) }
+/^@quote$/ { quoting = 1 ; printf "\\code{}" }
+/^@endquote$/ { quoting = 0 ; printf "\\edoc{}" }
+/^@file / { printf "\\filename{%s}\n", substr($0, 7) }
+/^@literal / { printf "%s", substr($0, 10) }
+function convquotes(s, r, i) {
+ r = ""
+ while (i = index(s, "[[")) {
+ r = r substr(s, 1, i-1) "\\code{}"
+ s = substr(s, i+2)
+ if (i = match(s, "\\]\\]+")) {
+ r = r substr(s, 1, i-1+RLENGTH-2) "\\edoc{}"
+ s = substr(s, i+RLENGTH)
+ } else {
+ r = r s "\\edoc{}"
+ s = ""
+ }
+ }
+ return r s
+}'
+status=$?
+if [ $tex -eq 1 ]; then echo "\\bye"; fi
+if [ $latex -eq 1 ]; then echo '\\end{document}' ; fi
+exit $status
diff --git a/web/noweb/src/shell/noweave.simple b/web/noweb/src/shell/noweave.simple
new file mode 100644
index 0000000000..b5a55e9f5a
--- /dev/null
+++ b/web/noweb/src/shell/noweave.simple
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+LIB=|LIBDIR|
+awk=nawk
+
+for i do
+ case "$i" in
+ -*) ;; # ignore
+ *) files="$files $i" ;;
+ esac
+done
+
+$LIB/markup $files | $awk '
+BEGIN { code=0
+ print "\\documentstyle{article}"
+ print "\\newcommand{\\fragment}[1]{{\\sl$\\langle$#1\\/$\\rangle$}}"
+ print "\\begin{document}"
+ }
+END { if (code) print "\\end{trivlist}"
+ print "\\end{document}"
+ }
+/^@quote$/ { printf "\\verb@"}
+/^@endquote$/ { printf "@" }
+/^@begin code/ { if (!code) print "\\begin{trivlist}\\raggedright\\obeylines\\leftskip=2em\\small\\item[]%"; code=1 }
+/^@end code/ { }
+/^@begin docs/ { if (code) print "\\end{trivlist}"; code=0 }
+/^@end docs/ { }
+/^@defn / { gsub(/\[\[/, "\\verb@"); gsub(/]]/, "@")
+ name = substr($0,7)
+ printf "\\hspace{-2em}"
+ printf "\\fragment{%s}", name
+ defs[name] += 1
+ if (defs[name] > 1)
+ printf "$+\\!\\!\\equiv$"
+ else
+ printf "$\\equiv$"
+ printf "\\index{\\fragment{%s}}", name
+ }
+/^@use / { gsub(/\[\[/, "\\verb@"); gsub(/]]/, "@")
+ name = substr($0,6)
+ printf "\\fragment{%s}", name
+ printf "\\index{\\fragment{%s}}", name
+ }
+/^@literal / { printf "%s", substr($0, 10) }
+/^@nl$/ { print ""}
+/^@text / { if (code) printf "\\verb@%s@", substr($0,7)
+ else printf "%s", substr($0,7) }'
+
diff --git a/web/noweb/src/shell/noweb b/web/noweb/src/shell/noweb
new file mode 100644
index 0000000000..0264a46905
--- /dev/null
+++ b/web/noweb/src/shell/noweb
@@ -0,0 +1,34 @@
+#!/bin/sh
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+# $Id: noweb.nw,v 1.3 1997/09/13 20:29:56 nr Exp $
+# $Name: $
+LIB=|LIBDIR|
+markup=$LIB/markup mntopt=-L status=0 tex=1 output=1
+while [ $# -gt 0 ]; do
+ case $1 in
+ -to|-ot) tex= output= ; shift ;;
+ -t) tex= ; shift ;;
+ -o) output= ; shift ;;
+ -L*) mntopt="$1" ; shift ;;
+ -markup) markup="$2" ; shift; shift ;;
+ -*) echo "Unrecognized option $1" 1>&2; exit 1 ;;
+ *) break ;;
+ esac
+done
+if [ $# -eq 0 ]; then echo "Usage: $0 [-L[fmt] -t -o] file [...]" 1>&2; exit 1; fi
+
+for source do
+ if [ -n "$output" ]; then
+ PATH="$PATH:$LIB" $markup -t "$source" | $LIB/mnt -t8 "$mntopt" -all || status=1
+ fi
+ if [ -n "$tex" ]; then
+ texname=`echo "$source" | sed '/\./s/\.[^.]*$//'`
+ texname="$texname.tex"
+ PATH="$PATH:$LIB" $markup "$source" | $LIB/finduses -noquote | $LIB/noidx -delay |
+ nawk '{print}
+ /^@defn [^ ]*$/ { print "@literal \\let\\nwnotused=\\nwoutput{}" }' |
+ $LIB/totex -delay | cpif $texname || status=1
+ fi
+done
+exit $status
diff --git a/web/noweb/src/shell/noweb.nw b/web/noweb/src/shell/noweb.nw
new file mode 100644
index 0000000000..1f258cb755
--- /dev/null
+++ b/web/noweb/src/shell/noweb.nw
@@ -0,0 +1,74 @@
+\section{Generating all outputs from a {\tt noweb} file}
+The copyright applies both to the {\tt noweb} source and to the
+generated shell script.
+<<copyright notice>>=
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+@
+Here's the organization of the source:
+<<noweb>>=
+#!/bin/sh
+<<copyright notice>>
+# $Id: noweb.nw,v 1.3 1997/09/13 20:29:56 nr Exp $
+# $Name: $
+LIB=|LIBDIR|
+markup=$LIB/markup mntopt=-L status=0 tex=1 output=1
+<<consume options, setting [[tex]], [[output]], [[mntopt]], and [[markup]]>>
+if [ $# -eq 0 ]; then <<complain of no args and exit>>; fi
+
+for source do
+ if [ -n "$output" ]; then
+ PATH="$PATH:$LIB" $markup -t "$source" | $LIB/mnt -t8 "$mntopt" -all || status=1
+ fi
+ if [ -n "$tex" ]; then
+ <<write {\TeX} output>> || status=1
+ fi
+done
+exit $status
+@
+{\tt noweb} could be modified to follow two Knuth-like and {\tt nuweb}-like conventions:
+\begin{itemize}
+\item
+Treat multiple white space within chunk names as single blanks, and
+ignore leading and trailing whitespace.
+\item
+Permit chunk names to be abbreviated by writing an initial subsequence
+of the name followed by ``[[...]]''.
+\end{itemize}
+The modification is simple; just add these two programs to the
+pipeline.
+([[disambiguate]] is an Icon program found in the [[icon]] directory
+of the [[noweb]] distribution.)
+<<compress multiple blanks in uses and defns>>=
+sed -e '/^@[ud][se][ef][ n]/s/[ ][ ]*/ /g' \
+ -e '/^@[ud][se][ef][ n]/s/ $//'
+<<disambiguate uses and defns ending in three dots>>=
+$LIB/disambiguate
+@
+When writing {\TeX} output, I call [[$markup]] a second time to expand tabs.
+%% timings on nuweb
+% markup 0.4u 0.1s
+% noxref 3.9u 1.0s
+% nawk 6.5u 0.2s
+<<write {\TeX} output>>=
+texname=`echo "$source" | sed '/\./s/\.[^.]*$//'`
+texname="$texname.tex"
+PATH="$PATH:$LIB" $markup "$source" | $LIB/finduses -noquote | $LIB/noidx -delay |
+nawk '{print}
+/^@defn [^ ]*$/ { print "@literal \\let\\nwnotused=\\nwoutput{}" }' |
+$LIB/totex -delay | cpif $texname
+<<consume options, setting [[tex]], [[output]], [[mntopt]], and [[markup]]>>=
+while [ $# -gt 0 ]; do
+ case $1 in
+ -to|-ot) tex= output= ; shift ;;
+ -t) tex= ; shift ;;
+ -o) output= ; shift ;;
+ -L*) mntopt="$1" ; shift ;;
+ -markup) markup="$2" ; shift; shift ;;
+ -*) echo "Unrecognized option $1" 1>&2; exit 1 ;;
+ *) break ;;
+ esac
+done
+<<complain of no args and exit>>=
+echo "Usage: $0 [-L[fmt] -t -o] file [...]" 1>&2; exit 1
+@
diff --git a/web/noweb/src/shell/nuweb2noweb b/web/noweb/src/shell/nuweb2noweb
new file mode 100644
index 0000000000..cf10ed2cc8
--- /dev/null
+++ b/web/noweb/src/shell/nuweb2noweb
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# convert nuweb to noweb
+
+LIB=|LIBDIR|
+
+$LIB/numarkup "$@" | $LIB/unmarkup
diff --git a/web/noweb/src/shell/roff.nw b/web/noweb/src/shell/roff.nw
new file mode 100644
index 0000000000..24ddee69f3
--- /dev/null
+++ b/web/noweb/src/shell/roff.nw
@@ -0,0 +1,731 @@
+.nr N 4
+.nr O 1i
+.nr P 2
+.nr W 6.5i
+.S 18 18
+'ce
+Converting noweb markup to troff markup
+.sp 0.5i
+.S 12 15
+.PH "'Converting noweb markup to troff markup''%'"
+.P
+Toroff is a noweb backend for formatting text with troff
+markup. Toroff was written by Phil Bewig ([[pbewig@netcom.com]])
+during April, 1996, and contributed to Norman Ramsey's noweb
+literate programming system. Liam Quin ([[lee@sq.com]]) provided technical
+assistance with troff.
+Norman Ramsey made the code easier to port and made it conform with
+his idea of the noweb philosophy.
+Arnold Robbins ([[arnold@skeeve.com]]) modified it for use with
+GNU troff (hopefully improving portability even more),
+improved the flexibility of the noroff script,
+and added extra explanation about the gory troff details.
+.P
+The high-level view of toroff is that it comes in two parts.
+The first part is an ordinary back end, which produces
+troff augmented with special comments, using the [[.tm]] macro.
+The second part, [[noroff]], runs troff, with all of its
+pre-processors and post-processors.
+[[noroff]] also processes the
+comments in to a [[tags]] file.
+Moreover, [[noroff]] gathers from the tags file the
+cross-referencing information gathered on the previous formatting run.
+The trick that makes the whole thing work is that the
+troff markup added by toroff causes cross-referencing
+information to be written to standard error during the formatting run;
+the [[noroff]] script cleverly gathers this material into
+the [[tags]] file,
+which can be used as input to the next
+formatting run.
+As with LaTeX, the cross-referencing information is always one
+formatter run behind, and to get a consistent document you must keep
+running [[noroff]] until you reach a fixed point.
+([[noroff]] ought to provide some help for this, to show when the tags
+file has changed, for example.)
+.HU "The shell wrapper"
+Toroff is implemented as an awk program in a shell wrapper, and
+uses a macro package to control the final formatting. In the following
+discussion, a sample macro package, suitable for use with either [[-mm]]
+or [[-ms]], is presented alongside the awk code which calls the
+macros. Users may wish to modify the sample macros to suit local
+preferences. Many do-nothing macros are provided as user exits so
+knowledgeable users can modify document formatting without changing
+the awk program.
+<<toroff>>=
+#!/bin/sh
+LIB=|LIBDIR|
+AWK=nawk
+<<process arguments>>
+<<invoke awk program>>
+@ .P
+Processing arguments is simple.
+The only effect of the [[-delay]] flag is to control placement of
+the ``begin document'' document macro;
+the noroff script supplies the command to source the noroff macros
+as the very first line. This avoids groff warnings about undefined
+strings in the generated markup for the indexing and cross-references.
+<<process arguments>>=
+delay=0 noindex=0
+for i do
+ case $i in
+ -delay) delay=1 ;;
+ -noindex) noindex=1 ;;
+ *) echo "This can't happen -- $i passed to toroff" 1>&2;
+ exit 1;;
+ esac
+done
+@ %def delay noindex
+.P
+Invoking the awk program is hard, because the program uses both
+single quotes and double quotes, so neither can be used to protect the
+other, and quoting each quote is ugly. The pragmatic solution is to
+copy the awk program into a temporary file, using a shell here-document.
+<<invoke awk program>>=
+awkfile=$($LIB/nwmktemp) || { echo "$0: Cannot create temporary file" >&2; exit 1; }
+trap 'rm -f $awkfile' 0 1 2 10 14 15
+cat > $awkfile << 'EOF'
+<<awk program>>
+EOF
+$AWK -f $awkfile -v delay=$delay noindex=$noindex
+@ %def awkfile tagsfile
+.HU "The main program"
+The overall structure of the awk program is simple. The [[tags]]
+file is processed in the [[BEGIN]] action, and the noweb source is
+processed by awk's pattern-action loop.
+<<awk program>>=
+<<read and process noweb source>>
+<<functions>>
+@ .HU "Beginning and ending the document"
+The [[-delay]] option allows the initial document chunk to be processed
+before invoking the ``begin document'' macro,
+so that necessary initialization may
+be performed. The only commands which are useful in such an initial chunk
+are bare troff commands. The delay is handled by special patterns for
+the initial document chunk. Because several noweb files can be
+processed in the same formatting run, there can be several document
+chunks numbered zero. The later ones are not treated specially, by the
+simple expedient of turning off [[delay]] after the first one. This
+code also handles the [[trailer]] at the end of the document.
+<<read and process noweb source>>=
+/^@begin docs 0$/ { if (delay) next }
+/^@end docs 0$/ { if (delay) { <<start document>>; delay = 0; next } }
+/^@header m/ { if (!delay) { <<start document>> } }
+/^@trailer/ { print ".ENDOFDOCUMENT" }
+<<tmac.w>>=
+.de ENDOFDOCUMENT
+..
+<<start document>>=
+printf ".BEGINNINGOFDOCUMENT\n"
+<<tmac.w>>=
+.de BEGINNINGOFDOCUMENT
+..
+@ .HU "Labels, references, and section numbers"
+Here is the code to number code chunks in the page-number-and-letter
+style used by noweb. The current page number is always stored in
+troff's [[%]] number register, and we will arrange an
+auto-incrementing number register [[SECTIONLETTER]] which is
+reset at each top-of-page and is formatted as lower-case alphabetic
+characters using troff's [[.af]] request. The top-of-page trap is
+sprung one unit below the top of the page in order not to interfere with
+the top-of-page macros of [[-mm]] or [[-ms]].
+<<read and process noweb source>>=
+/^@xref label/ { lastxreflabel = $3 }
+/^@xref ref/ { lastxrefref = tag(substr($0, 11)) }
+@ %def lastxreflabel lastxrefref
+<<tmac.w>>=
+.de RESETLETTER \" reset letter at top of page
+.nr SECTIONLETTER 0 1 \" count code sections on same page
+.af SECTIONLETTER a \" ... formatted as lower-case alpha
+..
+.wh 1u RESETLETTER \" trap just below top of page
+@ .P
+Note that the link information on the previous chunk shows that this
+chunk uses the [[code]] variable, when in fact [[code]] only appears
+as text within a comment. This error is an artifact of the language
+independence of noweb.
+@ .HU "Beginning and ending chunks"
+Except for the initial document chunk, which was processed above, all
+beginnings and endings of documentation and code chunks are processed
+here. Variable [[code]] is [[0]] in text chunks, [[1]] in code
+chunks and [[2]] in quoted code. The argument to
+the [[.ENDCODECHUNK]] macro is the label which was in effect when the
+code chunk was started, which is stored in the variable [[lastdefnlabel]].
+<<read and process noweb source>>=
+/^@begin docs/ { printf ".BEGINDOCCHUNK\n" }
+/^@end docs/ { printf ".ENDDOCCHUNK\n" }
+/^@begin code/ { code = 1; printf ".BEGINCODECHUNK\n" }
+/^@end code/ { code = 0; printf ".ENDCODECHUNK %s\n", lastdefnlabel }
+@ %def code
+.P
+The macros related to document chunks are simple: [[.BEGINDOCCHUNK]] does
+nothing, and [[.ENDDOCCHUNK]] merely flushes any unprinted output.
+<<tmac.w>>=
+.de BEGINDOCCHUNK
+..
+.de ENDDOCCHUNK
+.br
+..
+@ .P
+A code chunk uses a font, type size, leading, fill and adjust modes,
+indent and tab stops which are distinct from those in the documentation.
+These environment variables must be saved on entering a code chunk,
+appropriate values for a code chunk must be established, and the
+original values restored at the end of a code chunk.
+<<tmac.w>>=
+.de BEGINCODECHUNK
+.sp 0.4v
+<<save environment>>
+<<set local environment>>
+.di CODECHUNK
+..
+.de ENDCODECHUNK
+<<read back code chunk from diversion>>
+<<restore environment>>
+..
+@ .P
+The code below replaces the built-in [[.ta]] tab-setting command with a
+custom tab-setting command that allows tab stops to be reset and later
+recalled.
+(A.R.: I don't see a use for this; furthermore this saves
+the new settings in [[ta_saved]], it doesn't save the old ones.)
+<<tmac.w>>=
+.rn ta real_ta
+.de ta
+.ds ta_saved \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.real_ta \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+@ .P
+The font, type size and leading require two saved values, so
+that both the current value and the previous value can be restored.
+For those not intimately familiar with troff, [[.f]] is the current
+font number, [[.s]] is the current point size, [[.v]] is the current
+vertical spacing, [[.u]] is 1 or 0 for fill/no-fill, [[.j]] is the
+current adjust mode, and [[.i]] is the current indent mode.
+<<save environment>>=
+.nr OLDft \\n(.f
+.ft P
+.nr PREVft \\n(.f
+.nr OLDps \\n(.s
+.ps
+.nr PREVps \\n(.s
+.nr OLDvs \\n(.v
+.vs
+.nr PREVvs \\n(.v
+.nr OLDfi \\n(.u
+.nr OLDad \\n(.j
+.nr OLDin \\n(.in
+@ .P
+Code is printed in a constant-width font at 80% the size of document text.
+Code is collected in fill mode with explicit breaks after each line;
+although it might seem more natural to collect lines of code in no-fill
+mode, that is not possible here because uses of code chunks must be able
+to appear on the same line as actual code.
+<<set local environment>>=
+.ft CW
+.ps \\n(.s*4/5
+.vs \\n(.vu*4u/5u
+.in +0.5i
+.real_ta 0.5i 1i 1.5i 2i 2.5i 3i 3.5i 4i
+.fi
+@ .P
+In order to prevent page breaks within code chunks, each code chunk
+is read into a diversion and a page break is issued if the code chunk
+is too big to fit on the current page. After the diversion is read back
+in, when it is known what page the code is printed on, the location of
+the code chunk is written using a [[.tm]] command.
+(The [[dn]] number register is the height of the most recent diversion,
+and [[.t]] is the distance to the next trap.)
+<<read back code chunk from diversion>>=
+.br \" flush last line of code
+.di \" end diversion
+.if \\n(dn>\\n(.t .bp \" force form feed if too big
+.nf \" no fill mode -- already formatted
+.in -0.5i \" don't re-indent when re-reading text
+.CODECHUNK \" output body of diversion
+.tm ###TAG### \\$1 \\n[%]\\n+[SECTIONLETTER] \" write tag info
+.rm CODECHUNK \" reset diversion for next code chunk
+@ .P
+Finally, here is the code to restore the environment that existed before
+the beginning of the code chunk.
+<<restore environment>>=
+.ft \\n[PREVft]
+.ft \\n[OLDft]
+.ps \\n[PREVps]
+.ps \\n[OLDps]
+.vs \\n[PREVvs]u
+.vs \\n[OLDvs]u
+.if \\n[OLDfi] .fi
+.ad \\n[OLDad]
+.in \\n[OLDin]u
+.real_ta
+@ .HU "Text, code, and quoted code"
+In text chunks, text is copied from input to output basically unchanged.
+However, when quoted code is included in a line of text, the quoted code
+is processed by separate macros and it is possible that the continuation
+of the line of text after the quoted code begins with a character which
+is special to troff at the beginning of a line: a space, period, or
+single quote. To prevent problems in this case, variable [[text]] is
+set to [[0]] at the beginning of each line and incremented whenever text
+is written, and each text after the first is guarded by a non-printing
+null character.
+<<read and process noweb source>>=
+/^@text/ && code == 0 { s = substr($0, 7)
+ if (text++) printf "\\&"
+ printf "%s", substr($0, 7) }
+/^@nl/ && code != 1 { text = 0; printf "\n" }
+@ %def text
+.P
+In code chunks, backslashes are replaced with troff's [[\e]] escape
+sequence and a non-printing null character is added at the beginning of
+each text to guard leading periods. If your macro package issues a [[.ec]]
+command, this code will have to change; fortunately, both [[-mm]] and
+[[-ms]] are nicely-behaved with respect to escape characters.
+<<read and process noweb source>>=
+/^@text/ && code != 0 { s = substr($0, 7)
+ gsub(/\\/, "\\e", s)
+ printf "\\&%s\\c\n", s }
+@ .P
+Dealing with newlines in code chunks is surprisingly hard. We would like
+to print lines of code in [[nofill]] mode, but since noweb's markup
+and filter programs may split lines of code, we are forced to use
+[[fill]] mode and deal with newlines ourselves. Further, if a line is
+too long to print on a single line, it must be split, and the continuation
+line right-justified instead of left-justified. All of this processing is
+accomplished by calling a macro at each newline; the macro plants a
+page-position trap at the next line so that any continuation line will be
+right-justified.
+(The [[.dt]] command defines a trap for use within the current
+diversion, whereas the more common [[.wh]] is for a particular
+page position.)
+<<read and process noweb source>>=
+/^@nl/ && code == 1 { printf ".NEWLINE\n" }
+<<tmac.w>>=
+.de LINETRAP
+.dt \\n[TRAPplace]u \"cancel current trap
+'ad r \" right-adjust continuation lines
+..
+.de NEWLINE
+.dt \\n[TRAPplace]u \" cancel current trap
+\& \" end continued word
+.br \" flush output
+<<plant newline trap>>
+..
+@ .P
+The newline trap is planted after each definition line, for the first
+line of code in the code chunk, and again after each newline in the
+code chunk.
+(The [[.d]] register indicates the current vertical position
+within the diversion.)
+<<plant newline trap>>=
+.nr TRAPplace \\n(.du+1u \" location of next trap
+.dt \\n[TRAPplace]u LINETRAP \" plant trap at next line
+.ad l \" left-adjust first line
+@ .P
+Quoted code in a documentation chunk is printed within its own macros,
+which must not cause a break.
+<<read and process noweb source>>=
+/^@quote/ { code = 2; printf "\\c\n.BEGINQUOTEDCODE\n" }
+/^@endquote/ { code = 0; text++; printf ".ENDQUOTEDCODE\n" }
+<<tmac.w>>=
+.de BEGINQUOTEDCODE
+.nr SAVEft \\n(.f
+.ft P
+.nr SAVEftP \\n(.f
+.ft CW
+..
+.de ENDQUOTEDCODE
+.ft \\n[SAVEftP]
+.ft \\n[SAVEft]
+..
+@ .HU "Definitions and uses of code chunks"
+Definitions and uses of code chunks are handled below. Variable
+[[defn[name]]] is set to a plus sign after a definition is printed, so
+that continuations of the definition are properly identified. Variable
+[[lastxrefref]] is the tag associated with the most-recently-seen
+cross-reference label, and refers to the section number of the original
+definition of the code chunk.
+<<read and process noweb source>>=
+/^@defn/ { name = convquote(substr($0, 7))
+ lastdefnlabel = lastxreflabel
+ if (! (name in defn))
+ defn[name] = "\\(=="
+ printf ".DEFINITION %s \"%s\" %s %s\n",
+ tag(lastdefnlabel), name, lastxrefref, defn[name]
+ defn[name] = "\\(pl\\(==" }
+/^@use/ { name = convquote(substr($0, 6))
+ printf "\\c\n"
+ printf ".USE \"%s\" %s\n", name, lastxrefref }
+@ %def name defn lastdefnlabel
+@ The original version of toroff used [[\(oG]] and [[\(cG]] for
+the double angle bracket characters. These appear to be non-standard,
+thus we define our own strings to take their place. (A.R.)
+<<tmac.w>>=
+.ds o< <\h'-0.1m'<
+.ds c> >\h'-0.1m'>
+.de DEFINITION
+.ti -0.5i
+\\fR\\(sc\\$1 \\*(o<\\$2 \\$3\\*(c>\\$4\\fP
+<<plant newline trap>>
+..
+.de USE
+\\fR\\*(o<\\$1 \\$2\\*(c>\\fP\c \" section name and original number
+..
+@ .P
+Processing of quoted code within definitions and uses is performed by the
+[[convquote]] function. This must be processed differently than quoted
+code within text because the noweb markup program doesn't emit
+[[@quote]] .\|.\|. [[@endquote]] markers within definitions and uses. And,
+because the subject string is used as an argument to a macro, it would not
+possible to call the [[.BEGINQUOTEDCODE]] and [[.ENDQUOTEDCODE]] macros,
+even if noweb did emit the markers within definitions and uses.
+.P
+The original version just did [[gsub(/\]\]/, "\\*[ENDCONVQUOTE]", s)]],
+but this does not catch the case of something like \f(CW[\&[a[i\&]\&]\&]\fP.
+A more complicated loop using [[match()]] is in order.
+It loops through the string, picking it apart, and replacing
+each quoted code section individually.
+<<functions>>=
+function convquote(s, out, front, mid, tail) {
+ gsub(/\[\[/, "\\*[BEGINCONVQUOTE]", s)
+ # gsub(/\]\]/, "\\*[ENDCONVQUOTE]", s)
+ out = ""
+ mid = "\\*[ENDCONVQUOTE]"
+ while (match(s, /\]\]+/) != 0) {
+ # RLENGTH is length of match, want to remove last two chars
+ # RSTART is where sequence of ]s begins
+ tail = substr(s, RSTART + RLENGTH)
+ if (RLENGTH == 2) # easy
+ front = substr(s, 1, RSTART - 1)
+ else
+ front = substr(s, 1, RSTART - 1 + RLENGTH - 2)
+ out = out front mid
+ s = tail
+ }
+ out = out s
+ return out }
+# my test program for the revised function - ADR
+# BEGIN { str = "abc[[foo[i]]]]]]]]junk"
+# print str
+# print convquote(str)
+# str2 = "nothing here"
+# print str2
+# print convquote(str2)
+# str3 = "abc[[foo[i]]]]]]]]junk[[bar[i]]more stuff[[baz]]"
+# print str3
+# print convquote(str3)
+# }
+@ %def convquote
+<<tmac.w>>=
+.ds BEGINCONVQUOTE \f[CW]
+.ds ENDCONVQUOTE \fP
+@ .HU "Cross-referencing and indexing"
+The code for producing the ``hypertext links'' at the end of each
+code section is given below: for each type, the beginning of the message
+is printed, items are accumulated in a list, and the list is printed
+after the number of items in the list is known. The first time any of
+the cross-reference or identifier-index messages appears, it is necessary
+to reset the point size and leading to the small font used for this
+material, which is 80% of the size of code and 64% of the size of text.
+All of these lines are part of the diversion which collects a
+code chunk. First is the code to report definitions and uses of code.
+<<read and process noweb source>>=
+/^@xref begindefs/ { <<checkcode>>; printf ".XREFDEFS\n" }
+/^@xref beginuses/ { <<checkcode>>; printf ".XREFUSES\n" }
+/^@xref notused/ { <<checkcode>>; printf ".XREFNOTUSED\n" }
+/^@xref (def|use)item/ { printf ".ADDLIST %s\n", tag($3) }
+/^@xref end(def|use)s/ { printf ".PRINTLIST\n"; code = 1 }
+<<tmac.w>>=
+.de XREFDEFS
+This definition continued in
+..
+.de XREFUSES
+This code used in
+..
+.de XREFNOTUSED
+This code is not used in this document.
+.br
+..
+@ .P
+The code to report the definitions of identifiers appears below. The
+[[if]] in [[@index isused]] prevents index definitions from pointing
+to themselves.
+<<read and process noweb source>>=
+/^@index begindefs/ && !noindex { <<checkcode>>; printf ".INDEXDEF\n" }
+/^@index isused/ && !noindex {
+ if (tag($3) != lastxrefref) printf ".ADDLIST %s\n", tag($3) }
+/^@index defitem/ && !noindex { printf ".DEFITEM %s\n.PRINTLIST\n", $3 }
+<<tmac.w>>=
+.de INDEXDEF
+Defines:
+.br
+..
+.de DEFITEM
+.ti +1m
+\\*[BEGINCONVQUOTE]\\$1\\*[ENDCONVQUOTE],
+.if \\n[NLIST]>0 used in
+..
+@ .P
+Finally, here is the code to report uses of identifiers.
+<<read and process noweb source>>=
+/^@index beginuses/ && !noindex { <<checkcode>>; printf ".INDEXUSE\n" }
+/^@index isdefined/ && !noindex { lastuse = tag($3) }
+/^@index useitem/ && !noindex {
+ printf ".ADDLIST \"\\*[BEGINCONVQUOTE]%s\\*[ENDCONVQUOTE] %s\"\n",
+ $3, lastuse }
+/^@index enduses/ && !noindex { printf ".PRINTLIST\n" }
+@ %def lastuse
+<<tmac.w>>=
+.de INDEXUSE
+Uses
+..
+@ .P
+The macros [[.ADDLIST s]], which adds string [[s]] to a queued list
+waiting to be printed, and [[.PRINTLIST]], which prints the list,
+appropriately formatted with commas, are described below. These macros
+make use of some interesting troff idioms. [[LIST]] is an array of
+strings; the [[n]]-th string in [[LIST]] can be set to [[s]] by
+[[.ds LISTn s]]. The expression [[.nr n \\$1]] converts the string
+passed as the first argument to a macro to the number [[n]]. Loops
+are implemented in troff as recursive macros, as in [[.PRINTITEM]].
+<<tmac.w>>=
+.nr NLIST 0 1 \" initialize list index to 0 with auto-increment 1
+.de ADDLIST
+.ds LIST\\n+[NLIST] \\$1
+..
+.de PRINTITEM
+.nr PLIST \\$1
+.nr PLISTPLUS \\n[PLIST]+1
+.if \\n[NLIST]-\\n[PLIST]<0 not used in this document.
+.if \\n[NLIST]-\\n[PLIST]=0 \\*[LIST\\n[PLIST]].
+.if \\n[NLIST]-\\n[PLIST]=1 \
+ \\*[LIST\\n[PLIST]] and \\*[LIST\\n[PLISTPLUS]].
+.if \\n[NLIST]-\\n[PLIST]>1 \{ \\*[LIST\\n[PLIST]],
+. PRINTITEM 1+\\n[PLIST] \}
+..
+.de PRINTLIST
+.PRINTITEM 1
+.br
+.nr NLIST 0 1 \" re-initialize for next list
+..
+@ .P
+This code and macro reduces the font size in which the cross-reference
+and identifier index information is printed at the end of a code chunk.
+The [[code]] variable is set to [[0]] to ensure that [[.STARTXREF]]
+is performed only once at the end of each code chunk. This code also
+resets the adjustment mode, which was changed to left-adjustment or
+right-adjustment by the [[LINETRAP]] macro, and cancels the [[NEWLINE]]
+trap at [[TRAPplace]].
+<<checkcode>>=
+if (code) { code = 0; printf ".STARTXREF\n" }
+<<tmac.w>>=
+.de STARTXREF
+.ps \\n(.s*4/5
+.vs \\n(.vu*4u/5u
+.ft \\n[OLDft]
+.ad \\n[OLDad]
+.dt \\n[TRAPplace]u
+.sp 0.4v
+..
+@ .HU "Collecting the lists of chunks and identifiers"
+Collecting the lists of chunks and identifiers takes two passes over the
+file, because the section numbers which tags refer to aren't known on
+the first pass. Therefore, the strategy on the first pass is to write
+the chunk and identifier index entries to the [[tags]] file on standard
+error, and actually prepare the lists when reading the [[tags]] file on
+the second pass. Thus, the first pass code shown here merely copies
+the chunk and identifier index entries from the noweb intermediate
+file to the [[tags]] file using troff's [[.tm]] command. The
+first section below handles chunks, the second section handles
+identifiers.
+<<read and process noweb source>>=
+/^@xref beginchunks/ { printf ".tm ###BEGINCHUNKS###\n" }
+/^@xref chunkbegin/ { printf ".tm ###CHUNKBEGIN### %s\n",
+ substr($0, length($3) + 19) }
+/^@xref chunkuse/ { printf ".tm ###CHUNKUSE### %s\n", $3 }
+/^@xref chunkdefn/ { printf ".tm ###CHUNKDEFN### %s\n", $3 }
+/^@xref chunkend/ { printf ".tm ###CHUNKEND###\n" }
+/^@xref endchunks/ { printf ".tm ###ENDCHUNKS###\n" }
+<<read and process noweb source>>=
+/^@index beginindex/ { printf ".tm ###BEGININDEX###\n" }
+/^@index entrybegin/ { printf ".tm ###ENTRYBEGIN### %s\n",
+ substr($0, length($3) + 20) }
+/^@index entryuse/ { printf ".tm ###ENTRYUSE### %s\n", $3 }
+/^@index entrydefn/ { printf ".tm ###ENTRYDEFN### %s\n", $3 }
+/^@index entryend/ { printf ".tm ###ENTRYEND###\n" }
+/^@index endindex/ { printf ".tm ###ENDINDEX###\n" }
+@ .HU "The \f[CW]tags\fP file"
+The [[tags]] file is re-created at each formatter run by the troff
+idiom (some people would call it a trick) of capturing the output of
+troff's [[.tm]] command, which writes to the standard error, in a
+file via command-line redirection. The code below uses an awk idiom; the
+[[sub]] simultaneously tests for a match and deletes the matched text.
+<<action for [[tags]] line>>=
+{
+ if (sub(/^###TAG### / , "")) tags[$1] = $2
+ else if (sub(/^###BEGINCHUNKS###/, "")) printf ".de CLIST\n.CLISTBEGIN\n"
+ else if (sub(/^###CHUNKBEGIN### /, "")) { name = convquote($0)
+ chunkuse = chunkdefn = "" }
+ else if (sub(/^###CHUNKUSE### / , "")) chunkuse = chunkuse " " tag($0)
+ else if (sub(/^###CHUNKDEFN### / , "")) chunkdefn = chunkdefn " " tag($0)
+ else if (sub(/^###CHUNKEND###/ , ""))
+ printf ".CITEM \"%s\" \"%s\" \"%s\"\n", name, chunkdefn, chunkuse
+ else if (sub(/^###ENDCHUNKS###/ , "")) printf ".CLISTEND\n..\n"
+ else if (sub(/^###BEGININDEX###/ , "")) printf ".de ILIST\n.ILISTBEGIN\n"
+ else if (sub(/^###ENTRYBEGIN### /, "")) { name = convquote($0)
+ entryuse = entrydefn = "" }
+ else if (sub(/^###ENTRYUSE### / , "")) entryuse = entryuse " " tag($0)
+ else if (sub(/^###ENTRYDEFN### / , "")) entrydefn = entrydefn " " tag($0)
+ else if (sub(/^###ENTRYEND###/ , "")) {
+ for (i = 1; i <= split(entrydefn, entryarray); i++)
+ sub(entryarray[i], "\\*[BEGINDEFN]&\\*[ENDDEFN]", entryuse)
+ printf ".IITEM \"%s\" \"%s\"\n", name, entryuse }
+ else if (sub(/^###ENDINDEX###/ , "")) printf ".ILISTEND\n..\n"
+}
+@ %def tags chunkuse chunkdefn entryuse entrydefn entryarray
+.P
+The [[sub]] within the [[ENTRYEND]] causes definitions of identifiers
+to be italicized, according to the following defined strings.
+<<tmac.w>>=
+.ds BEGINDEFN \fI
+.ds ENDDEFN \fP
+@ .P
+Lookup of the section number corresponding to a particular tag is
+performed by the [[tag]] function.
+<<functions>>=
+function tag(s) { if (s in tags) return tags[s]; else return "???" }
+@ %def tag
+@ .P
+To use the tags, we have to read the tags file from the back end.
+The tags file name is the basename of the file, with the suffix
+replaced with [[".nwt"]] (see the toroff script, below).
+<<awk program>>=
+/^@file / {
+ if (tagsfile == "") {
+ tagsfile = substr($0, 7)
+ sub(".*/", "", tagsfile)
+ sub(/\.[^.]*$/, "", tagsfile)
+ tagsfile = tagsfile ".nwt"
+ while (getline <tagsfile > 0) <<action for [[tags]] line>>
+ }
+}
+@
+.HU "Using \\f[CW]toroff\fP"
+Toroff is one element of the normal noweave pipeline. Using
+toroff in its full generality is hard. The sample program shown
+below
+allows the user to specify the macro package (although it defaults to
+[[-mgm]]),
+and allows the user to specify troff pre-processors,
+post-processors and options.
+(Command line options to [[groff]] can be used to invoke tbl, pic, etc.)
+See the section below on how to generate the final formatted document.
+.P
+To avoid a race condition reading the tags file
+(troff is writing to it while the awk program is reading it),
+we first copy it for
+use by the awk program, and then remove the copy.
+The location of [[macrodir]] is likely to require customization.
+<<noroff>>=
+#!/bin/sh
+#
+# noroff -- run troff using tags file trick
+
+ROFF="groff"
+AWK=nawk
+macrodir=|LIBDIR|
+LIB=|LIBDIR|
+
+opts=
+
+if [ $# -eq 0 ]; then
+ echo "Usage: noroff [groff-arguments] files" 1>&2
+ exit 1
+fi
+
+while [ $# -gt 0 ]
+do
+ case $1 in
+ -*) opts="$opts $1"
+ shift
+ ;;
+ *) # end of options
+ break;
+ ;;
+ esac
+done
+
+if [ "$opts" = "" ]
+then
+ # no options, default to -mm
+ # groff already defaults to -Tps
+ opts="-mm"
+fi
+# otherwise assume user passed in all the arguments they want
+
+base="`basename $1 | sed '/\./s/\.[^.]*$//'`"
+tagsfile="$base.nwt"
+(echo ".so $macrodir/tmac.w"
+if [ -r "$tagsfile" ]; then
+ tagstemp=$($LIB/nwmktemp) || { echo "$0: Cannot create temporary file" >&2; exit 1; }
+ cp $tagsfile $tagstemp
+ $AWK '<<action for [[tags]] line>>
+ <<functions>>' $tagstemp
+ rm -f $tagstemp
+ fi
+ cat "$@") |
+($ROFF $opts 2>$tagsfile)
+sed '/^###[A-Z][A-Z]*###/d' $tagsfile >&2
+@ %def macrodir
+@ .HU "Macros for indexing chunks and identifiers"
+Toroff creates macros [[.CLIST]] and [[.ILIST]] which insert the
+lists of chunks and identifiers, respectively, in the output. These
+macros, in turn, call other macros which format the lists. The macros
+below cause each item to be written on a separate line, with continuation
+lines indented one-quarter inch.
+<<tmac.w>>=
+.de CLISTBEGIN
+.in +0.25i
+..
+.de CITEM
+.ti -0.25i
+.ie '\\$3'' \\*(o<\\$1 \\$2\\*(c> Not used in this document.
+.el \\*(o<\\$1 \\$2\\*(c> \\$3
+.br
+..
+.de CLISTEND
+.in -0.25i
+..
+<<tmac.w>>=
+.de ILISTBEGIN
+.in +0.25i
+..
+.de IITEM
+.ti -0.25i
+\\f[CW]\\$1\\fP: \\$2
+.br
+..
+.de ILISTEND
+.in -0.25i
+..
+@ .HU "Using \f[CW]noweave -troff\fP and \f[CW]noroff\fP"
+To produce the final document,
+the tags file is needed for both the [[noweave]]
+and the [[noroff]] steps. This creates a bit of a boot-strapping
+problem, since it is troff that first creates the tags file.
+The way to do it is to run [[noweave]] and [[noroff]] in turn, twice.
+For example, to make a printable version of this document, you would
+run the programs like this.
+<<Example run>>=
+noweave -index -troff roff.nw > roff.tr
+noroff roff.tr > /dev/null # ignore warnings about CLIST and ILIST
+noweave -index -troff roff.nw > roff.tr
+noroff roff.tr > roff.ps # print this one
+@ .HU "Index of chunks and identifiers"
+The automatically-generated index of chunks and identifiers for
+toroff is shown below.
+.S 10 12
+.sp
+.CLIST
+.sp
+.2C
+.ILIST
diff --git a/web/noweb/src/shell/tmac.w b/web/noweb/src/shell/tmac.w
new file mode 100644
index 0000000000..3c75c52b62
--- /dev/null
+++ b/web/noweb/src/shell/tmac.w
@@ -0,0 +1,171 @@
+.de ENDOFDOCUMENT
+..
+.de BEGINNINGOFDOCUMENT
+..
+.de RESETLETTER \" reset letter at top of page
+.nr SECTIONLETTER 0 1 \" count code sections on same page
+.af SECTIONLETTER a \" ... formatted as lower-case alpha
+..
+.wh 1u RESETLETTER \" trap just below top of page
+.de BEGINDOCCHUNK
+..
+.de ENDDOCCHUNK
+.br
+..
+.de BEGINCODECHUNK
+.sp 0.4v
+.nr OLDft \\n(.f
+.ft P
+.nr PREVft \\n(.f
+.nr OLDps \\n(.s
+.ps
+.nr PREVps \\n(.s
+.nr OLDvs \\n(.v
+.vs
+.nr PREVvs \\n(.v
+.nr OLDfi \\n(.u
+.nr OLDad \\n(.j
+.nr OLDin \\n(.in
+.ft CW
+.ps \\n(.s*4/5
+.vs \\n(.vu*4u/5u
+.in +0.5i
+.real_ta 0.5i 1i 1.5i 2i 2.5i 3i 3.5i 4i
+.fi
+.di CODECHUNK
+..
+.de ENDCODECHUNK
+.br \" flush last line of code
+.di \" end diversion
+.if \\n(dn>\\n(.t .bp \" force form feed if too big
+.nf \" no fill mode -- already formatted
+.in -0.5i \" don't re-indent when re-reading text
+.CODECHUNK \" output body of diversion
+.tm ###TAG### \\$1 \\n[%]\\n+[SECTIONLETTER] \" write tag info
+.rm CODECHUNK \" reset diversion for next code chunk
+.ft \\n[PREVft]
+.ft \\n[OLDft]
+.ps \\n[PREVps]
+.ps \\n[OLDps]
+.vs \\n[PREVvs]u
+.vs \\n[OLDvs]u
+.if \\n[OLDfi] .fi
+.ad \\n[OLDad]
+.in \\n[OLDin]u
+.real_ta
+..
+.rn ta real_ta
+.de ta
+.ds ta_saved \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.real_ta \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de LINETRAP
+.dt \\n[TRAPplace]u \"cancel current trap
+'ad r \" right-adjust continuation lines
+..
+.de NEWLINE
+.dt \\n[TRAPplace]u \" cancel current trap
+\& \" end continued word
+.br \" flush output
+.nr TRAPplace \\n(.du+1u \" location of next trap
+.dt \\n[TRAPplace]u LINETRAP \" plant trap at next line
+.ad l \" left-adjust first line
+..
+.de BEGINQUOTEDCODE
+.nr SAVEft \\n(.f
+.ft P
+.nr SAVEftP \\n(.f
+.ft CW
+..
+.de ENDQUOTEDCODE
+.ft \\n[SAVEftP]
+.ft \\n[SAVEft]
+..
+.ds o< <\h'-0.1m'<
+.ds c> >\h'-0.1m'>
+.de DEFINITION
+.ti -0.5i
+\\fR\\(sc\\$1 \\*(o<\\$2 \\$3\\*(c>\\$4\\fP
+.nr TRAPplace \\n(.du+1u \" location of next trap
+.dt \\n[TRAPplace]u LINETRAP \" plant trap at next line
+.ad l \" left-adjust first line
+..
+.de USE
+\\fR\\*(o<\\$1 \\$2\\*(c>\\fP\c \" section name and original number
+..
+.ds BEGINCONVQUOTE \f[CW]
+.ds ENDCONVQUOTE \fP
+.de XREFDEFS
+This definition continued in
+..
+.de XREFUSES
+This code used in
+..
+.de XREFNOTUSED
+This code is not used in this document.
+.br
+..
+.de INDEXDEF
+Defines:
+.br
+..
+.de DEFITEM
+.ti +1m
+\\*[BEGINCONVQUOTE]\\$1\\*[ENDCONVQUOTE],
+.if \\n[NLIST]>0 used in
+..
+.de INDEXUSE
+Uses
+..
+.nr NLIST 0 1 \" initialize list index to 0 with auto-increment 1
+.de ADDLIST
+.ds LIST\\n+[NLIST] \\$1
+..
+.de PRINTITEM
+.nr PLIST \\$1
+.nr PLISTPLUS \\n[PLIST]+1
+.if \\n[NLIST]-\\n[PLIST]<0 not used in this document.
+.if \\n[NLIST]-\\n[PLIST]=0 \\*[LIST\\n[PLIST]].
+.if \\n[NLIST]-\\n[PLIST]=1 \
+ \\*[LIST\\n[PLIST]] and \\*[LIST\\n[PLISTPLUS]].
+.if \\n[NLIST]-\\n[PLIST]>1 \{ \\*[LIST\\n[PLIST]],
+. PRINTITEM 1+\\n[PLIST] \}
+..
+.de PRINTLIST
+.PRINTITEM 1
+.br
+.nr NLIST 0 1 \" re-initialize for next list
+..
+.de STARTXREF
+.ps \\n(.s*4/5
+.vs \\n(.vu*4u/5u
+.ft \\n[OLDft]
+.ad \\n[OLDad]
+.dt \\n[TRAPplace]u
+.sp 0.4v
+..
+.ds BEGINDEFN \fI
+.ds ENDDEFN \fP
+.de CLISTBEGIN
+.in +0.25i
+..
+.de CITEM
+.ti -0.25i
+.ie '\\$3'' \\*(o<\\$1 \\$2\\*(c> Not used in this document.
+.el \\*(o<\\$1 \\$2\\*(c> \\$3
+.br
+..
+.de CLISTEND
+.in -0.25i
+..
+.de ILISTBEGIN
+.in +0.25i
+..
+.de IITEM
+.ti -0.25i
+\\f[CW]\\$1\\fP: \\$2
+.br
+..
+.de ILISTEND
+.in -0.25i
+..
diff --git a/web/noweb/src/shell/toroff b/web/noweb/src/shell/toroff
new file mode 100644
index 0000000000..ea5212c315
--- /dev/null
+++ b/web/noweb/src/shell/toroff
@@ -0,0 +1,135 @@
+#!/bin/sh
+LIB=|LIBDIR|
+AWK=nawk
+delay=0 noindex=0
+for i do
+ case $i in
+ -delay) delay=1 ;;
+ -noindex) noindex=1 ;;
+ *) echo "This can't happen -- $i passed to toroff" 1>&2;
+ exit 1;;
+ esac
+done
+awkfile=$($LIB/nwmktemp) || { echo "$0: Cannot create temporary file" >&2; exit 1; }
+trap 'rm -f $awkfile' 0 1 2 10 14 15
+cat > $awkfile << 'EOF'
+/^@begin docs 0$/ { if (delay) next }
+/^@end docs 0$/ { if (delay) { printf ".BEGINNINGOFDOCUMENT\n"; delay = 0; next } }
+/^@header m/ { if (!delay) { printf ".BEGINNINGOFDOCUMENT\n" } }
+/^@trailer/ { print ".ENDOFDOCUMENT" }
+/^@xref label/ { lastxreflabel = $3 }
+/^@xref ref/ { lastxrefref = tag(substr($0, 11)) }
+/^@begin docs/ { printf ".BEGINDOCCHUNK\n" }
+/^@end docs/ { printf ".ENDDOCCHUNK\n" }
+/^@begin code/ { code = 1; printf ".BEGINCODECHUNK\n" }
+/^@end code/ { code = 0; printf ".ENDCODECHUNK %s\n", lastdefnlabel }
+/^@text/ && code == 0 { s = substr($0, 7)
+ if (text++) printf "\\&"
+ printf "%s", substr($0, 7) }
+/^@nl/ && code != 1 { text = 0; printf "\n" }
+/^@text/ && code != 0 { s = substr($0, 7)
+ gsub(/\\/, "\\e", s)
+ printf "\\&%s\\c\n", s }
+/^@nl/ && code == 1 { printf ".NEWLINE\n" }
+/^@quote/ { code = 2; printf "\\c\n.BEGINQUOTEDCODE\n" }
+/^@endquote/ { code = 0; text++; printf ".ENDQUOTEDCODE\n" }
+/^@defn/ { name = convquote(substr($0, 7))
+ lastdefnlabel = lastxreflabel
+ if (! (name in defn))
+ defn[name] = "\\(=="
+ printf ".DEFINITION %s \"%s\" %s %s\n",
+ tag(lastdefnlabel), name, lastxrefref, defn[name]
+ defn[name] = "\\(pl\\(==" }
+/^@use/ { name = convquote(substr($0, 6))
+ printf "\\c\n"
+ printf ".USE \"%s\" %s\n", name, lastxrefref }
+/^@xref begindefs/ { if (code) { code = 0; printf ".STARTXREF\n" }; printf ".XREFDEFS\n" }
+/^@xref beginuses/ { if (code) { code = 0; printf ".STARTXREF\n" }; printf ".XREFUSES\n" }
+/^@xref notused/ { if (code) { code = 0; printf ".STARTXREF\n" }; printf ".XREFNOTUSED\n" }
+/^@xref (def|use)item/ { printf ".ADDLIST %s\n", tag($3) }
+/^@xref end(def|use)s/ { printf ".PRINTLIST\n"; code = 1 }
+/^@index begindefs/ && !noindex { if (code) { code = 0; printf ".STARTXREF\n" }; printf ".INDEXDEF\n" }
+/^@index isused/ && !noindex {
+ if (tag($3) != lastxrefref) printf ".ADDLIST %s\n", tag($3) }
+/^@index defitem/ && !noindex { printf ".DEFITEM %s\n.PRINTLIST\n", $3 }
+/^@index beginuses/ && !noindex { if (code) { code = 0; printf ".STARTXREF\n" }; printf ".INDEXUSE\n" }
+/^@index isdefined/ && !noindex { lastuse = tag($3) }
+/^@index useitem/ && !noindex {
+ printf ".ADDLIST \"\\*[BEGINCONVQUOTE]%s\\*[ENDCONVQUOTE] %s\"\n",
+ $3, lastuse }
+/^@index enduses/ && !noindex { printf ".PRINTLIST\n" }
+/^@xref beginchunks/ { printf ".tm ###BEGINCHUNKS###\n" }
+/^@xref chunkbegin/ { printf ".tm ###CHUNKBEGIN### %s\n",
+ substr($0, length($3) + 19) }
+/^@xref chunkuse/ { printf ".tm ###CHUNKUSE### %s\n", $3 }
+/^@xref chunkdefn/ { printf ".tm ###CHUNKDEFN### %s\n", $3 }
+/^@xref chunkend/ { printf ".tm ###CHUNKEND###\n" }
+/^@xref endchunks/ { printf ".tm ###ENDCHUNKS###\n" }
+/^@index beginindex/ { printf ".tm ###BEGININDEX###\n" }
+/^@index entrybegin/ { printf ".tm ###ENTRYBEGIN### %s\n",
+ substr($0, length($3) + 20) }
+/^@index entryuse/ { printf ".tm ###ENTRYUSE### %s\n", $3 }
+/^@index entrydefn/ { printf ".tm ###ENTRYDEFN### %s\n", $3 }
+/^@index entryend/ { printf ".tm ###ENTRYEND###\n" }
+/^@index endindex/ { printf ".tm ###ENDINDEX###\n" }
+function convquote(s, out, front, mid, tail) {
+ gsub(/\[\[/, "\\*[BEGINCONVQUOTE]", s)
+ # gsub(/\]\]/, "\\*[ENDCONVQUOTE]", s)
+ out = ""
+ mid = "\\*[ENDCONVQUOTE]"
+ while (match(s, /\]\]+/) != 0) {
+ # RLENGTH is length of match, want to remove last two chars
+ # RSTART is where sequence of ]s begins
+ tail = substr(s, RSTART + RLENGTH)
+ if (RLENGTH == 2) # easy
+ front = substr(s, 1, RSTART - 1)
+ else
+ front = substr(s, 1, RSTART - 1 + RLENGTH - 2)
+ out = out front mid
+ s = tail
+ }
+ out = out s
+ return out }
+# my test program for the revised function - ADR
+# BEGIN { str = "abc[[foo[i]]]]]]]]junk"
+# print str
+# print convquote(str)
+# str2 = "nothing here"
+# print str2
+# print convquote(str2)
+# str3 = "abc[[foo[i]]]]]]]]junk[[bar[i]]more stuff[[baz]]"
+# print str3
+# print convquote(str3)
+# }
+function tag(s) { if (s in tags) return tags[s]; else return "???" }
+/^@file / {
+ if (tagsfile == "") {
+ tagsfile = substr($0, 7)
+ sub(".*/", "", tagsfile)
+ sub(/\.[^.]*$/, "", tagsfile)
+ tagsfile = tagsfile ".nwt"
+ while (getline <tagsfile > 0) {
+ if (sub(/^###TAG### / , "")) tags[$1] = $2
+ else if (sub(/^###BEGINCHUNKS###/, "")) printf ".de CLIST\n.CLISTBEGIN\n"
+ else if (sub(/^###CHUNKBEGIN### /, "")) { name = convquote($0)
+ chunkuse = chunkdefn = "" }
+ else if (sub(/^###CHUNKUSE### / , "")) chunkuse = chunkuse " " tag($0)
+ else if (sub(/^###CHUNKDEFN### / , "")) chunkdefn = chunkdefn " " tag($0)
+ else if (sub(/^###CHUNKEND###/ , ""))
+ printf ".CITEM \"%s\" \"%s\" \"%s\"\n", name, chunkdefn, chunkuse
+ else if (sub(/^###ENDCHUNKS###/ , "")) printf ".CLISTEND\n..\n"
+ else if (sub(/^###BEGININDEX###/ , "")) printf ".de ILIST\n.ILISTBEGIN\n"
+ else if (sub(/^###ENTRYBEGIN### /, "")) { name = convquote($0)
+ entryuse = entrydefn = "" }
+ else if (sub(/^###ENTRYUSE### / , "")) entryuse = entryuse " " tag($0)
+ else if (sub(/^###ENTRYDEFN### / , "")) entrydefn = entrydefn " " tag($0)
+ else if (sub(/^###ENTRYEND###/ , "")) {
+ for (i = 1; i <= split(entrydefn, entryarray); i++)
+ sub(entryarray[i], "\\*[BEGINDEFN]&\\*[ENDDEFN]", entryuse)
+ printf ".IITEM \"%s\" \"%s\"\n", name, entryuse }
+ else if (sub(/^###ENDINDEX###/ , "")) printf ".ILISTEND\n..\n"
+ }
+ }
+}
+EOF
+$AWK -f $awkfile -v delay=$delay noindex=$noindex
diff --git a/web/noweb/src/shell/toroff.nw b/web/noweb/src/shell/toroff.nw
new file mode 100644
index 0000000000..b9cdf5d29b
--- /dev/null
+++ b/web/noweb/src/shell/toroff.nw
@@ -0,0 +1,617 @@
+.nr N 4
+.nr O 1i
+.nr P 2
+.nr W 6.5i
+.fp 1 PR
+.fp 2 PI
+.fp 3 PB
+@ .ft 1
+.S 18 18
+'ce
+Converting noweb markup to troff markup
+.sp 0.5i
+.S 12 15
+.PH "'Converting noweb markup to troff markup''%'"
+.P
+Toroff is a noweb backend for formatting text with troff
+markup. Toroff was written by Phil Bewig ([[pbewig@netcom.com]])
+during April, 1996, and contributed to Norman Ramsey's noweb
+literate programming system. Liam Quin ([[lee@sq.com]]) provided technical
+assistance with troff.
+Norman Ramsey made the code easier to port and made it conform with
+his idea of the noweb philosophy.
+.P
+The high-level view of toroff is that it comes in two parts.
+The first part is an ordinary back end, which produces
+troff augmented with special comments, using the [[.tm]] macro.
+The second part, [[noroff]], runs troff, with all of its
+pre-processors and post-processors.
+[[noroff]] also processes the
+comments in to a [[tags]] file.
+Moreover, [[noroff]] gathers from the tags file the
+cross-referencing information gathered on the previous formatting run.
+The trick that makes the whole thing work is that the
+troff markup added by toroff causes cross-referencing
+information to be written to standard error during the formatting run;
+the [[noroff]] script cleverly gathers this material into
+the [[tags]] file,
+which can be used as input to the next
+formatting run.
+As with LaTeX, the cross-referencing information is always one
+formatter run behind, and to get a consistent document you must keep
+running [[noroff]] until you reach a fixed point.
+([[noroff]] ought to provide some help for this, to show when the tags
+file has changed, for example.)
+.HU "The shell wrapper"
+Toroff is implemented as an awk program in a shell wrapper, and
+uses a macro package to control the final formatting. In the following
+discussion, a sample macro package, suitable for use with either [[-mm]]
+or [[-ms]], is presented alongside the awk code which calls the
+macros. Users may wish to modify the sample macros to suit local
+preferences. Many do-nothing macros are provided as user exits so
+knowledgeable users can modify document formatting without changing
+the awk program.
+<<toroff>>=
+#!/bin/sh
+<<process arguments>>
+<<invoke awk program>>
+@ .P
+Processing arguments is simple.
+<<process arguments>>=
+delay=0 noindex=0
+for i do
+ case $i in
+ -delay) delay=1 ;;
+ -noindex) noindex=1 ;;
+ *) echo "This can't happen -- $i passed to toroff" 1>&2;
+ exit 1;;
+ esac
+done
+@ %def delay noindex
+.P
+Invoking the awk program is hard, because the program uses both
+single quotes and double quotes, so neither can be used to protect the
+other, and quoting each quote is ugly. The pragmatic solution is to
+copy the awk program into a temporary file, using a shell here-document.
+<<invoke awk program>>=
+export awkfile="$(LIB/nwmktemp)"
+trap 'rm -f $awkfile' 0 1 2 10 14 15
+cat > $awkfile << 'EOF'
+<<awk program>>
+EOF
+awk -f $awkfile -v tagsfile=$tagsfile delay=$delay noindex=$noindex macrodir=|LIBDIR|
+@ %def awkfile tagsfile
+.HU "The main program"
+The overall structure of the awk program is simple. The [[tags]]
+file is processed in the [[BEGIN]] action, and the noweb source is
+processed by awk's pattern-action loop.
+<<awk program>>=
+<<read and process noweb source>>
+<<functions>>
+@ .HU "Beginning and ending the document"
+The [[-delay]] option allows the initial document chunk to be processed
+before reading the macro packages, so that necessary initialization may
+be performed. The only commands which are useful in such an initial chunk
+are bare troff commands. The delay is handled by special patterns for
+the initial document chunk. Because several noweb files can be
+processed in the same formatting run, there can be several document
+chunks numbered zero. The later ones are not treated specially, by the
+simple expedient of turning off [[delay]] after the first one. This
+code also handles the [[trailer]] at the end of the document.
+<<read and process noweb source>>=
+/^@begin docs 0$/ { if (delay) next }
+/^@end docs 0$/ { if (delay) { <<load macro package>>; delay = 0; next } }
+/^@header m/ { macros = substr($0, 10)
+ if (!delay) { <<load macro package>> } }
+/^@trailer/ { print ".ENDOFDOCUMENT" }
+@ %def macros
+<<tmac.w>>=
+.de ENDOFDOCUMENT
+..
+@ .P
+The location of [[macrodir]] is likely to require customization.
+<<load macro package>>=
+printf ".so %s/tmac.%s\n", macrodir, macros
+printf ".so %s/tmac.w\n", macrodir
+printf ".BEGINNINGOFDOCUMENT\n"
+@ %def macrodir
+<<tmac.w>>=
+.de BEGINNINGOFDOCUMENT
+..
+@ .HU "Labels, references, and section numbers"
+Here is the code to number code chunks in the page-number-and-letter
+style used by noweb. The current page number is always stored in
+troff's [[%]] number register, and we will arrange an
+auto-incrementing number register [[SECTIONLETTER]] which is
+reset at each top-of-page and is formatted as lower-case alphabetic
+characters using troff's [[.af]] request. The top-of-page trap is
+sprung one unit below the top of the page in order not to interfere with
+the top-of-page macros of [[-mm]] or [[-ms]].
+<<read and process noweb source>>=
+/^@xref label/ { lastxreflabel = $3 }
+/^@xref ref/ { lastxrefref = tag(substr($0, 11)) }
+@ %def lastxreflabel lastxrefref
+<<tmac.w>>=
+.de RESETLETTER \" reset letter at top of page
+.nr SECTIONLETTER 0 1 \" count code sections on same page
+.af SECTIONLETTER a \" ... formatted as lower-case alpha
+..
+.wh 1u RESETLETTER \" trap just below top of page
+@ .P
+Note that the link information on the previous chunk shows that this
+chunk uses the [[code]] variable, when in fact [[code]] only appears
+as text within a comment. This error is an artifact of the language
+independence of noweb.
+@ .HU "Beginning and ending chunks"
+Except for the initial document chunk, which was processed above, all
+beginnings and endings of documentation and code chunks are processed
+here. Variable [[code]] is [[0]] in text chunks, [[1]] in code
+chunks and [[2]] in quoted code. The argument to
+the [[.ENDCODECHUNK]] macro is the label which was in effect when the
+code chunk was started, which is stored in the variable [[lastdefnlabel]].
+<<read and process noweb source>>=
+/^@begin docs/ { printf ".BEGINDOCCHUNK\n" }
+/^@end docs/ { printf ".ENDDOCCHUNK\n" }
+/^@begin code/ { code = 1; printf ".BEGINCODECHUNK\n" }
+/^@end code/ { code = 0; printf ".ENDCODECHUNK %s\n", lastdefnlabel }
+@ %def code
+.P
+The macros related to document chunks are simple: [[.BEGINDOCCHUNK]] does
+nothing, and [[.ENDDOCCHUNK]] merely flushes any unprinted output.
+<<tmac.w>>=
+.de BEGINDOCCHUNK
+..
+.de ENDDOCCHUNK
+.br
+..
+@ .P
+A code chunk uses a font, type size, leading, fill and adjust modes,
+indent and tab stops which are distinct from those in the documentation.
+These environment variables must be saved on entering a code chunk,
+appropriate values for a code chunk must be established, and the
+original values restored at the end of a code chunk.
+<<tmac.w>>=
+.de BEGINCODECHUNK
+.sp 0.4v
+<<save environment>>
+<<set local environment>>
+.di CODECHUNK
+..
+.de ENDCODECHUNK
+<<read back code chunk from diversion>>
+<<restore environment>>
+..
+@ .P
+The code below replaces the built-in [[.ta]] tab-setting command with a
+custom tab-setting command that allows tab stops to be reset and later
+recalled.
+<<tmac.w>>=
+.rn ta real_ta
+.de ta
+.ds ta_saved \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.real_ta \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+@ .P
+The font, type size and leading require two saved values, so
+that both the current value and the previous value can be restored.
+<<save environment>>=
+.nr OLDft \\n(.f
+.ft P
+.nr PREVft \\n(.f
+.nr OLDps \\n(.s
+.ps
+.nr PREVps \\n(.s
+.nr OLDvs \\n(.v
+.vs
+.nr PREVvs \\n(.v
+.nr OLDfi \\n(.u
+.nr OLDad \\n(.j
+.nr OLDin \\n(.in
+@ .P
+Code is printed in a constant-width font at 80% the size of document text.
+Code is collected in fill mode with explicit breaks after each line;
+although it might seem more natural to collect lines of code in no-fill
+mode, that is not possible here because uses of code chunks must be able
+to appear on the same line as actual code.
+<<set local environment>>=
+.ft CW
+.ps \\n(.s*4/5
+.vs \\n(.vu*4u/5u
+.in +0.5i
+.real_ta 0.5i 1i 1.5i 2i 2.5i 3i 3.5i 4i
+.fi
+@ .P
+In order to prevent page breaks within code chunks, each code chunk
+is read into a diversion and a page break is issued if the code chunk
+is too big to fit on the current page. After the diversion is read back
+in, when it is known what page the code is printed on, the location of
+the code chunk is written using a [[.tm]] command.
+<<read back code chunk from diversion>>=
+.br \" flush last line of code
+.di \" end diversion
+.if \\n(dn>\\n(.t .bp \" force form feed if too big
+.nf \" no fill mode -- already formatted
+.in -0.5i \" don't re-indent when re-reading text
+.CODECHUNK \" output body of diversion
+.tm ###TAG### \\$1 \\n[%]\\n+[SECTIONLETTER] \" write tag info
+.rm CODECHUNK \" reset diversion for next code chunk
+@ .P
+Finally, here is the code to restore the environment that existed before
+the beginning of the code chunk.
+<<restore environment>>=
+.ft \\n[PREVft]
+.ft \\n[OLDft]
+.ps \\n[PREVps]
+.ps \\n[OLDps]
+.vs \\n[PREVvs]u
+.vs \\n[OLDvs]u
+.if \\n[OLDfi] .fi
+.ad \\n[OLDad]u
+.in \\n[OLDin]u
+.real_ta \\*[ta_saved]
+@ .HU "Text, code, and quoted code"
+In text chunks, text is copied from input to output basically unchanged.
+However, when quoted code is included in a line of text, the quoted code
+is processed by separate macros and it is possible that the continuation
+of the line of text after the quoted code begins with a character which
+is special to troff at the beginning of a line: a space, period, or
+single quote. To prevent problems in this case, variable [[text]] is
+set to [[0]] at the beginning of each line and incremented whenever text
+is written, and each text after the first is guarded by a non-printing
+null character.
+<<read and process noweb source>>=
+/^@text/ && code == 0 { s = substr($0, 7)
+ if (text++) printf "\\&"
+ printf "%s", substr($0, 7) }
+/^@nl/ && code != 1 { text = 0; printf "\n" }
+@ %def text
+.P
+In code chunks, backslashes are replaced with troff's [[\e]] escape
+sequence and a non-printing null character is added at the beginning of
+each text to guard leading periods. If your macro package issues a [[.ec]]
+command, this code will have to change; fortunately, both [[-mm]] and
+[[-ms]] are nicely-behaved with respect to escape characters.
+<<read and process noweb source>>=
+/^@text/ && code != 0 { s = substr($0, 7)
+ gsub(/\\/, "\\e", s)
+ printf "\\&%s\\c\n", s }
+@ .P
+Dealing with newlines in code chunks is surprisingly hard. We would like
+to print lines of code in [[nofill]] mode, but since noweb's markup
+and filter programs may split lines of code, we are forced to use
+[[fill]] mode and deal with newlines ourselves. Further, if a line is
+too long to print on a single line, it must be split, and the continuation
+line right-justified instead of left-justified. All of this processing is
+accomplished by calling a macro at each newline; the macro plants a
+page-position trap at the next line so that any continuation line will be
+right-justified.
+<<read and process noweb source>>=
+/^@nl/ && code == 1 { printf ".NEWLINE\n" }
+<<tmac.w>>=
+.de LINETRAP
+.dt \\n[TRAPplace]u \"cancel current trap
+'ad r \" right-adjust continuation lines
+..
+.de NEWLINE
+.dt \\n[TRAPplace]u \" cancel current trap
+\& \" end continued word
+.br \" flush output
+<<plant newline trap>>
+..
+@ .P
+The newline trap is planted after each definition line, for the first
+line of code in the code chunk, and again after each newline in the
+code chunk.
+<<plant newline trap>>=
+.nr TRAPplace \\n(.du+1u \" location of next trap
+.dt \\n[TRAPplace]u LINETRAP \" plant trap at next line
+.ad l \" left-adjust first line
+@ .P
+Quoted code in a documentation chunk is printed within its own macros,
+which must not cause a break.
+<<read and process noweb source>>=
+/^@quote/ { code = 2; printf "\\c\n.BEGINQUOTEDCODE\n" }
+/^@endquote/ { code = 0; text++; printf ".ENDQUOTEDCODE\n" }
+<<tmac.w>>=
+.de BEGINQUOTEDCODE
+.nr SAVEft \\n(.f
+.ft P
+.nr SAVEftP \\n(.f
+.ft CW
+..
+.de ENDQUOTEDCODE
+.ft \\n[SAVEftP]
+.ft \\n[SAVEft]
+..
+@ .HU "Definitions and uses of code chunks"
+Definitions and uses of code chunks are handled below. Variable
+[[defn[name]]] is set to a plus sign after a definition is printed, so
+that continuations of the definition are properly identified. Variable
+[[lastxrefref]] is the tag associated with the most-recently-seen
+cross-reference label, and refers to the section number of the original
+definition of the code chunk.
+<<read and process noweb source>>=
+/^@defn/ { name = convquote(substr($0, 7))
+ lastdefnlabel = lastxreflabel
+ printf ".DEFINITION %s \"%s\" %s %s\n",
+ tag(lastdefnlabel), name, lastxrefref, defn[name]
+ defn[name] = "\\(pl" }
+/^@use/ { name = convquote(substr($0, 6))
+ printf "\c\n"
+ printf ".USE \"%s\" %s\n", name, lastxrefref }
+@ %def name defn lastdefnlabel
+<<tmac.w>>=
+.de DEFINITION
+.ti -0.5i
+\\fR\\(sc\\$1 \\(oG\\$2 \\$3\\(cG \\$4\\(==\\fP
+<<plant newline trap>>
+..
+.de USE
+\\fR\\(oG\\$1 \\$2\\(cG\\fP\c \" section name and original number
+..
+@ .P
+Processing of quoted code within definitions and uses is performed by the
+[[convquote]] function. This must be processed differently than quoted
+code within text because the noweb markup program doesn't emit
+[[@quote]] .\|.\|. [[@endquote]] markers within definitions and uses. And,
+because the subject string is used as an argument to a macro, it would not
+possible to call the [[.BEGINQUOTEDCODE]] and [[.ENDQUOTEDCODE]] macros,
+even if noweb did emit the markers within definitions and uses.
+<<functions>>=
+function convquote(s) {
+ gsub(/\[\[/, "\\*[BEGINCONVQUOTE]", s)
+ gsub(/\]\]/, "\\*[ENDCONVQUOTE]", s); return s }
+@ %def convquote
+<<tmac.w>>=
+.ds BEGINCONVQUOTE \f[CW]
+.ds ENDCONVQUOTE \fP
+@ .HU "Cross-referencing and indexing"
+The code for producing the \(odhypertext links\(cd at the end of each
+code section is given below: for each type, the beginning of the message
+is printed, items are accumulated in a list, and the list is printed
+after the number of items in the list is known. The first time any of
+the cross-reference or identifier-index messages appears, it is necessary
+to reset the point size and leading to the small font used for this
+material, which is 80% of the size of code and 64% of the size of text.
+All of these lines are part of the diversion which collects a
+code chunk. First is the code to report definitions and uses of code.
+<<read and process noweb source>>=
+/^@xref begindefs/ { <<checkcode>>; printf ".XREFDEFS\n" }
+/^@xref beginuses/ { <<checkcode>>; printf ".XREFUSES\n" }
+/^@xref notused/ { <<checkcode>>; printf ".XREFNOTUSED\n" }
+/^@xref (def|use)item/ { printf ".ADDLIST %s\n", tag($3) }
+/^@xref end(def|use)s/ { printf ".PRINTLIST\n" }
+<<tmac.w>>=
+.de XREFDEFS
+This definition continued in
+..
+.de XREFUSES
+This code used in
+..
+.de XREFNOTUSED
+This code not used in this document.
+.br
+..
+@ .P
+The code to report the definitions of identifiers appears below. The
+[[if]] in [[@index isused]] prevents index definitions from pointing
+to themselves.
+<<read and process noweb source>>=
+/^@index begindefs/ && !noindex { <<checkcode>>; printf ".INDEXDEF\n" }
+/^@index isused/ && !noindex {
+ if (tag($3) != lastxrefref) printf ".ADDLIST %s\n", tag($3) }
+/^@index defitem/ && !noindex { printf ".DEFITEM %s\n.PRINTLIST\n", $3 }
+<<tmac.w>>=
+.de INDEXDEF
+Defines:
+.br
+..
+.de DEFITEM
+.ti +1m
+\\*[BEGINCONVQUOTE]\\$1\\*[ENDCONVQUOTE],
+.if \\n[NLIST]>0 used in
+..
+@ .P
+Finally, here is the code to report uses of identifiers.
+<<read and process noweb source>>=
+/^@index beginuses/ && !noindex { <<checkcode>>; printf ".INDEXUSE\n" }
+/^@index isdefined/ && !noindex { lastuse = tag($3) }
+/^@index useitem/ && !noindex {
+ printf ".ADDLIST \"\\*[BEGINCONVQUOTE]%s\\*[ENDCONVQUOTE] %s\"\n",
+ $3, lastuse }
+/^@index enduses/ && !noindex { printf ".PRINTLIST\n" }
+@ %def lastuse
+<<tmac.w>>=
+.de INDEXUSE
+Uses
+..
+@ .P
+The macros [[.ADDLIST s]], which adds string [[s]] to a queued list
+waiting to be printed, and [[.PRINTLIST]], which prints the list,
+appropriately formatted with commas, are described below. These macros
+make use of some interesting troff idioms. [[LIST]] is an array of
+strings; the [[n]]-th string in [[LIST]] can be set to [[s]] by
+[[.ds LISTn s]]. The expression [[.nr n \\$1]] converts the string
+passed as the first argument to a macro to the number [[n]]. Loops
+are implemented in troff as recursive macros, as in [[.PRINTITEM]].
+<<tmac.w>>=
+.nr NLIST 0 1 \" initialize list index to 0 with auto-increment 1
+.de ADDLIST
+.ds LIST\\n+[NLIST] \\$1
+..
+.de PRINTITEM
+.nr PLIST \\$1
+.nr PLISTPLUS \\n[PLIST]+1
+.if \\n[NLIST]-\\n[PLIST]<0 not used in this document.
+.if \\n[NLIST]-\\n[PLIST]=0 \\*[LIST\\n[PLIST]].
+.if \\n[NLIST]-\\n[PLIST]=1 \
+ \\*[LIST\\n[PLIST]] and \\*[LIST\\n[PLISTPLUS]].
+.if \\n[NLIST]-\\n[PLIST]>1 \{ \\*[LIST\\n[PLIST]],
+. PRINTITEM 1+\\n[PLIST] \}
+..
+.de PRINTLIST
+.PRINTITEM 1
+.br
+.nr NLIST 0 1 \" re-initialize for next list
+..
+@ .P
+This code and macro reduces the font size in which the cross-reference
+and identifier index information is printed at the end of a code chunk.
+The [[code]] variable is set to [[0]] to ensure that [[.STARTXREF]]
+is performed only once at the end of each code chunk. This code also
+resets the adjustment mode, which was changed to left-adjustment or
+right-adjustment by the [[LINETRAP]] macro, and cancels the [[NEWLINE]]
+trap at [[TRAPplace]].
+<<checkcode>>=
+if (code) { code = 0; printf ".STARTXREF\n" }
+<<tmac.w>>=
+.de STARTXREF
+.ps \\n(.s*4/5
+.vs \\n(.vu*4u/5u
+.ft \\n[OLDft]
+.ad \\n[OLDad]u
+.dt \\n[TRAPplace]u
+.sp 0.4v
+..
+@ .HU "Collecting the lists of chunks and identifiers"
+Collecting the lists of chunks and identifiers takes two passes over the
+file, because the section numbers which tags refer to aren't known on
+the first pass. Therefore, the strategy on the first pass is to write
+the chunk and identifier index entries to the [[tags]] file on standard
+error, and actually prepare the lists when reading the [[tags]] file on
+the second pass. Thus, the first pass code shown here merely copies
+the chunk and identifier index entries from the noweb intermediate
+file to the [[tags]] file using troff's [[.tm]] command. The
+first section below handles chunks, the second section handles
+identifiers.
+<<read and process noweb source>>=
+/^@xref beginchunks/ { printf ".tm ###BEGINCHUNKS###\n" }
+/^@xref chunkbegin/ { printf ".tm ###CHUNKBEGIN### %s\n",
+ substr($0, length($3) + 19) }
+/^@xref chunkuse/ { printf ".tm ###CHUNKUSE### %s\n", $3 }
+/^@xref chunkdefn/ { printf ".tm ###CHUNKDEFN### %s\n", $3 }
+/^@xref chunkend/ { printf ".tm ###CHUNKEND###\n" }
+/^@xref endchunks/ { printf ".tm ###ENDCHUNKS###\n" }
+<<read and process noweb source>>=
+/^@index beginindex/ { printf ".tm ###BEGININDEX###\n" }
+/^@index entrybegin/ { printf ".tm ###ENTRYBEGIN### %s\n",
+ substr($0, length($3) + 20) }
+/^@index entryuse/ { printf ".tm ###ENTRYUSE### %s\n", $3 }
+/^@index entrydefn/ { printf ".tm ###ENTRYDEFN### %s\n", $3 }
+/^@index entryend/ { printf ".tm ###ENTRYEND###\n" }
+/^@index endindex/ { printf ".tm ###ENDINDEX###\n" }
+@ .HU "The \f[CW]tags\fP file"
+The [[tags]] file is re-created at each formatter run by the troff
+idiom (some people would call it a trick) of capturing the output of
+troff's [[.tm]] command, which writes to the standard error, in a
+file via command-line redirection. The code below uses an awk idiom; the
+[[sub]] simultaneously tests for a match and deletes the matched text.
+<<process [[tags]] file>>=
+{
+ if (sub(/^###TAG### / , "")) tags[$1] = $2
+ else if (sub(/^###BEGINCHUNKS###/, "")) printf ".de CLIST\n.CLISTBEGIN\n"
+ else if (sub(/^###CHUNKBEGIN### /, "")) { name = convquote($0)
+ chunkuse = chunkdefn = "" }
+ else if (sub(/^###CHUNKUSE### / , "")) chunkuse = chunkuse " " tag($0)
+ else if (sub(/^###CHUNKDEFN### / , "")) chunkdefn = chunkdefn " " tag($0)
+ else if (sub(/^###CHUNKEND###/ , ""))
+ printf ".CITEM \"%s\" \"%s\" \"%s\"\n", name, chunkdefn, chunkuse
+ else if (sub(/^###ENDCHUNKS###/ , "")) printf ".CLISTEND\n..\n"
+ else if (sub(/^###BEGININDEX###/ , "")) printf ".de ILIST\n.ILISTBEGIN\n"
+ else if (sub(/^###ENTRYBEGIN### /, "")) { name = convquote($0)
+ entryuse = entrydefn = "" }
+ else if (sub(/^###ENTRYUSE### / , "")) entryuse = entryuse " " tag($0)
+ else if (sub(/^###ENTRYDEFN### / , "")) entrydefn = entrydefn " " tag($0)
+ else if (sub(/^###ENTRYEND###/ , "")) {
+ for (i = 1; i <= split(entrydefn, entryarray); i++)
+ sub(entryarray[i], "\\*[BEGINDEFN]&\\*[ENDDEFN]", entryuse)
+ printf ".IITEM \"%s\" \"%s\"\n", name, entryuse }
+ else if (sub(/^###ENDINDEX###/ , "")) printf ".ILISTEND\n..\n"
+}
+<<tag functions>>
+@ %def tags chunkuse chunkdefn entryuse entrydefn entryarray
+.P
+The [[sub]] within the [[ENTRYEND]] causes definitions of identifiers
+to be italicized, according to the following defined strings.
+<<tmac.w>>=
+.ds BEGINDEFN \fI
+.ds ENDDEFN \fP
+@ .P
+Lookup of the section number corresponding to a particular tag is
+performed by the [[tag]] function.
+<<tag functions>>=
+function tag(s) { if (s in tags) return tags[s]; else return "???" }
+@ %def tag
+.HU "Using \\f[CW]toroff\fP"
+Toroff is one element of the normal noweave pipeline. Using
+toroff in its full generality is hard. The sample program shown
+below was used by the author during the development of toroff and
+is an example of the use of toroff. A real noweave should
+allow the user to specify the macro package rather than defaulting to
+[[-mm]], allow the user to select the noweb filters which are used,
+allow the user to specify the [[-delay]] and [[-noindex]] switches to
+toroff, allow the user to specify troff pre-processors,
+post-processors and options, and eliminate the temp output from tee
+which allowed the author to peek at the pipeline and find out why
+toroff wasn't acting as expected. Given the shell script shown
+below, toroff could be woven by issuing the command [[xweave toroff.nw]]
+twice in succession and printed by copying [[toroff.ps]] to a PostScript
+printer.
+<<noroff>>=
+#!/bin/sh
+#
+# noroff -- run troff using tags file trick
+
+ROFF="psroff -t" # produce postscript on stdout
+AWK=nawk
+
+if [ $# -ne 1 ]; then
+ echo "Usage: noroff file" 1>&2
+ exit 1
+fi
+base="`echo $1 | sed '/\./s/\.[^.]*$//'`"
+tagsfile="$base.nwt"
+(if [ -r "$tagsfile" ] then $AWK '<<process [[tags]] file>>' $tagsfile; fi
+ cat $1) |
+($ROFF -Tps 2>$tagsfile)
+sed '/^###[A-Z][A-Z]*###/d' $tagsfile >&2
+@ .HU "Index of chunks and identifiers"
+Toroff creates macros [[.CLIST]] and [[.ILIST]] which insert the
+lists of chunks and identifiers, respectively, in the output. These
+macros, in turn, call other macros which format the lists. The macros
+below cause each item to be written on a separate line, with continuation
+lines indented one-quarter inch.
+<<tmac.w>>=
+.de CLISTBEGIN
+.in +0.25i
+..
+.de CITEM
+.ti -0.25i
+.ie '\\$3'' \\(oG\\$1 \\$2\\(cG Not used in this document.
+.el \\(oG\\$1 \\$2\\(cG \\$3
+.br
+..
+.de CLISTEND
+.in -0.25i
+..
+<<tmac.w>>=
+.de ILISTBEGIN
+.in +0.25i
+..
+.de IITEM
+.ti -0.25i
+\\f[CW]\\$1\\fP: \\$2
+.br
+..
+.de ILISTEND
+.in -0.25i
+..
+@ .P
+The automatically-generated index of chunks and identifiers for
+toroff is shown below.
+.S 10 12
+.sp
+.CLIST
+.sp
+.2C
+.ILIST
diff --git a/web/noweb/src/shell/unmarkup b/web/noweb/src/shell/unmarkup
new file mode 100644
index 0000000000..a6ce6cc347
--- /dev/null
+++ b/web/noweb/src/shell/unmarkup
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# Copyright 1991 by Norman Ramsey. All rights reserved.
+# See file COPYRIGHT for more information.
+
+nawk '
+/^@file / {
+# if (file) printf "EndOf%s\n", file
+# file = substr($0,7);
+# printf "diff %s - <<'"'EndOf%s'"'\n", file, file
+}
+
+END {
+# if (file) printf "EndOf%s\n", file
+}
+
+/^@begin docs 0$/ { next }
+/^@begin docs / { printf "@ " }
+/^@end docs / { }
+
+/^@begin code / { }
+/^@defn / { printf "<<%s>>=", substr($0,7) }
+
+/^@text $/ {next}
+/^@text / {
+ gsub("<<", "@<<");
+ gsub(">>", "@>>");
+ printf "%s", substr($0,7)
+}
+/^@quote$/ { printf("[[") }
+/^@endquote$/ { printf("]]") }
+/^@nl$/ { printf "\n"}
+
+/^@use / { printf "<<%s>>", substr($0,6) }' "$@" | sed 's/^@ $/@/'
diff --git a/web/noweb/src/solmake b/web/noweb/src/solmake
new file mode 100755
index 0000000000..3e406cfdde
--- /dev/null
+++ b/web/noweb/src/solmake
@@ -0,0 +1,3 @@
+#!/bin/sh
+if [ $# -eq 0 ]; then set all install; fi # "$@" breaks make for empty args
+make CC="cc" LIBSRC=awk BIN=/usr/local/noweb/bin LIB=/usr/local/noweb/lib MAN=/usr/local/noweb/man TEXINPUTS=/usr/local/noweb/tex ELISP=$HOME/emacs "$@"
diff --git a/web/noweb/src/testmake b/web/noweb/src/testmake
new file mode 100644
index 0000000000..074b899d84
--- /dev/null
+++ b/web/noweb/src/testmake
@@ -0,0 +1,3 @@
+#!/bin/sh
+if [ $# -eq 0 ]; then set all install; fi # "$@" breaks make for empty args
+/usr/bin/make CC="gcc -ansi -pedantic -O -Wall -Werror" LIBSRC=awk BIN=/usr/local/noweb-test/bin LIB=/usr/local/noweb-test/lib MAN=/usr/local/noweb-test/man TEXINPUTS=/usr/local/tex/inputs ELISP=/dev/null "$@"
diff --git a/web/noweb/src/tex/Makefile b/web/noweb/src/tex/Makefile
new file mode 100644
index 0000000000..e70616104e
--- /dev/null
+++ b/web/noweb/src/tex/Makefile
@@ -0,0 +1,28 @@
+SHELL=/bin/sh
+NAME="name of version checked in"
+CIMSG="message for version checked in"
+RCSFILES=support.nw Makefile
+
+all: nwmac.tex noweb.sty
+source: nwmac.tex noweb.sty
+touch: nwmac.tex noweb.sty
+ touch nwmac.tex noweb.sty
+boot:
+ touch nwmac.tex noweb.sty
+
+checkin:
+ ci -l $(CINAME) $(CIMSG) $(RCSFILES)
+
+nwmac.tex: support.nw
+ notangle -Rnwmac.tex support.nw > nwmac.tex
+
+noweb.sty: support.nw
+ notangle -Rnoweb.sty support.nw > noweb.sty
+
+support.tex: support.nw
+ noweave -delay -x support.nw > support.tex
+
+clean:
+ /bin/rm -f *~ *.dvi *.aux *.log *.blg *.bbl *.toc
+ /bin/rm -f support.tex
+clobber: clean
diff --git a/web/noweb/src/tex/multlang.nw b/web/noweb/src/tex/multlang.nw
new file mode 100644
index 0000000000..b5b7851b51
--- /dev/null
+++ b/web/noweb/src/tex/multlang.nw
@@ -0,0 +1,1785 @@
+% -*- mode: Noweb; noweb-code-mode: tex-mode -*-
+\documentclass[twoside]{article}
+\usepackage{noweb}
+\pagestyle{noweb}
+\noweboptions{longchunks,smallcode}
+\title{{\TeX} and {\LaTeX} support for {\tt noweb}\\
+{\small Multilingual version for {\LaTeX}}}
+\author{Norman Ramsay\\
+{\small (with changes by Miguel Filgueiras)}}
+\newcommand{\stylehook}{\marginpar{\raggedright\sl Style hook}}
+\begin{document}
+\maketitle
+\tableofcontents
+@
+
+\begin{quote}
+{\bf Explanatory note} on the changes made by Miguel Filgueiras
+(DCC-FCUP \& LIACC, Universidade do Porto)\\
+The changes provide multilingual support. The
+English wording for text inserted by {\tt noweb.sty} was replaced by
+macros that are then defined in a specific language depending on the
+(apparently standard) {\LaTeX} macro [[\languagename]]. This macro is
+defined by the {\tt babel} package, and therefore if this package is
+included with the appropriate language name {\em before} the inclusion
+of the {\tt noweb} package, all the wording will appear in that language.
+Note however that at present there is only support for English
+(preserving the original text), Portuguese, German and French. The latter is
+faulty: the translations might be not the best ones, and there are
+bugs in the implementation that I could not solve (I am no experienced
+{\TeX} user). Other languages can easily be accomodated by inserting
+new translations in subsection~\ref{subsection:langdeps}.
+\end{quote}
+
+This document describes the {\TeX} code that supports {\tt noweave}
+and {\tt noweb}. Those interested in customizing their output should
+focus on Section~\ref{section:sty}.
+Hooks you can easily use (apart from those provided by
+[[\noweboptions]]) are indicated by marginal notes.
+This file contains both plain {\TeX} and {\LaTeX} support:
+<<nwmac.tex>>=
+% nwmac.tex -- plain TeX support for noweb
+% DON'T read or edit this file! Use ...noweb-source/tex/support.nw instead.
+<<noweb.sty>>=
+% noweb-LANGUAGE.sty -- LaTeX support for noweb
+% DON'T read or edit this file! Use .../support-multiling.nw instead.
+@
+
+\section{Basic {\TeX} support for {\tt noweb}}
+This basic code is used for both {\TeX} and {\LaTeX}.
+The first step is to define [[\codehsize]], which is the width in
+which code is set, and [[\codemargin]], which is the amount by which
+it is indented.\stylehook
+<<kernel>>=
+% make \hsize in code sufficient for 88 columns
+\setbox0=\hbox{\tt m}
+\newdimen\codehsize
+\codehsize=91\wd0 % 88 columns wasn't enough; I don't know why
+\newdimen\codemargin
+\codemargin=0pt
+@ %def \codehsize \codemargin
+[[\defspace]] is the space we would like on the right of navigational info
+that appears on definition lines, so that it lines up with the text above
+and below.
+<<kernel>>=
+\newdimen\nwdefspace
+\nwdefspace=\codehsize
+% need to use \textwidth in {\LaTeX} to handle styles with
+% non-standard margins (David Bruce). Don't know why we sometimes
+% wanted \hsize. 27 August 1997.
+%% \advance\nwdefspace by -\hsize\relax
+\ifx\textwidth\undefined
+ \advance\nwdefspace by -\hsize\relax
+\else
+ \advance\nwdefspace by -\textwidth\relax
+\fi
+@
+Most code is set in an environment in which [[\setupcode]] has been
+executed.
+In this environment, only [[\]], [[{]], and [[}]] have their usual
+categories; every other character represents itself.
+Appropriate [[\chardef]]s ensure that the special characters can be
+escaped with a backslash.
+<<kernel>>=
+\chardef\other=12
+\def\setupcode{%
+ \chardef\\=`\\
+ \chardef\{=`\{
+ \chardef\}=`\}
+ \catcode`\$=\other
+ \catcode`\&=\other
+ \catcode`\#=\other
+ \catcode`\%=\other
+ \catcode`\~=\other
+ \catcode`\_=\other
+ \catcode`\^=\other
+ \catcode`\"=\other % fixes problem with german.sty
+ \obeyspaces\Tt
+}
+\let\nwlbrace=\{
+\let\nwrbrace=\}
+@ %def \setupcode
+[[\eatline]] is used to consume newlines that should be ignored,
+for example, the newlines at the end of [[@ %def ]]{\em identifiers} lines.
+I can't remember what [[\startline]] or [[\newlines]] are for; I don't
+think {\tt noweave} ever emits them.
+<<kernel>>=
+{\catcode`\^^M=\active % make CR an active character
+ \gdef\newlines{\catcode`\^^M=\active % make CR an active character
+ \def^^M{\par\startline}}%
+ \gdef\eatline#1^^M{\relax}%
+}
+%%% DON'T \gdef^^M{\par\startline}}% in case ^^M appears in a \write
+\def\startline{\noindent\hskip\parindent\ignorespaces}
+\def\nwnewline{\ifvmode\else\hfil\break\fi}
+@ %def \startline \eatline \nwnewline
+
+Within a code environment, it may be necessary to restore the
+category codes in order to set a module (chunk) name.
+This hack doesn't properly restore [["]] for use in {\tt german.sty}.
+<<kernel>>=
+\def\setupmodname{%
+ \catcode`\$=3
+ \catcode`\&=4
+ \catcode`\#=6
+ \catcode`\%=14
+ \catcode`\~=13
+ \catcode`\_=8
+ \catcode`\^=7
+ \catcode`\ =10
+ \catcode`\^^M=5
+ \let\{\nwlbrace
+ \let\}\nwrbrace
+ % bad news --- don't know what catcode to give "
+ \Rm}
+@ %def \setupmodname
+@ \sublabel{ref:fred}
+@
+Setting up the space code has to be done differently for {\TeX} and
+{\LaTeX}, so as not to screw up {\LaTeX}'s \texttt{verbatim} package.
+(Fix from Rafael Laboissiere.)
+<<nwmac.tex>>=
+{\obeyspaces\global\let =\ } % from texbook, p 381
+<<noweb.sty>>=
+{\obeyspaces\AtBeginDocument{\global\let =\ }} % from texbook, p 381
+@
+
+{\tt noweave} brackets uses of chunk names with [[\LA]] and [[\RA]], which
+handle the angle brackets, font, and environment.
+
+As it stands, chunk names can be broken across lines (or pages). This
+could result in unnecessary page breaks in code
+(c.f.~p.~\pageref{sec:pagebreaking}). [[\let\\maybehbox=\mbox]] to
+\stylehook
+avoid breaking them
+(or to make them work in math mode); this is done in code chunks, but could be done
+in general.
+<<kernel>>=
+\def\LA{\begingroup\maybehbox\bgroup\setupmodname\It$\langle$}
+\def\RA{\/$\rangle$\egroup\endgroup}
+\def\code{\leavevmode\begingroup\setupcode\newlines}
+\def\edoc{\endgroup}
+\let\maybehbox\relax
+@ %def \LA \RA \maybehbox
+
+[[\equivbox]] and [[\plusequivbox]] are used to set the
+``\unhcopy\equivbox''
+and ``\unhcopy\plusequivbox'' that open a chunk definition or its
+continuation.
+{\tt noweave} brackets definitions of chunk names with [[\moddef]] and
+either [[\endmoddef]] or [[\plusendmoddef]].
+<<kernel>>=
+\newbox\equivbox
+\setbox\equivbox=\hbox{$\equiv$}
+\newbox\plusequivbox
+\setbox\plusequivbox=\hbox{$\mathord{+}\mathord{\equiv}$}
+% \moddef can't have an argument because there might be \code...\edoc
+\def\moddef{\leavevmode\kern-\codemargin\LA}
+\def\endmoddef{\RA\ifmmode\equiv\else\unhcopy\equivbox\fi
+ \nobreak\hfill\nobreak}
+\def\plusendmoddef{\RA\ifmmode\mathord{+}\mathord{\equiv}\else\unhcopy\plusequivbox\fi
+ \nobreak\hfill\nobreak}
+@ %def \equivbox \plusequivbox \moddef \endmoddef \plusendmoddef
+@
+Within a code environment, margin tags might be used to mark sub-page
+numbers in the margins, separated by [[\nwmarginglue]].\stylehook
+The interaction with [[\moddef]] involves tricky kerning.
+The tag itself is displayed using [[\nwthemargintag]]
+<<noweb.sty>>=
+\def\nwopt@nomargintag{\let\nwmargintag=\@gobble}
+\def\nwopt@margintag{%
+ \def\nwmargintag##1{\leavevmode\llap{##1\kern\nwmarginglue\kern\codemargin}}}
+\def\nwopt@margintag{%
+ \def\nwmargintag##1{\leavevmode\kern-\codemargin\nwthemargintag{##1}\kern\codemargin}}
+\def\nwthemargintag#1{\llap{#1\kern\nwmarginglue}}
+\nwopt@margintag
+\newdimen\nwmarginglue
+\nwmarginglue=0.3in
+@ %def \nwmargintag margintag nomargintag \nwmarginglue
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B margintag
+Put the sub-page number (tag) of each code-chunk definition in the
+left margin. (Default)
+.TP
+.B nomargintag
+Don't use margin tags.
+@ \fi
+[[\nwtagstyle]] determines the style in which tags are displayed.\stylehook
+<<noweb.sty>>=
+\def\nwtagstyle{\footnotesize\Rm}
+@
+<<kernel>>=
+\def\chunklist{%
+\errhelp{I changed \chunklist to \nowebchunks.
+I'll try to avoid such incompatible changes in the future.}%
+\errmessage{Use \string\nowebchunks\space instead of \string\chunklist}}
+\def\nowebchunks{\message{<Warning: You need noweave -x to use \string\nowebchunks>}}
+\def\nowebindex{\message{<Warning: You need noweave -index to use \string\nowebindex>}}
+@ %def \chunklist \nowebchunks \nowebindex
+@ We have to be careful with font-changing in the presence of
+different font-selection schemes. In the \LaTeX{} New Font Selection
+Scheme something like [[\it\tt]] will attempt to use an italic
+typewriter font. Thus we define new commands like [[\Tt]] which will
+work with both the Plain and old and new \LaTeX{} schemes. (Note that
+NFSS will be standard in the next version of \LaTeX.) A problem with
+these definitions arises with NFSS: in math mode the won't work
+unless the {\tt oldlfont} backwards-compatibility option is in effect.
+For the moment, you can get round this by using [[\mbox]].
+
+If you wanted code set in a different font, you could re-define
+[[\Tt]].\stylehook{} [\LaTeX2e actually behaves like OFSS, but the
+extra [[\reset@font]] does no harm.]
+<<kernel>>=
+% here is support for the new-style (capitalized) font-changing commands
+% thanks to Dave Love
+\ifx\documentstyle\undefined
+ \let\Rm=\rm \let\It=\it \let\Tt=\tt % plain
+\else\ifx\selectfont\undefined
+ \let\Rm=\rm \let\It=\it \let\Tt=\tt % LaTeX OFSS
+\else % LaTeX NFSS
+ \def\Rm{\reset@font\rm}
+ \def\It{\reset@font\it}
+ \def\Tt{\reset@font\tt}
+ \def\Bf{\reset@font\bf}
+\fi\fi
+\ifx\reset@font\undefined \let\reset@font=\relax \fi
+@ %def \Rm \Tt \It \Bf
+@
+\clearpage
+\section{The {\tt noweb} document-style option for {\LaTeX}}
+\label{section:sty}
+{\LaTeX} support begins with the kernel shown above.
+<<noweb.sty>>=
+<<kernel>>
+@
+\subsection{Support for noweb options}
+<<noweb.sty>>=
+\def\noweboptions#1{%
+ \def\@nwoptionlist{#1}%
+ \@for\@nwoption:=\@nwoptionlist\do{%
+ \@ifundefined{nwopt@\@nwoption}{%
+ \@latexerr{There is no such noweb option as '\@nwoption'}\@eha}{%
+ \csname nwopt@\@nwoption\endcsname}}}
+@ %def \noweboptions
+\subsection{Adjusting placement of code on the page}
+{\LaTeX} requires a larger [[\codehsize]] because
+code is indented by [[\codemargin]].\stylehook
+<<noweb.sty>>=
+\codemargin=10pt
+\advance\codehsize by \codemargin % make room for indentation of code
+\advance\nwdefspace by \codemargin % and fix adjustment for def/use
+\def\setcodemargin#1{%
+ \advance\codehsize by -\codemargin % make room for indentation of code
+ \advance\nwdefspace by -\codemargin % and fix adjustment for def/use
+ \codemargin=#1
+ \advance\codehsize by \codemargin % make room for indentation of code
+ \advance\nwdefspace by \codemargin % and fix adjustment for
+ % def/use
+}
+@
+[[\noweboptions{shift}]] is used to shift the whole page left to make room for
+the wide code lines.
+It may be emitted by {\tt noweave -shift}, or it might be given by a user.
+<<noweb.sty>>=
+\def\nwopt@shift{%
+ \dimen@=-0.8in
+ \if@twoside % Values for two-sided printing:
+ \advance\evensidemargin by \dimen@
+ \else % Values for one-sided printing:
+ \advance\evensidemargin by \dimen@
+ \advance\oddsidemargin by \dimen@
+ \fi
+% \advance \marginparwidth -\dimen@
+}
+\let\nwopt@noshift\@empty
+@ %def shift noshift
+
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B shift
+Shift text to the left so that long code lines won't extend
+off the right-hand side of the page.
+@ \fi
+
+\subsection{Page-breaking strategy}\label{sec:pagebreaking}
+
+We want to insert penalties aiming for:
+\begin{enumerate}
+\item
+No page breaks in the middle of a code chunk unless necessary to avoid
+an overfull vbox;
+\item
+Documentation immediately preceding a code chunk should appear on
+the same page as that code chunk unless doing so would violate rule 1.
+\end{enumerate}
+[[\filbreak]] is useful for this sort of thing (see {\em The \TeX
+ book\/}) and is used to encourage breaks at the right places between
+chunks. Appropriate penalties are inserted elsewhere, between code
+lines in particular.
+
+\subsection{Environments for setting code}
+
+[[\nwbegincode]] and [[\nwendcode]] are used by {\tt noweave} to bracket
+code chunks.
+The [[webcode]] environment is intended for users who want to paste
+{\tt noweave} output into papers.
+
+The definition of [[\nwbegincode]] is based on the verbatim
+implementation in {\tt verbatim.sty}, which will, presumably be in the
+next version of \LaTeX\@. One thing it does differently, apart from
+the catcode changes is setting [[\linewidth]]; this will avoid some
+overfull hboxen when the code lines are too long, but the lines won't
+be broken anyhow (even within chunk names because of the
+[[\maybehbox]] definition).
+<<noweb.sty>>=
+\def\nwbegincode#1{%
+ \begingroup
+ <<[[\nwbegincode]] separation and penalties>>
+ \@begincode }
+\def\nwendcode{\endtrivlist \endgroup \filbreak} % keeps code on 1 page
+
+\newenvironment{webcode}{%
+ \@begincode
+}{%
+ \endtrivlist}
+@ %def \nwbegincode \nwendcode webcode
+@ This is just common code between [[\nwbegincode]] and [[webcode]].
+<<noweb.sty>>=
+\def\@begincode{%
+ <<[[\trivlist]] clich\'e (\`a la {\Tt verbatim})>>
+ \linewidth\codehsize
+ <<[[\obeylines]] setup>>
+ <<zap ligatures, fix spaces>>
+ \nowebsize \setupcode
+ \let\maybehbox\mbox }
+@ %def \@begincode
+@ \iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B smallcode
+Set code in
+.I LaTeX
+.B "\\\\small"
+font instead of
+.B "\\\\normalsize."
+Similar options exist for all the
+.I LaTeX
+size-changing commands.
+@ \fi
+@ [[\nowebsize]] governs the size at which code is set; users who want
+to minimize code can [[\let\nowebsize=\small]].
+Slitex users should try
+\begin{quote}
+[[\def\nowebsize{\normalsize\baselineskip=20pt \parskip=5pt }]]
+\end{quote}
+to avoid code lines that are too far apart.
+[[\nwcodetopsep]] is
+the glue placed before code chunks.\stylehook
+<<noweb.sty>>=
+ \newskip\nwcodetopsep \nwcodetopsep = 3pt plus 1.2pt minus 1pt
+ \let\nowebsize=\normalsize
+ \def\nwopt@tinycode{\let\nowebsize=\tiny}
+ \def\nwopt@footnotesizecode{\let\nowebsize=\footnotesize}
+ \def\nwopt@scriptsizecode{\let\nowebsize=\scriptsize}
+ \def\nwopt@smallcode{\let\nowebsize=\small}
+ \def\nwopt@normalsizecode{\let\nowebsize=\normalsize}
+ \def\nwopt@largecode{\let\nowebsize=\large}
+ \def\nwopt@Largecode{\let\nowebsize=\Large}
+ \def\nwopt@LARGEcode{\let\nowebsize=\LARGE}
+ \def\nwopt@hugecode{\let\nowebsize=\huge}
+ \def\nwopt@Hugecode{\let\nowebsize=\Huge}
+@ %def \nwcodetopsep \nowebsize smallcode
+@ Maybe the penalties ought to be parameters\dots
+<<[[\nwbegincode]] separation and penalties>>=
+ \topsep \nwcodetopsep
+ \@beginparpenalty \@highpenalty
+ \@endparpenalty -\@highpenalty
+@
+The [[\trivlist]] clich\'e isn't quite a clich\'e because we adjust
+[[\leftskip]] for indentation by [[\codemargin]] and adjust
+[[\rightskip]] to allow lines up to [[\codehsize]] long without
+overfull boxen
+($\mbox{[[\codehsize]]}=\mbox{[[\hsize]]}+\mbox{[[\rightskip]]}$).
+Note that [[\hsize]] isn't altered.
+<<[[\trivlist]] clich\'e (\`a la {\Tt verbatim})>>=
+ \trivlist \item[]%
+ \leftskip\@totalleftmargin \advance\leftskip\codemargin
+ \rightskip\hsize \advance\rightskip -\codehsize
+ \parskip\z@ \parindent\z@ \parfillskip\@flushglue
+@ The penalty inserted between verbatim lines would normally be
+[[\interlinepenalty]], but we want to prohibit breaks there.
+@
+Note the bug lurking somewhere in this code, as reported by Steven Ooms:
+\begin{quote}
+I have some lay-out
+problems in the documentation chunks. When using the (La)TeX commands
+[[\hline]] or [[\vtop]] the right margin is always extended far beyond the page
+margin after the first code chunk has been typeset. I'm still looking for
+the exact cause of it, but to me it seems that LaTeX supposes for those
+commands that the line width for the documentation chunk is as large as that
+for code chunks, which isn't true in reality.
+\end{quote}
+@
+<<[[\obeylines]] setup>>=
+ \@@par
+ \def\par{\leavevmode\null \@@par \penalty\nwcodepenalty}%
+ \obeylines
+@ [[\nwcodepenalty]] is the penalty for breaking between lines in a
+code chunk. If you set it to 10000, code will never be broken across
+pages.\stylehook{} I guess this should be settable in [[\noweboptions]].
+<<noweb.sty>>=
+\newcount\nwcodepenalty \nwcodepenalty=\@highpenalty
+@ %def \nwcodepenalty
+The cursing chunk accounts for the addition of a mess of characters
+to those reset by [[\@noligs]] in \LaTeX2e.
+<<zap ligatures, fix spaces>>=
+ \@noligs <<make all those damn active characters ``other''>>
+ \setupcode \frenchspacing \@vobeyspaces
+@
+We can't make [[`]] ``other,'' because then we'll get ligatures.
+(Why Don put these ligatures in the [[\tt]] font I wish I knew.)
+But we'll step on all the others.
+<<make all those damn active characters ``other''>>=
+ \ifx\verbatim@nolig@list\undefined\else
+ \let\do=\nw@makeother \verbatim@nolig@list \do@noligs\`
+ \fi
+<<noweb.sty>>=
+\def\nw@makeother#1{\catcode`#1=12 }
+@
+{\tt noweave} uses [[\nwbegindocs{nnn}]] and [[\nwenddocs]] to bracket
+documentation chunks.
+If a documentation chunk does not continue the current paragraph,
+{\tt noweave} inserts [[\nwdocspar]], which uses
+[[\filbreak]] in an attempt to keep the documentation chunk on the
+same page as the code chunk that follows it. (The code chunk will
+have another [[\filbreak]] after it---see [[\nwbegincode]].)
+[[\nwbegindocs]] doesn't start a
+new paragraph if the previous chunk didn't end one, i.e.\ didn't enter
+vmode; if it does start a new one, it's only indented by the use of
+[[\nwdocspar]].
+<<noweb.sty>>=
+\def\nwbegindocs#1{\ifvmode\noindent\fi}
+\let\nwenddocs=\relax
+\let\nwdocspar=\filbreak
+@ %def \nwbegindocs \nwdocspar \nwenddocs
+The page-breaking strategy implies ragged bottom pages, so we should
+turn it on in general (this is relevant for the {\tt report} style):
+<<noweb.sty>>=
+\raggedbottom
+<<nwmac.tex>>=
+\def\nwdocspar{\par\semifilbreak}
+@
+
+{\tt noweave} doesn't bracket quoted code with [[\code]] and [[\edoc]] any more.
+It probably should do something nifty, just to make {\TeX} hackers happy, but it doesn't.
+<<noweb.sty>>=
+\def\code{\leavevmode\begingroup\setupcode\@vobeyspaces\obeylines}
+\let\edoc=\endgroup
+@
+\subsection{The {\tt noweb} page style}
+Headers contain file name, date, and page number.
+{\tt noweave} emits [[\nwfilename{]]{\em name}[[}]] for each new file.
+In the {\tt noweb} page style, new files cause page breaks;
+otherwise they are ignored.
+<<noweb.sty>>=
+\newdimen\@original@textwidth
+\def\ps@noweb{%
+ \@original@textwidth=\textwidth
+ \let\@mkboth\@gobbletwo
+ \def\@oddfoot{}\def\@evenfoot{}% No feet.
+ \if@twoside % If two-sided printing.
+ \def\@evenhead{\hbox to \@original@textwidth{%
+ \Rm \thepage\qquad{\Tt\leftmark}\hfil\today}}% Left heading.
+ \def\@oddhead{\hbox to \@original@textwidth{%
+ \Rm \today\hfil{\Tt\leftmark}\qquad\thepage}}% Right heading.
+ \else % If one-sided printing.
+ \def\@oddhead{\hbox to \@original@textwidth{%
+ \Rm \today\hfil{\Tt\leftmark}\qquad\thepage}}% Right heading.
+ \let\@evenhead\@oddhead
+ \fi
+ \let\chaptermark\@gobble
+ \let\sectionmark\@gobble
+ \let\subsectionmark\@gobble
+ \let\subsubsectionmark\@gobble
+ \let\paragraphmark\@gobble
+ \let\subparagraphmark\@gobble
+ \def\nwfilename{\begingroup\let\do\@makeother\dospecials
+ \catcode`\{=1 \catcode`\}=2 \nw@filename}
+ \def\nw@filename##1{\endgroup\markboth{##1}{##1}\let\nw@filename=\nw@laterfilename}%
+}
+\def\nw@laterfilename#1{\endgroup\clearpage \markboth{#1}{#1}}
+\let\nwfilename=\@gobble
+@ %def \@original@textwidth \ps@noweb \nwfilename
+@
+\subsection{Chunk cross-reference}
+[[\nwalsodefined]], [[\nwused]], and [[\nwnotused]] are emitted by the {\tt
+noweb} cross-referencers. (What arguments?)
+If unused chunks are output chunks, a filter can slip in
+[[\let\nwnotused\nwoutput]].
+The style uses [[\nwcodecomment]] for all annotations that follow code
+chunks.
+Fiddling with it can change the appearance of the output.
+Note that [[\nwcodecomment]] is used after [[\nwbegincode]], with
+[[\obeylines]] in efect. Since linebreaking can occur here, we need
+to change the [[\interlinepenalty]].
+A little vertical space ([[\nwcodecommentsep]]\stylehook) appears before the first
+comment.
+
+We firkled with [[\rightskip]] in [[\nwbegincode]] above; now we want to
+reset it so that paragraphs are the normal width ([[\textwidth]],
+possibly less [[\codemargin]]) and set ragged right. This is done as
+usuall by making [[\rightskip]] naturally zero but stretchable.
+<<noweb.sty>>=
+\def\nwcodecomment#1{\@@par\penalty\nwcodepenalty
+ <<add [[\nwcodecommentsep]] if this is the first [[\nwcodecomment]]>>%
+ \hspace{-\codemargin}{%
+ \rightskip=0pt plus1in
+ \interlinepenalty\nwcodepenalty
+ \let\\\relax\footnotesize\Rm #1\@@par\penalty\nwcodepenalty}}
+@ %def \nwcodecomment
+This stuff is used at the end of a chunk.
+<<noweb.sty>>=
+\def\@nwalsodefined#1{\nwcodecomment{\@nwlangdepdef\ \nwpageprep\ \@pagesl{#1}.}}
+\def\@nwused#1{\nwcodecomment{\@nwlangdepcud\ \nwpageprep\ \@pagesl{#1}.}}
+\def\@nwnotused#1{\nwcodecomment{\@nwlangdeprtc.}}
+\def\nwoutput#1{\nwcodecomment{\@nwlangdepcwf\ {\Tt \@stripstar#1*\stripped}.}}
+\def\@stripstar#1*#2\stripped{#1}
+@ %def \nwalsodefined \nwused \nwnotused \nwoutput
+<<add [[\nwcodecommentsep]] if this is the first [[\nwcodecomment]]>>=
+\if@firstnwcodecomment
+ \vskip\nwcodecommentsep\penalty\nwcodepenalty\@firstnwcodecommentfalse
+\fi
+@
+This stuff on the definition line.
+Note the hooks\stylehook{} for pointer styles.
+<<noweb.sty>>=
+\newcommand{\nwprevdefptr}[1]{%
+ \mbox{$\mathord{\triangleleft}\,\mathord{\mbox{\subpageref{#1}}}$}}
+\newcommand{\nwnextdefptr}[1]{%
+ \mbox{$\mathord{\mbox{\subpageref{#1}}}\,\mathord{\triangleright}$}}
+
+\newcommand{\@nwprevnextdefs}[2]{%
+ {\nwtagstyle
+ \ifx\relax#1\else ~~\nwprevdefptr{#1}\fi
+ \ifx\relax#2\else ~~\nwnextdefptr{#2}\fi}}
+\newcommand{\@nwusesondefline}[1]{{\nwtagstyle~~(\@pagenumsl{#1})}}
+\newcommand{\@nwstartdeflinemarkup}{\nobreak\hskip 1.5em plus 1fill\nobreak}
+\newcommand{\@nwenddeflinemarkup}{\nobreak\hskip \nwdefspace minus\nwdefspace\nobreak}
+@
+And here are the options we use to choose one or the other.
+<<noweb.sty>>=
+\def\nwopt@longxref{%
+ \let\nwalsodefined\@nwalsodefined
+ \let\nwused\@nwused
+ \let\nwnotused\@nwnotused
+ \let\nwprevnextdefs\@gobbletwo
+ \let\nwusesondefline\@gobble
+ \let\nwstartdeflinemarkup\relax
+ \let\nwenddeflinemarkup\relax
+}
+\def\nwopt@shortxref{%
+ \let\nwalsodefined\@gobble
+ \let\nwused\@gobble
+ \let\nwnotused\@gobble
+ \let\nwprevnextdefs\@nwprevnextdefs
+ \let\nwusesondefline\@nwusesondefline
+ \let\nwstartdeflinemarkup\@nwstartdeflinemarkup
+ \let\nwenddeflinemarkup\@nwenddeflinemarkup
+}
+\nwopt@shortxref % to hell with backward compatibility!
+@ \iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B longxref, shortxref
+Use either long, Knuth-style chunk cross-reference, or short,
+Hanson-style chunk cross-reference.
+The former uses small paragraphs after the chunk;
+the latter uses symbols on the definition line.
+Defaults to
+.B shortxref.
+@ \fi
+<<noweb.sty>>=
+\newskip\nwcodecommentsep \nwcodecommentsep=3pt plus 1pt minus 1pt
+\newif\if@firstnwcodecomment\@firstnwcodecommenttrue
+@
+\subsection{Page ranges}
+The goal is to combine sub-page numbers in a way that makes sense.
+Multiple sub-pages of one page become that page, and individual
+pages are combined into ranges.
+(A range may be only one page.)
+<<noweb.sty>>=
+\newcount\@nwlopage\newcount\@nwhipage % range lo..hi-1
+\newcount\@nwlosub % subpage of lo
+\newcount\@nwhisub % subpage of hi
+\def\@nwfirstpage#1#2#3{% subpage page xref-tag
+ \@nwlopage=#2 \@nwlosub=#1
+ \def\@nwloxreftag{#3}%
+ \advance\@nwpagecount by \@ne
+ <<$\mbox{[[\@nwhipage]]} := \mbox{[[\@nwlopage]]}+1$>>}
+\def\@nwnextpage#1#2#3{% subpage page xref-tag
+ \ifnum\@nwhipage=#2
+ \advance\@nwhipage by \@ne
+ \advance\@nwpagecount by \@ne
+ \@nwhisub=#1
+ \def\@nwhixreftag{#3}\else
+ \ifnum#2<\@nwlopage <<new range starting with [[#2]]>>\else
+ \ifnum#2>\@nwhipage <<new range starting with [[#2]]>>\else
+ \@nwlosub=0 \@nwhisub=0
+ \fi\fi\fi
+ }
+<<new range starting with [[#2]]>>=
+<<add range to range list>>\@nwfirstpage{#1}{#2}{#3}
+<<$\mbox{[[\@nwhipage]]} := \mbox{[[\@nwlopage]]}+1$>>=
+\@nwhipage=\@nwlopage\advance\@nwhipage by \@ne
+<<add range to range list>>=
+<<set [[\@tempa]] to page range(s), marked with [[\\]]>>%
+\edef\@tempa{\noexpand\nwix@cons\noexpand\nw@pages{\@tempa}}\@tempa
+<<set [[\@tempa]] to page range(s), marked with [[\\]]>>=
+\advance\@nwhipage by \m@ne
+\ifnum\@nwhipage=\@nwlopage
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}}%
+\else
+ \count@=\@nwhipage \advance\count@ by \m@ne
+ \ifnum\count@=\@nwlopage % consecutive pages
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}%
+ \noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwhisub}{\number\@nwhipage}}
+ {\@nwhixreftag}}}%
+ \else <<use rules from Chicago style manual>>%
+ \fi
+\fi
+<<use rules from Chicago style manual>>=
+\ifnum\@nwlopage<110 <<normal range>>\else
+ \count@=\@nwlopage \divide\count@ by 100 \multiply\count@ by 100
+ \ifnum\count@=\@nwlopage <<normal range>>\else
+ \count@=\@nwlopage \divide\count@ by 100
+ \@nwpagetemp=\@nwhipage \divide\@nwpagetemp by 100
+ \ifnum\count@=\@nwpagetemp % lo--least 2 digits of hi
+ \multiply\@nwpagetemp by 100
+ \advance \@nwhipage by -\@nwpagetemp
+ <<normal range>>%
+ \else <<normal range>>%
+ \fi
+ \fi
+\fi
+<<normal range>>=
+\edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}
+<<noweb.sty>>=
+\newcount\@nwpagetemp
+@
+The sequence [[\@pagesl]] makes a range of pages from a list of labels.
+[[\subpages]] works from a list of [[{{subpage}{page}}]].
+<<noweb.sty>>=
+\newcount\@nwpagecount
+\def\@nwfirstpagel#1{% label
+ \@ifundefined{r@#1}{<<warn of undefined reference to [[#1]] and add page ??>>}{%
+ \edef\@tempa{\noexpand\@nwfirstpage\subpagepair{#1}{#1}}\@tempa}}
+\def\@nwnextpagel#1{% label
+ \@ifundefined{r@#1}{<<warn of undefined reference to [[#1]] and add page ??>>}{%
+ \edef\@tempa{\noexpand\@nwnextpage\subpagepair{#1}{#1}}\@tempa}}
+<<noweb.sty>>=
+\def\@pagesl#1{% list of labels
+ \gdef\nw@pages{}\@nwpagecount=0
+ \def\\##1{\@nwfirstpagel{##1}\let\\=\@nwnextpagel}#1%
+ <<add range to range list>>\def\\##1{\@nwhyperpagenum##1}%
+ \nwpageword\ifnum\@nwpagecount=1 \else s\fi~\commafy{\nw@pages}}
+\def\@nwhyperpagenum#1#2{\nwhyperreference{#2}{#1}}
+
+\def\@pagenumsl#1{% list of labels -- doesn't include word `pages', commas, or `and'
+ \gdef\nw@pages{}\@nwpagecount=0
+ \def\\##1{\@nwfirstpagel{##1}\let\\=\@nwnextpagel}#1%
+ <<add range to range list>>%
+ \def\\##1{\@nwhyperpagenum##1\let\\=\@nwpagenumslrest}\nw@pages}
+\def\@nwpagenumslrest#1{~\@nwhyperpagenum#1}
+<<noweb.sty>>=
+\def\subpages#1{% list of {{subpage}{page}}
+ \gdef\nw@pages{}\@nwpagecount=0
+ \def\\##1{\edef\@tempa{\noexpand\@nwfirstpage##1{}}\@tempa
+ \def\\####1{\edef\@tempa{\noexpand\@nwnextpage####1}\@tempa}}#1%
+ <<add range to range list>>\def\\##1{\@firstoftwo##1}%
+ \nwpageword\ifnum\@nwpagecount=1 \else s\fi~\commafy{\nw@pages}}
+\def\@nwaddrange{<<add range to range list>>}
+@
+[[\nwpageword]] and [[\nwpageprep]] let you change the wording of the cross-reference
+information.
+<<noweb.sty>>=
+\def\nwpageword{\@nwlangdepchk} % chunk, was page
+\def\nwpageprep{\@nwlangdepin} % in, was on
+<<warn of undefined reference to [[#1]] and add page ??>>=
+<<warn of undefined reference to [[#1]]>>%
+\nwix@cons\nw@pages{\\{\bf ??}}
+@
+\subsection{Sub-page references}
+
+This is the wonderful code that Dave Love provided to make page
+references like 7a, 7b, and so on.
+
+This code
+provides a mechanism for defining `page
+sub-references' using [[\sublabel{foo}]] referenced with
+[[\subpageref{foo}]]. Sub-references will be numbered like these real
+examples: \subpageref{ref:foo}, \subpageref{ref:bar},
+\subpageref{ref:baz}\sublabel{ref:foo}\sublabel{ref:bar}\sublabel{ref:baz}
+etc.\ unless there is only one on the page, in which case the letter
+will be dropped like this: \subpageref{ref:fred}.
+
+To be able to use [[\subpageref]] we must define the label with
+[[\sublabel]], used like label. (Using
+[[\ref]] with a label defined by [[\sublabel]] will
+produce the sub-reference number, by the way, and [[\pageref]]
+works as expected.) Note that
+[[\subpageref]] is robust and [[\ref]] and [[\pageref]] are redefined to be
+robust also, as they will be in future \LaTeX{} releases.
+Incidentally, these expand to the relevant text plus [[\null]]---you
+might want to strip this off, e.g.\ for sorting lists.
+
+
+There are various ways we could attack this task (which is made
+non-trivial by the well-known asynchrony of (La)\TeX's output
+routine), but
+they all must depend on hacks in the [[.aux]] file or a similar one.
+Joachim Schrod's [[fnpag.sty]] does the same sort of thing differently
+to this \LaTeX-specific approach. See [[latex.tex]] for enlightenment
+on the cross-referencing mechanism and the \LaTeX{} internals used
+below. [DL: The internals change in \LaTeX2e compared with
+\LaTeX~2.09. The code here still works, though.]
+@
+The new-style {\LaTeX} page-reference macros all work the same way:
+if the thing is undefined, barf. Otherwise, do the specified thing.
+We need to handle the fact that the expansion of the label may be two
+items or five items, depending on whether hypertext is used.
+Since we're only ever interested in the first two items, we use a
+hack---the ``do the specified thing'' must be defined as
+\mbox{[[\def\dome#1#2#3\\{...}]]} where [[...]] uses only the first two parameters.
+<<noweb.sty>>=
+\newcommand\nw@genericref[2]{% what to do, name of ref
+ \expandafter\nw@g@nericref\csname r@#2\endcsname#1{#2}}
+\newcommand\nw@g@nericref[3]{% control sequence, what to do, name
+ \ifx#1\relax
+ \ref{#3}% trigger the standard `undefined ref' mechanisms
+ \else
+ \expandafter#2#1.\\%
+ \fi}
+@ Much of what we want can be done by pulling out the first, second,
+or first and second elements of a ref.
+<<noweb.sty>>=
+\def\nw@selectone#1#2#3\\{#1}
+\def\nw@selecttwo#1#2#3\\{#2}
+\def\nw@selectonetwo#1#2#3\\{{#1}{#2}}
+@
+The [[\subpageref]] macro first does a normal [[\pageref]]. If the
+reference is actually defined, it then goes on to check whether the
+control sequence [[2on]]\LA{}{page referenced}\RA{} is defined and sets the
+[[\ref]] value to get [[a]] etc.\ if so. The magic, of course, is in
+defining the [[2on]] bit appropriately.
+[[\subpageref]] also tries to include the right hyperstuff for xhdvi.
+<<noweb.sty>>=
+\newcommand{\subpageref}[1]{%
+ \nwhyperreference{#1}{\nw@genericref\@subpageref{#1}}}
+\def\@subpageref#1#2#3\\{%
+ \@ifundefined{2on#2}{#2}{\nwthepagenum{#1}{#2}}}
+@ %def \subpageref
+[[\subpagepair]] produces a [[{subpage}{page}]] pair.
+<<noweb.sty>>=
+\newcommand{\subpagepair}[1]{% % produces {subpage}{page}
+ \@ifundefined{r@#1}%
+ {{0}{0}}%
+ {\nw@genericref\@subpagepair{#1}}}
+\def\@subpagepair#1#2#3\\{%
+ \@ifundefined{2on#2}{{0}{#2}}{{#1}{#2}}}
+@
+[[\sublabel]] is like the [[\label]] command, except that it writes
+[[\newsublabel]] onto the [[.aux]] file rather than [[\newlabel]].
+For hyperreferencing, all labels must be hypertext
+anchors, for which we use [[\nwblindhyperanchor]].
+<<noweb.sty>>=
+\newcommand{\sublabel}[1]{%
+ \nwblindhyperanchor{#1}%
+ \@bsphack\if@filesw {\let\thepage\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string
+ \newsublabel{#1}{{}{\thepage}}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+@ %def \sublabel
+[[\nosublabel]] creates a label with a sub-page part of~0.
+<<noweb.sty>>=
+\newcommand{\nosublabel}[1]{%
+ \@bsphack\if@filesw {\let\thepage\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string
+ \newlabel{#1}{{0}{\thepage}}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+@ %def \nosublabel
+@
+[[\newsublabel]] is the macro that does the important work. It is called with the
+same sort of arguments as [[\newlabel]]: the first argument is the
+label name and the second is [[{<<ref value>>}{<<page number>>}]].
+(Note that the only definition here which needs to be
+global is the one which is, and that [[\global]] is redefined by
+[[\enddocument]], which will bite you if you use it\dots)
+<<noweb.sty>>=
+<<definition of [[\newsublabel]]>>
+@
+Before we create a [[\newsublabel]] for the first time, we set the
+proper trailers.
+<<definition of [[\newsublabel]]>>=
+\newcommand\newsublabel{%
+ \nw@settrailers
+ \global\let\newsublabel\@newsublabel
+ \@newsublabel}
+@ First we extract the page number into [[\this@page]].
+<<definition of [[\newsublabel]]>>=
+\newcommand{\@newsublabel}[2]{%
+ \edef\this@page{\@cdr#2\@nil}%
+@ %def \newsublabel
+@
+Then we see whether it's changed from the value of [[\last@page]]
+which was stashed away by the last [[\newsublabel]] (or is [[\relax]] if
+this is the first one). If the page has changed, we reset the
+counter [[\sub@page]] telling us how many sub-labels there have been
+on the page.
+<<definition of [[\newsublabel]]>>=
+ \ifx\this@page\last@page\else
+ \sub@page=\z@
+ \fi
+ \edef\last@page{\this@page}
+ \advance\sub@page by \@ne
+@
+If we've had at least two on the page, we define the
+[[2on]]\LA{}{page no.}\RA{} macro to indicate the fact.
+<<definition of [[\newsublabel]]>>=
+ \ifnum\sub@page=\tw@
+ \global\@namedef{2on\this@page}{}%
+ \fi
+@
+\nextchunklabel{cl1}\nextchunklabel{cl2}
+Then we write a normal [[\newlabel]] with the sub-reference as the
+normal reference value in the second argument.
+Unfortunately, if we want hypertext support, the second argument of
+[[\newlabel]] gets complicated.
+It is either
+\begin{itemize}
+\item
+[[{<<ref value>>}{<<page number>>}]], when normal {\LaTeX} is
+running, or
+\item
+[[{<<ref value>>}{<<page number>>}{<<text>>}}{<<hyper category>>}{<<URL>>}]],
+when the \texttt{hyperref} package is running.
+(We actually detect this by looking for the \texttt{nameref} package,
+because that's the one that changes the use of labels.)
+\end{itemize}
+We unify these two things by producing
+[[{<<ref value>>}{<<page number>>}\nw@labeltrailers]]
+
+We may have pending labels in support of [[\nextchunklabel]], as defined in
+chunk~\subpageref{chunklabel}.
+Because we want to define all of the ``pending sublabels'' in exactly
+the same way, we do something a bit odd---we make the current label a
+pending label as well.
+<<definition of [[\newsublabel]]>>=
+ \pendingsublabel{#1}%
+ \edef\@tempa##1{\noexpand\newlabel{##1}%
+ {{\number\sub@page}{\this@page}\nw@labeltrailers}}%
+ \pending@sublabels
+ \def\pending@sublabels{}}
+@
+We can't use [[\@ifpackageloaded]] to see if \texttt{nameref} is
+loaded, because that is restricted to the preamble, and
+[[\newsublabel]] goes into the [[.aux]] file, which is executed after
+the whole document is processed.
+We therefore test for [[\@secondoffive]].
+This is lame, but what else can we do?
+<<noweb.sty>>=
+\newcommand\nw@settrailers{% -- won't work on first run
+ \@ifpackageloaded{nameref}%
+ {\gdef\nw@labeltrailers{{}{}{}}}%
+ {\gdef\nw@labeltrailers{}}}
+\renewcommand\nw@settrailers{%
+ \@ifundefined{@secondoffive}%
+ {\gdef\nw@labeltrailers{}}%
+ {\gdef\nw@labeltrailers{{}{}{}}}}
+@
+Now we keep track of those pending guys.\nextchunklabel{chunklabel}
+The goal here is to save them up until they're all equivalent to the
+label on the next chunk.
+We have to control expansion so chunks like \subpageref{cl1}
+(\subpageref{cl2}) can be labelled twice.
+<<noweb.sty>>=
+\newcommand{\nextchunklabel}[1]{%
+ \nwblindhyperanchor{#1}% % looks slightly bogus --- nr
+ \@bsphack\if@filesw {\let\thepage\relax
+ \edef\@tempa{\write\@auxout{\string\pendingsublabel{#1}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+\newcommand\pendingsublabel[1]{%
+ \def\@tempa{\noexpand\@tempa}%
+ \edef\pending@sublabels{\noexpand\@tempa{#1}\pending@sublabels}}
+\def\pending@sublabels{}
+<<man page: noweb style control sequences>>=
+.PP \" .TP will not work with the backslashes on the next line. Period.
+\fB\\nextchunklabel{l}\fP
+.RS
+Associates label \fBl\fP
+with the sub-page reference of the next code chunk.
+Can be used in for concise chunk cross-reference with, e.g.,
+\fBchunk~\\subpageref{l}\fP.
+.RE
+@
+We need to define these.
+<<noweb.sty>>=
+\def\last@page{\relax}
+\newcount\sub@page
+@ %def \last@page \sub@page
+@
+We no longer use Rainer's new expandable definitions of [[\ref]] and
+[[\pageref]] to minimise the risk of nasty surprises; enough time has
+elapsed that this should no longer be necessary.
+<<old noweb.sty>>=
+% RmS 92/08/14: made \ref and \pageref robust
+\def\ref#1{\@ifundefined{r@#1}{{\bf ??}<<warn of undefined reference to [[#1]]>>}%
+ {\expandafter\expandafter\expandafter
+ \@car\csname r@#1\endcsname\@nil\null}}
+\def\pageref#1{\@ifundefined{r@#1}{{\bf ??}<<warn of undefined reference to [[#1]]>>}%
+ {\expandafter\expandafter\expandafter
+ \@cdr\csname r@#1\endcsname\@nil\null}}
+\def\@refpair#1{\@ifundefined{r@#1}{{0}{0}<<warn of undefined reference to [[#1]]>>}%
+ {\@nameuse{r@#1}}}
+<<warn of undefined reference to [[#1]]>>=
+\@warning{Reference `#1' on page \thepage \space undefined}
+@ %def \ref \pageref
+@
+
+Here a a couple of hooks for formatting sub-page numbers,
+which can be alphabetic, numeric, or omitted.\stylehook
+<<noweb.sty>>=
+\def\@alphasubpagenum#1#2{#2\ifnum#1=0 \else\@alph{#1}\fi}
+\def\@nosubpagenum#1#2{#2}
+\def\@numsubpagenum#1#2{#2\ifnum#1=0 \else.\@arabic{#1}\fi}
+\def\nwopt@nosubpage{\let\nwthepagenum=\@nosubpagenum\nwopt@nomargintag}
+\def\nwopt@numsubpage{\let\nwthepagenum=\@numsubpagenum}
+\def\nwopt@alphasubpage{\let\nwthepagenum=\@alphasubpagenum}
+\nwopt@alphasubpage
+@ %def \nwthepagenum nosubpage numsubpage alphasubpage
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B alphasubpage, numsubpage, nosubpage
+Number chunks by the number of the page on which they appear,
+followed by an alphabetic (numeric, not used) ``sub-page'' indicator.
+Defaults to
+.B alphasubpage.
+.B nosubpage
+implies
+.B nomargintag.
+@ \fi
+@
+
+\subsection{{\tt WEB}-like chunk numbering}
+Here's a righteous hack: we get the effect of WEB-like chunk numbers
+just by redefining [[\sublabel]] to use a counter instead of the current page number.
+Since the numbers are all distinct, no sub-page number is ever used.
+<<noweb.sty>>=
+\newcount\nw@chunkcount
+\nw@chunkcount=\@ne
+\newcommand{\weblabel}[1]{%
+ \@bsphack\if@filesw {\let\thepage\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string
+ \newsublabel{#1}{{}{\number\nw@chunkcount}}}}%
+ \expandafter}\@tempa
+ \global\advance\nw@chunkcount by \@ne
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+\def\nwopt@webnumbering{\let\sublabel=\weblabel\def\nwpageword{chunk}\def\nwpageprep{in}}
+@ %def \weblabel webnumbering
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B webnumbering
+Number chunks consecutively, in
+.I WEB
+style, instead of using sub-page numbers.
+@ \fi
+@
+\subsection{Indexing (identifier cross-reference) support}
+
+\subsubsection{Tracking definitions and uses}
+All index definitions and uses are associated with
+a label defined with [[\sublabel]] or [[\nosublabel]].
+Either the label is the [[\sublabel]] of the code chunk in which the definition or use
+appears, or it is a [[\nosublabel]] appearing in the middle of a
+documentation chunk.
+<<noweb.sty>>=
+% \nwindexdefn{printable name}{identifying label}{label of chunk}
+% \nwindexuse{printable name}{identifying label}{label of chunk}
+
+\def\nwindexdefn#1#2#3{\@auxix{\protect\nwixd}{#2}{#3}}
+\def\nwindexuse#1#2#3{\@auxix{\protect\nwixu}{#2}{#3}}
+
+\def\@auxix#1#2#3{% {marker}{id label}{subpage label}
+ \@bsphack\if@filesw {\let\nwixd\relax\let\nwixu\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string\nwixadd{#1}{#2}{#3}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+@ %def \nwindexdefn \nwindexuse \@auxix
+<<noweb.sty>>=
+% \nwixadd{marker}{idlabel}{subpage label}
+\def\nwixadd#1#2#3{%
+ \@ifundefined{nwixl@#2}%
+ {\global\@namedef{nwixl@#2}{#1{#3}}}%
+ {\expandafter\nwix@cons\csname nwixl@#2\endcsname{#1{#3}}}}
+@ %def \nwixadd
+@
+\subsubsection{Subscripted identifiers}
+We use either explicit subscripts or hyperlinks to point identifiers
+to their definitions.
+<<noweb.sty>>=
+\def\@nwsubscriptident#1#2{\mbox{$\mbox{#1}_{\mathrm{\subpageref{#2}}}$}}
+\def\@nwnosubscriptident#1#2{#1}
+\def\@nwhyperident#1#2{\leavevmode\nwhyperreference{#2}{#1}}
+@
+We can use subscripts, hyperlinks, or nothing on all identifiers.
+<<noweb.sty>>=
+\def\nwopt@subscriptidents{%
+ \let\nwlinkedidentq\@nwsubscriptident
+ \let\nwlinkedidentc\@nwsubscriptident
+}
+\def\nwopt@nosubscriptidents{%
+ \let\nwlinkedidentq\@nwnosubscriptident
+ \let\nwlinkedidentc\@nwnosubscriptident
+}
+\def\nwopt@hyperidents{%
+ \let\nwlinkedidentq\@nwhyperident
+ \let\nwlinkedidentc\@nwhyperident
+}
+\def\nwopt@nohyperidents{%
+ \let\nwlinkedidentq\@nwnosubscriptident
+ \let\nwlinkedidentc\@nwnosubscriptident
+}
+@
+We can change only identifiers appearing in quoted code.
+<<noweb.sty>>=
+\def\nwopt@subscriptquotedidents{%
+ \let\nwlinkedidentq\@nwsubscriptident
+}
+\def\nwopt@nosubscriptquotedidents{%
+ \let\nwlinkedidentq\@nwnosubscriptident
+}
+\def\nwopt@hyperquotedidents{%
+ \let\nwlinkedidentq\@nwhyperident
+}
+\def\nwopt@nohyperquotedidents{%
+ \let\nwlinkedidentq\@nwnosubscriptident
+}
+@
+The default is to hyperlink everything.
+<<noweb.sty>>=
+\nwopt@hyperidents
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B subscriptidents, nosubscriptidents, hyperidents, nohyperidents
+Controls subscripting of identifiers in code, including quoted code.
+Selecting
+.B subscriptidents
+means an identifier appearing in a code chunk (or in quoted code
+within a documentation
+chunk) will be subscripted with the chunk number of its definition.
+.B hyperidents
+means such identifiers will be hyperlinked to their definitions,
+provided of course that a hypertext package like
+.B hyperref
+is loaded.
+.B nosubscriptidents
+and
+.B nohyperidents
+are equivalent, and they turn off such markings.
+The default is
+.B hyperidents.
+.TP
+.B subscriptquotedidents, nosubscriptquotedidents, hyperquotedidents, nohyperquotedidents
+Controls linking of identifiers as above, but applies only to uses of
+identifiers
+in quoted code.
+@ \fi
+@
+\subsubsection{Writing lists with commas and ``and''}
+You get one of
+\begin{itemize}
+\item ``$a$''
+\item ``$a$ and $b$''
+\item ``$a$, $\ldots$, $b$, and $c$''
+\end{itemize}
+Plus [[\\]] is applied to each element of the list.
+<<noweb.sty>>=
+\newcount\@commacount
+\def\commafy#1{%
+ {\nwix@listcount{#1}\@commacount=\nwix@counter
+ \let\@comma@each=\\%
+ \ifcase\@commacount\let\\=\@comma@each\or\let\\=\@comma@each\or
+ \def\\{\def\\{ \@nwlangdepand\ \@comma@each}\@comma@each}\else
+ \def\\{\def\\{, %
+ \advance\@commacount by \m@ne
+ \ifnum\@commacount=1 \@nwlangdepand~\fi\@comma@each}\@comma@each}\fi
+ #1}}
+@ %def \@commacount \commafy
+
+\subsubsection{New, improved index code}
+There are two kinds of lists.
+One kind is a generic list in which elements are preceded by [[\\]].
+If the elements are index elements, they are {\em[[{]]printable
+identifier[[}{]]label[[}]]} pairs.
+The other kind is a list of sub-page labels, in which each
+element is preceded by either [[\nwixd]] or [[\nwixu]].
+<<noweb.sty>>=
+\def\nwix@cons#1#2{% {list}{\marker{element}}
+ {\toks0=\expandafter{#1}\def\@tempa{#2}\toks2=\expandafter{\@tempa}%
+ \xdef#1{\the\toks0 \the\toks2 }}}
+@ %def \nwix@cons
+The reference list for an identifier labelled {\em id}
+is always called [[\nwixl@]]{\em id}.
+Most applications will work with reference lists by applying [[\\]]
+either to the defs or to the uses.
+<<noweb.sty>>=
+\def\nwix@uses#1{% {label}
+ \def\nwixu{\\}\let\nwixd\@gobble\@nameuse{nwixl@#1}}
+\def\nwix@defs#1{% {label}
+ \def\nwixd{\\}\let\nwixu\@gobble\@nameuse{nwixl@#1}}
+@ %def \nwix@uses \nwix@defs
+
+Some applications count uses to see whether there is any need to
+display information.
+<<noweb.sty>>=
+\newcount\nwix@counter
+\def\nwix@listcount#1{% {list with \\}
+ {\count@=0
+ \def\\##1{\advance\count@ by \@ne }%
+ #1\global\nwix@counter=\count@ }}
+\def\nwix@usecount#1{\nwix@listcount{\nwix@uses{#1}}}
+\def\nwix@defcount#1{\nwix@listcount{\nwix@defs{#1}}}
+@ %def \nwix@listcount \nwix@usecount \nwix@defcount
+@
+\subsubsection{Supporting a mini-index at the end of each chunk}
+When displaying identifiers used, show the identifier and its
+definitions.
+<<noweb.sty>>=
+\def\nwix@id@defs#1{% index pair
+ {{\Tt \@car#1\@nil}%
+ \def\\##1{~\subpageref{##1}}\nwix@defs{\@cdr#1\@nil}}}
+\def\nwidentuses#1{% list of index pairs
+ \nwcodecomment{\@nwlangdepuss\ \let\\=\nwix@id@defs\commafy{#1}.}}
+@ %def \nwidentuses \nwix@id@defs
+The definitions section is a bit more complex, because it is omitted
+if none of the identifiers defined is ever used.
+<<noweb.sty>>=
+\def\nwix@totaluses#1{% list of index pairs
+ {\count@=0
+ \def\\##1{\nwix@usecount{\@cdr##1\@nil}\advance\count@ by\nwix@counter}%
+ #1\global\nwix@counter\count@ }}
+\def\nwix@id@uses#1#2{% {ident}{label}
+ \nwix@usecount{#2}\ifnum\nwix@counter>0
+ {\advance\leftskip by \codemargin
+ \nwcodecomment{{\Tt #1}, \@nwlangdepusd\ \nwpageprep\ \@pagesl{\nwix@uses{#2}}.}}%
+ \else
+ \ifnw@hideunuseddefs\else
+ {\advance\leftskip by \codemargin \nwcodecomment{{\Tt #1}, \@nwlangdepnvu.}}%
+ \fi
+ \fi}
+\def\nwidentdefs#1{% list of index pairs
+ \ifnw@hideunuseddefs\nwix@totaluses{#1}\else\nwix@listcount{#1}\fi
+ \ifnum\nwix@counter>0
+ \nwcodecomment{\@nwlangdepdfs:}%
+ {\def\\##1{\nwix@id@uses ##1}#1}%
+ \fi}
+<<noweb.sty>>=
+\newif\ifnw@hideunuseddefs\nw@hideunuseddefsfalse
+\def\nwopt@hideunuseddefs{\nw@hideunuseddefstrue}
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B hideunuseddefs
+Omit defined but unused identifiers from
+the local identifier cross-reference (Preston Briggs).
+@ \fi
+<<noweb.sty>>=
+\def\nwopt@noidentxref{%
+ \let\nwidentdefs\@gobble
+ \let\nwidentuses\@gobble}
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B noidentxref
+Omit the local identifier cross-reference which follows each code chunk.
+@ \fi
+
+\subsubsection{Support for chunk and identifier indices}
+The index in the back shows absolutely all the pages.
+<<noweb.sty>>=
+\def\nw@underlinedefs{% {list with \nwixd, \nwixu}
+ \let\\=\relax\def\nw@comma{, }
+ \def\nwixd##1{\\\underline{\subpageref{##1}}\let\\\nw@comma}%
+ \def\nwixu##1{\\\subpageref{##1}\let\\\nw@comma}}
+
+\def\nw@indexline#1#2{%
+ {\indent {\Tt #1}: \nw@underlinedefs\@nameuse{nwixl@#2}\par}}
+
+\newenvironment{thenowebindex}{\parindent=-10pt \parskip=\z@
+ \advance\leftskip by 10pt
+ \advance\rightskip by 0pt plus1in\par\@afterindenttrue
+ \def\\##1{\nw@indexline##1}}{}
+@
+The information comes from the list [[nwisx@i]].
+<<noweb.sty>>=
+\def\nowebindex{%
+ \@ifundefined{nwixs@i}%
+ {\@warning{The \string\nowebindex\space is empty}}%
+ {\begin{thenowebindex}\@nameuse{nwixs@i}\end{thenowebindex}}}
+@
+Here's a more efficient version for the external case:
+<<noweb.sty>>=
+\def\nowebindex@external{%
+ {\let\nwixadds@c=\@gobble
+ \def\nwixadds@i##1{\nw@indexline##1}%
+ \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}%
+ \begin{thenowebindex}\@input{\jobname.nwi}\end{thenowebindex}}}
+@
+That list ([[nwisx@i]]) is created by calls to [[\nwixlogsorted{i}]].
+<<noweb.sty>>=
+\def\nwixlogsorted#1#2{% list data
+ \@bsphack\if@filesw
+ \toks0={#2}\immediate\write\@auxout{\string\nwixadds{#1}{\the\toks0}}
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+@
+[[nwixs@c]] and [[nwixs@i]] are sorted lists of chunks and identifiers, respectively.
+<<noweb.sty>>=
+\def\nwixadds#1#2{%
+ \@ifundefined{nwixs@#1}%
+ {\global\@namedef{nwixs@#1}{\\{#2}}}%
+ {\expandafter\nwix@cons\csname nwixs@#1\endcsname{\\{#2}}}}
+\let\nwixaddsx=\@gobbletwo
+@
+If an external index is used, we need a [[.nwi]] file,
+[[\nwixadds]] is to be ignored, and we use [[\nwixaddsx]].
+<<noweb.sty>>=
+\def\nwopt@externalindex{%
+ \ifx\nwixadds\@gobbletwo % already called
+ \else
+ \let\nwixaddsx=\nwixadds \let\nwixadds=\@gobbletwo
+ \let\nowebindex=\nowebindex@external
+ \let\nowebchunks=\nowebchunks@external
+ \fi}
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B externalindex
+Use an index generated with
+.I noindex(1)
+(q.v.).
+@ \fi
+@
+<<noweb.sty>>=
+\def\nowebchunks{%
+ \@ifundefined{nwixs@c}%
+ {\@warning{The are no \string\nowebchunks}}%
+ {\begin{thenowebchunks}\@nameuse{nwixs@c}\end{thenowebchunks}}}
+\def\nowebchunks@external{%
+ {\let\nwixadds@i=\@gobble
+ \def\nwixadds@c##1{\nw@onechunk##1}%
+ \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}%
+ \begin{thenowebchunks}\@input{\jobname.nwi}\end{thenowebchunks}}}
+ \@namedef{r@nw@notdef}{{0}{(\@nwlangdepnvd)}}
+<<noweb.sty>>=
+\def\nw@chunkunderlinedefs{% {list of labels with \nwixd, \nwixu}
+ \let\\=\relax\def\nw@comma{, }
+ \def\nwixd##1{\\\underline{\subpageref{##1}}\let\\\nw@comma}%
+ \def\nwixu##1{\\\subpageref{##1}\let\\\nw@comma}}
+<<noweb.sty>>=
+\def\nw@onechunk#1#2#3{% {name}{label of first definition}{list with \nwixd, \nwixu}
+ \@ifundefined{r@#2}{}{%
+ \indent\LA #1~{\nwtagstyle\subpageref{#2}}\RA
+ \if@nwlongchunks{~\nw@chunkunderlinedefs#3}\fi\par}}
+<<noweb.sty>>=
+\newenvironment{thenowebchunks}{\vskip3pt
+ \parskip=\z@\parindent=-10pt \advance\leftskip by 10pt
+ \advance\rightskip by 0pt plus10pt \@afterindenttrue
+ \def\\##1{\nw@onechunk##1}}{}
+<<noweb.sty>>=
+\newif\if@nwlongchunks
+\@nwlongchunksfalse
+\let\nwopt@longchunks\@nwlongchunkstrue
+@ \iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B longchunks
+When expanding
+.B "\\\\nowebchunks,"
+show page numbers of definitions and uses of each chunk.
+@ \fi
+
+@
+\subsection{Support for hypertext}
+There are two sets of support for hypertext.
+ Balasubramanian Narasimhan wrote initial support for \texttt{hyper.sty}.
+<<noweb.sty>>=
+\newcommand\@nw@hyper@ref{\hyperreference} % naras
+\newcommand\@nw@hyper@anc{\blindhyperanchor} % naras
+@ Norman Ramsey wrote support for the \texttt{hyperrref} package (May
+ 1998).
+<<noweb.sty>>=
+\newcommand\@nw@hyperref@ref[2]{\hyperlink{noweb.#1}{#2}} % nr
+\newcommand\@nw@hyperref@anc[1]{\hypertarget{noweb.#1}{\relax}} % nr
+%%\renewcommand\@nw@hyperref@ref[2]{{#2}} % nr
+%%\renewcommand\@nw@hyperref@anc[1]{} % nr
+@ We define the independent macros [[\nwhyperreference]] and
+ [[\nwblindhyperanchor]],
+which test for the presence of one of these two packages,
+redefine themselve accordingly, and re-invoke themselves.
+<<noweb.sty>>=
+\newcommand\nwhyperreference{%
+ \@ifundefined{hyperlink}
+ {\@ifundefined{hyperreference}
+ {\global\let\nwhyperreference\@gobble}
+ {\global\let\nwhyperreference\@nw@hyper@ref}}
+ {\global\let\nwhyperreference\@nw@hyperref@ref}%
+ \nwhyperreference
+}
+
+\newcommand\nwblindhyperanchor{%
+ \@ifundefined{hyperlink}
+ {\@ifundefined{hyperreference}
+ {\global\let\nwblindhyperanchor\@gobble}
+ {\global\let\nwblindhyperanchor\@nw@hyper@anc}}
+ {\global\let\nwblindhyperanchor\@nw@hyperref@anc}%
+ \nwblindhyperanchor
+}
+@
+\subsection{Support for hypertext translation to HTML}
+<<noweb.sty>>=
+\newcommand\nwanchorto{%
+ \begingroup\let\do\@makeother\dospecials
+ \catcode`\{=1 \catcode`\}=2 \nw@anchorto}
+\newcommand\nw@anchorto[1]{\endgroup\def\nw@next{#1}\nw@anchortofin}
+\newcommand\nw@anchortofin[1]{#1\footnote{See URL \texttt{\nw@next}.}}
+\let\nwanchorname\@gobble
+<<man page: noweb style control sequences>>=
+.PP
+.B "\\\\nwanchorto{URL}{anchor text}"
+.RS
+Creates a link to the given URL with the given anchor text.
+Implemented in
+.I latex(1)
+using footnotes, but
+.I sl2h(1)
+translates this to
+.B "<a href=URL>anchor text</a>"
+.RE
+.PP
+.B "\\\\nwanchorname{name}{anchor text}"
+.RS
+Creates an anchor point for a hyperlink.
+Implemented in
+.I latex(1)
+using
+.B "\\\\label",
+but
+.I sl2h(1)
+translates this to
+.B "<a name=name>anchor text</a>"
+.RE
+@
+This lets us hide stuff intended for use only when converting to HTML:
+<<noweb.sty>>=
+\newif\ifhtml
+\htmlfalse
+<<man page: noweb style control sequences>>=
+.PP
+.B "\\\\ifhtml ... \\\\fi"
+.RS
+Text between
+.B "\\\\ifhtml"
+and
+.B "\\\\fi"
+is ignored by
+.I latex(1),
+but
+.I sl2h(1)
+and the
+.I l2h
+noweb filter translate the text into HTML.
+.RE
+@
+\subsection{Support for Prettyprinting}
+The following macro can be redefined to allow custom typesetting of
+identifiers in the index and mini-indices.
+<<noweb.sty>>=
+\let\nwixident=\relax
+@ %def \nwixident
+@
+The following macros can be redefined to typeset `[[\]]', `[[{]]' and
+`[[}]]' correctly in non-typewriter fonts.
+The problem is that the built-in {\LaTeX} [[\{]] tries to produce a
+math symbol, which doesn't exist in the typewriter font, so we get a
+brace in the wrong font and a warning. Most unpleasant.
+Noweave therefore attempts to emit [[\nwlbrace]] and [[\nwrbrace]]
+wherever it believes braces should appear.
+The standard noweb style is to set code in typewriter font, and so the
+standard definitions just select the proper characters from that font.
+ People setting code in
+fonts other than typewriter are responsible for redefining those
+macros to work in their environment.
+<<noweb.sty>>=
+\def\nwbackslash{\char92}
+\def\nwlbrace{\char123}
+\def\nwrbrace{\char125}
+<<nwmac.tex>>=
+\def\nwbackslash{\char92}
+\def\nwlbrace{\char123}
+\def\nwrbrace{\char125}
+@
+\subsection{Language-dependent macros}
+
+\label{subsection:langdeps}
+
+The language-dependent macros are defined here in each supported
+language in a different subsubsection.
+
+The choice of language depends on testing the [[\languagename]]
+macro. There must be a more elegant way of coding the tests below\ldots
+<<noweb.sty>>=
+<<language support>>
+\ifx\languagename\undefined % default is English
+ \nwoptions{english}
+\else
+ \@ifundefined{nwopt@\languagename}
+ {\nwoptions{english}}
+ {\expandafter\nwoptions\expandafter{\languagename}}
+\fi
+@
+\subsubsection{Support for English}
+
+This describes the original English text.
+<<language support>>=
+\def\nwopt@english{%
+ \def\@nwlangdepdef{This definition is continued}%
+ \def\@nwlangdepcud{This code is used}%
+ \def\@nwlangdeprtc{Root chunk (not used in this document)}%
+ \def\@nwlangdepcwf{This code is written to file}%
+ \def\@nwlangdepchk{chunk}%
+ \def\@nwlangdepin{in}%
+ \def\@nwlangdepand{and}%
+ \def\@nwlangdepuss{Uses}%
+ \def\@nwlangdepusd{used}%
+ \def\@nwlangdepnvu{never used}%
+ \def\@nwlangdepdfs{Defines}%
+ \def\@nwlangdepnvd{never defined}%
+}
+\let\nwopt@american\nwopt@english
+@
+
+@
+\subsubsection{Support for Portuguese}
+
+This contains the text in Portuguese.
+<<language support>>=
+\def\nwopt@portuges{%
+ \def\@nwlangdepdef{Defini\c{c}\~ao continuada em}%
+ % This definition is continued
+ \def\@nwlangdepcud{C\'odigo usado em}%
+ % This code is used
+ \def\@nwlangdeprtc{Fragmento de topo (sem uso no documento)}%
+ % Root chunk (not used in this document)
+ \def\@nwlangdepcwf{Este c\'odigo foi escrito no ficheiro}%
+ % This code is written to file
+ \def\@nwlangdepchk{fragmento}%
+ % chunk
+ \def\@nwlangdepin{no(s)}%
+ % in
+ \def\@nwlangdepand{e}%
+ % and
+ \def\@nwlangdepuss{Usa}%
+ % Uses
+ \def\@nwlangdepusd{usado}%
+ % used
+ \def\@nwlangdepnvu{nunca usado}%
+ % never used
+ \def\@nwlangdepdfs{Define}%
+ % Defines
+ \def\@nwlangdepnvd{nunca definido}%
+ % never defined
+}
+@
+\subsubsection{Support for French}
+
+This is a tentative translation to French that should probably be
+corrected by some French native speaker\ldots
+
+There are problems with using accents: on the [[\@nwlangdepnvd]] macro
+(which apparently is not used in the context of [[\nwcodecomment]]),
+and in some other macros (\LaTeX{} complains about missing
+[[\endcsname]]). This should be fixed by someone with experience in
+using \TeX\ldots
+<<language support>>=
+\def\nwopt@frenchb{%
+ \def\@nwlangdepdef{Cette d\'efinition suit dans}%
+ % This definition is continued
+ \def\@nwlangdepcud{Ce code est employ\'e dans}%
+ % This code is used
+ \def\@nwlangdeprtc{Morceau racine (pas employ\'e dans ce document)}%
+ % Root chunk (not used in this document)
+ \def\@nwlangdepcwf{Ce code est \'ecrit dans le fichier}%
+ % This code is written to file
+ \def\@nwlangdepchk{morceau}%
+ % chunk
+ \def\@nwlangdepin{dans le(s)}%
+ % in
+ \def\@nwlangdepand{et}%
+ % and
+ \def\@nwlangdepuss{Il emploie}%
+ % Uses
+ \def\@nwlangdepusd{employ\'{e}}%
+ % used
+ \def\@nwlangdepnvu{jamais employ\'{e}}%
+ % never used
+ \def\@nwlangdepdfs{Il d\'{e}fine}%
+ % Defines
+ % Cannot use the accent here: \def\@nwlangdepnvd{jamais d\'{e}fini}%
+ \def\@nwlangdepnvd{jamais defini}%
+ % never defined
+}
+\let\nwopt@french\nwopt@frenchb
+@
+\subsubsection{Support for German}
+
+This is a translation to German by Sabine Broda (DCC-FCUP \& LIACC,
+Universidade do Porto).
+<<language support>>=
+\def\nwopt@german{%
+ \def\@nwlangdepdef{Diese Definition wird fortgesetzt}%
+ % This definition is continued
+ \def\@nwlangdepcud{Dieser Code wird benutzt}%
+ % This code is used
+ \def\@nwlangdeprtc{Hauptteil (nicht in diesem Dokument benutzt)}%
+ % Root chunk (not used in this document)
+ \def\@nwlangdepcwf{Dieser Code schreibt man zum File}%
+ % This code is written to file
+ \def\@nwlangdepchk{Teil}%
+ % chunk
+ \def\@nwlangdepin{im}%
+ % in
+ \def\@nwlangdepand{und}%
+ % and
+ \def\@nwlangdepuss{Benutztt}%
+ % Uses
+ \def\@nwlangdepusd{benutzt}%
+ % used
+ \def\@nwlangdepnvu{nicht benutzt}%
+ % never used
+ \def\@nwlangdepdfs{Definiert}%
+ % Defines
+ \def\@nwlangdepnvd{nicht definiert}%
+ % never defined
+}
+\let\nwopt@ngerman\nwopt@german
+@
+@ \iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B english, french, german, portuges
+Write cross-reference information in the language specified.
+Defaults to
+.B english.
+@ \fi
+@
+\clearpage
+\section{The {\tt nwmac} macros for use with plain {\TeX}}
+
+First we make [[@]] a letter so that we can use `private' macro names.
+<<nwmac.tex>>=
+\catcode`\@=11
+<<nwmac.tex>>=
+% scale cmbx10 instead of using cmbx12 because {\LaTeX} does, so fonts exist
+\font\twlbf=cmbx10 scaled \magstep1
+\font\frtbf=cmbx10 scaled \magstep2
+% These fonts don't work with xdvi!
+
+\advance\hoffset 0.5 true in
+\advance\hsize -1.5 true in
+\newdimen\textsize
+\textsize=\hsize
+\def\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}
+@ %def \textsize \today
+<<nwmac.tex>>=
+\long\def\ifundefined#1#2#3{%
+ \expandafter\ifx\csname#1\endcsname\relax
+ #2%
+ \else#3%
+ \fi}
+
+\ifundefined{myheadline}
+ {\headline={\hbox to \textsize{\tentt\firstmark\hfil\tenrm\today\hbox
+ to 4em{\hss\folio}}\hss}}
+ {\expandafter\headline\expandafter{\myheadline}}
+
+\ifundefined{myfootline}
+ {\footline={\hfil}}
+ {\expandafter\footline\expandafter{\myfootline}}
+@ %def \ifundefined
+<<nwmac.tex>>=
+\def\semifilbreak{\vskip0pt plus1.5in\penalty-200\vskip0pt plus -1.5in}
+\raggedbottom
+@ %def \semifilbreak
+<<nwmac.tex>>=
+%
+% \chapcenter macro to produce nice centered chapter titles
+%
+\def\chapcenter{\leftskip=0.5 true in plus 4em minus 0.5 true in
+ \rightskip=\leftskip
+ \parfillskip=0pt \spaceskip=.3333em \xspaceskip=.5em
+ \pretolerance=9999 \tolerance=9999
+ \hyphenpenalty=9999 \exhyphenpenalty=9999}
+@ %def \chapcenter
+<<nwmac.tex>>=
+% \startsection{LEVEL}{INDENT}{BEFORESKIP}{AFTERSKIP}{STYLE}{HEADING}
+% #1 #2 #3 #4 #5 #6
+%
+% LEVEL: depth; e.g. part=0 chapter=1 sectino=2...
+% INDENT: indentation of heading from left margin
+% BEFORESKIP: skip before header
+% AFTERSKIP: skip after header
+% STYLE: style of heading; e.g.\bf
+% HEADING: heading of the sectino
+%
+\def\startsection#1#2#3#4#5#6{\par\vskip#3 plus 2in
+ \penalty-200\vskip 0pt plus -2in
+ \noindent{\leftskip=#2 \rightskip=0.5true in plus 4em minus 0.5 true in
+ \hyphenpenalty=9999 \exhyphenpenalty=9999
+ #5#6\par}\vskip#4%
+ {\def\code##1{[[}\def\edoc##1{]]}\message{[#6]}}
+ \settocparms{#1}
+ \def\themodtitle{#6}
+%%%% {\def\code{\string\code}\def\edoc{\string\edoc}%
+ \edef\next{\noexpand\write\cont{\tocskip
+ \tocline{\hskip\tocindent\tocstyle\relax\themodtitle}
+ {\noexpand\the\pageno}}}\next % write to toc
+ %}
+}
+@ %def \startsection
+<<nwmac.tex>>=
+\def\settocparms#1{
+ \count@=#1
+ \ifnum\count@<1
+ \def\tocskip{\vskip3ptplus1in\penalty-100
+ \vskip0ptplus-1in}%
+ \def\tocstyle{\bf}
+ \def\tocindent{0pt}
+ \else
+ \def\tocskip{}
+ \def\tocstyle{\rm}
+ \dimen@=2em \advance\count@ by \m@ne \dimen@=\count@\dimen@
+ \edef\tocindent{\the\dimen@}
+ \fi
+}
+@ %def \settocparms
+<<nwmac.tex>>=
+\def\tocline#1#2{\line{{\ignorespaces#1}\leaders\hbox to .5em{.\hfil}\hfil
+ \hbox to1.5em{\hss#2}}}
+@ %def \tocline
+<<nwmac.tex>>=
+\def\section#1{\par \vskip3ex\noindent {\bf #1}\par\nobreak\vskip1ex\nobreak}
+\def\chapter#1{\vfil\eject\startsection{0}{0pt}{6ex}{3ex}{\frtbf\chapcenter}{#1}}
+\def\section#1{\startsection{1}{0pt}{4ex}{2ex}{\twlbf}{#1}}
+\def\subsection#1{\startsection{2}{0pt}{2ex}{1ex}{\bf}{#1}}
+\def\subsubsection#1{\startsection{3}{0pt}{1ex}{0.5ex}{\it}{#1}}
+\def\paragraph#1{\startsection{4}{0pt}{1.5ex}{0ex}{\it}{#1}}
+
+<<kernel>>
+
+\def\nwfilename#1{\vfil\eject\mark{#1}}
+
+\def\nwbegindocs#1{\filbreak}
+\def\nwenddocs{\par}
+\def\nwbegincode#1{\par\nobreak
+ \begingroup\setupcode\newlines\parindent=0pt\parskip=0pt
+ \let\oendmoddef=\endmoddef \let\oplusendmoddef=\plusendmoddef
+ \def\endmoddef{\oendmoddef\par}\def\plusendmoddef{\oplusendmoddef\par}%
+ \hsize=\codehsize\noindent\bchack}
+\def\nwendcode{\endgroup}
+{\catcode`\^^M=\active % make CR an active character
+ \gdef\bchack#1^^M{\relax#1}%
+}
+@ %def \section \chapter \section \subsection \subsubsection \paragraph
+@ %def \nwbegindocs \nwenddocs \nwbegincode \nwendcode \nwfilename
+<<nwmac.tex>>=
+\edef\contentsfile{\jobname.toc } % file that gets table of contents info
+\def\readcontents{\expandafter\input \contentsfile}
+
+\newwrite\cont
+\openout\cont=\contentsfile
+\write\cont{\string\catcode`\string\@=11}% a hack to make contents
+@ %def \readcontents \cont
+<<nwmac.tex>>=
+ % take stuff in plain.tex
+\def\bye{%
+ \write\cont{}% ensure that the contents file isn't empty
+ \closeout\cont
+ \vfil\eject\pageno=-1 % new page causes contents to be really closed
+ \topofcontents\readcontents\botofcontents
+ \vfil\eject\end}
+\def\topofcontents{\vfil\mark{{\bf Contents}}}
+\def\botofcontents{}
+@ %def \bye \topofcontents \botofcontents
+<<nwmac.tex>>=
+\let\em=\it
+% used to produce an itemized (bulleted) list in plain {\TeX}
+% such lists can be nested
+% mostly useful with WEB
+
+% Usage:
+% \itemize
+% \item First thing
+% \item second thing
+% \enditemize
+
+\newcount\listlevel
+\listlevel=0
+\newdimen\itemwidth
+\itemwidth=3em
+
+\def\itemize{\begingroup\advance\listlevel by1
+ \def\item{\par\noindent
+ \raise2pt\llap{$\scriptstyle\bullet$\ }\ignorespaces}%
+ \def\nameditem##1{\par\noindent
+ \llap{\rlap{##1}\hskip\itemwidth}\ignorespaces}%
+ \par\advance\leftskip by\itemwidth\advance\rightskip by0.5\itemwidth}
+\def\enditemize{\par\endgroup\noindent\ignorespaces}
+
+\let\begindocument=\relax
+@ %def \listlevel \itemwidth \itemize \enditemize
+Finally we make [[@]] `other' again.
+<<nwmac.tex>>=
+\catcode`\@=12
+
+@
+\section{Chunks} \nowebchunks
+\twocolumn[\section{Index}]
+\nowebindex*
+\end{document}
+
+
+
diff --git a/web/noweb/src/tex/n.sty b/web/noweb/src/tex/n.sty
new file mode 100644
index 0000000000..b27eaa2ad8
--- /dev/null
+++ b/web/noweb/src/tex/n.sty
@@ -0,0 +1,159 @@
+\def\semifilbreak{\vskip0pt plus1.5in\penalty-200\vskip0pt plus -1.5in}
+\let\filbreak=\semifilbreak
+\raggedbottom
+\def\begindocument{\begin{document}}
+
+\def\LL{<<}
+\def\GG{>>}
+\def\LLS{[[}
+\def\RRS{]]}
+
+% make \hsize in code sufficient for 88 columns
+\setbox0=\hbox{\tt m}
+\newdimen\codehsize
+\codehsize=91\wd0 % 88 columns wasn't enough; I don't know why
+\newdimen\codemargin
+\codemargin=10pt
+\advance\codehsize by \codemargin
+
+\begingroup \catcode `|=0 \catcode `[= 1
+\catcode`]=2 \catcode `\{=12 \catcode `\}=12
+\catcode`\\=12 |gdef|@xbegincode#1|endcode[#1|@xendcode]
+|gdef|@xwebcode#1\end{webcode}[#1|end[webcode]]
+|endgroup
+
+
+\def\@gobble#1{}
+
+\def\@begincode{\par\linewidth\codehsize\hsize\codehsize\textwidth\codehsize
+\trivlist \item[]\if@minipage\else\vskip\parskip\fi
+\leftskip\@totalleftmargin\rightskip\z@
+\advance\leftskip\codemargin
+\parindent\z@\parfillskip\@flushglue\parskip\z@
+\@tempswafalse \def\par{\if@tempswa\hbox{}\fi\@tempswatrue\@@par}
+\obeylines \tt \catcode``=13 \@noligs \setupcode}
+
+\def\begincode#1{\begingroup\@begincode \frenchspacing\@vobeyspaces \@xbegincode}
+\def\@xendcode{\endtrivlist\endgroup}
+
+\def\webcode{\@webcode \frenchspacing\@vobeyspaces \@xwebcode}
+\let\endwebcode=\endtrivlist
+
+
+\chardef\other=12
+\def\setupcode{
+ \chardef\\=`\\
+ \chardef\{=`\{
+ \chardef\}=`\}
+ \catcode`\$=\other
+ \catcode`\&=\other
+ \catcode`\#=\other
+ \catcode`\%=\other
+ \catcode`\~=\other
+ \catcode`\_=\other
+ \catcode`\^=\other
+ \obeyspaces \@vobeyspaces\tt
+}
+\def\setupmodname{%
+ \catcode`\$=3
+ \catcode`\&=4
+ \catcode`\#=6
+ \catcode`\%=14
+ \catcode`\~=13
+ \catcode`\_=8
+ \catcode`\^=7
+ \catcode`\ =10
+ \catcode`\^^M=5
+ \rm}
+\def\LA{\begingroup\setupmodname\it$\langle${}}
+\def\RA{\/$\rangle$\endgroup}
+\def\code{\leavevmode\begingroup\setupcode}
+\def\edoc{\endgroup}
+
+\def\begindocs#1{\relax}
+\def\enddocs{\relax}
+\newbox\equivbox
+\setbox\equivbox=\hbox{$\equiv$}
+\newbox\plusequivbox
+\setbox\plusequivbox=\hbox{$\mathord{+}\mathord{\equiv}$}
+% \moddef can't have an argument because there might be \code...\edoc
+\def\moddef{\leavevmode\kern-\codemargin\LA}
+\def\endmoddef{\RA\unhcopy\equivbox}
+\def\plusendmoddef{\RA\unhcopy\plusequivbox}
+
+\def\filename#1{\vfil\eject\mark{#1}}
+
+
+\let\chunklist=\relax
+
+%%%%%%%%%%%%%%%% following code supports cross-referencing
+% lists of page references cause all the trouble
+
+
+\def\alsodefined#1{\hspace{-\parindent}{\footnotesize\rm
+ This definition is continued on \pages{#1}.}}
+\def\used#1{\hspace{-\parindent}{\footnotesize\rm
+ This code is used on \pages{#1}.}}
+\def\notused{\hspace{-\parindent}{\footnotesize\rm
+ Root module (not used in this document).}}
+
+
+\def\empty{}
+\def\lop#1\to#2{\expandafter\lopoff#1\lopoff#1#2}
+\long\def\lopoff\\#1#2\lopoff#3#4{\def#4{#1}\def#3{#2}}
+\def\loop#1\repeat{\def\iterate{#1\expandafter\iterate\fi}%
+ \iterate \let\iterate\relax}
+
+\def\thepageref#1{\@ifundefined{r@#1}{0\@warning
+ {Reference `#1' on page \thepage \space
+ undefined}}{\@nameuse{r@#1}}}
+
+\newcount\lastpage
+\newcount\thispage
+\newcount\pagesout
+
+\def\dosetpage#1#2#3\@nil{\thispage=#2\relax}
+
+\def\setthispage#1\done{%
+ \@ifundefined{r@#1}{{\bf ??}\@warning
+ {Reference `#1' on page \thepage \space
+ undefined}\thispage=0}{\edef\@tempa{\@nameuse{r@#1}}\expandafter
+ \dosetpage\@tempa\@nil}}
+
+\def\setpagenumbers#1{%
+ \def\thepages{#1}%
+ \def\pagenumbers{}%
+ \lastpage=-1
+ \loop\ifx\thepages\empty\else
+ \lop\thepages\to\lastref
+ \expandafter\setthispage\lastref\done
+ \ifnum\thispage=\lastpage \else
+ \edef\pagenumbers{\pagenumbers\noexpand\\{\the\thispage}}%
+ \lastpage=\thispage
+ \fi
+ \repeat}
+
+\def\pages#1{%
+ \setpagenumbers{#1}%
+ \expandafter\dopages\pagenumbers\done
+}
+
+\def\dopages#1\done{%
+ \def\thepages{#1}%
+ \lop\thepages\to\lastref
+ \lastpage=\lastref
+ \ifx\thepages\empty page \else pages \fi
+ \the\lastpage
+ \pagesout=1
+ \loop\ifx\thepages\empty\else
+ \lop\thepages\to\lastref
+ \thispage=\lastref
+ \ifx\thepages\empty
+ \ifnum\pagesout>1 , \else{} \fi
+ and
+ \else ,
+ \fi
+ \the\thispage
+ \advance\pagesout by 1
+ \lastpage=\thispage
+ \repeat}
diff --git a/web/noweb/src/tex/noweb.sty b/web/noweb/src/tex/noweb.sty
new file mode 100644
index 0000000000..ea294c0a1c
--- /dev/null
+++ b/web/noweb/src/tex/noweb.sty
@@ -0,0 +1,969 @@
+% noweb.sty -- LaTeX support for noweb
+% DON'T read or edit this file! Use ...noweb-source/tex/support.nw instead.
+{\obeyspaces\AtBeginDocument{\global\let =\ }} % from texbook, p 381
+\def\nwopt@nomargintag{\let\nwmargintag=\@gobble}
+\def\nwopt@margintag{%
+ \def\nwmargintag##1{\leavevmode\llap{##1\kern\nwmarginglue\kern\codemargin}}}
+\def\nwopt@margintag{%
+ \def\nwmargintag##1{\leavevmode\kern-\codemargin\nwthemargintag{##1}\kern\codemargin}}
+\def\nwthemargintag#1{\llap{#1\kern\nwmarginglue}}
+\nwopt@margintag
+\newdimen\nwmarginglue
+\nwmarginglue=0.3in
+\def\nwtagstyle{\footnotesize\Rm}
+% make \hsize in code sufficient for 88 columns
+\setbox0=\hbox{\tt m}
+\newdimen\codehsize
+\codehsize=91\wd0 % 88 columns wasn't enough; I don't know why
+\newdimen\codemargin
+\codemargin=0pt
+\newdimen\nwdefspace
+\nwdefspace=\codehsize
+% need to use \textwidth in {\LaTeX} to handle styles with
+% non-standard margins (David Bruce). Don't know why we sometimes
+% wanted \hsize. 27 August 1997.
+%% \advance\nwdefspace by -\hsize\relax
+\ifx\textwidth\undefined
+ \advance\nwdefspace by -\hsize\relax
+\else
+ \advance\nwdefspace by -\textwidth\relax
+\fi
+\chardef\other=12
+\def\setupcode{%
+ \chardef\\=`\\
+ \chardef\{=`\{
+ \chardef\}=`\}
+ \catcode`\$=\other
+ \catcode`\&=\other
+ \catcode`\#=\other
+ \catcode`\%=\other
+ \catcode`\~=\other
+ \catcode`\_=\other
+ \catcode`\^=\other
+ \catcode`\"=\other % fixes problem with german.sty
+ \obeyspaces\Tt
+}
+\def\nwendquote{\relax\ifhmode\spacefactor=1000 \fi}
+{\catcode`\^^M=\active % make CR an active character
+ \gdef\newlines{\catcode`\^^M=\active % make CR an active character
+ \def^^M{\par\startline}}%
+ \gdef\eatline#1^^M{\relax}%
+}
+%%% DON'T \gdef^^M{\par\startline}}% in case ^^M appears in a \write
+\def\startline{\noindent\hskip\parindent\ignorespaces}
+\def\nwnewline{\ifvmode\else\hfil\break\leavevmode\hbox{}\fi}
+\def\setupmodname{%
+ \catcode`\$=3
+ \catcode`\&=4
+ \catcode`\#=6
+ \catcode`\%=14
+ \catcode`\~=13
+ \catcode`\_=8
+ \catcode`\^=7
+ \catcode`\ =10
+ \catcode`\^^M=5
+ \let\{\lbrace
+ \let\}\rbrace
+ % bad news --- don't know what catcode to give "
+ \Rm}
+\def\LA{\begingroup\maybehbox\bgroup\setupmodname\It$\langle$}
+\def\RA{\/$\rangle$\egroup\endgroup}
+\def\code{\leavevmode\begingroup\setupcode\newlines}
+\def\edoc{\endgroup}
+\let\maybehbox\relax
+\newbox\equivbox
+\setbox\equivbox=\hbox{$\equiv$}
+\newbox\plusequivbox
+\setbox\plusequivbox=\hbox{$\mathord{+}\mathord{\equiv}$}
+% \moddef can't have an argument because there might be \code...\edoc
+\def\moddef{\leavevmode\kern-\codemargin\LA}
+\def\endmoddef{\RA\ifmmode\equiv\else\unhcopy\equivbox\fi
+ \nobreak\hfill\nobreak}
+\def\plusendmoddef{\RA\ifmmode\mathord{+}\mathord{\equiv}\else\unhcopy\plusequivbox\fi
+ \nobreak\hfill\nobreak}
+\def\chunklist{%
+\errhelp{I changed \chunklist to \nowebchunks.
+I'll try to avoid such incompatible changes in the future.}%
+\errmessage{Use \string\nowebchunks\space instead of \string\chunklist}}
+\def\nowebchunks{\message{<Warning: You need noweave -x to use \string\nowebchunks>}}
+\def\nowebindex{\message{<Warning: You need noweave -index to use \string\nowebindex>}}
+% here is support for the new-style (capitalized) font-changing commands
+% thanks to Dave Love
+\ifx\documentstyle\undefined
+ \let\Rm=\rm \let\It=\it \let\Tt=\tt % plain
+\else\ifx\selectfont\undefined
+ \let\Rm=\rm \let\It=\it \let\Tt=\tt % LaTeX OFSS
+\else % LaTeX NFSS
+ \def\Rm{\reset@font\rm}
+ \def\It{\reset@font\it}
+ \def\Tt{\reset@font\tt}
+ \def\Bf{\reset@font\bf}
+\fi\fi
+\ifx\reset@font\undefined \let\reset@font=\relax \fi
+\def\nwbackslash{\char92}
+\def\nwlbrace{\char123}
+\def\nwrbrace{\char125}
+\def\noweboptions#1{%
+ \def\@nwoptionlist{#1}%
+ \@for\@nwoption:=\@nwoptionlist\do{%
+ \@ifundefined{nwopt@\@nwoption}{%
+ \@latexerr{There is no such noweb option as '\@nwoption'}\@eha}{%
+ \csname nwopt@\@nwoption\endcsname}}}
+\codemargin=10pt
+\advance\codehsize by \codemargin % make room for indentation of code
+\advance\nwdefspace by \codemargin % and fix adjustment for def/use
+\def\setcodemargin#1{%
+ \advance\codehsize by -\codemargin % make room for indentation of code
+ \advance\nwdefspace by -\codemargin % and fix adjustment for def/use
+ \codemargin=#1
+ \advance\codehsize by \codemargin % make room for indentation of code
+ \advance\nwdefspace by \codemargin % and fix adjustment for
+ % def/use
+}
+\def\nwopt@shift{%
+ \dimen@=-0.8in
+ \if@twoside % Values for two-sided printing:
+ \advance\evensidemargin by \dimen@
+ \else % Values for one-sided printing:
+ \advance\evensidemargin by \dimen@
+ \advance\oddsidemargin by \dimen@
+ \fi
+% \advance \marginparwidth -\dimen@
+}
+\let\nwopt@noshift\@empty
+\def\nwbegincode#1{%
+ \begingroup
+ \topsep \nwcodetopsep
+ \@beginparpenalty \@highpenalty
+ \@endparpenalty -\@highpenalty
+ \@begincode }
+\def\nwendcode{\endtrivlist \endgroup \filbreak} % keeps code on 1 page
+
+\newenvironment{webcode}{%
+ \@begincode
+}{%
+ \endtrivlist}
+\def\@begincode{%
+ \trivlist \item[]%
+ \leftskip\@totalleftmargin \advance\leftskip\codemargin
+ \rightskip\hsize \advance\rightskip -\codehsize
+ \parskip\z@ \parindent\z@ \parfillskip\@flushglue
+ \linewidth\codehsize
+ \@@par
+ \def\par{\leavevmode\null \@@par \penalty\nwcodepenalty}%
+ \obeylines
+ \@noligs \ifx\verbatim@nolig@list\undefined\else
+ \let\do=\nw@makeother \verbatim@nolig@list \do@noligs\`
+ \fi
+ \setupcode \frenchspacing \@vobeyspaces
+ \nowebsize \setupcode
+ \let\maybehbox\mbox }
+ \newskip\nwcodetopsep \nwcodetopsep = 3pt plus 1.2pt minus 1pt
+ \let\nowebsize=\normalsize
+ \def\nwopt@tinycode{\let\nowebsize=\tiny}
+ \def\nwopt@footnotesizecode{\let\nowebsize=\footnotesize}
+ \def\nwopt@scriptsizecode{\let\nowebsize=\scriptsize}
+ \def\nwopt@smallcode{\let\nowebsize=\small}
+ \def\nwopt@normalsizecode{\let\nowebsize=\normalsize}
+ \def\nwopt@largecode{\let\nowebsize=\large}
+ \def\nwopt@Largecode{\let\nowebsize=\Large}
+ \def\nwopt@LARGEcode{\let\nowebsize=\LARGE}
+ \def\nwopt@hugecode{\let\nowebsize=\huge}
+ \def\nwopt@Hugecode{\let\nowebsize=\Huge}
+\newcount\nwcodepenalty \nwcodepenalty=\@highpenalty
+\def\nw@makeother#1{\catcode`#1=12 }
+\def\nwbegindocs#1{\ifvmode\noindent\fi}
+\let\nwenddocs=\relax
+\let\nwdocspar=\filbreak
+\def\@nwsemifilbreak#1{\vskip0pt plus#1\penalty-200\vskip0pt plus -#1}
+\newdimen\nwbreakcodespace
+\nwbreakcodespace=0.2in % by default, leave no more than this on a page
+\def\nwopt@breakcode{%
+ \def\nwdocspar{\@nwsemifilbreak{0.2in}}%
+ \def\nwendcode{\endtrivlist\endgroup} % ditches filbreak
+}
+\raggedbottom
+\def\code{\leavevmode\begingroup\setupcode\@vobeyspaces\obeylines}
+\let\edoc=\endgroup
+\newdimen\@original@textwidth
+\def\ps@noweb{%
+ \@original@textwidth=\textwidth
+ \let\@mkboth\@gobbletwo
+ \def\@oddfoot{}\def\@evenfoot{}% No feet.
+ \if@twoside % If two-sided printing.
+ \def\@evenhead{\hbox to \@original@textwidth{%
+ \Rm \thepage\qquad{\Tt\leftmark}\hfil\today}}% Left heading.
+ \def\@oddhead{\hbox to \@original@textwidth{%
+ \Rm \today\hfil{\Tt\leftmark}\qquad\thepage}}% Right heading.
+ \else % If one-sided printing.
+ \def\@oddhead{\hbox to \@original@textwidth{%
+ \Rm \today\hfil{\Tt\leftmark}\qquad\thepage}}% Right heading.
+ \let\@evenhead\@oddhead
+ \fi
+ \let\chaptermark\@gobble
+ \let\sectionmark\@gobble
+ \let\subsectionmark\@gobble
+ \let\subsubsectionmark\@gobble
+ \let\paragraphmark\@gobble
+ \let\subparagraphmark\@gobble
+ \def\nwfilename{\begingroup\let\do\@makeother\dospecials
+ \catcode`\{=1 \catcode`\}=2 \nw@filename}
+ \def\nw@filename##1{\endgroup\markboth{##1}{##1}\let\nw@filename=\nw@laterfilename}%
+}
+\def\nw@laterfilename#1{\endgroup\clearpage \markboth{#1}{#1}}
+\let\nwfilename=\@gobble
+\def\nwcodecomment#1{\@@par\penalty\nwcodepenalty
+ \if@firstnwcodecomment
+ \vskip\nwcodecommentsep\penalty\nwcodepenalty\@firstnwcodecommentfalse
+ \fi%
+ \hspace{-\codemargin}{%
+ \rightskip=0pt plus1in
+ \interlinepenalty\nwcodepenalty
+ \let\\\relax\footnotesize\Rm #1\@@par\penalty\nwcodepenalty}}
+\def\@nwalsodefined#1{\nwcodecomment{\@nwlangdepdef\ \nwpageprep\ \@pagesl{#1}.}}
+\def\@nwused#1{\nwcodecomment{\@nwlangdepcud\ \nwpageprep\ \@pagesl{#1}.}}
+\def\@nwnotused#1{\nwcodecomment{\@nwlangdeprtc.}}
+\def\nwoutput#1{\nwcodecomment{\@nwlangdepcwf\ {\Tt \@stripstar#1*\stripped}.}}
+\def\@stripstar#1*#2\stripped{#1}
+\newcommand{\nwprevdefptr}[1]{%
+ \mbox{$\mathord{\triangleleft}\,\mathord{\mbox{\subpageref{#1}}}$}}
+\newcommand{\nwnextdefptr}[1]{%
+ \mbox{$\mathord{\mbox{\subpageref{#1}}}\,\mathord{\triangleright}$}}
+
+\newcommand{\@nwprevnextdefs}[2]{%
+ {\nwtagstyle
+ \ifx\relax#1\else ~~\nwprevdefptr{#1}\fi
+ \ifx\relax#2\else ~~\nwnextdefptr{#2}\fi}}
+\newcommand{\@nwusesondefline}[1]{{\nwtagstyle~~(\@pagenumsl{#1})}}
+\newcommand{\@nwstartdeflinemarkup}{\nobreak\hskip 1.5em plus 1fill\nobreak}
+\newcommand{\@nwenddeflinemarkup}{\nobreak\hskip \nwdefspace minus\nwdefspace\nobreak}
+\def\nwopt@longxref{%
+ \let\nwalsodefined\@nwalsodefined
+ \let\nwused\@nwused
+ \let\nwnotused\@nwnotused
+ \let\nwprevnextdefs\@gobbletwo
+ \let\nwusesondefline\@gobble
+ \let\nwstartdeflinemarkup\relax
+ \let\nwenddeflinemarkup\relax
+}
+\def\nwopt@shortxref{%
+ \let\nwalsodefined\@gobble
+ \let\nwused\@gobble
+ \let\nwnotused\@gobble
+ \let\nwprevnextdefs\@nwprevnextdefs
+ \let\nwusesondefline\@nwusesondefline
+ \let\nwstartdeflinemarkup\@nwstartdeflinemarkup
+ \let\nwenddeflinemarkup\@nwenddeflinemarkup
+}
+\def\nwopt@noxref{%
+ \let\nwalsodefined\@gobble
+ \let\nwused\@gobble
+ \let\nwnotused\@gobble
+ \let\nwprevnextdefs\@gobbletwo
+ \let\nwusesondefline\@gobble
+ \let\nwstartdeflinemarkup\relax
+ \let\nwenddeflinemarkup\relax
+}
+\nwopt@shortxref % to hell with backward compatibility!
+\newskip\nwcodecommentsep \nwcodecommentsep=3pt plus 1pt minus 1pt
+\newif\if@firstnwcodecomment\@firstnwcodecommenttrue
+\newcount\@nwlopage\newcount\@nwhipage % range lo..hi-1
+\newcount\@nwlosub % subpage of lo
+\newcount\@nwhisub % subpage of hi
+\def\@nwfirstpage#1#2#3{% subpage page xref-tag
+ \@nwlopage=#2 \@nwlosub=#1
+ \def\@nwloxreftag{#3}%
+ \advance\@nwpagecount by \@ne
+ \@nwhipage=\@nwlopage\advance\@nwhipage by \@ne }
+\def\@nwnextpage#1#2#3{% subpage page xref-tag
+ \ifnum\@nwhipage=#2
+ \advance\@nwhipage by \@ne
+ \advance\@nwpagecount by \@ne
+ \@nwhisub=#1
+ \def\@nwhixreftag{#3}\else
+ \ifnum#2<\@nwlopage \advance\@nwhipage by \m@ne
+ \ifnum\@nwhipage=\@nwlopage
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}}%
+ \else
+ \count@=\@nwhipage \advance\count@ by \m@ne
+ \ifnum\count@=\@nwlopage % consecutive pages
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}%
+ \noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwhisub}{\number\@nwhipage}}
+ {\@nwhixreftag}}}%
+ \else \ifnum\@nwlopage<110 \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}\else
+ \count@=\@nwlopage \divide\count@ by 100 \multiply\count@ by 100
+ \ifnum\count@=\@nwlopage \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}\else
+ \count@=\@nwlopage \divide\count@ by 100
+ \@nwpagetemp=\@nwhipage \divide\@nwpagetemp by 100
+ \ifnum\count@=\@nwpagetemp % lo--least 2 digits of hi
+ \multiply\@nwpagetemp by 100
+ \advance \@nwhipage by -\@nwpagetemp
+ \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}%
+ \else \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}%
+ \fi
+ \fi
+ \fi%
+ \fi
+ \fi%
+ \edef\@tempa{\noexpand\nwix@cons\noexpand\nw@pages{\@tempa}}\@tempa\@nwfirstpage{#1}{#2}{#3}\else
+ \ifnum#2>\@nwhipage \advance\@nwhipage by \m@ne
+ \ifnum\@nwhipage=\@nwlopage
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}}%
+ \else
+ \count@=\@nwhipage \advance\count@ by \m@ne
+ \ifnum\count@=\@nwlopage % consecutive pages
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}%
+ \noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwhisub}{\number\@nwhipage}}
+ {\@nwhixreftag}}}%
+ \else \ifnum\@nwlopage<110 \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}\else
+ \count@=\@nwlopage \divide\count@ by 100 \multiply\count@ by 100
+ \ifnum\count@=\@nwlopage \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}\else
+ \count@=\@nwlopage \divide\count@ by 100
+ \@nwpagetemp=\@nwhipage \divide\@nwpagetemp by 100
+ \ifnum\count@=\@nwpagetemp % lo--least 2 digits of hi
+ \multiply\@nwpagetemp by 100
+ \advance \@nwhipage by -\@nwpagetemp
+ \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}%
+ \else \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}%
+ \fi
+ \fi
+ \fi%
+ \fi
+ \fi%
+ \edef\@tempa{\noexpand\nwix@cons\noexpand\nw@pages{\@tempa}}\@tempa\@nwfirstpage{#1}{#2}{#3}\else
+ \@nwlosub=0 \@nwhisub=0
+ \fi\fi\fi
+ }
+\newcount\@nwpagetemp
+\newcount\@nwpagecount
+\def\@nwfirstpagel#1{% label
+ \@ifundefined{r@#1}{\@warning{Reference `#1' on page \thepage \space undefined}%
+ \nwix@cons\nw@pages{\\{\bf ??}}}{%
+ \edef\@tempa{\noexpand\@nwfirstpage\subpagepair{#1}{#1}}\@tempa}}
+\def\@nwnextpagel#1{% label
+ \@ifundefined{r@#1}{\@warning{Reference `#1' on page \thepage \space undefined}%
+ \nwix@cons\nw@pages{\\{\bf ??}}}{%
+ \edef\@tempa{\noexpand\@nwnextpage\subpagepair{#1}{#1}}\@tempa}}
+\def\@pagesl#1{% list of labels
+ \gdef\nw@pages{}\@nwpagecount=0
+ \def\\##1{\@nwfirstpagel{##1}\let\\=\@nwnextpagel}#1%
+ \advance\@nwhipage by \m@ne
+ \ifnum\@nwhipage=\@nwlopage
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}}%
+ \else
+ \count@=\@nwhipage \advance\count@ by \m@ne
+ \ifnum\count@=\@nwlopage % consecutive pages
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}%
+ \noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwhisub}{\number\@nwhipage}}
+ {\@nwhixreftag}}}%
+ \else \ifnum\@nwlopage<110 \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}\else
+ \count@=\@nwlopage \divide\count@ by 100 \multiply\count@ by 100
+ \ifnum\count@=\@nwlopage \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}\else
+ \count@=\@nwlopage \divide\count@ by 100
+ \@nwpagetemp=\@nwhipage \divide\@nwpagetemp by 100
+ \ifnum\count@=\@nwpagetemp % lo--least 2 digits of hi
+ \multiply\@nwpagetemp by 100
+ \advance \@nwhipage by -\@nwpagetemp
+ \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}%
+ \else \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}%
+ \fi
+ \fi
+ \fi%
+ \fi
+ \fi%
+ \edef\@tempa{\noexpand\nwix@cons\noexpand\nw@pages{\@tempa}}\@tempa\def\\##1{\@nwhyperpagenum##1}%
+ \ifnum\@nwpagecount=1 \nwpageword \else \nwpagesword\fi~\commafy{\nw@pages}}
+\def\@nwhyperpagenum#1#2{\nwhyperreference{#2}{#1}}
+
+\def\@pagenumsl#1{% list of labels -- doesn't include word `pages', commas, or `and'
+ \gdef\nw@pages{}\@nwpagecount=0
+ \def\\##1{\@nwfirstpagel{##1}\let\\=\@nwnextpagel}#1%
+ \advance\@nwhipage by \m@ne
+ \ifnum\@nwhipage=\@nwlopage
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}}%
+ \else
+ \count@=\@nwhipage \advance\count@ by \m@ne
+ \ifnum\count@=\@nwlopage % consecutive pages
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}%
+ \noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwhisub}{\number\@nwhipage}}
+ {\@nwhixreftag}}}%
+ \else \ifnum\@nwlopage<110 \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}\else
+ \count@=\@nwlopage \divide\count@ by 100 \multiply\count@ by 100
+ \ifnum\count@=\@nwlopage \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}\else
+ \count@=\@nwlopage \divide\count@ by 100
+ \@nwpagetemp=\@nwhipage \divide\@nwpagetemp by 100
+ \ifnum\count@=\@nwpagetemp % lo--least 2 digits of hi
+ \multiply\@nwpagetemp by 100
+ \advance \@nwhipage by -\@nwpagetemp
+ \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}%
+ \else \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}%
+ \fi
+ \fi
+ \fi%
+ \fi
+ \fi%
+ \edef\@tempa{\noexpand\nwix@cons\noexpand\nw@pages{\@tempa}}\@tempa%
+ \def\\##1{\@nwhyperpagenum##1\let\\=\@nwpagenumslrest}\nw@pages}
+\def\@nwpagenumslrest#1{~\@nwhyperpagenum#1}
+\def\subpages#1{% list of {{subpage}{page}}
+ \gdef\nw@pages{}\@nwpagecount=0
+ \def\\##1{\edef\@tempa{\noexpand\@nwfirstpage##1{}}\@tempa
+ \def\\####1{\edef\@tempa{\noexpand\@nwnextpage####1}\@tempa}}#1%
+ \advance\@nwhipage by \m@ne
+ \ifnum\@nwhipage=\@nwlopage
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}}%
+ \else
+ \count@=\@nwhipage \advance\count@ by \m@ne
+ \ifnum\count@=\@nwlopage % consecutive pages
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}%
+ \noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwhisub}{\number\@nwhipage}}
+ {\@nwhixreftag}}}%
+ \else \ifnum\@nwlopage<110 \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}\else
+ \count@=\@nwlopage \divide\count@ by 100 \multiply\count@ by 100
+ \ifnum\count@=\@nwlopage \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}\else
+ \count@=\@nwlopage \divide\count@ by 100
+ \@nwpagetemp=\@nwhipage \divide\@nwpagetemp by 100
+ \ifnum\count@=\@nwpagetemp % lo--least 2 digits of hi
+ \multiply\@nwpagetemp by 100
+ \advance \@nwhipage by -\@nwpagetemp
+ \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}%
+ \else \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}%
+ \fi
+ \fi
+ \fi%
+ \fi
+ \fi%
+ \edef\@tempa{\noexpand\nwix@cons\noexpand\nw@pages{\@tempa}}\@tempa\def\\##1{\@firstoftwo##1}%
+ \ifnum\@nwpagecount=1 \nwpageword \else \nwpagesword\fi~\commafy{\nw@pages}}
+\def\@nwaddrange{\advance\@nwhipage by \m@ne
+ \ifnum\@nwhipage=\@nwlopage
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}}%
+ \else
+ \count@=\@nwhipage \advance\count@ by \m@ne
+ \ifnum\count@=\@nwlopage % consecutive pages
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}%
+ \noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwhisub}{\number\@nwhipage}}
+ {\@nwhixreftag}}}%
+ \else \ifnum\@nwlopage<110 \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}\else
+ \count@=\@nwlopage \divide\count@ by 100 \multiply\count@ by 100
+ \ifnum\count@=\@nwlopage \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}\else
+ \count@=\@nwlopage \divide\count@ by 100
+ \@nwpagetemp=\@nwhipage \divide\@nwpagetemp by 100
+ \ifnum\count@=\@nwpagetemp % lo--least 2 digits of hi
+ \multiply\@nwpagetemp by 100
+ \advance \@nwhipage by -\@nwpagetemp
+ \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}%
+ \else \edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}%
+ \fi
+ \fi
+ \fi%
+ \fi
+ \fi%
+ \edef\@tempa{\noexpand\nwix@cons\noexpand\nw@pages{\@tempa}}\@tempa}
+\def\nwpageword{\@nwlangdepchk} % chunk, was page
+\def\nwpagesword{\@nwlangdepchks} % chunk, was page
+\def\nwpageprep{\@nwlangdepin} % in, was on
+\newcommand\nw@genericref[2]{% what to do, name of ref
+ \expandafter\nw@g@nericref\csname r@#2\endcsname#1{#2}}
+\newcommand\nw@g@nericref[3]{% control sequence, what to do, name
+ \ifx#1\relax
+ \ref{#3}% trigger the standard `undefined ref' mechanisms
+ \else
+ \expandafter#2#1.\\%
+ \fi}
+\def\nw@selectone#1#2#3\\{#1}
+\def\nw@selecttwo#1#2#3\\{#2}
+\def\nw@selectonetwo#1#2#3\\{{#1}{#2}}
+\newcommand{\subpageref}[1]{%
+ \nwhyperreference{#1}{\nw@genericref\@subpageref{#1}}}
+\def\@subpageref#1#2#3\\{%
+ \@ifundefined{2on#2}{#2}{\nwthepagenum{#1}{#2}}}
+\newcommand{\subpagepair}[1]{% % produces {subpage}{page}
+ \@ifundefined{r@#1}%
+ {{0}{0}}%
+ {\nw@genericref\@subpagepair{#1}}}
+\def\@subpagepair#1#2#3\\{%
+ \@ifundefined{2on#2}{{0}{#2}}{{#1}{#2}}}
+\newcommand{\sublabel}[1]{%
+ \leavevmode % needed to make \@bsphack work
+ \@bsphack
+ \nwblindhyperanchor{#1}%
+ \if@filesw {\let\thepage\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string
+ \newsublabel{#1}{{}{\thepage}}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+\newcommand{\nosublabel}[1]{%
+ \@bsphack\if@filesw {\let\thepage\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string
+ \newlabel{#1}{{0}{\thepage}}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+\newcommand\newsublabel{%
+ \nw@settrailers
+ \global\let\newsublabel\@newsublabel
+ \@newsublabel}
+\newcommand{\@newsublabel}[2]{%
+ \edef\this@page{\@cdr#2\@nil}%
+ \ifx\this@page\last@page\else
+ \sub@page=\z@
+ \fi
+ \edef\last@page{\this@page}
+ \advance\sub@page by \@ne
+ \ifnum\sub@page=\tw@
+ \global\@namedef{2on\this@page}{}%
+ \fi
+ \pendingsublabel{#1}%
+ \edef\@tempa##1{\noexpand\newlabel{##1}%
+ {{\number\sub@page}{\this@page}\nw@labeltrailers}}%
+ \pending@sublabels
+ \def\pending@sublabels{}}
+\newcommand\nw@settrailers{% -- won't work on first run
+ \@ifpackageloaded{nameref}%
+ {\gdef\nw@labeltrailers{{}{}{}}}%
+ {\gdef\nw@labeltrailers{}}}
+\renewcommand\nw@settrailers{%
+ \@ifundefined{@secondoffive}%
+ {\gdef\nw@labeltrailers{}}%
+ {\gdef\nw@labeltrailers{{}{}{}}}}
+\newcommand{\nextchunklabel}[1]{%
+ \nwblindhyperanchor{#1}% % looks slightly bogus --- nr
+ \@bsphack\if@filesw {\let\thepage\relax
+ \edef\@tempa{\write\@auxout{\string\pendingsublabel{#1}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+\newcommand\pendingsublabel[1]{%
+ \def\@tempa{\noexpand\@tempa}%
+ \edef\pending@sublabels{\noexpand\@tempa{#1}\pending@sublabels}}
+\def\pending@sublabels{}
+\def\last@page{\relax}
+\newcount\sub@page
+\def\@alphasubpagenum#1#2{#2\ifnum#1=0 \else\@alph{#1}\fi}
+\def\@nosubpagenum#1#2{#2}
+\def\@numsubpagenum#1#2{#2\ifnum#1=0 \else.\@arabic{#1}\fi}
+\def\nwopt@nosubpage{\let\nwthepagenum=\@nosubpagenum\nwopt@nomargintag}
+\def\nwopt@numsubpage{\let\nwthepagenum=\@numsubpagenum}
+\def\nwopt@alphasubpage{\let\nwthepagenum=\@alphasubpagenum}
+\nwopt@alphasubpage
+\newcount\@nwalph@n
+\let\@nwalph@d\@tempcnta
+\let\@nwalph@bound\@tempcntb
+\def\@nwlongalph#1{{%
+ \@nwalph@n=#1\advance\@nwalph@n by-1
+ \@nwalph@bound=26
+ \loop\ifnum\@nwalph@n<\@nwalph@bound\else
+ \advance\@nwalph@n by -\@nwalph@bound
+ \multiply\@nwalph@bound by 26
+ \repeat
+ \loop\ifnum\@nwalph@bound>1
+ \divide\@nwalph@bound by 26
+ \@nwalph@d=\@nwalph@n\divide\@nwalph@d by \@nwalph@bound
+ % d := d * bound ; n -:= d; d := d / bound --- saves a temporary
+ \multiply\@nwalph@d by \@nwalph@bound
+ \advance\@nwalph@n by -\@nwalph@d
+ \divide\@nwalph@d by \@nwalph@bound
+ \advance\@nwalph@d by 1 \@alph{\@nwalph@d}%
+ \repeat
+}}
+\newcount\nw@chunkcount
+\nw@chunkcount=\@ne
+\newcommand{\weblabel}[1]{%
+ \@bsphack
+ \nwblindhyperanchor{#1}%
+ \if@filesw {\let\thepage\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string
+ \newsublabel{#1}{{}{\number\nw@chunkcount}}}}%
+ \expandafter}\@tempa
+ \global\advance\nw@chunkcount by \@ne
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+\def\nwopt@webnumbering{%
+ \let\sublabel=\weblabel
+ \def\nwpageword{chunk}\def\nwpagesword{chunks}%
+ \def\nwpageprep{in}}
+% \nwindexdefn{printable name}{identifying label}{label of chunk}
+% \nwindexuse{printable name}{identifying label}{label of chunk}
+
+\def\nwindexdefn#1#2#3{\@auxix{\protect\nwixd}{#2}{#3}}
+\def\nwindexuse#1#2#3{\@auxix{\protect\nwixu}{#2}{#3}}
+
+\def\@auxix#1#2#3{% {marker}{id label}{subpage label}
+ \@bsphack\if@filesw {\let\nwixd\relax\let\nwixu\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string\nwixadd{#1}{#2}{#3}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+% \nwixadd{marker}{idlabel}{subpage label}
+\def\nwixadd#1#2#3{%
+ \@ifundefined{nwixl@#2}%
+ {\global\@namedef{nwixl@#2}{#1{#3}}}%
+ {\expandafter\nwix@cons\csname nwixl@#2\endcsname{#1{#3}}}}
+\def\@nwsubscriptident#1#2{\mbox{$\mbox{#1}_{\mathrm{\subpageref{#2}}}$}}
+\def\@nwnosubscriptident#1#2{#1}
+\def\@nwhyperident#1#2{\leavevmode\nwhyperreference{#2}{#1}}
+\def\nwopt@subscriptidents{%
+ \let\nwlinkedidentq\@nwsubscriptident
+ \let\nwlinkedidentc\@nwsubscriptident
+}
+\def\nwopt@nosubscriptidents{%
+ \let\nwlinkedidentq\@nwnosubscriptident
+ \let\nwlinkedidentc\@nwnosubscriptident
+}
+\def\nwopt@hyperidents{%
+ \let\nwlinkedidentq\@nwhyperident
+ \let\nwlinkedidentc\@nwhyperident
+}
+\def\nwopt@nohyperidents{%
+ \let\nwlinkedidentq\@nwnosubscriptident
+ \let\nwlinkedidentc\@nwnosubscriptident
+}
+\def\nwopt@subscriptquotedidents{%
+ \let\nwlinkedidentq\@nwsubscriptident
+}
+\def\nwopt@nosubscriptquotedidents{%
+ \let\nwlinkedidentq\@nwnosubscriptident
+}
+\def\nwopt@hyperquotedidents{%
+ \let\nwlinkedidentq\@nwhyperident
+}
+\def\nwopt@nohyperquotedidents{%
+ \let\nwlinkedidentq\@nwnosubscriptident
+}
+\nwopt@hyperidents
+\newcount\@commacount
+\def\commafy#1{%
+ {\nwix@listcount{#1}\@commacount=\nwix@counter
+ \let\@comma@each=\\%
+ \ifcase\@commacount\let\\=\@comma@each\or\let\\=\@comma@each\or
+ \def\\{\def\\{ \@nwlangdepand\ \@comma@each}\@comma@each}\else
+ \def\\{\def\\{, %
+ \advance\@commacount by \m@ne
+ \ifnum\@commacount=1 \@nwlangdepand~\fi\@comma@each}\@comma@each}\fi
+ #1}}
+\def\nwix@cons#1#2{% {list}{\marker{element}}
+ {\toks0=\expandafter{#1}\def\@tempa{#2}\toks2=\expandafter{\@tempa}%
+ \xdef#1{\the\toks0 \the\toks2 }}}
+\def\nwix@uses#1{% {label}
+ \def\nwixu{\\}\let\nwixd\@gobble\@nameuse{nwixl@#1}}
+\def\nwix@defs#1{% {label}
+ \def\nwixd{\\}\let\nwixu\@gobble\@nameuse{nwixl@#1}}
+\newcount\nwix@counter
+\def\nwix@listcount#1{% {list with \\}
+ {\count@=0
+ \def\\##1{\advance\count@ by \@ne }%
+ #1\global\nwix@counter=\count@ }}
+\def\nwix@usecount#1{\nwix@listcount{\nwix@uses{#1}}}
+\def\nwix@defcount#1{\nwix@listcount{\nwix@defs{#1}}}
+\def\nwix@id@defs#1{% index pair
+ {{\Tt \@car#1\@nil}%
+ \def\\##1{\nwix@defs@space\subpageref{##1}}\nwix@defs{\@cdr#1\@nil}}}
+ % useful above to change ~ into something that can break
+% this option is undocumented because I think breakdefs is always right
+\def\nwopt@breakdefs{\def\nwix@defs@space{\penalty200\ }}
+\def\nwopt@nobreakdefs{\def\nwix@defs@space{~}} % old code
+\nwopt@breakdefs
+\def\nwidentuses#1{% list of index pairs
+ \nwcodecomment{\@nwlangdepuss\ \let\\=\nwix@id@defs\commafy{#1}.}}
+\def\nwix@totaluses#1{% list of index pairs
+ {\count@=0
+ \def\\##1{\nwix@usecount{\@cdr##1\@nil}\advance\count@ by\nwix@counter}%
+ #1\global\nwix@counter\count@ }}
+\def\nwix@id@uses#1#2{% {ident}{label}
+ \nwix@usecount{#2}\ifnum\nwix@counter>0
+ {\advance\leftskip by \codemargin
+ \nwcodecomment{{\Tt #1}, \@nwlangdepusd\ \nwpageprep\ \@pagesl{\nwix@uses{#2}}.}}%
+ \else
+ \ifnw@hideunuseddefs\else
+ {\advance\leftskip by \codemargin \nwcodecomment{{\Tt #1}, \@nwlangdepnvu.}}%
+ \fi
+ \fi}
+\def\nwidentdefs#1{% list of index pairs
+ \ifnw@hideunuseddefs\nwix@totaluses{#1}\else\nwix@listcount{#1}\fi
+ \ifnum\nwix@counter>0
+ \nwcodecomment{\@nwlangdepdfs:}%
+ {\def\\##1{\nwix@id@uses ##1}#1}%
+ \fi}
+\newif\ifnw@hideunuseddefs\nw@hideunuseddefsfalse
+\def\nwopt@hideunuseddefs{\nw@hideunuseddefstrue}
+\def\nwopt@noidentxref{%
+ \let\nwidentdefs\@gobble
+ \let\nwidentuses\@gobble}
+\def\nw@underlinedefs{% {list with \nwixd, \nwixu}
+ \let\\=\relax\def\nw@comma{, }
+ \def\nwixd##1{\\\underline{\subpageref{##1}}\let\\\nw@comma}%
+ \def\nwixu##1{\\\subpageref{##1}\let\\\nw@comma}}
+
+\def\nw@indexline#1#2{%
+ {\indent {\Tt #1}: \nw@underlinedefs\@nameuse{nwixl@#2}\par}}
+
+\newenvironment{thenowebindex}{\parindent=-10pt \parskip=\z@
+ \advance\leftskip by 10pt
+ \advance\rightskip by 0pt plus1in\par\@afterindenttrue
+ \def\\##1{\nw@indexline##1}}{}
+\def\nowebindex{%
+ \@ifundefined{nwixs@i}%
+ {\@warning{The \string\nowebindex\space is empty}}%
+ {\begin{thenowebindex}\@nameuse{nwixs@i}\end{thenowebindex}}}
+\def\nowebindex@external{%
+ {\let\nwixadds@c=\@gobble
+ \def\nwixadds@i##1{\nw@indexline##1}%
+ \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}%
+ \begin{thenowebindex}\@input{\jobname.nwi}\end{thenowebindex}}}
+\def\nwixlogsorted#1#2{% list data
+ \@bsphack\if@filesw
+ \toks0={#2}\immediate\write\@auxout{\string\nwixadds{#1}{\the\toks0}}
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+\def\nwixadds#1#2{%
+ \@ifundefined{nwixs@#1}%
+ {\global\@namedef{nwixs@#1}{\\{#2}}}%
+ {\expandafter\nwix@cons\csname nwixs@#1\endcsname{\\{#2}}}}
+\let\nwixaddsx=\@gobbletwo
+\def\nwopt@externalindex{%
+ \ifx\nwixadds\@gobbletwo % already called
+ \else
+ \let\nwixaddsx=\nwixadds \let\nwixadds=\@gobbletwo
+ \let\nowebindex=\nowebindex@external
+ \let\nowebchunks=\nowebchunks@external
+ \fi}
+\def\nowebchunks{%
+ \@ifundefined{nwixs@c}%
+ {\@warning{The are no \string\nowebchunks}}%
+ {\begin{thenowebchunks}\@nameuse{nwixs@c}\end{thenowebchunks}}}
+\def\nowebchunks@external{%
+ {\let\nwixadds@i=\@gobble
+ \def\nwixadds@c##1{\nw@onechunk##1}%
+ \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}%
+ \begin{thenowebchunks}\@input{\jobname.nwi}\end{thenowebchunks}}}
+ \@namedef{r@nw@notdef}{{0}{(\@nwlangdepnvd)}}
+\def\nw@chunkunderlinedefs{% {list of labels with \nwixd, \nwixu}
+ \let\\=\relax\def\nw@comma{, }
+ \def\nwixd##1{\\\underline{\subpageref{##1}}\let\\\nw@comma}%
+ \def\nwixu##1{\\\subpageref{##1}\let\\\nw@comma}}
+\def\nw@onechunk#1#2#3{% {name}{label of first definition}{list with \nwixd, \nwixu}
+ \@ifundefined{r@#2}{}{%
+ \indent\LA #1~{\nwtagstyle\subpageref{#2}}\RA
+ \if@nwlongchunks{~\nw@chunkunderlinedefs#3}\fi\par}}
+\newenvironment{thenowebchunks}{\vskip3pt
+ \parskip=\z@\parindent=-10pt \advance\leftskip by 10pt
+ \advance\rightskip by 0pt plus10pt \@afterindenttrue
+ \def\\##1{\nw@onechunk##1}}{}
+\newif\if@nwlongchunks
+\@nwlongchunksfalse
+\let\nwopt@longchunks\@nwlongchunkstrue
+\newcommand\@nw@hyper@ref{\hyperreference} % naras
+\newcommand\@nw@hyper@anc{\blindhyperanchor} % naras
+\newcommand\@nw@hyperref@ref[2]{\hyperlink{noweb.#1}{#2}} % nr
+\newcommand\@nw@hyperref@anc[1]{\hypertarget{noweb.#1}{\relax}} % nr
+%%\renewcommand\@nw@hyperref@ref[2]{{#2}} % nr
+%%\renewcommand\@nw@hyperref@anc[1]{} % nr
+\newcommand\nwhyperreference{%
+ \@ifundefined{hyperlink}
+ {\@ifundefined{hyperreference}
+ {\global\let\nwhyperreference\@gobble}
+ {\global\let\nwhyperreference\@nw@hyper@ref}}
+ {\global\let\nwhyperreference\@nw@hyperref@ref}%
+ \nwhyperreference
+}
+
+\newcommand\nwblindhyperanchor{%
+ \@ifundefined{hyperlink}
+ {\@ifundefined{hyperreference}
+ {\global\let\nwblindhyperanchor\@gobble}
+ {\global\let\nwblindhyperanchor\@nw@hyper@anc}}
+ {\global\let\nwblindhyperanchor\@nw@hyperref@anc}%
+ \nwblindhyperanchor
+}
+\newcommand\nwanchorto{%
+ \begingroup\let\do\@makeother\dospecials
+ \catcode`\{=1 \catcode`\}=2 \nw@anchorto}
+\newcommand\nw@anchorto[1]{\endgroup\def\nw@next{#1}\nw@anchortofin}
+\newcommand\nw@anchortofin[1]{#1\footnote{See URL \texttt{\nw@next}.}}
+\let\nwanchorname\@gobble
+\newif\ifhtml
+\htmlfalse
+\let\nwixident=\relax
+\def\nwopt@english{%
+ \def\@nwlangdepdef{This definition is continued}%
+ \def\@nwlangdepcud{This code is used}%
+ \def\@nwlangdeprtc{Root chunk (not used in this document)}%
+ \def\@nwlangdepcwf{This code is written to file}%
+ \def\@nwlangdepchk{chunk}%
+ \def\@nwlangdepchks{chunks}%
+ \def\@nwlangdepin{in}%
+ \def\@nwlangdepand{and}%
+ \def\@nwlangdepuss{Uses}%
+ \def\@nwlangdepusd{used}%
+ \def\@nwlangdepnvu{never used}%
+ \def\@nwlangdepdfs{Defines}%
+ \def\@nwlangdepnvd{never defined}%
+}
+\let\nwopt@american\nwopt@english
+\def\nwopt@icelandic{%
+ \def\@nwlangdepdef{This definition is continued}%
+ \def\@nwlangdepcud{This code is used}%
+ \def\@nwlangdeprtc{Root chunk (not used in this document)}%
+ \def\@nwlangdepcwf{This code is written to file}%
+ \def\@nwlangdepchk{kóða}%
+ \def\@nwlangdepchks{kóðum}%
+ \def\@nwlangdepin{í}%
+ \def\@nwlangdepand{og}%
+ \def\@nwlangdepuss{Notar}%
+ \def\@nwlangdepusd{notað}%
+ \def\@nwlangdepnvu{hvergi notað}%
+ \def\@nwlangdepdfs{Skilgreinir}%
+ \def\@nwlangdepnvd{hvergi skilgreint}%
+}
+\def\nwopt@portuges{%
+ \def\@nwlangdepdef{Defini\c{c}\~ao continuada em}%
+ % This definition is continued
+ \def\@nwlangdepcud{C\'odigo usado em}%
+ % This code is used
+ \def\@nwlangdeprtc{Fragmento de topo (sem uso no documento)}%
+ % Root chunk (not used in this document)
+ \def\@nwlangdepcwf{Este c\'odigo foi escrito no ficheiro}%
+ % This code is written to file
+ \def\@nwlangdepchk{fragmento}%
+ % chunk
+ \def\@nwlangdepchks{fragmentos}%
+ % chunks
+ \def\@nwlangdepin{no(s)}%
+ % in
+ \def\@nwlangdepand{e}%
+ % and
+ \def\@nwlangdepuss{Usa}%
+ % Uses
+ \def\@nwlangdepusd{usado}%
+ % used
+ \def\@nwlangdepnvu{nunca usado}%
+ % never used
+ \def\@nwlangdepdfs{Define}%
+ % Defines
+ \def\@nwlangdepnvd{nunca definido}%
+ % never defined
+}
+\def\nwopt@frenchb{%
+ \def\@nwlangdepdef{Suite de la d\'efinition}%
+ % This definition is continued
+ \def\@nwlangdepcud{Ce code est employ\'e}%
+ % This code is used
+ \def\@nwlangdeprtc{Morceau racine (pas employ\'e dans ce document)}%
+ % Root chunk (not used in this document)
+ \def\@nwlangdepcwf{Ce code est \'ecrit dans le fichier}%
+ % This code is written to file
+ \def\@nwlangdepchk{le morceau}%
+ % chunk
+ \def\@nwlangdepchks{les morceaux}%
+ % chunks
+ \def\@nwlangdepin{dans}%
+ % in
+ \def\@nwlangdepand{et}%
+ % and
+ \def\@nwlangdepuss{Utilise}%
+ % Uses
+ \def\@nwlangdepusd{utilis\'{e}}%
+ % used
+ \def\@nwlangdepnvu{jamais employ\'{e}}%
+ % never used
+ \def\@nwlangdepdfs{D\'{e}finit}%
+ % Defines
+ % Cannot use the accent here: \def\@nwlangdepnvd{jamais d\'{e}fini}%
+ \def\@nwlangdepnvd{jamais defini}%
+ % never defined
+}
+\let\nwopt@french\nwopt@frenchb
+\def\nwopt@german{%
+ \def\@nwlangdepdef{Diese Definition wird fortgesetzt}%
+ % This definition is continued
+ \def\@nwlangdepcud{Dieser Code wird benutzt}%
+ % This code is used
+ \def\@nwlangdeprtc{Hauptteil (nicht in diesem Dokument benutzt)}%
+ % Root chunk (not used in this document)
+ \def\@nwlangdepcwf{Geh\"ort in die Datei}%
+ % This code is written to file
+ \def\@nwlangdepchk{Abschnitt}%
+ % chunk
+ \def\@nwlangdepchks{den Abschnitten}%
+ % chunks
+ \def\@nwlangdepin{in}%
+ % in
+ \def\@nwlangdepand{und}%
+ % and
+ \def\@nwlangdepuss{Benutzt}%
+ % Uses
+ \def\@nwlangdepusd{benutzt}%
+ % used
+ \def\@nwlangdepnvu{nicht benutzt}%
+ % never used
+ \def\@nwlangdepdfs{Definiert}%
+ % Defines
+ \def\@nwlangdepnvd{nicht definiert}%
+ % never defined
+}
+\def\nwopt@german{%
+ \def\@nwlangdepdef{Diese Definition wird fortgesetzt}%
+ % This definition is continued
+ \def\@nwlangdepcud{Dieser Code wird benutzt}%
+ % This code is used
+ \def\@nwlangdeprtc{Hauptteil (nicht in diesem Dokument benutzt)}%
+ % Root chunk (not used in this document)
+ \def\@nwlangdepcwf{Dieser Code erzeugt die Datei}
+ % This code generates the file
+ \def\@nwlangdepchk{Teil}%
+ % chunk
+ \def\@nwlangdepchks{Teils}%
+ % chunks
+ \def\@nwlangdepin{im}%
+ % in
+ \def\@nwlangdepand{und}%
+ % and
+ \def\@nwlangdepuss{Benutzt}%
+ % Uses
+ \def\@nwlangdepusd{benutzt}%
+ % used
+ \def\@nwlangdepnvu{nicht benutzt}%
+ % never used
+ \def\@nwlangdepdfs{Definiert}%
+ % Defines
+ \def\@nwlangdepnvd{nicht definiert}%
+ % never defined
+}
+\let\nwopt@ngerman\nwopt@german
+\ifx\languagename\undefined % default is English
+ \noweboptions{english}
+\else
+ \@ifundefined{nwopt@\languagename}
+ {\noweboptions{english}}
+ {\expandafter\noweboptions\expandafter{\languagename}}
+\fi
diff --git a/web/noweb/src/tex/nwkernel.tex b/web/noweb/src/tex/nwkernel.tex
new file mode 100644
index 0000000000..f196628254
--- /dev/null
+++ b/web/noweb/src/tex/nwkernel.tex
@@ -0,0 +1,83 @@
+\def\LL{<<}
+\def\GG{>>}
+\def\LLS{[[}
+\def\RRS{]]}
+
+% make \hsize in code sufficient for 88 columns
+\setbox0=\hbox{\tt m}
+\newdimen\codehsize
+\codehsize=91\wd0 % 88 columns wasn't enough; I don't know why
+\newdimen\codemargin
+\codemargin=0pt
+
+\chardef\other=12
+\def\setupcode{%
+ \chardef\\=`\\
+ \chardef\{=`\{
+ \chardef\}=`\}
+ \catcode`\$=\other
+ \catcode`\&=\other
+ \catcode`\#=\other
+ \catcode`\%=\other
+ \catcode`\~=\other
+ \catcode`\_=\other
+ \catcode`\^=\other
+ \obeyspaces\Tt
+}
+{\catcode`\^^M=\active % make CR an active character
+ \gdef\newlines{\catcode`\^^M=\active % make CR an active character
+ \def^^M{\par\startline}}%
+ \gdef\eatline#1^^M{\relax}%
+}
+%%% DON'T \gdef^^M{\par\startline}}% in case ^^M appears in a \write
+\def\startline{\noindent\hskip\parindent\ignorespaces}
+
+{\obeyspaces\global\let =\ } % from texbook, p 381
+\def\setupmodname{%
+ \catcode`\$=3
+ \catcode`\&=4
+ \catcode`\#=6
+ \catcode`\%=14
+ \catcode`\~=13
+ \catcode`\_=8
+ \catcode`\^=7
+ \catcode`\ =10
+ \catcode`\^^M=5
+ \rm}
+\def\LA{\begingroup\setupmodname\it$\langle${}}
+\def\RA{\/$\rangle$\endgroup}
+\def\code{\leavevmode\begingroup\setupcode\newlines}
+\def\edoc{\endgroup}
+
+\newbox\equivbox
+\setbox\equivbox=\hbox{$\equiv$}
+\newbox\plusequivbox
+\setbox\plusequivbox=\hbox{$\mathord{+}\mathord{\equiv}$}
+% \moddef can't have an argument because there might be \code...\edoc
+\def\moddef{\leavevmode\kern-\codemargin\LA}
+\def\endmoddef{\RA\unhcopy\equivbox}
+\def\plusendmoddef{\RA\unhcopy\plusequivbox}
+
+\def\filename#1{\vfil\eject\mark{#1}}
+
+\def\chunklist{%
+\expandafter\errhelp\expandafter{I changed \noexpand\chunklist\space
+to \noexpand\nowebchunks. I'll try to avoid such incompatible changes
+in the future.}%
+\errmessage{Use \string\nowebchunks\space instead of \chunklist.}}
+\def\nowebchunks{\message{<Warning: You need noweave -x to use \string\nowebchunks>}}
+\def\nowebindex{\message{<Warning: You need noweave -idx to use \string\nowebindex>}}
+
+% here is support for the new-style (capitalized) font-changing commands
+% thanks to Dave Love
+\ifx\documentstyle\undefined
+ \let\Rm=\rm \let\Tt=\tt % plain
+\else\ifx\selectfont\undefined
+ \let\Rm=\rm \let\Tt=\tt % LaTeX OFSS
+\else % LaTeX NFSS
+ \def\Rm{\fontfamily\rmdefault \fontseries\default@series
+ \fontshape\default@shape \selectfont}
+ \def\Tt{\fontfamily\ttdefault \fontseries\default@series
+ \fontshape\default@shape \selectfont}
+\fi
+\fi
diff --git a/web/noweb/src/tex/nwmac.tex b/web/noweb/src/tex/nwmac.tex
new file mode 100644
index 0000000000..ec54fbce9d
--- /dev/null
+++ b/web/noweb/src/tex/nwmac.tex
@@ -0,0 +1,240 @@
+% nwmac.tex -- plain TeX support for noweb
+% DON'T read or edit this file! Use ...noweb-source/tex/support.nw instead.
+{\obeyspaces\global\let =\ } % from texbook, p 381
+\def\nwdocspar{\par\semifilbreak}
+\def\nwstartdeflinemarkup{\nobreak\hskip 1.5em plus 1fill\nobreak}
+\def\nwenddeflinemarkup{\nobreak\hskip \nwdefspace minus\nwdefspace\nobreak}
+\catcode`\@=11
+% scale cmbx10 instead of using cmbx12 because {\LaTeX} does, so fonts exist
+\font\twlbf=cmbx10 scaled \magstep1
+\font\frtbf=cmbx10 scaled \magstep2
+% These fonts don't work with xdvi!
+
+\advance\hoffset 0.5 true in
+\advance\hsize -1.5 true in
+\newdimen\textsize
+\textsize=\hsize
+\def\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}
+\long\def\ifundefined#1#2#3{%
+ \expandafter\ifx\csname#1\endcsname\relax
+ #2%
+ \else#3%
+ \fi}
+
+\ifundefined{myheadline}
+ {\headline={\hbox to \textsize{\tentt\firstmark\hfil\tenrm\today\hbox
+ to 4em{\hss\folio}}\hss}}
+ {\expandafter\headline\expandafter{\myheadline}}
+
+\ifundefined{myfootline}
+ {\footline={\hfil}}
+ {\expandafter\footline\expandafter{\myfootline}}
+\def\semifilbreak{\vskip0pt plus1.5in\penalty-200\vskip0pt plus -1.5in}
+\raggedbottom
+%
+% \chapcenter macro to produce nice centered chapter titles
+%
+\def\chapcenter{\leftskip=0.5 true in plus 4em minus 0.5 true in
+ \rightskip=\leftskip
+ \parfillskip=0pt \spaceskip=.3333em \xspaceskip=.5em
+ \pretolerance=9999 \tolerance=9999
+ \hyphenpenalty=9999 \exhyphenpenalty=9999}
+% \startsection{LEVEL}{INDENT}{BEFORESKIP}{AFTERSKIP}{STYLE}{HEADING}
+% #1 #2 #3 #4 #5 #6
+%
+% LEVEL: depth; e.g. part=0 chapter=1 sectino=2...
+% INDENT: indentation of heading from left margin
+% BEFORESKIP: skip before header
+% AFTERSKIP: skip after header
+% STYLE: style of heading; e.g.\bf
+% HEADING: heading of the sectino
+%
+\def\startsection#1#2#3#4#5#6{\par\vskip#3 plus 2in
+ \penalty-200\vskip 0pt plus -2in
+ \noindent{\leftskip=#2 \rightskip=0.5true in plus 4em minus 0.5 true in
+ \hyphenpenalty=9999 \exhyphenpenalty=9999
+ #5#6\par}\vskip#4%
+ {\def\code##1{[[}\def\edoc##1{]]}\message{[#6]}}
+ \settocparms{#1}
+ \def\themodtitle{#6}
+%%%% {\def\code{\string\code}\def\edoc{\string\edoc}%
+ \edef\next{\noexpand\write\cont{\tocskip
+ \tocline{\hskip\tocindent\tocstyle\relax\themodtitle}
+ {\noexpand\the\pageno}}}\next % write to toc
+ %}
+}
+\def\settocparms#1{
+ \count@=#1
+ \ifnum\count@<1
+ \def\tocskip{\vskip3ptplus1in\penalty-100
+ \vskip0ptplus-1in}%
+ \def\tocstyle{\bf}
+ \def\tocindent{0pt}
+ \else
+ \def\tocskip{}
+ \def\tocstyle{\rm}
+ \dimen@=2em \advance\count@ by \m@ne \dimen@=\count@\dimen@
+ \edef\tocindent{\the\dimen@}
+ \fi
+}
+\def\tocline#1#2{\line{{\ignorespaces#1}\leaders\hbox to .5em{.\hfil}\hfil
+ \hbox to1.5em{\hss#2}}}
+\def\section#1{\par \vskip3ex\noindent {\bf #1}\par\nobreak\vskip1ex\nobreak}
+\def\chapter#1{\vfil\eject\startsection{0}{0pt}{6ex}{3ex}{\frtbf\chapcenter}{#1}}
+\def\section#1{\startsection{1}{0pt}{4ex}{2ex}{\twlbf}{#1}}
+\def\subsection#1{\startsection{2}{0pt}{2ex}{1ex}{\bf}{#1}}
+\def\subsubsection#1{\startsection{3}{0pt}{1ex}{0.5ex}{\it}{#1}}
+\def\paragraph#1{\startsection{4}{0pt}{1.5ex}{0ex}{\it}{#1}}
+
+% make \hsize in code sufficient for 88 columns
+\setbox0=\hbox{\tt m}
+\newdimen\codehsize
+\codehsize=91\wd0 % 88 columns wasn't enough; I don't know why
+\newdimen\codemargin
+\codemargin=0pt
+\newdimen\nwdefspace
+\nwdefspace=\codehsize
+% need to use \textwidth in {\LaTeX} to handle styles with
+% non-standard margins (David Bruce). Don't know why we sometimes
+% wanted \hsize. 27 August 1997.
+%% \advance\nwdefspace by -\hsize\relax
+\ifx\textwidth\undefined
+ \advance\nwdefspace by -\hsize\relax
+\else
+ \advance\nwdefspace by -\textwidth\relax
+\fi
+\chardef\other=12
+\def\setupcode{%
+ \chardef\\=`\\
+ \chardef\{=`\{
+ \chardef\}=`\}
+ \catcode`\$=\other
+ \catcode`\&=\other
+ \catcode`\#=\other
+ \catcode`\%=\other
+ \catcode`\~=\other
+ \catcode`\_=\other
+ \catcode`\^=\other
+ \catcode`\"=\other % fixes problem with german.sty
+ \obeyspaces\Tt
+}
+\def\nwendquote{\relax\ifhmode\spacefactor=1000 \fi}
+{\catcode`\^^M=\active % make CR an active character
+ \gdef\newlines{\catcode`\^^M=\active % make CR an active character
+ \def^^M{\par\startline}}%
+ \gdef\eatline#1^^M{\relax}%
+}
+%%% DON'T \gdef^^M{\par\startline}}% in case ^^M appears in a \write
+\def\startline{\noindent\hskip\parindent\ignorespaces}
+\def\nwnewline{\ifvmode\else\hfil\break\leavevmode\hbox{}\fi}
+\def\setupmodname{%
+ \catcode`\$=3
+ \catcode`\&=4
+ \catcode`\#=6
+ \catcode`\%=14
+ \catcode`\~=13
+ \catcode`\_=8
+ \catcode`\^=7
+ \catcode`\ =10
+ \catcode`\^^M=5
+ \let\{\lbrace
+ \let\}\rbrace
+ % bad news --- don't know what catcode to give "
+ \Rm}
+\def\LA{\begingroup\maybehbox\bgroup\setupmodname\It$\langle$}
+\def\RA{\/$\rangle$\egroup\endgroup}
+\def\code{\leavevmode\begingroup\setupcode\newlines}
+\def\edoc{\endgroup}
+\let\maybehbox\relax
+\newbox\equivbox
+\setbox\equivbox=\hbox{$\equiv$}
+\newbox\plusequivbox
+\setbox\plusequivbox=\hbox{$\mathord{+}\mathord{\equiv}$}
+% \moddef can't have an argument because there might be \code...\edoc
+\def\moddef{\leavevmode\kern-\codemargin\LA}
+\def\endmoddef{\RA\ifmmode\equiv\else\unhcopy\equivbox\fi
+ \nobreak\hfill\nobreak}
+\def\plusendmoddef{\RA\ifmmode\mathord{+}\mathord{\equiv}\else\unhcopy\plusequivbox\fi
+ \nobreak\hfill\nobreak}
+\def\chunklist{%
+\errhelp{I changed \chunklist to \nowebchunks.
+I'll try to avoid such incompatible changes in the future.}%
+\errmessage{Use \string\nowebchunks\space instead of \string\chunklist}}
+\def\nowebchunks{\message{<Warning: You need noweave -x to use \string\nowebchunks>}}
+\def\nowebindex{\message{<Warning: You need noweave -index to use \string\nowebindex>}}
+% here is support for the new-style (capitalized) font-changing commands
+% thanks to Dave Love
+\ifx\documentstyle\undefined
+ \let\Rm=\rm \let\It=\it \let\Tt=\tt % plain
+\else\ifx\selectfont\undefined
+ \let\Rm=\rm \let\It=\it \let\Tt=\tt % LaTeX OFSS
+\else % LaTeX NFSS
+ \def\Rm{\reset@font\rm}
+ \def\It{\reset@font\it}
+ \def\Tt{\reset@font\tt}
+ \def\Bf{\reset@font\bf}
+\fi\fi
+\ifx\reset@font\undefined \let\reset@font=\relax \fi
+\def\nwbackslash{\char92}
+\def\nwlbrace{\char123}
+\def\nwrbrace{\char125}
+
+\def\nwfilename#1{\vfil\eject\mark{#1}}
+
+\def\nwbegindocs#1{\filbreak}
+\def\nwenddocs{\par}
+\def\nwbegincode#1{\par\nobreak
+ \begingroup\setupcode\newlines\parindent=0pt\parskip=0pt
+ %\let\oendmoddef=\endmoddef \let\oplusendmoddef=\plusendmoddef
+ %\def\endmoddef{\oendmoddef\par}\def\plusendmoddef{\oplusendmoddef\par}%
+ \let\onwenddeflinemarkup=\nwenddeflinemarkup
+ \def\nwenddeflinemarkup{\onwenddeflinemarkup\par}%
+ \hsize=\codehsize\noindent\bchack}
+\def\nwendcode{\endgroup}
+{\catcode`\^^M=\active % make CR an active character
+ \gdef\bchack#1^^M{\relax#1}%
+}
+\edef\contentsfile{\jobname.toc } % file that gets table of contents info
+\def\readcontents{\expandafter\input \contentsfile}
+
+\newwrite\cont
+\openout\cont=\contentsfile
+\write\cont{\string\catcode`\string\@=11}% a hack to make contents
+ % take stuff in plain.tex
+\def\bye{%
+ \write\cont{}% ensure that the contents file isn't empty
+ \closeout\cont
+ \vfil\eject\pageno=-1 % new page causes contents to be really closed
+ \topofcontents\readcontents\botofcontents
+ \vfil\eject\end}
+\def\topofcontents{\vfil\mark{{\bf Contents}}}
+\def\botofcontents{}
+\let\em=\it
+% used to produce an itemized (bulleted) list in plain {\TeX}
+% such lists can be nested
+% mostly useful with WEB
+
+% Usage:
+% \itemize
+% \item First thing
+% \item second thing
+% \enditemize
+
+\newcount\listlevel
+\listlevel=0
+\newdimen\itemwidth
+\itemwidth=3em
+
+\def\itemize{\begingroup\advance\listlevel by1
+ \def\item{\par\noindent
+ \raise2pt\llap{$\scriptstyle\bullet$\ }\ignorespaces}%
+ \def\nameditem##1{\par\noindent
+ \llap{\rlap{##1}\hskip\itemwidth}\ignorespaces}%
+ \par\advance\leftskip by\itemwidth\advance\rightskip by0.5\itemwidth}
+\def\enditemize{\par\endgroup\noindent\ignorespaces}
+
+\let\begindocument=\relax
+\catcode`\@=12
diff --git a/web/noweb/src/tex/support.nw b/web/noweb/src/tex/support.nw
new file mode 100644
index 0000000000..8db76dbaff
--- /dev/null
+++ b/web/noweb/src/tex/support.nw
@@ -0,0 +1,1993 @@
+% -*- mode: Noweb; noweb-code-mode: tex-mode -*-
+\documentclass[twoside]{article}
+\usepackage[hypertex]{hyperref}
+\usepackage{url}
+\usepackage{noweb}
+\pagestyle{noweb}
+\noweboptions{longchunks,smallcode}
+\title{{\TeX} and {\LaTeX} support for {\tt noweb}}
+\author{Norman Ramsey}
+\newcommand{\stylehook}{\marginpar{\raggedright\sl Style hook}}
+\begin{document}
+\maketitle
+\tableofcontents
+@
+This document describes the {\TeX} code that supports {\tt noweave}
+and {\tt noweb}. Those interested in customizing their output should
+focus on Section~\ref{section:sty}.
+Hooks you can easily use (apart from those provided by
+[[\noweboptions]]) are indicated by marginal notes.
+This file contains both plain {\TeX} and {\LaTeX} support:
+<<nwmac.tex>>=
+% nwmac.tex -- plain TeX support for noweb
+% DON'T read or edit this file! Use ...noweb-source/tex/support.nw instead.
+<<noweb.sty>>=
+% noweb.sty -- LaTeX support for noweb
+% DON'T read or edit this file! Use ...noweb-source/tex/support.nw instead.
+@
+
+\section{Basic {\TeX} support for {\tt noweb}}
+This basic code is used for both {\TeX} and {\LaTeX}.
+The first step is to define [[\codehsize]], which is the width in
+which code is set, and [[\codemargin]], which is the amount by which
+it is indented.\stylehook
+<<kernel>>=
+% make \hsize in code sufficient for 88 columns
+\setbox0=\hbox{\tt m}
+\newdimen\codehsize
+\codehsize=91\wd0 % 88 columns wasn't enough; I don't know why
+\newdimen\codemargin
+\codemargin=0pt
+@
+[[\defspace]] is the space we would like on the right of navigational info
+that appears on definition lines, so that it lines up with the text above
+and below.
+<<kernel>>=
+\newdimen\nwdefspace
+\nwdefspace=\codehsize
+% need to use \textwidth in {\LaTeX} to handle styles with
+% non-standard margins (David Bruce). Don't know why we sometimes
+% wanted \hsize. 27 August 1997.
+%% \advance\nwdefspace by -\hsize\relax
+\ifx\textwidth\undefined
+ \advance\nwdefspace by -\hsize\relax
+\else
+ \advance\nwdefspace by -\textwidth\relax
+\fi
+@
+Most code is set in an environment in which [[\setupcode]] has been
+executed.
+In this environment, only [[\]], [[{]], and [[}]] have their usual
+categories; every other character represents itself.
+Appropriate [[\chardef]]s ensure that the special characters can be
+escaped with a backslash.
+<<kernel>>=
+\chardef\other=12
+\def\setupcode{%
+ \chardef\\=`\\
+ \chardef\{=`\{
+ \chardef\}=`\}
+ \catcode`\$=\other
+ \catcode`\&=\other
+ \catcode`\#=\other
+ \catcode`\%=\other
+ \catcode`\~=\other
+ \catcode`\_=\other
+ \catcode`\^=\other
+ \catcode`\"=\other % fixes problem with german.sty
+ \obeyspaces\Tt
+}
+@
+[[\nwendquote]] is called after quoted code.
+It resets the spacefactor
+<<kernel>>=
+\def\nwendquote{\relax\ifhmode\spacefactor=1000 \fi}
+@
+[[\eatline]] is used to consume newlines that should be ignored,
+for example, the newlines at the end of [[@ %def ]]{\em identifiers} lines.
+I can't remember what [[\startline]] or [[\newlines]] are for; I don't
+think {\tt noweave} ever emits them.
+<<kernel>>=
+{\catcode`\^^M=\active % make CR an active character
+ \gdef\newlines{\catcode`\^^M=\active % make CR an active character
+ \def^^M{\par\startline}}%
+ \gdef\eatline#1^^M{\relax}%
+}
+%%% DON'T \gdef^^M{\par\startline}}% in case ^^M appears in a \write
+\def\startline{\noindent\hskip\parindent\ignorespaces}
+\def\nwnewline{\ifvmode\else\hfil\break\leavevmode\hbox{}\fi}
+@
+
+Within a code environment, it may be necessary to restore the
+category codes in order to set a module (chunk) name.
+This hack doesn't properly restore [["]] for use in {\tt german.sty}.
+<<kernel>>=
+\def\setupmodname{%
+ \catcode`\$=3
+ \catcode`\&=4
+ \catcode`\#=6
+ \catcode`\%=14
+ \catcode`\~=13
+ \catcode`\_=8
+ \catcode`\^=7
+ \catcode`\ =10
+ \catcode`\^^M=5
+ \let\{\lbrace
+ \let\}\rbrace
+ % bad news --- don't know what catcode to give "
+ \Rm}
+@ \sublabel{ref:fred}
+@
+Setting up the space code has to be done differently for {\TeX} and
+{\LaTeX}, so as not to screw up {\LaTeX}'s \texttt{verbatim} package.
+(Fix from Rafael Laboissiere.)
+<<nwmac.tex>>=
+{\obeyspaces\global\let =\ } % from texbook, p 381
+<<noweb.sty>>=
+{\obeyspaces\AtBeginDocument{\global\let =\ }} % from texbook, p 381
+@
+
+{\tt noweave} brackets uses of chunk names with [[\LA]] and [[\RA]], which
+handle the angle brackets, font, and environment.
+
+As it stands, chunk names can be broken across lines (or pages). This
+could result in unnecessary page breaks in code
+(c.f.~p.~\pageref{sec:pagebreaking}). [[\let\\maybehbox=\mbox]] to
+\stylehook
+avoid breaking them
+(or to make them work in math mode); this is done in code chunks, but could be done
+in general.
+<<kernel>>=
+\def\LA{\begingroup\maybehbox\bgroup\setupmodname\It$\langle$}
+\def\RA{\/$\rangle$\egroup\endgroup}
+\def\code{\leavevmode\begingroup\setupcode\newlines}
+\def\edoc{\endgroup}
+\let\maybehbox\relax
+@
+
+[[\equivbox]] and [[\plusequivbox]] are used to set the
+``\unhcopy\equivbox''
+and ``\unhcopy\plusequivbox'' that open a chunk definition or its
+continuation.
+{\tt noweave} brackets definitions of chunk names with [[\moddef]] and
+either [[\endmoddef]] or [[\plusendmoddef]].
+<<kernel>>=
+\newbox\equivbox
+\setbox\equivbox=\hbox{$\equiv$}
+\newbox\plusequivbox
+\setbox\plusequivbox=\hbox{$\mathord{+}\mathord{\equiv}$}
+% \moddef can't have an argument because there might be \code...\edoc
+\def\moddef{\leavevmode\kern-\codemargin\LA}
+\def\endmoddef{\RA\ifmmode\equiv\else\unhcopy\equivbox\fi
+ \nobreak\hfill\nobreak}
+\def\plusendmoddef{\RA\ifmmode\mathord{+}\mathord{\equiv}\else\unhcopy\plusequivbox\fi
+ \nobreak\hfill\nobreak}
+@
+Within a code environment, margin tags might be used to mark sub-page
+numbers in the margins, separated by [[\nwmarginglue]].\stylehook
+The interaction with [[\moddef]] involves tricky kerning.
+The tag itself is displayed using [[\nwthemargintag]]
+<<noweb.sty>>=
+\def\nwopt@nomargintag{\let\nwmargintag=\@gobble}
+\def\nwopt@margintag{%
+ \def\nwmargintag##1{\leavevmode\llap{##1\kern\nwmarginglue\kern\codemargin}}}
+\def\nwopt@margintag{%
+ \def\nwmargintag##1{\leavevmode\kern-\codemargin\nwthemargintag{##1}\kern\codemargin}}
+\def\nwthemargintag#1{\llap{#1\kern\nwmarginglue}}
+\nwopt@margintag
+\newdimen\nwmarginglue
+\nwmarginglue=0.3in
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B margintag
+Put the sub-page number (tag) of each code-chunk definition in the
+left margin. (Default)
+.TP
+.B nomargintag
+Don't use margin tags.
+@ \fi
+[[\nwtagstyle]] determines the style in which tags are displayed.\stylehook
+<<noweb.sty>>=
+\def\nwtagstyle{\footnotesize\Rm}
+@
+<<kernel>>=
+\def\chunklist{%
+\errhelp{I changed \chunklist to \nowebchunks.
+I'll try to avoid such incompatible changes in the future.}%
+\errmessage{Use \string\nowebchunks\space instead of \string\chunklist}}
+\def\nowebchunks{\message{<Warning: You need noweave -x to use \string\nowebchunks>}}
+\def\nowebindex{\message{<Warning: You need noweave -index to use \string\nowebindex>}}
+@ We have to be careful with font-changing in the presence of
+different font-selection schemes. In the \LaTeX{} New Font Selection
+Scheme something like [[\it\tt]] will attempt to use an italic
+typewriter font. Thus we define new commands like [[\Tt]] which will
+work with both the Plain and old and new \LaTeX{} schemes. (Note that
+NFSS will be standard in the next version of \LaTeX.) A problem with
+these definitions arises with NFSS: in math mode the won't work
+unless the {\tt oldlfont} backwards-compatibility option is in effect.
+For the moment, you can get round this by using [[\mbox]].
+
+If you wanted code set in a different font, you could re-define
+[[\Tt]].\stylehook{} [\LaTeX2e actually behaves like OFSS, but the
+extra [[\reset@font]] does no harm.]
+<<kernel>>=
+% here is support for the new-style (capitalized) font-changing commands
+% thanks to Dave Love
+\ifx\documentstyle\undefined
+ \let\Rm=\rm \let\It=\it \let\Tt=\tt % plain
+\else\ifx\selectfont\undefined
+ \let\Rm=\rm \let\It=\it \let\Tt=\tt % LaTeX OFSS
+\else % LaTeX NFSS
+ \def\Rm{\reset@font\rm}
+ \def\It{\reset@font\it}
+ \def\Tt{\reset@font\tt}
+ \def\Bf{\reset@font\bf}
+\fi\fi
+\ifx\reset@font\undefined \let\reset@font=\relax \fi
+@
+\clearpage
+\section{The {\tt noweb} document-style option for {\LaTeX}}
+\label{section:sty}
+{\LaTeX} support begins with the kernel shown above.
+<<noweb.sty>>=
+<<kernel>>
+@
+\subsection{Support for noweb options}
+<<noweb.sty>>=
+\def\noweboptions#1{%
+ \def\@nwoptionlist{#1}%
+ \@for\@nwoption:=\@nwoptionlist\do{%
+ \@ifundefined{nwopt@\@nwoption}{%
+ \@latexerr{There is no such noweb option as '\@nwoption'}\@eha}{%
+ \csname nwopt@\@nwoption\endcsname}}}
+@
+\subsection{Adjusting placement of code on the page}
+{\LaTeX} requires a larger [[\codehsize]] because
+code is indented by [[\codemargin]].\stylehook
+<<noweb.sty>>=
+\codemargin=10pt
+\advance\codehsize by \codemargin % make room for indentation of code
+\advance\nwdefspace by \codemargin % and fix adjustment for def/use
+\def\setcodemargin#1{%
+ \advance\codehsize by -\codemargin % make room for indentation of code
+ \advance\nwdefspace by -\codemargin % and fix adjustment for def/use
+ \codemargin=#1
+ \advance\codehsize by \codemargin % make room for indentation of code
+ \advance\nwdefspace by \codemargin % and fix adjustment for
+ % def/use
+}
+@
+[[\noweboptions{shift}]] is used to shift the whole page left to make room for
+the wide code lines.
+It may be emitted by {\tt noweave -shift}, or it might be given by a user.
+<<noweb.sty>>=
+\def\nwopt@shift{%
+ \dimen@=-0.8in
+ \if@twoside % Values for two-sided printing:
+ \advance\evensidemargin by \dimen@
+ \else % Values for one-sided printing:
+ \advance\evensidemargin by \dimen@
+ \advance\oddsidemargin by \dimen@
+ \fi
+% \advance \marginparwidth -\dimen@
+}
+\let\nwopt@noshift\@empty
+@
+
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B shift
+Shift text to the left so that long code lines won't extend
+off the right-hand side of the page.
+@ \fi
+
+\subsection{Page-breaking strategy}\label{sec:pagebreaking}
+
+We want to insert penalties aiming for:
+\begin{enumerate}
+\item
+No page breaks in the middle of a code chunk unless necessary to avoid
+an overfull vbox;
+\item
+Documentation immediately preceding a code chunk should appear on
+the same page as that code chunk unless doing so would violate rule 1.
+\end{enumerate}
+[[\filbreak]] is useful for this sort of thing (see {\em The \TeX
+ book\/}) and is used to encourage breaks at the right places between
+chunks. Appropriate penalties are inserted elsewhere, between code
+lines in particular.
+
+\subsection{Environments for setting code}
+
+[[\nwbegincode]] and [[\nwendcode]] are used by {\tt noweave} to bracket
+code chunks.
+The [[webcode]] environment is intended for users who want to paste
+{\tt noweave} output into papers.
+
+The definition of [[\nwbegincode]] is based on the verbatim
+implementation in {\tt verbatim.sty}, which will, presumably be in the
+next version of \LaTeX\@. One thing it does differently, apart from
+the catcode changes is setting [[\linewidth]]; this will avoid some
+overfull hboxen when the code lines are too long, but the lines won't
+be broken anyhow (even within chunk names because of the
+[[\maybehbox]] definition).
+<<noweb.sty>>=
+\def\nwbegincode#1{%
+ \begingroup
+ <<[[\nwbegincode]] separation and penalties>>
+ \@begincode }
+\def\nwendcode{\endtrivlist \endgroup \filbreak} % keeps code on 1 page
+
+\newenvironment{webcode}{%
+ \@begincode
+}{%
+ \endtrivlist}
+@ This is just common code between [[\nwbegincode]] and [[webcode]].
+<<noweb.sty>>=
+\def\@begincode{%
+ <<[[\trivlist]] clich\'e (\`a la {\Tt verbatim})>>
+ \linewidth\codehsize
+ <<[[\obeylines]] setup>>
+ <<zap ligatures, fix spaces>>
+ \nowebsize \setupcode
+ \let\maybehbox\mbox }
+@ \iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B smallcode
+Set code in
+.I LaTeX
+.B "\\\\small"
+font instead of
+.B "\\\\normalsize."
+Similar options exist for all the
+.I LaTeX
+size-changing commands.
+@ \fi
+@ [[\nowebsize]] governs the size at which code is set; users who want
+to minimize code can [[\let\nowebsize=\small]].
+Slitex users should try
+\begin{quote}
+[[\def\nowebsize{\normalsize\baselineskip=20pt \parskip=5pt }]]
+\end{quote}
+to avoid code lines that are too far apart.
+[[\nwcodetopsep]] is
+the glue placed before code chunks.\stylehook
+<<noweb.sty>>=
+ \newskip\nwcodetopsep \nwcodetopsep = 3pt plus 1.2pt minus 1pt
+ \let\nowebsize=\normalsize
+ \def\nwopt@tinycode{\let\nowebsize=\tiny}
+ \def\nwopt@footnotesizecode{\let\nowebsize=\footnotesize}
+ \def\nwopt@scriptsizecode{\let\nowebsize=\scriptsize}
+ \def\nwopt@smallcode{\let\nowebsize=\small}
+ \def\nwopt@normalsizecode{\let\nowebsize=\normalsize}
+ \def\nwopt@largecode{\let\nowebsize=\large}
+ \def\nwopt@Largecode{\let\nowebsize=\Large}
+ \def\nwopt@LARGEcode{\let\nowebsize=\LARGE}
+ \def\nwopt@hugecode{\let\nowebsize=\huge}
+ \def\nwopt@Hugecode{\let\nowebsize=\Huge}
+@ Maybe the penalties ought to be parameters\dots
+<<[[\nwbegincode]] separation and penalties>>=
+ \topsep \nwcodetopsep
+ \@beginparpenalty \@highpenalty
+ \@endparpenalty -\@highpenalty
+@
+The [[\trivlist]] clich\'e isn't quite a clich\'e because we adjust
+[[\leftskip]] for indentation by [[\codemargin]] and adjust
+[[\rightskip]] to allow lines up to [[\codehsize]] long without
+overfull boxen
+($\mbox{[[\codehsize]]}=\mbox{[[\hsize]]}+\mbox{[[\rightskip]]}$).
+Note that [[\hsize]] isn't altered.
+<<[[\trivlist]] clich\'e (\`a la {\Tt verbatim})>>=
+ \trivlist \item[]%
+ \leftskip\@totalleftmargin \advance\leftskip\codemargin
+ \rightskip\hsize \advance\rightskip -\codehsize
+ \parskip\z@ \parindent\z@ \parfillskip\@flushglue
+@ The penalty inserted between verbatim lines would normally be
+[[\interlinepenalty]], but we want to prohibit breaks there.
+@
+Note the bug lurking somewhere in this code, as reported by Steven Ooms:
+\begin{quote}
+I have some lay-out
+problems in the documentation chunks. When using the (La)TeX commands
+[[\hline]] or [[\vtop]] the right margin is always extended far beyond the page
+margin after the first code chunk has been typeset. I'm still looking for
+the exact cause of it, but to me it seems that LaTeX supposes for those
+commands that the line width for the documentation chunk is as large as that
+for code chunks, which isn't true in reality.
+\end{quote}
+@
+<<[[\obeylines]] setup>>=
+ \@@par
+ \def\par{\leavevmode\null \@@par \penalty\nwcodepenalty}%
+ \obeylines
+@ [[\nwcodepenalty]] is the penalty for breaking between lines in a
+code chunk. If you set it to 10000, code will never be broken across
+pages.\stylehook{} I guess this should be settable in [[\noweboptions]].
+<<noweb.sty>>=
+\newcount\nwcodepenalty \nwcodepenalty=\@highpenalty
+@
+The cursing chunk accounts for the addition of a mess of characters
+to those reset by [[\@noligs]] in \LaTeX2e.
+<<zap ligatures, fix spaces>>=
+ \@noligs <<make all those damn active characters ``other''>>
+ \setupcode \frenchspacing \@vobeyspaces
+@
+We can't make [[`]] ``other,'' because then we'll get ligatures.
+(Why Don put these ligatures in the [[\tt]] font I wish I knew.)
+But we'll step on all the others.
+<<make all those damn active characters ``other''>>=
+ \ifx\verbatim@nolig@list\undefined\else
+ \let\do=\nw@makeother \verbatim@nolig@list \do@noligs\`
+ \fi
+<<noweb.sty>>=
+\def\nw@makeother#1{\catcode`#1=12 }
+@
+{\tt noweave} uses [[\nwbegindocs{nnn}]] and [[\nwenddocs]] to bracket
+documentation chunks.
+If a documentation chunk does not continue the current paragraph,
+{\tt noweave} inserts [[\nwdocspar]], which uses
+[[\filbreak]] in an attempt to keep the documentation chunk on the
+same page as the code chunk that follows it. (The code chunk will
+have another [[\filbreak]] after it---see [[\nwbegincode]].)
+[[\nwbegindocs]] doesn't start a
+new paragraph if the previous chunk didn't end one, i.e.\ didn't enter
+vmode; if it does start a new one, it's only indented by the use of
+[[\nwdocspar]].
+<<noweb.sty>>=
+\def\nwbegindocs#1{\ifvmode\noindent\fi}
+\let\nwenddocs=\relax
+\let\nwdocspar=\filbreak
+@
+Some people don't like it that noweb leaves so much white space.
+The secret, undocument style option [[breakcode]] will break up code
+in order to use less white space.
+The parameter [[\nwbreakcodespace]] controls how much white space to
+leave.
+<<noweb.sty>>=
+\def\@nwsemifilbreak#1{\vskip0pt plus#1\penalty-200\vskip0pt plus -#1}
+\newdimen\nwbreakcodespace
+\nwbreakcodespace=0.2in % by default, leave no more than this on a page
+\def\nwopt@breakcode{%
+ \def\nwdocspar{\@nwsemifilbreak{0.2in}}%
+ \def\nwendcode{\endtrivlist\endgroup} % ditches filbreak
+}
+@
+The page-breaking strategy implies ragged bottom pages, so we should
+turn it on in general (this is relevant for the {\tt report} style):
+<<noweb.sty>>=
+\raggedbottom
+<<nwmac.tex>>=
+\def\nwdocspar{\par\semifilbreak}
+@
+
+{\tt noweave} doesn't bracket quoted code with [[\code]] and [[\edoc]] any more.
+It probably should do something nifty, just to make {\TeX} hackers happy, but it doesn't.
+<<noweb.sty>>=
+\def\code{\leavevmode\begingroup\setupcode\@vobeyspaces\obeylines}
+\let\edoc=\endgroup
+@
+\subsection{The {\tt noweb} page style}
+Headers contain file name, date, and page number.
+{\tt noweave} emits [[\nwfilename{]]{\em name}[[}]] for each new file.
+In the {\tt noweb} page style, new files cause page breaks;
+otherwise they are ignored.
+<<noweb.sty>>=
+\newdimen\@original@textwidth
+\def\ps@noweb{%
+ \@original@textwidth=\textwidth
+ \let\@mkboth\@gobbletwo
+ \def\@oddfoot{}\def\@evenfoot{}% No feet.
+ \if@twoside % If two-sided printing.
+ \def\@evenhead{\hbox to \@original@textwidth{%
+ \Rm \thepage\qquad{\Tt\leftmark}\hfil\today}}% Left heading.
+ \def\@oddhead{\hbox to \@original@textwidth{%
+ \Rm \today\hfil{\Tt\leftmark}\qquad\thepage}}% Right heading.
+ \else % If one-sided printing.
+ \def\@oddhead{\hbox to \@original@textwidth{%
+ \Rm \today\hfil{\Tt\leftmark}\qquad\thepage}}% Right heading.
+ \let\@evenhead\@oddhead
+ \fi
+ \let\chaptermark\@gobble
+ \let\sectionmark\@gobble
+ \let\subsectionmark\@gobble
+ \let\subsubsectionmark\@gobble
+ \let\paragraphmark\@gobble
+ \let\subparagraphmark\@gobble
+ \def\nwfilename{\begingroup\let\do\@makeother\dospecials
+ \catcode`\{=1 \catcode`\}=2 \nw@filename}
+ \def\nw@filename##1{\endgroup\markboth{##1}{##1}\let\nw@filename=\nw@laterfilename}%
+}
+\def\nw@laterfilename#1{\endgroup\clearpage \markboth{#1}{#1}}
+\let\nwfilename=\@gobble
+@
+\subsection{Chunk cross-reference}
+[[\nwalsodefined]], [[\nwused]], and [[\nwnotused]] are emitted by the {\tt
+noweb} cross-referencers. (What arguments?)
+If unused chunks are output chunks, a filter can slip in
+[[\let\nwnotused\nwoutput]].
+The style uses [[\nwcodecomment]] for all annotations that follow code
+chunks.
+Fiddling with it can change the appearance of the output.
+Note that [[\nwcodecomment]] is used after [[\nwbegincode]], with
+[[\obeylines]] in efect. Since linebreaking can occur here, we need
+to change the [[\interlinepenalty]].
+A little vertical space ([[\nwcodecommentsep]]\stylehook) appears before the first
+comment.
+
+We firkled with [[\rightskip]] in [[\nwbegincode]] above; now we want to
+reset it so that paragraphs are the normal width ([[\textwidth]],
+possibly less [[\codemargin]]) and set ragged right. This is done as
+usuall by making [[\rightskip]] naturally zero but stretchable.
+<<noweb.sty>>=
+\def\nwcodecomment#1{\@@par\penalty\nwcodepenalty
+ <<add [[\nwcodecommentsep]] if this is the first [[\nwcodecomment]]>>%
+ \hspace{-\codemargin}{%
+ \rightskip=0pt plus1in
+ \interlinepenalty\nwcodepenalty
+ \let\\\relax\footnotesize\Rm #1\@@par\penalty\nwcodepenalty}}
+@
+This stuff is used at the end of a chunk.
+<<noweb.sty>>=
+\def\@nwalsodefined#1{\nwcodecomment{\@nwlangdepdef\ \nwpageprep\ \@pagesl{#1}.}}
+\def\@nwused#1{\nwcodecomment{\@nwlangdepcud\ \nwpageprep\ \@pagesl{#1}.}}
+\def\@nwnotused#1{\nwcodecomment{\@nwlangdeprtc.}}
+\def\nwoutput#1{\nwcodecomment{\@nwlangdepcwf\ {\Tt \@stripstar#1*\stripped}.}}
+\def\@stripstar#1*#2\stripped{#1}
+<<add [[\nwcodecommentsep]] if this is the first [[\nwcodecomment]]>>=
+\if@firstnwcodecomment
+ \vskip\nwcodecommentsep\penalty\nwcodepenalty\@firstnwcodecommentfalse
+\fi
+@
+This stuff on the definition line.
+Note the hooks\stylehook{} for pointer styles.
+<<noweb.sty>>=
+\newcommand{\nwprevdefptr}[1]{%
+ \mbox{$\mathord{\triangleleft}\,\mathord{\mbox{\subpageref{#1}}}$}}
+\newcommand{\nwnextdefptr}[1]{%
+ \mbox{$\mathord{\mbox{\subpageref{#1}}}\,\mathord{\triangleright}$}}
+
+\newcommand{\@nwprevnextdefs}[2]{%
+ {\nwtagstyle
+ \ifx\relax#1\else ~~\nwprevdefptr{#1}\fi
+ \ifx\relax#2\else ~~\nwnextdefptr{#2}\fi}}
+\newcommand{\@nwusesondefline}[1]{{\nwtagstyle~~(\@pagenumsl{#1})}}
+\newcommand{\@nwstartdeflinemarkup}{\nobreak\hskip 1.5em plus 1fill\nobreak}
+\newcommand{\@nwenddeflinemarkup}{\nobreak\hskip \nwdefspace minus\nwdefspace\nobreak}
+<<nwmac.tex>>=
+\def\nwstartdeflinemarkup{\nobreak\hskip 1.5em plus 1fill\nobreak}
+\def\nwenddeflinemarkup{\nobreak\hskip \nwdefspace minus\nwdefspace\nobreak}
+@
+And here are the options we use to choose one, the other, or neither.
+<<noweb.sty>>=
+\def\nwopt@longxref{%
+ \let\nwalsodefined\@nwalsodefined
+ \let\nwused\@nwused
+ \let\nwnotused\@nwnotused
+ \let\nwprevnextdefs\@gobbletwo
+ \let\nwusesondefline\@gobble
+ \let\nwstartdeflinemarkup\relax
+ \let\nwenddeflinemarkup\relax
+}
+\def\nwopt@shortxref{%
+ \let\nwalsodefined\@gobble
+ \let\nwused\@gobble
+ \let\nwnotused\@gobble
+ \let\nwprevnextdefs\@nwprevnextdefs
+ \let\nwusesondefline\@nwusesondefline
+ \let\nwstartdeflinemarkup\@nwstartdeflinemarkup
+ \let\nwenddeflinemarkup\@nwenddeflinemarkup
+}
+\def\nwopt@noxref{%
+ \let\nwalsodefined\@gobble
+ \let\nwused\@gobble
+ \let\nwnotused\@gobble
+ \let\nwprevnextdefs\@gobbletwo
+ \let\nwusesondefline\@gobble
+ \let\nwstartdeflinemarkup\relax
+ \let\nwenddeflinemarkup\relax
+}
+\nwopt@shortxref % to hell with backward compatibility!
+@ \iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B longxref, shortxref, noxref
+Choose a style for chunk cross-reference.
+Long style uses small paragraphs after each chunk, as in Knuth.
+Short style uses symbols on the definition line, as in Hanson.
+.B noxref
+provides no chunk cross-reference.
+Defaults to
+.B shortxref.
+@ \fi
+<<noweb.sty>>=
+\newskip\nwcodecommentsep \nwcodecommentsep=3pt plus 1pt minus 1pt
+\newif\if@firstnwcodecomment\@firstnwcodecommenttrue
+@
+\subsection{Page ranges}
+The goal is to combine sub-page numbers in a way that makes sense.
+Multiple sub-pages of one page become that page, and individual
+pages are combined into ranges.
+(A range may be only one page.)
+<<noweb.sty>>=
+\newcount\@nwlopage\newcount\@nwhipage % range lo..hi-1
+\newcount\@nwlosub % subpage of lo
+\newcount\@nwhisub % subpage of hi
+\def\@nwfirstpage#1#2#3{% subpage page xref-tag
+ \@nwlopage=#2 \@nwlosub=#1
+ \def\@nwloxreftag{#3}%
+ \advance\@nwpagecount by \@ne
+ <<$\mbox{[[\@nwhipage]]} := \mbox{[[\@nwlopage]]}+1$>>}
+\def\@nwnextpage#1#2#3{% subpage page xref-tag
+ \ifnum\@nwhipage=#2
+ \advance\@nwhipage by \@ne
+ \advance\@nwpagecount by \@ne
+ \@nwhisub=#1
+ \def\@nwhixreftag{#3}\else
+ \ifnum#2<\@nwlopage <<new range starting with [[#2]]>>\else
+ \ifnum#2>\@nwhipage <<new range starting with [[#2]]>>\else
+ \@nwlosub=0 \@nwhisub=0
+ \fi\fi\fi
+ }
+<<new range starting with [[#2]]>>=
+<<add range to range list>>\@nwfirstpage{#1}{#2}{#3}
+<<$\mbox{[[\@nwhipage]]} := \mbox{[[\@nwlopage]]}+1$>>=
+\@nwhipage=\@nwlopage\advance\@nwhipage by \@ne
+<<add range to range list>>=
+<<set [[\@tempa]] to page range(s), marked with [[\\]]>>%
+\edef\@tempa{\noexpand\nwix@cons\noexpand\nw@pages{\@tempa}}\@tempa
+<<set [[\@tempa]] to page range(s), marked with [[\\]]>>=
+\advance\@nwhipage by \m@ne
+\ifnum\@nwhipage=\@nwlopage
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}}%
+\else
+ \count@=\@nwhipage \advance\count@ by \m@ne
+ \ifnum\count@=\@nwlopage % consecutive pages
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ {\@nwloxreftag}}%
+ \noexpand\noexpand\noexpand\\%
+ {{\nwthepagenum{\number\@nwhisub}{\number\@nwhipage}}
+ {\@nwhixreftag}}}%
+ \else <<use rules from Chicago style manual>>%
+ \fi
+\fi
+<<use rules from Chicago style manual>>=
+\ifnum\@nwlopage<110 <<normal range>>\else
+ \count@=\@nwlopage \divide\count@ by 100 \multiply\count@ by 100
+ \ifnum\count@=\@nwlopage <<normal range>>\else
+ \count@=\@nwlopage \divide\count@ by 100
+ \@nwpagetemp=\@nwhipage \divide\@nwpagetemp by 100
+ \ifnum\count@=\@nwpagetemp % lo--least 2 digits of hi
+ \multiply\@nwpagetemp by 100
+ \advance \@nwhipage by -\@nwpagetemp
+ <<normal range>>%
+ \else <<normal range>>%
+ \fi
+ \fi
+\fi
+<<normal range>>=
+\edef\@tempa{\noexpand\noexpand\noexpand\\{{\number\@nwlopage--\number\@nwhipage}{}}}
+<<noweb.sty>>=
+\newcount\@nwpagetemp
+@
+The sequence [[\@pagesl]] makes a range of pages from a list of labels.
+[[\subpages]] works from a list of [[{{subpage}{page}}]].
+<<noweb.sty>>=
+\newcount\@nwpagecount
+\def\@nwfirstpagel#1{% label
+ \@ifundefined{r@#1}{<<warn of undefined reference to [[#1]] and add page ??>>}{%
+ \edef\@tempa{\noexpand\@nwfirstpage\subpagepair{#1}{#1}}\@tempa}}
+\def\@nwnextpagel#1{% label
+ \@ifundefined{r@#1}{<<warn of undefined reference to [[#1]] and add page ??>>}{%
+ \edef\@tempa{\noexpand\@nwnextpage\subpagepair{#1}{#1}}\@tempa}}
+<<noweb.sty>>=
+\def\@pagesl#1{% list of labels
+ \gdef\nw@pages{}\@nwpagecount=0
+ \def\\##1{\@nwfirstpagel{##1}\let\\=\@nwnextpagel}#1%
+ <<add range to range list>>\def\\##1{\@nwhyperpagenum##1}%
+ \ifnum\@nwpagecount=1 \nwpageword \else \nwpagesword\fi~\commafy{\nw@pages}}
+\def\@nwhyperpagenum#1#2{\nwhyperreference{#2}{#1}}
+
+\def\@pagenumsl#1{% list of labels -- doesn't include word `pages', commas, or `and'
+ \gdef\nw@pages{}\@nwpagecount=0
+ \def\\##1{\@nwfirstpagel{##1}\let\\=\@nwnextpagel}#1%
+ <<add range to range list>>%
+ \def\\##1{\@nwhyperpagenum##1\let\\=\@nwpagenumslrest}\nw@pages}
+\def\@nwpagenumslrest#1{~\@nwhyperpagenum#1}
+<<noweb.sty>>=
+\def\subpages#1{% list of {{subpage}{page}}
+ \gdef\nw@pages{}\@nwpagecount=0
+ \def\\##1{\edef\@tempa{\noexpand\@nwfirstpage##1{}}\@tempa
+ \def\\####1{\edef\@tempa{\noexpand\@nwnextpage####1}\@tempa}}#1%
+ <<add range to range list>>\def\\##1{\@firstoftwo##1}%
+ \ifnum\@nwpagecount=1 \nwpageword \else \nwpagesword\fi~\commafy{\nw@pages}}
+\def\@nwaddrange{<<add range to range list>>}
+@
+[[\nwpageword]], [[\nwpagesword]], and [[\nwpageprep]] let you change
+the wording of the cross-reference information.
+<<noweb.sty>>=
+\def\nwpageword{\@nwlangdepchk} % chunk, was page
+\def\nwpagesword{\@nwlangdepchks} % chunk, was page
+\def\nwpageprep{\@nwlangdepin} % in, was on
+<<warn of undefined reference to [[#1]] and add page ??>>=
+<<warn of undefined reference to [[#1]]>>%
+\nwix@cons\nw@pages{\\{\bf ??}}
+@
+\subsection{Sub-page references}
+
+This is the wonderful code that Dave Love provided to make page
+references like 7a, 7b, and so on.
+
+This code
+provides a mechanism for defining `page
+sub-references' using [[\sublabel{foo}]] referenced with
+[[\subpageref{foo}]]. Sub-references will be numbered like these real
+examples: \subpageref{ref:foo}, \subpageref{ref:bar},
+\subpageref{ref:baz}\sublabel{ref:foo}\sublabel{ref:bar}\sublabel{ref:baz}
+etc.\ unless there is only one on the page, in which case the letter
+will be dropped like this: \subpageref{ref:fred}.
+
+To be able to use [[\subpageref]] we must define the label with
+[[\sublabel]], used like label. (Using
+[[\ref]] with a label defined by [[\sublabel]] will
+produce the sub-reference number, by the way, and [[\pageref]]
+works as expected.) Note that
+[[\subpageref]] is robust and [[\ref]] and [[\pageref]] are redefined to be
+robust also, as they will be in future \LaTeX{} releases.
+Incidentally, these expand to the relevant text plus [[\null]]---you
+might want to strip this off, e.g.\ for sorting lists.
+
+
+There are various ways we could attack this task (which is made
+non-trivial by the well-known asynchrony of (La)\TeX's output
+routine), but
+they all must depend on hacks in the [[.aux]] file or a similar one.
+Joachim Schrod's [[fnpag.sty]] does the same sort of thing differently
+to this \LaTeX-specific approach. See [[latex.tex]] for enlightenment
+on the cross-referencing mechanism and the \LaTeX{} internals used
+below. [DL: The internals change in \LaTeX2e compared with
+\LaTeX~2.09. The code here still works, though.]
+@
+The new-style {\LaTeX} page-reference macros all work the same way:
+if the thing is undefined, barf. Otherwise, do the specified thing.
+We need to handle the fact that the expansion of the label may be two
+items or five items, depending on whether hypertext is used.
+Since we're only ever interested in the first two items, we use a
+hack---the ``do the specified thing'' must be defined as
+\mbox{[[\def\dome#1#2#3\\{...}]]} where [[...]] uses only the first two parameters.
+<<noweb.sty>>=
+\newcommand\nw@genericref[2]{% what to do, name of ref
+ \expandafter\nw@g@nericref\csname r@#2\endcsname#1{#2}}
+\newcommand\nw@g@nericref[3]{% control sequence, what to do, name
+ \ifx#1\relax
+ \ref{#3}% trigger the standard `undefined ref' mechanisms
+ \else
+ \expandafter#2#1.\\%
+ \fi}
+@ Much of what we want can be done by pulling out the first, second,
+or first and second elements of a ref.
+<<noweb.sty>>=
+\def\nw@selectone#1#2#3\\{#1}
+\def\nw@selecttwo#1#2#3\\{#2}
+\def\nw@selectonetwo#1#2#3\\{{#1}{#2}}
+@
+The [[\subpageref]] macro first does a normal [[\pageref]]. If the
+reference is actually defined, it then goes on to check whether the
+control sequence [[2on]]\LA{}{page referenced}\RA{} is defined and sets the
+[[\ref]] value to get [[a]] etc.\ if so. The magic, of course, is in
+defining the [[2on]] bit appropriately.
+[[\subpageref]] also tries to include the right hyperstuff for xhdvi.
+<<noweb.sty>>=
+\newcommand{\subpageref}[1]{%
+ \nwhyperreference{#1}{\nw@genericref\@subpageref{#1}}}
+\def\@subpageref#1#2#3\\{%
+ \@ifundefined{2on#2}{#2}{\nwthepagenum{#1}{#2}}}
+@
+[[\subpagepair]] produces a [[{subpage}{page}]] pair.
+<<noweb.sty>>=
+\newcommand{\subpagepair}[1]{% % produces {subpage}{page}
+ \@ifundefined{r@#1}%
+ {{0}{0}}%
+ {\nw@genericref\@subpagepair{#1}}}
+\def\@subpagepair#1#2#3\\{%
+ \@ifundefined{2on#2}{{0}{#2}}{{#1}{#2}}}
+@
+[[\sublabel]] is like the [[\label]] command, except that it writes
+[[\newsublabel]] onto the [[.aux]] file rather than [[\newlabel]].
+For hyperreferencing, all labels must be hypertext
+anchors, for which we use [[\nwblindhyperanchor]].
+<<noweb.sty>>=
+\newcommand{\sublabel}[1]{%
+ \leavevmode % needed to make \@bsphack work
+ \@bsphack
+ \nwblindhyperanchor{#1}%
+ \if@filesw {\let\thepage\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string
+ \newsublabel{#1}{{}{\thepage}}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+@
+[[\nosublabel]] creates a label with a sub-page part of~0.
+<<noweb.sty>>=
+\newcommand{\nosublabel}[1]{%
+ \@bsphack\if@filesw {\let\thepage\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string
+ \newlabel{#1}{{0}{\thepage}}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+@
+[[\newsublabel]] is the macro that does the important work. It is called with the
+same sort of arguments as [[\newlabel]]: the first argument is the
+label name and the second is [[{<<ref value>>}{<<page number>>}]].
+(Note that the only definition here which needs to be
+global is the one which is, and that [[\global]] is redefined by
+[[\enddocument]], which will bite you if you use it\dots)
+<<noweb.sty>>=
+<<definition of [[\newsublabel]]>>
+@
+Before we create a [[\newsublabel]] for the first time, we set the
+proper trailers.
+<<definition of [[\newsublabel]]>>=
+\newcommand\newsublabel{%
+ \nw@settrailers
+ \global\let\newsublabel\@newsublabel
+ \@newsublabel}
+@ First we extract the page number into [[\this@page]].
+<<definition of [[\newsublabel]]>>=
+\newcommand{\@newsublabel}[2]{%
+ \edef\this@page{\@cdr#2\@nil}%
+@
+Then we see whether it's changed from the value of [[\last@page]]
+which was stashed away by the last [[\newsublabel]] (or is [[\relax]] if
+this is the first one). If the page has changed, we reset the
+counter [[\sub@page]] telling us how many sub-labels there have been
+on the page.
+<<definition of [[\newsublabel]]>>=
+ \ifx\this@page\last@page\else
+ \sub@page=\z@
+ \fi
+ \edef\last@page{\this@page}
+ \advance\sub@page by \@ne
+@
+If we've had at least two on the page, we define the
+[[2on]]\LA{}{page no.}\RA{} macro to indicate the fact.
+<<definition of [[\newsublabel]]>>=
+ \ifnum\sub@page=\tw@
+ \global\@namedef{2on\this@page}{}%
+ \fi
+@
+\nextchunklabel{cl1}\nextchunklabel{cl2}
+Then we write a normal [[\newlabel]] with the sub-reference as the
+normal reference value in the second argument.
+Unfortunately, if we want hypertext support, the second argument of
+[[\newlabel]] gets complicated.
+It is either
+\begin{itemize}
+\item
+[[{<<ref value>>}{<<page number>>}]], when normal {\LaTeX} is
+running, or
+\item
+[[{<<ref value>>}{<<page number>>}{<<text>>}}{<<hyper category>>}{<<URL>>}]],
+when the \texttt{hyperref} package is running.
+(We actually detect this by looking for the \texttt{nameref} package,
+because that's the one that changes the use of labels.)
+\end{itemize}
+We unify these two things by producing
+[[{<<ref value>>}{<<page number>>}\nw@labeltrailers]]
+
+We may have pending labels in support of [[\nextchunklabel]], as defined in
+chunk~\subpageref{chunklabel}.
+Because we want to define all of the ``pending sublabels'' in exactly
+the same way, we do something a bit odd---we make the current label a
+pending label as well.
+<<definition of [[\newsublabel]]>>=
+ \pendingsublabel{#1}%
+ \edef\@tempa##1{\noexpand\newlabel{##1}%
+ {{\number\sub@page}{\this@page}\nw@labeltrailers}}%
+ \pending@sublabels
+ \def\pending@sublabels{}}
+@
+We can't use [[\@ifpackageloaded]] to see if \texttt{nameref} is
+loaded, because that is restricted to the preamble, and
+[[\newsublabel]] goes into the [[.aux]] file, which is executed after
+the whole document is processed.
+We therefore test for [[\@secondoffive]].
+This is lame, but what else can we do?
+<<noweb.sty>>=
+\newcommand\nw@settrailers{% -- won't work on first run
+ \@ifpackageloaded{nameref}%
+ {\gdef\nw@labeltrailers{{}{}{}}}%
+ {\gdef\nw@labeltrailers{}}}
+\renewcommand\nw@settrailers{%
+ \@ifundefined{@secondoffive}%
+ {\gdef\nw@labeltrailers{}}%
+ {\gdef\nw@labeltrailers{{}{}{}}}}
+@
+Now we keep track of those pending guys.\nextchunklabel{chunklabel}
+The goal here is to save them up until they're all equivalent to the
+label on the next chunk.
+We have to control expansion so chunks like \subpageref{cl1}
+(\subpageref{cl2}) can be labelled twice.
+<<noweb.sty>>=
+\newcommand{\nextchunklabel}[1]{%
+ \nwblindhyperanchor{#1}% % looks slightly bogus --- nr
+ \@bsphack\if@filesw {\let\thepage\relax
+ \edef\@tempa{\write\@auxout{\string\pendingsublabel{#1}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+\newcommand\pendingsublabel[1]{%
+ \def\@tempa{\noexpand\@tempa}%
+ \edef\pending@sublabels{\noexpand\@tempa{#1}\pending@sublabels}}
+\def\pending@sublabels{}
+<<man page: noweb style control sequences>>=
+.PP \" .TP will not work with the backslashes on the next line. Period.
+\fB\\nextchunklabel{l}\fP
+.RS
+Associates label \fBl\fP
+with the sub-page reference of the next code chunk.
+Can be used in for concise chunk cross-reference with, e.g.,
+\fBchunk~\\subpageref{l}\fP.
+.RE
+@
+We need to define these.
+<<noweb.sty>>=
+\def\last@page{\relax}
+\newcount\sub@page
+@
+We no longer use Rainer's new expandable definitions of [[\ref]] and
+[[\pageref]] to minimise the risk of nasty surprises; enough time has
+elapsed that this should no longer be necessary.
+<<old noweb.sty>>=
+% RmS 92/08/14: made \ref and \pageref robust
+\def\ref#1{\@ifundefined{r@#1}{{\bf ??}<<warn of undefined reference to [[#1]]>>}%
+ {\expandafter\expandafter\expandafter
+ \@car\csname r@#1\endcsname\@nil\null}}
+\def\pageref#1{\@ifundefined{r@#1}{{\bf ??}<<warn of undefined reference to [[#1]]>>}%
+ {\expandafter\expandafter\expandafter
+ \@cdr\csname r@#1\endcsname\@nil\null}}
+\def\@refpair#1{\@ifundefined{r@#1}{{0}{0}<<warn of undefined reference to [[#1]]>>}%
+ {\@nameuse{r@#1}}}
+<<warn of undefined reference to [[#1]]>>=
+\@warning{Reference `#1' on page \thepage \space undefined}
+@
+
+Here a a couple of hooks for formatting sub-page numbers,
+which can be alphabetic, numeric, or omitted.\stylehook
+<<noweb.sty>>=
+\def\@alphasubpagenum#1#2{#2\ifnum#1=0 \else\@alph{#1}\fi}
+\def\@nosubpagenum#1#2{#2}
+\def\@numsubpagenum#1#2{#2\ifnum#1=0 \else.\@arabic{#1}\fi}
+\def\nwopt@nosubpage{\let\nwthepagenum=\@nosubpagenum\nwopt@nomargintag}
+\def\nwopt@numsubpage{\let\nwthepagenum=\@numsubpagenum}
+\def\nwopt@alphasubpage{\let\nwthepagenum=\@alphasubpagenum}
+\nwopt@alphasubpage
+@
+In rare cases, there may be more than 26 chunks on a page.
+In such a case, we need a sub-page numbering scheme that can go beyond
+``a to z.''
+The scheme I have chosen is ``a to z, then aa to zz, then aaa to zzz,
+etc.''
+The conversion requires a bit of thought because it is \emph{not} an
+ordinary conversion of integer to string as we usually think of such
+things.
+The problem is that the meaning of the letters depends on the
+position; the letter~a acts like a zero in some positions or a one in
+others.
+
+The solution I have implemented uses a variable [[bound]] which is
+always equal to $26^k$ for some~$k$.
+If we write the recurrence $B_k = B_{k-1} + 26^k$, with $B_0 = 0$, we
+then use a string of~$k$ letters to represent numbers between
+$B_{k-1}$~and~$B_k$.
+Within that string, a's are 0's, and so on up to z's which are 25's,
+and we use standard integer-conversion methods to encode $n-B_{k-1}$.
+
+The following Icon implementation may be more perspicuous than the
+{\TeX} code actually used.
+Here the variable [[bound]] is $26^k$, with $k=1$ initially, and
+[[n]]~is $n-B_{k-1}$.
+The first loop finds the right~$k$, and the second does the usual
+string conversion.
+<<Icon code for subpage numbering>>=
+procedure alphastring(n)
+ bound := 26
+
+ while n >= bound do {
+ # invariant: bound = 26^(k+1) & n is initial n - B_k
+ n -:= bound
+ bound *:= 26
+ }
+
+ while bound > 1 do {
+ bound /:= 26
+ d := integer(n / bound)
+ n -:= d * bound
+ writes(&lcase[d+1])
+ }
+end
+@
+Here's {\TeX} code to achieve the same end.
+The entire macro body is enclosed in braces, so that it can be used
+with [[\loop]] without picking up the wrong [[\repeat]].
+<<noweb.sty>>=
+\newcount\@nwalph@n
+\let\@nwalph@d\@tempcnta
+\let\@nwalph@bound\@tempcntb
+\def\@nwlongalph#1{{%
+ \@nwalph@n=#1\advance\@nwalph@n by-1
+ \@nwalph@bound=26
+ \loop\ifnum\@nwalph@n<\@nwalph@bound\else
+ \advance\@nwalph@n by -\@nwalph@bound
+ \multiply\@nwalph@bound by 26
+ \repeat
+ \loop\ifnum\@nwalph@bound>1
+ \divide\@nwalph@bound by 26
+ \@nwalph@d=\@nwalph@n\divide\@nwalph@d by \@nwalph@bound
+ % d := d * bound ; n -:= d; d := d / bound --- saves a temporary
+ \multiply\@nwalph@d by \@nwalph@bound
+ \advance\@nwalph@n by -\@nwalph@d
+ \divide\@nwalph@d by \@nwalph@bound
+ \advance\@nwalph@d by 1 \@alph{\@nwalph@d}%
+ \repeat
+}}
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B alphasubpage, numsubpage, nosubpage
+Number chunks by the number of the page on which they appear,
+followed by an alphabetic (numeric, not used) ``sub-page'' indicator.
+Defaults to
+.B alphasubpage.
+.B nosubpage
+implies
+.B nomargintag.
+@ \fi
+@
+
+\subsection{{\tt WEB}-like chunk numbering}
+Here's a righteous hack: we get the effect of WEB-like chunk numbers
+just by redefining [[\sublabel]] to use a counter instead of the current page number.
+Since the numbers are all distinct, no sub-page number is ever used.
+<<noweb.sty>>=
+\newcount\nw@chunkcount
+\nw@chunkcount=\@ne
+\newcommand{\weblabel}[1]{%
+ \@bsphack
+ \nwblindhyperanchor{#1}%
+ \if@filesw {\let\thepage\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string
+ \newsublabel{#1}{{}{\number\nw@chunkcount}}}}%
+ \expandafter}\@tempa
+ \global\advance\nw@chunkcount by \@ne
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+\def\nwopt@webnumbering{%
+ \let\sublabel=\weblabel
+ \def\nwpageword{chunk}\def\nwpagesword{chunks}%
+ \def\nwpageprep{in}}
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B webnumbering
+Number chunks consecutively, in
+.I WEB
+style, instead of using sub-page numbers.
+@ \fi
+@
+\subsection{Indexing (identifier cross-reference) support}
+
+\subsubsection{Tracking definitions and uses}
+All index definitions and uses are associated with
+a label defined with [[\sublabel]] or [[\nosublabel]].
+Either the label is the [[\sublabel]] of the code chunk in which the definition or use
+appears, or it is a [[\nosublabel]] appearing in the middle of a
+documentation chunk.
+<<noweb.sty>>=
+% \nwindexdefn{printable name}{identifying label}{label of chunk}
+% \nwindexuse{printable name}{identifying label}{label of chunk}
+
+\def\nwindexdefn#1#2#3{\@auxix{\protect\nwixd}{#2}{#3}}
+\def\nwindexuse#1#2#3{\@auxix{\protect\nwixu}{#2}{#3}}
+
+\def\@auxix#1#2#3{% {marker}{id label}{subpage label}
+ \@bsphack\if@filesw {\let\nwixd\relax\let\nwixu\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string\nwixadd{#1}{#2}{#3}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+<<noweb.sty>>=
+% \nwixadd{marker}{idlabel}{subpage label}
+\def\nwixadd#1#2#3{%
+ \@ifundefined{nwixl@#2}%
+ {\global\@namedef{nwixl@#2}{#1{#3}}}%
+ {\expandafter\nwix@cons\csname nwixl@#2\endcsname{#1{#3}}}}
+@
+\subsubsection{Subscripted identifiers}
+We use either explicit subscripts or hyperlinks to point identifiers
+to their definitions.
+<<noweb.sty>>=
+\def\@nwsubscriptident#1#2{\mbox{$\mbox{#1}_{\mathrm{\subpageref{#2}}}$}}
+\def\@nwnosubscriptident#1#2{#1}
+\def\@nwhyperident#1#2{\leavevmode\nwhyperreference{#2}{#1}}
+@
+We can use subscripts, hyperlinks, or nothing on all identifiers.
+<<noweb.sty>>=
+\def\nwopt@subscriptidents{%
+ \let\nwlinkedidentq\@nwsubscriptident
+ \let\nwlinkedidentc\@nwsubscriptident
+}
+\def\nwopt@nosubscriptidents{%
+ \let\nwlinkedidentq\@nwnosubscriptident
+ \let\nwlinkedidentc\@nwnosubscriptident
+}
+\def\nwopt@hyperidents{%
+ \let\nwlinkedidentq\@nwhyperident
+ \let\nwlinkedidentc\@nwhyperident
+}
+\def\nwopt@nohyperidents{%
+ \let\nwlinkedidentq\@nwnosubscriptident
+ \let\nwlinkedidentc\@nwnosubscriptident
+}
+@
+We can change only identifiers appearing in quoted code.
+<<noweb.sty>>=
+\def\nwopt@subscriptquotedidents{%
+ \let\nwlinkedidentq\@nwsubscriptident
+}
+\def\nwopt@nosubscriptquotedidents{%
+ \let\nwlinkedidentq\@nwnosubscriptident
+}
+\def\nwopt@hyperquotedidents{%
+ \let\nwlinkedidentq\@nwhyperident
+}
+\def\nwopt@nohyperquotedidents{%
+ \let\nwlinkedidentq\@nwnosubscriptident
+}
+@
+The default is to hyperlink everything.
+<<noweb.sty>>=
+\nwopt@hyperidents
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B subscriptidents, nosubscriptidents, hyperidents, nohyperidents
+Controls subscripting of identifiers in code, including quoted code.
+Selecting
+.B subscriptidents
+means an identifier appearing in a code chunk (or in quoted code
+within a documentation
+chunk) will be subscripted with the chunk number of its definition.
+.B hyperidents
+means such identifiers will be hyperlinked to their definitions,
+provided of course that a hypertext package like
+.B hyperref
+is loaded.
+.B nosubscriptidents
+and
+.B nohyperidents
+are equivalent, and they turn off such markings.
+The default is
+.B hyperidents.
+.TP
+.B subscriptquotedidents, nosubscriptquotedidents, hyperquotedidents, nohyperquotedidents
+Controls linking of identifiers as above, but applies only to uses of
+identifiers
+in quoted code.
+@ \fi
+@
+\subsubsection{Writing lists with commas and ``and''}
+You get one of
+\begin{itemize}
+\item ``$a$''
+\item ``$a$ and $b$''
+\item ``$a$, $\ldots$, $b$, and $c$''
+\end{itemize}
+Plus [[\\]] is applied to each element of the list.
+<<noweb.sty>>=
+\newcount\@commacount
+\def\commafy#1{%
+ {\nwix@listcount{#1}\@commacount=\nwix@counter
+ \let\@comma@each=\\%
+ \ifcase\@commacount\let\\=\@comma@each\or\let\\=\@comma@each\or
+ \def\\{\def\\{ \@nwlangdepand\ \@comma@each}\@comma@each}\else
+ \def\\{\def\\{, %
+ \advance\@commacount by \m@ne
+ \ifnum\@commacount=1 \@nwlangdepand~\fi\@comma@each}\@comma@each}\fi
+ #1}}
+@
+
+\subsubsection{New, improved index code}
+There are two kinds of lists.
+One kind is a generic list in which elements are preceded by [[\\]].
+If the elements are index elements, they are {\em[[{]]printable
+identifier[[}{]]label[[}]]} pairs.
+The other kind is a list of sub-page labels, in which each
+element is preceded by either [[\nwixd]] or [[\nwixu]].
+<<noweb.sty>>=
+\def\nwix@cons#1#2{% {list}{\marker{element}}
+ {\toks0=\expandafter{#1}\def\@tempa{#2}\toks2=\expandafter{\@tempa}%
+ \xdef#1{\the\toks0 \the\toks2 }}}
+@
+The reference list for an identifier labelled {\em id}
+is always called [[\nwixl@]]{\em id}.
+Most applications will work with reference lists by applying [[\\]]
+either to the defs or to the uses.
+<<noweb.sty>>=
+\def\nwix@uses#1{% {label}
+ \def\nwixu{\\}\let\nwixd\@gobble\@nameuse{nwixl@#1}}
+\def\nwix@defs#1{% {label}
+ \def\nwixd{\\}\let\nwixu\@gobble\@nameuse{nwixl@#1}}
+@
+
+Some applications count uses to see whether there is any need to
+display information.
+<<noweb.sty>>=
+\newcount\nwix@counter
+\def\nwix@listcount#1{% {list with \\}
+ {\count@=0
+ \def\\##1{\advance\count@ by \@ne }%
+ #1\global\nwix@counter=\count@ }}
+\def\nwix@usecount#1{\nwix@listcount{\nwix@uses{#1}}}
+\def\nwix@defcount#1{\nwix@listcount{\nwix@defs{#1}}}
+@
+\subsubsection{Supporting a mini-index at the end of each chunk}
+When displaying identifiers used, show the identifier and its
+definitions.
+<<noweb.sty>>=
+\def\nwix@id@defs#1{% index pair
+ {{\Tt \@car#1\@nil}%
+ \def\\##1{\nwix@defs@space\subpageref{##1}}\nwix@defs{\@cdr#1\@nil}}}
+ % useful above to change ~ into something that can break
+% this option is undocumented because I think breakdefs is always right
+\def\nwopt@breakdefs{\def\nwix@defs@space{\penalty200\ }}
+\def\nwopt@nobreakdefs{\def\nwix@defs@space{~}} % old code
+\nwopt@breakdefs
+\def\nwidentuses#1{% list of index pairs
+ \nwcodecomment{\@nwlangdepuss\ \let\\=\nwix@id@defs\commafy{#1}.}}
+@
+\iffalse
+<<undocumented -- man page: [[\noweboptions]]>>=
+.TP
+.B breakdefs, nobreakdefs
+.BR breakdefs ,
+which is the default,
+permits long lists of definitions to be broken in identifier cross-reference.
+Useful if identifier cross-reference produces lots of overfull hboxes.
+.B nobreakdefs
+is the old behavior, which should never be needed.
+@ \fi
+@
+The definitions section is a bit more complex, because it is omitted
+if none of the identifiers defined is ever used.
+<<noweb.sty>>=
+\def\nwix@totaluses#1{% list of index pairs
+ {\count@=0
+ \def\\##1{\nwix@usecount{\@cdr##1\@nil}\advance\count@ by\nwix@counter}%
+ #1\global\nwix@counter\count@ }}
+\def\nwix@id@uses#1#2{% {ident}{label}
+ \nwix@usecount{#2}\ifnum\nwix@counter>0
+ {\advance\leftskip by \codemargin
+ \nwcodecomment{{\Tt #1}, \@nwlangdepusd\ \nwpageprep\ \@pagesl{\nwix@uses{#2}}.}}%
+ \else
+ \ifnw@hideunuseddefs\else
+ {\advance\leftskip by \codemargin \nwcodecomment{{\Tt #1}, \@nwlangdepnvu.}}%
+ \fi
+ \fi}
+\def\nwidentdefs#1{% list of index pairs
+ \ifnw@hideunuseddefs\nwix@totaluses{#1}\else\nwix@listcount{#1}\fi
+ \ifnum\nwix@counter>0
+ \nwcodecomment{\@nwlangdepdfs:}%
+ {\def\\##1{\nwix@id@uses ##1}#1}%
+ \fi}
+<<noweb.sty>>=
+\newif\ifnw@hideunuseddefs\nw@hideunuseddefsfalse
+\def\nwopt@hideunuseddefs{\nw@hideunuseddefstrue}
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B hideunuseddefs
+Omit defined but unused identifiers from
+the local identifier cross-reference (Preston Briggs).
+@ \fi
+<<noweb.sty>>=
+\def\nwopt@noidentxref{%
+ \let\nwidentdefs\@gobble
+ \let\nwidentuses\@gobble}
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B noidentxref
+Omit the local identifier cross-reference which follows each code chunk.
+@ \fi
+
+\subsubsection{Support for chunk and identifier indices}
+The index in the back shows absolutely all the pages.
+<<noweb.sty>>=
+\def\nw@underlinedefs{% {list with \nwixd, \nwixu}
+ \let\\=\relax\def\nw@comma{, }
+ \def\nwixd##1{\\\underline{\subpageref{##1}}\let\\\nw@comma}%
+ \def\nwixu##1{\\\subpageref{##1}\let\\\nw@comma}}
+
+\def\nw@indexline#1#2{%
+ {\indent {\Tt #1}: \nw@underlinedefs\@nameuse{nwixl@#2}\par}}
+
+\newenvironment{thenowebindex}{\parindent=-10pt \parskip=\z@
+ \advance\leftskip by 10pt
+ \advance\rightskip by 0pt plus1in\par\@afterindenttrue
+ \def\\##1{\nw@indexline##1}}{}
+@
+The information comes from the list [[nwisx@i]].
+<<noweb.sty>>=
+\def\nowebindex{%
+ \@ifundefined{nwixs@i}%
+ {\@warning{The \string\nowebindex\space is empty}}%
+ {\begin{thenowebindex}\@nameuse{nwixs@i}\end{thenowebindex}}}
+@
+Here's a more efficient version for the external case:
+<<noweb.sty>>=
+\def\nowebindex@external{%
+ {\let\nwixadds@c=\@gobble
+ \def\nwixadds@i##1{\nw@indexline##1}%
+ \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}%
+ \begin{thenowebindex}\@input{\jobname.nwi}\end{thenowebindex}}}
+@
+That list ([[nwisx@i]]) is created by calls to [[\nwixlogsorted{i}]].
+<<noweb.sty>>=
+\def\nwixlogsorted#1#2{% list data
+ \@bsphack\if@filesw
+ \toks0={#2}\immediate\write\@auxout{\string\nwixadds{#1}{\the\toks0}}
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+@
+[[nwixs@c]] and [[nwixs@i]] are sorted lists of chunks and identifiers, respectively.
+<<noweb.sty>>=
+\def\nwixadds#1#2{%
+ \@ifundefined{nwixs@#1}%
+ {\global\@namedef{nwixs@#1}{\\{#2}}}%
+ {\expandafter\nwix@cons\csname nwixs@#1\endcsname{\\{#2}}}}
+\let\nwixaddsx=\@gobbletwo
+@
+If an external index is used, we need a [[.nwi]] file,
+[[\nwixadds]] is to be ignored, and we use [[\nwixaddsx]].
+<<noweb.sty>>=
+\def\nwopt@externalindex{%
+ \ifx\nwixadds\@gobbletwo % already called
+ \else
+ \let\nwixaddsx=\nwixadds \let\nwixadds=\@gobbletwo
+ \let\nowebindex=\nowebindex@external
+ \let\nowebchunks=\nowebchunks@external
+ \fi}
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B externalindex
+Use an index generated with
+.I noindex(1)
+(q.v.).
+@ \fi
+@
+<<noweb.sty>>=
+\def\nowebchunks{%
+ \@ifundefined{nwixs@c}%
+ {\@warning{The are no \string\nowebchunks}}%
+ {\begin{thenowebchunks}\@nameuse{nwixs@c}\end{thenowebchunks}}}
+\def\nowebchunks@external{%
+ {\let\nwixadds@i=\@gobble
+ \def\nwixadds@c##1{\nw@onechunk##1}%
+ \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}%
+ \begin{thenowebchunks}\@input{\jobname.nwi}\end{thenowebchunks}}}
+ \@namedef{r@nw@notdef}{{0}{(\@nwlangdepnvd)}}
+<<noweb.sty>>=
+\def\nw@chunkunderlinedefs{% {list of labels with \nwixd, \nwixu}
+ \let\\=\relax\def\nw@comma{, }
+ \def\nwixd##1{\\\underline{\subpageref{##1}}\let\\\nw@comma}%
+ \def\nwixu##1{\\\subpageref{##1}\let\\\nw@comma}}
+<<noweb.sty>>=
+\def\nw@onechunk#1#2#3{% {name}{label of first definition}{list with \nwixd, \nwixu}
+ \@ifundefined{r@#2}{}{%
+ \indent\LA #1~{\nwtagstyle\subpageref{#2}}\RA
+ \if@nwlongchunks{~\nw@chunkunderlinedefs#3}\fi\par}}
+<<noweb.sty>>=
+\newenvironment{thenowebchunks}{\vskip3pt
+ \parskip=\z@\parindent=-10pt \advance\leftskip by 10pt
+ \advance\rightskip by 0pt plus10pt \@afterindenttrue
+ \def\\##1{\nw@onechunk##1}}{}
+<<noweb.sty>>=
+\newif\if@nwlongchunks
+\@nwlongchunksfalse
+\let\nwopt@longchunks\@nwlongchunkstrue
+@ \iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B longchunks
+When expanding
+.B "\\\\nowebchunks,"
+show page numbers of definitions and uses of each chunk.
+@ \fi
+
+@
+\subsection{Support for hypertext}
+There are two sets of support for hypertext.
+ Balasubramanian Narasimhan wrote initial support for \texttt{hyper.sty}.
+<<noweb.sty>>=
+\newcommand\@nw@hyper@ref{\hyperreference} % naras
+\newcommand\@nw@hyper@anc{\blindhyperanchor} % naras
+@ Norman Ramsey wrote support for the \texttt{hyperrref} package (May
+ 1998).
+<<noweb.sty>>=
+\newcommand\@nw@hyperref@ref[2]{\hyperlink{noweb.#1}{#2}} % nr
+\newcommand\@nw@hyperref@anc[1]{\hypertarget{noweb.#1}{\relax}} % nr
+%%\renewcommand\@nw@hyperref@ref[2]{{#2}} % nr
+%%\renewcommand\@nw@hyperref@anc[1]{} % nr
+@ We define the independent macros [[\nwhyperreference]] and
+ [[\nwblindhyperanchor]],
+which test for the presence of one of these two packages,
+redefine themselve accordingly, and re-invoke themselves.
+<<noweb.sty>>=
+\newcommand\nwhyperreference{%
+ \@ifundefined{hyperlink}
+ {\@ifundefined{hyperreference}
+ {\global\let\nwhyperreference\@gobble}
+ {\global\let\nwhyperreference\@nw@hyper@ref}}
+ {\global\let\nwhyperreference\@nw@hyperref@ref}%
+ \nwhyperreference
+}
+
+\newcommand\nwblindhyperanchor{%
+ \@ifundefined{hyperlink}
+ {\@ifundefined{hyperreference}
+ {\global\let\nwblindhyperanchor\@gobble}
+ {\global\let\nwblindhyperanchor\@nw@hyper@anc}}
+ {\global\let\nwblindhyperanchor\@nw@hyperref@anc}%
+ \nwblindhyperanchor
+}
+@
+\subsection{Support for hypertext translation to HTML}
+<<noweb.sty>>=
+\newcommand\nwanchorto{%
+ \begingroup\let\do\@makeother\dospecials
+ \catcode`\{=1 \catcode`\}=2 \nw@anchorto}
+\newcommand\nw@anchorto[1]{\endgroup\def\nw@next{#1}\nw@anchortofin}
+\newcommand\nw@anchortofin[1]{#1\footnote{See URL \texttt{\nw@next}.}}
+\let\nwanchorname\@gobble
+<<man page: noweb style control sequences>>=
+.PP
+.B "\\\\nwanchorto{URL}{anchor text}"
+.RS
+Creates a link to the given URL with the given anchor text.
+Implemented in
+.I latex(1)
+using footnotes, but
+.I sl2h(1)
+translates this to
+.B "<a href=URL>anchor text</a>"
+.RE
+.PP
+.B "\\\\nwanchorname{name}{anchor text}"
+.RS
+Creates an anchor point for a hyperlink.
+Implemented in
+.I latex(1)
+using
+.B "\\\\label",
+but
+.I sl2h(1)
+translates this to
+.B "<a name=name>anchor text</a>"
+.RE
+@
+This lets us hide stuff intended for use only when converting to HTML:
+<<noweb.sty>>=
+\newif\ifhtml
+\htmlfalse
+<<man page: noweb style control sequences>>=
+.PP
+.B "\\\\ifhtml ... \\\\fi"
+.RS
+Text between
+.B "\\\\ifhtml"
+and
+.B "\\\\fi"
+is ignored by
+.I latex(1),
+but
+.I sl2h(1)
+and the
+.I l2h
+noweb filter translate the text into HTML.
+.RE
+@
+\subsection{Support for Prettyprinting}
+The following macro can be redefined to allow custom typesetting of
+identifiers in the index and mini-indices.
+<<noweb.sty>>=
+\let\nwixident=\relax
+@
+@
+The following macros can be redefined to typeset `[[\]]', `[[{]]' and
+`[[}]]' correctly in non-typewriter fonts.
+The problem is that the built-in {\LaTeX} [[\{]] tries to produce a
+math symbol, which doesn't exist in the typewriter font, so we get a
+brace in the wrong font and a warning. Most unpleasant.
+Noweave therefore attempts to emit [[\nwlbrace]] and [[\nwrbrace]]
+wherever it believes braces should appear.
+The standard noweb style is to set code in typewriter font, and so the
+standard definitions just select the proper characters from that font.
+ People setting code in
+fonts other than typewriter are responsible for redefining those
+macros to work in their environment.
+<<kernel>>=
+\def\nwbackslash{\char92}
+\def\nwlbrace{\char123}
+\def\nwrbrace{\char125}
+@
+\subsection{Language-dependent macros}
+
+Miguel Filgueiras
+(DCC-FCUP \& LIACC, Universidade do Porto) provided some changes to
+add multilingual support for the words Noweb uses in indexing and
+cross-reference.
+He inserted macros that are defined by, e.g., [[\noweboptions{english}]].
+The Noweb package uses the
+(apparently standard) {\LaTeX} macro [[\languagename]] to select a
+language at load time.
+If the \texttt{babel} package is
+loaded (with the appropriate language name) before Noweb is loaded,
+the Noweb package will select language appropriately, provided the
+language is one of those Noweb supports.
+Mr.~Filgueiras provided support for English,
+Portuguese, German, and French.
+He notes that the French is
+faulty; the translations may be poor, and there are
+bugs in the implementation that he could not solve.
+
+\label{subsection:langdeps}
+
+The language-dependent macros are defined here in each supported
+language in a different subsubsection.
+
+The choice of language depends on testing the [[\languagename]]
+macro. There must be a more elegant way of coding the tests below\ldots
+<<noweb.sty>>=
+<<language support>>
+\ifx\languagename\undefined % default is English
+ \noweboptions{english}
+\else
+ \@ifundefined{nwopt@\languagename}
+ {\noweboptions{english}}
+ {\expandafter\noweboptions\expandafter{\languagename}}
+\fi
+@
+\subsubsection{Support for English}
+
+This describes the original English text.
+<<language support>>=
+\def\nwopt@english{%
+ \def\@nwlangdepdef{This definition is continued}%
+ \def\@nwlangdepcud{This code is used}%
+ \def\@nwlangdeprtc{Root chunk (not used in this document)}%
+ \def\@nwlangdepcwf{This code is written to file}%
+ \def\@nwlangdepchk{chunk}%
+ \def\@nwlangdepchks{chunks}%
+ \def\@nwlangdepin{in}%
+ \def\@nwlangdepand{and}%
+ \def\@nwlangdepuss{Uses}%
+ \def\@nwlangdepusd{used}%
+ \def\@nwlangdepnvu{never used}%
+ \def\@nwlangdepdfs{Defines}%
+ \def\@nwlangdepnvd{never defined}%
+}
+\let\nwopt@american\nwopt@english
+@
+
+@
+\subsubsection{Partial support for Icelandic}
+
+Partial translation of noweb into Icelandic courtesy of
+Johann ``Myrkraverk'' Oskarsson" \verb+<johann@myrkraverk.com>+.
+<<language support>>=
+\def\nwopt@icelandic{%
+ \def\@nwlangdepdef{This definition is continued}%
+ \def\@nwlangdepcud{This code is used}%
+ \def\@nwlangdeprtc{Root chunk (not used in this document)}%
+ \def\@nwlangdepcwf{This code is written to file}%
+ \def\@nwlangdepchk{kóða}%
+ \def\@nwlangdepchks{kóðum}%
+ \def\@nwlangdepin{í}%
+ \def\@nwlangdepand{og}%
+ \def\@nwlangdepuss{Notar}%
+ \def\@nwlangdepusd{notað}%
+ \def\@nwlangdepnvu{hvergi notað}%
+ \def\@nwlangdepdfs{Skilgreinir}%
+ \def\@nwlangdepnvd{hvergi skilgreint}%
+}
+@
+\subsubsection{Support for Portuguese}
+
+This contains the text in Portuguese.
+<<language support>>=
+\def\nwopt@portuges{%
+ \def\@nwlangdepdef{Defini\c{c}\~ao continuada em}%
+ % This definition is continued
+ \def\@nwlangdepcud{C\'odigo usado em}%
+ % This code is used
+ \def\@nwlangdeprtc{Fragmento de topo (sem uso no documento)}%
+ % Root chunk (not used in this document)
+ \def\@nwlangdepcwf{Este c\'odigo foi escrito no ficheiro}%
+ % This code is written to file
+ \def\@nwlangdepchk{fragmento}%
+ % chunk
+ \def\@nwlangdepchks{fragmentos}%
+ % chunks
+ \def\@nwlangdepin{no(s)}%
+ % in
+ \def\@nwlangdepand{e}%
+ % and
+ \def\@nwlangdepuss{Usa}%
+ % Uses
+ \def\@nwlangdepusd{usado}%
+ % used
+ \def\@nwlangdepnvu{nunca usado}%
+ % never used
+ \def\@nwlangdepdfs{Define}%
+ % Defines
+ \def\@nwlangdepnvd{nunca definido}%
+ % never defined
+}
+@
+\subsubsection{Support for French}
+
+This is a tentative translation to French.
+NR has made some corrections, and it has been reviewed by Fr\'ed\'eric
+Lin\'e, but some errors may remain.
+
+There are problems with using accents: on the [[\@nwlangdepnvd]] macro
+(which apparently is not used in the context of [[\nwcodecomment]]),
+and in some other macros (\LaTeX{} complains about missing
+[[\endcsname]]). This should be fixed by someone with experience in
+using \TeX\ldots
+<<language support>>=
+\def\nwopt@frenchb{%
+ \def\@nwlangdepdef{Suite de la d\'efinition}%
+ % This definition is continued
+ \def\@nwlangdepcud{Ce code est employ\'e}%
+ % This code is used
+ \def\@nwlangdeprtc{Morceau racine (pas employ\'e dans ce document)}%
+ % Root chunk (not used in this document)
+ \def\@nwlangdepcwf{Ce code est \'ecrit dans le fichier}%
+ % This code is written to file
+ \def\@nwlangdepchk{le morceau}%
+ % chunk
+ \def\@nwlangdepchks{les morceaux}%
+ % chunks
+ \def\@nwlangdepin{dans}%
+ % in
+ \def\@nwlangdepand{et}%
+ % and
+ \def\@nwlangdepuss{Utilise}%
+ % Uses
+ \def\@nwlangdepusd{utilis\'{e}}%
+ % used
+ \def\@nwlangdepnvu{jamais employ\'{e}}%
+ % never used
+ \def\@nwlangdepdfs{D\'{e}finit}%
+ % Defines
+ % Cannot use the accent here: \def\@nwlangdepnvd{jamais d\'{e}fini}%
+ \def\@nwlangdepnvd{jamais defini}%
+ % never defined
+}
+\let\nwopt@french\nwopt@frenchb
+@
+\subsubsection{Support for German}
+
+This is a translation to German by Sabine Broda (DCC-FCUP \& LIACC,
+Universidade do Porto) with revisions by Christian Lindig and further
+revisions by Pascal Schmitt.
+<<language support>>=
+\def\nwopt@german{%
+ \def\@nwlangdepdef{Diese Definition wird fortgesetzt}%
+ % This definition is continued
+ \def\@nwlangdepcud{Dieser Code wird benutzt}%
+ % This code is used
+ \def\@nwlangdeprtc{Hauptteil (nicht in diesem Dokument benutzt)}%
+ % Root chunk (not used in this document)
+ \def\@nwlangdepcwf{Geh\"ort in die Datei}%
+ % This code is written to file
+ \def\@nwlangdepchk{Abschnitt}%
+ % chunk
+ \def\@nwlangdepchks{den Abschnitten}%
+ % chunks
+ \def\@nwlangdepin{in}%
+ % in
+ \def\@nwlangdepand{und}%
+ % and
+ \def\@nwlangdepuss{Benutzt}%
+ % Uses
+ \def\@nwlangdepusd{benutzt}%
+ % used
+ \def\@nwlangdepnvu{nicht benutzt}%
+ % never used
+ \def\@nwlangdepdfs{Definiert}%
+ % Defines
+ \def\@nwlangdepnvd{nicht definiert}%
+ % never defined
+}
+@
+Here is a revised version, because the version above did not satisy
+(explanations below).
+<<language support>>=
+\def\nwopt@german{%
+ \def\@nwlangdepdef{Diese Definition wird fortgesetzt}%
+ % This definition is continued
+ \def\@nwlangdepcud{Dieser Code wird benutzt}%
+ % This code is used
+ \def\@nwlangdeprtc{Hauptteil (nicht in diesem Dokument benutzt)}%
+ % Root chunk (not used in this document)
+ \def\@nwlangdepcwf{Dieser Code erzeugt die Datei}
+ % This code generates the file
+ \def\@nwlangdepchk{Teil}%
+ % chunk
+ \def\@nwlangdepchks{Teils}%
+ % chunks
+ \def\@nwlangdepin{im}%
+ % in
+ \def\@nwlangdepand{und}%
+ % and
+ \def\@nwlangdepuss{Benutzt}%
+ % Uses
+ \def\@nwlangdepusd{benutzt}%
+ % used
+ \def\@nwlangdepnvu{nicht benutzt}%
+ % never used
+ \def\@nwlangdepdfs{Definiert}%
+ % Defines
+ \def\@nwlangdepnvd{nicht definiert}%
+ % never defined
+}
+\let\nwopt@ngerman\nwopt@german
+@ Explanations:
+\begin{quote}
+Changed the [[\@nwlangdepcwf]] yet again.
+Johannes Wiedersich \url{<johannes@physik.blm.tu-muenchen.de>} writes:
+\begin{quote}
+The German latex files contain
+\begin{quote}
+Dieser Code schreibt man zum File
+\end{quote}
+this is not correct (or understandable) German and not a correct
+translation of the English ``This code is written to file.''
+A better translation would be
+\begin{quote}
+Dieser Code geht in Datei
+\end{quote}
+I would suggest to use either
+\begin{itemize}
+\item Dieser Code schreibt den File
+\item Dieser Code erzeugt die Datei
+\end{itemize}
+The first is closer to a literal translation of the English text; the
+second option is closer to the \emph{meaning} of the English text and to
+what
+actually happens. (This code generates the file)
+\end{quote}
+The old explanation was:
+\begin{quote}
+``Diese Code geht in Datei (x)'' isn't perfect either; the best
+translation would be ``Dieser Code wird in Datei (x) geschrieben'' but
+this would require to put the file name into the middle of the sentence.
+\begin{verbatim}
+ \def\@nwlangdepcwf{Dieser Code geht in Datei}%
+\end{verbatim}
+The [[\@nwlangdepchks]] macro is problematic because it has to work
+together with [[\@nwlangdepin]]. It would be best to emit:
+\begin{verbatim}
+ benutzt in den Teilen 1b und 2.
+ benutzt im Teil 1.
+\end{verbatim}
+This would require to switch between ``in'' and ``im''. Since ``im'' is a
+compund of ``in dem'', I suggest to use an article for the singular, too,
+and to emit:
+\begin{verbatim}
+ benutzt in den Teilen 1b und 2.
+ benutzt in dem Teil 1.
+\end{verbatim}
+Hence:
+\begin{verbatim}
+ \def\@nwlangdepchks{den Teilen}
+ \def\@nwlangdepchk{dem Teil}
+\end{verbatim}
+\end{quote}
+\end{quote}
+@
+@ \iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B english, french, german, portuges, icelandic
+Write cross-reference information in the language specified.
+Defaults to
+.B english.
+@ \fi
+@
+\clearpage
+\section{The {\tt nwmac} macros for use with plain {\TeX}}
+
+First we make [[@]] a letter so that we can use `private' macro names.
+<<nwmac.tex>>=
+\catcode`\@=11
+<<nwmac.tex>>=
+% scale cmbx10 instead of using cmbx12 because {\LaTeX} does, so fonts exist
+\font\twlbf=cmbx10 scaled \magstep1
+\font\frtbf=cmbx10 scaled \magstep2
+% These fonts don't work with xdvi!
+
+\advance\hoffset 0.5 true in
+\advance\hsize -1.5 true in
+\newdimen\textsize
+\textsize=\hsize
+\def\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}
+<<nwmac.tex>>=
+\long\def\ifundefined#1#2#3{%
+ \expandafter\ifx\csname#1\endcsname\relax
+ #2%
+ \else#3%
+ \fi}
+
+\ifundefined{myheadline}
+ {\headline={\hbox to \textsize{\tentt\firstmark\hfil\tenrm\today\hbox
+ to 4em{\hss\folio}}\hss}}
+ {\expandafter\headline\expandafter{\myheadline}}
+
+\ifundefined{myfootline}
+ {\footline={\hfil}}
+ {\expandafter\footline\expandafter{\myfootline}}
+<<nwmac.tex>>=
+\def\semifilbreak{\vskip0pt plus1.5in\penalty-200\vskip0pt plus -1.5in}
+\raggedbottom
+<<nwmac.tex>>=
+%
+% \chapcenter macro to produce nice centered chapter titles
+%
+\def\chapcenter{\leftskip=0.5 true in plus 4em minus 0.5 true in
+ \rightskip=\leftskip
+ \parfillskip=0pt \spaceskip=.3333em \xspaceskip=.5em
+ \pretolerance=9999 \tolerance=9999
+ \hyphenpenalty=9999 \exhyphenpenalty=9999}
+<<nwmac.tex>>=
+% \startsection{LEVEL}{INDENT}{BEFORESKIP}{AFTERSKIP}{STYLE}{HEADING}
+% #1 #2 #3 #4 #5 #6
+%
+% LEVEL: depth; e.g. part=0 chapter=1 sectino=2...
+% INDENT: indentation of heading from left margin
+% BEFORESKIP: skip before header
+% AFTERSKIP: skip after header
+% STYLE: style of heading; e.g.\bf
+% HEADING: heading of the sectino
+%
+\def\startsection#1#2#3#4#5#6{\par\vskip#3 plus 2in
+ \penalty-200\vskip 0pt plus -2in
+ \noindent{\leftskip=#2 \rightskip=0.5true in plus 4em minus 0.5 true in
+ \hyphenpenalty=9999 \exhyphenpenalty=9999
+ #5#6\par}\vskip#4%
+ {\def\code##1{[[}\def\edoc##1{]]}\message{[#6]}}
+ \settocparms{#1}
+ \def\themodtitle{#6}
+%%%% {\def\code{\string\code}\def\edoc{\string\edoc}%
+ \edef\next{\noexpand\write\cont{\tocskip
+ \tocline{\hskip\tocindent\tocstyle\relax\themodtitle}
+ {\noexpand\the\pageno}}}\next % write to toc
+ %}
+}
+<<nwmac.tex>>=
+\def\settocparms#1{
+ \count@=#1
+ \ifnum\count@<1
+ \def\tocskip{\vskip3ptplus1in\penalty-100
+ \vskip0ptplus-1in}%
+ \def\tocstyle{\bf}
+ \def\tocindent{0pt}
+ \else
+ \def\tocskip{}
+ \def\tocstyle{\rm}
+ \dimen@=2em \advance\count@ by \m@ne \dimen@=\count@\dimen@
+ \edef\tocindent{\the\dimen@}
+ \fi
+}
+<<nwmac.tex>>=
+\def\tocline#1#2{\line{{\ignorespaces#1}\leaders\hbox to .5em{.\hfil}\hfil
+ \hbox to1.5em{\hss#2}}}
+<<nwmac.tex>>=
+\def\section#1{\par \vskip3ex\noindent {\bf #1}\par\nobreak\vskip1ex\nobreak}
+\def\chapter#1{\vfil\eject\startsection{0}{0pt}{6ex}{3ex}{\frtbf\chapcenter}{#1}}
+\def\section#1{\startsection{1}{0pt}{4ex}{2ex}{\twlbf}{#1}}
+\def\subsection#1{\startsection{2}{0pt}{2ex}{1ex}{\bf}{#1}}
+\def\subsubsection#1{\startsection{3}{0pt}{1ex}{0.5ex}{\it}{#1}}
+\def\paragraph#1{\startsection{4}{0pt}{1.5ex}{0ex}{\it}{#1}}
+
+<<kernel>>
+
+\def\nwfilename#1{\vfil\eject\mark{#1}}
+
+\def\nwbegindocs#1{\filbreak}
+\def\nwenddocs{\par}
+\def\nwbegincode#1{\par\nobreak
+ \begingroup\setupcode\newlines\parindent=0pt\parskip=0pt
+ %\let\oendmoddef=\endmoddef \let\oplusendmoddef=\plusendmoddef
+ %\def\endmoddef{\oendmoddef\par}\def\plusendmoddef{\oplusendmoddef\par}%
+ \let\onwenddeflinemarkup=\nwenddeflinemarkup
+ \def\nwenddeflinemarkup{\onwenddeflinemarkup\par}%
+ \hsize=\codehsize\noindent\bchack}
+\def\nwendcode{\endgroup}
+{\catcode`\^^M=\active % make CR an active character
+ \gdef\bchack#1^^M{\relax#1}%
+}
+<<nwmac.tex>>=
+\edef\contentsfile{\jobname.toc } % file that gets table of contents info
+\def\readcontents{\expandafter\input \contentsfile}
+
+\newwrite\cont
+\openout\cont=\contentsfile
+\write\cont{\string\catcode`\string\@=11}% a hack to make contents
+<<nwmac.tex>>=
+ % take stuff in plain.tex
+\def\bye{%
+ \write\cont{}% ensure that the contents file isn't empty
+ \closeout\cont
+ \vfil\eject\pageno=-1 % new page causes contents to be really closed
+ \topofcontents\readcontents\botofcontents
+ \vfil\eject\end}
+\def\topofcontents{\vfil\mark{{\bf Contents}}}
+\def\botofcontents{}
+<<nwmac.tex>>=
+\let\em=\it
+% used to produce an itemized (bulleted) list in plain {\TeX}
+% such lists can be nested
+% mostly useful with WEB
+
+% Usage:
+% \itemize
+% \item First thing
+% \item second thing
+% \enditemize
+
+\newcount\listlevel
+\listlevel=0
+\newdimen\itemwidth
+\itemwidth=3em
+
+\def\itemize{\begingroup\advance\listlevel by1
+ \def\item{\par\noindent
+ \raise2pt\llap{$\scriptstyle\bullet$\ }\ignorespaces}%
+ \def\nameditem##1{\par\noindent
+ \llap{\rlap{##1}\hskip\itemwidth}\ignorespaces}%
+ \par\advance\leftskip by\itemwidth\advance\rightskip by0.5\itemwidth}
+\def\enditemize{\par\endgroup\noindent\ignorespaces}
+
+\let\begindocument=\relax
+@
+Finally we make [[@]] `other' again.
+<<nwmac.tex>>=
+\catcode`\@=12
+@
+\section{Chunks} \nowebchunks
+\twocolumn[\section{Index}]
+\nowebindex*
+@
+\end{document}
+
+
diff --git a/web/noweb/src/tex/support.nw.orig b/web/noweb/src/tex/support.nw.orig
new file mode 100644
index 0000000000..c706a0b4cb
--- /dev/null
+++ b/web/noweb/src/tex/support.nw.orig
@@ -0,0 +1,1301 @@
+% -*- mode: Noweb; noweb-code-mode: tex-mode -*-
+\documentstyle[noweb,twoside]{article}
+\pagestyle{noweb}
+\noweboptions{longchunks,smallcode}
+\title{{\TeX} support for {\tt noweb}}
+\author{Norman Ramsey}
+\newcommand{\stylehook}{\marginpar{\raggedright\sl Style hook}}
+\begin{document}
+\maketitle
+\tableofcontents
+@
+This document describes the {\TeX} code that supports {\tt noweave}
+and {\tt noweb}. Those interested in customizing their output should
+focus on Section~\ref{section:sty}.
+Hooks you can easily use (apart from those provided by
+[[\noweboptions]]) are indicated by marginal notes.
+This file contains both plain {\TeX} and {\LaTeX} support:
+<<nwmac.tex>>=
+% nwmac.tex -- plain TeX support for noweb
+% DON'T read or edit this file! Use ...noweb-source/tex/support.nw instead.
+<<noweb.sty>>=
+% noweb.sty -- LaTeX support for noweb
+% DON'T read or edit this file! Use ...noweb-source/tex/support.nw instead.
+@
+
+\section{Basic {\TeX} support for {\tt noweb}}
+This basic code is used for both {\TeX} and {\LaTeX}.
+The first step is to define [[\codehsize]], which is the width in
+which code is set, and [[\codemargin]], which is the amount by which
+it is indented.\stylehook
+<<kernel>>=
+% make \hsize in code sufficient for 88 columns
+\setbox0=\hbox{\tt m}
+\newdimen\codehsize
+\codehsize=91\wd0 % 88 columns wasn't enough; I don't know why
+\newdimen\codemargin
+\codemargin=0pt
+@ %def \codehsize \codemargin
+[[\defspace]] is the space we would like on the right of navigational info
+that appears on definition lines, so that it lines up with the text above
+and below.
+<<kernel>>=
+\newdimen\nwdefspace
+\nwdefspace=\codehsize
+%% \advance\nwdefspace by -\textwidth\relax
+\advance\nwdefspace by -\hsize\relax
+@
+Most code is set in an environment in which [[\setupcode]] has been
+executed.
+In this environment, only [[\]], [[{]], and [[}]] have their usual
+categories; every other character represents itself.
+Appropriate [[\chardef]]s ensure that the special characters can be
+escaped with a backslash.
+<<kernel>>=
+\chardef\other=12
+\def\setupcode{%
+ \chardef\\=`\\
+ \chardef\{=`\{
+ \chardef\}=`\}
+ \catcode`\$=\other
+ \catcode`\&=\other
+ \catcode`\#=\other
+ \catcode`\%=\other
+ \catcode`\~=\other
+ \catcode`\_=\other
+ \catcode`\^=\other
+ \catcode`\"=\other % fixes problem with german.sty
+ \obeyspaces\Tt
+}
+\let\nwlbrace=\{
+\let\nwrbrace=\}
+@ %def \setupcode
+[[\eatline]] is used to consume newlines that should be ignored,
+for example, the newlines at the end of [[@ %def ]]{\em identifiers} lines.
+I can't remember what [[\startline]] or [[\newlines]] are for; I don't
+think {\tt noweave} ever emits them.
+<<kernel>>=
+{\catcode`\^^M=\active % make CR an active character
+ \gdef\newlines{\catcode`\^^M=\active % make CR an active character
+ \def^^M{\par\startline}}%
+ \gdef\eatline#1^^M{\relax}%
+}
+%%% DON'T \gdef^^M{\par\startline}}% in case ^^M appears in a \write
+\def\startline{\noindent\hskip\parindent\ignorespaces}
+\def\nwnewline{\ifvmode\else\hfil\break\fi}
+@ %def \startline \eatline \nwnewline
+
+Within a code environment, it may be necessary to restore the
+category codes in order to set a module (chunk) name.
+This hack doesn't properly restore [["]] for use in {\tt german.sty}.
+<<kernel>>=
+{\obeyspaces\global\let =\ } % from texbook, p 381
+\def\setupmodname{%
+ \catcode`\$=3
+ \catcode`\&=4
+ \catcode`\#=6
+ \catcode`\%=14
+ \catcode`\~=13
+ \catcode`\_=8
+ \catcode`\^=7
+ \catcode`\ =10
+ \catcode`\^^M=5
+ \let\{\nwlbrace
+ \let\}\nwrbrace
+ % bad news --- don't know what catcode to give "
+ \Rm}
+@ %def \setupmodname
+@ \sublabel{ref:fred}
+
+{\tt noweave} brackets uses of chunk names with [[\LA]] and [[\RA]], which
+handle the angle brackets, font, and environment.
+
+As it stands, chunk names can be broken across lines (or pages). This
+could result in unnecessary page breaks in code
+(c.f.~p.~\pageref{sec:pagebreaking}). [[\let\\maybehbox=\mbox]] to
+\stylehook
+avoid breaking them
+(or to make them work in math mode); this is done in code chunks, but could be done
+in general.
+<<kernel>>=
+\def\LA{\begingroup\maybehbox\bgroup\setupmodname\It$\langle$}
+\def\RA{\/$\rangle$\egroup\endgroup}
+\def\code{\leavevmode\begingroup\setupcode\newlines}
+\def\edoc{\endgroup}
+\let\maybehbox\relax
+@ %def \LA \RA \maybehbox
+
+[[\equivbox]] and [[\plusequivbox]] are used to set the
+``\unhcopy\equivbox''
+and ``\unhcopy\plusequivbox'' that open a chunk definition or its
+continuation.
+{\tt noweave} brackets definitions of chunk names with [[\moddef]] and
+either [[\endmoddef]] or [[\plusendmoddef]].
+<<kernel>>=
+\newbox\equivbox
+\setbox\equivbox=\hbox{$\equiv$}
+\newbox\plusequivbox
+\setbox\plusequivbox=\hbox{$\mathord{+}\mathord{\equiv}$}
+% \moddef can't have an argument because there might be \code...\edoc
+\def\moddef{\leavevmode\kern-\codemargin\LA}
+\def\endmoddef{\RA\ifmmode\equiv\else\unhcopy\equivbox\fi
+ \nobreak\hfill\nobreak}
+\def\plusendmoddef{\RA\ifmmode\mathord{+}\mathord{\equiv}\else\unhcopy\plusequivbox\fi
+ \nobreak\hfill\nobreak}
+@ %def \equivbox \plusequivbox \moddef \endmoddef \plusendmoddef
+@
+Within a code environment, margin tags might be used to mark sub-page
+numbers in the margins, separated by [[\nwmarginglue]].\stylehook
+The interaction with [[\moddef]] involves tricky kerning.
+The tag itself is displayed using [[\nwthemargintag]]
+<<noweb.sty>>=
+\def\nwopt@nomargintag{\let\nwmargintag=\@gobble}
+\def\nwopt@margintag{%
+ \def\nwmargintag##1{\leavevmode\llap{##1\kern\nwmarginglue\kern\codemargin}}}
+\def\nwopt@margintag{%
+ \def\nwmargintag##1{\leavevmode\kern-\codemargin\nwthemargintag{##1}\kern\codemargin}}
+\def\nwthemargintag#1{\llap{#1\kern\nwmarginglue}}
+\nwopt@margintag
+\newdimen\nwmarginglue
+\nwmarginglue=0.3in
+@ %def \nwmargintag margintag nomargintag \nwmarginglue
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B margintag
+Put the sub-page number (tag) of each code-chunk definition in the
+left margin. (Default)
+.TP
+.B nomargintag
+Don't use margin tags.
+@ \fi
+[[\nwtagstyle]] determines the style in which tags are displayed.\stylehook
+<<noweb.sty>>=
+\def\nwtagstyle{\footnotesize\Rm}
+@
+<<kernel>>=
+\def\chunklist{%
+\errhelp{I changed \chunklist to \nowebchunks.
+I'll try to avoid such incompatible changes in the future.}%
+\errmessage{Use \string\nowebchunks\space instead of \string\chunklist}}
+\def\nowebchunks{\message{<Warning: You need noweave -x to use \string\nowebchunks>}}
+\def\nowebindex{\message{<Warning: You need noweave -index to use \string\nowebindex>}}
+@ %def \chunklist \nowebchunks \nowebindex
+@ We have to be careful with font-changing in the presence of
+different font-selection schemes. In the \LaTeX{} New Font Selection
+Scheme something like [[\it\tt]] will attempt to use an italic
+typewriter font. Thus we define new commands like [[\Tt]] which will
+work with both the Plain and old and new \LaTeX{} schemes. (Note that
+NFSS will be standard in the next version of \LaTeX.) A problem with
+these definitions arises with NFSS: in math mode the won't work
+unless the {\tt oldlfont} backwards-compatibility option is in effect.
+For the moment, you can get round this by using [[\mbox]].
+
+If you wanted code set in a different font, you could re-define
+[[\Tt]].\stylehook{} [\LaTeX2e actually behaves like OFSS, but the
+extra [[\reset@font]] does no harm.]
+<<kernel>>=
+% here is support for the new-style (capitalized) font-changing commands
+% thanks to Dave Love
+\ifx\documentstyle\undefined
+ \let\Rm=\rm \let\It=\it \let\Tt=\tt % plain
+\else\ifx\selectfont\undefined
+ \let\Rm=\rm \let\It=\it \let\Tt=\tt % LaTeX OFSS
+\else % LaTeX NFSS
+ \def\Rm{\reset@font\rm}
+ \def\It{\reset@font\it}
+ \def\Tt{\reset@font\tt}
+ \def\Bf{\reset@font\bf}
+\fi\fi
+\ifx\reset@font\undefined \let\reset@font=\relax \fi
+@ %def \Rm \Tt \It \Bf
+@
+\clearpage
+\section{The {\tt noweb} document-style option for {\LaTeX}}
+\label{section:sty}
+{\LaTeX} support begins with the kernel shown above.
+<<noweb.sty>>=
+<<kernel>>
+@
+\subsection{Support for noweb options}
+<<noweb.sty>>=
+\def\noweboptions#1{%
+ \def\@nwoptionlist{#1}%
+ \@for\@nwoption:=\@nwoptionlist\do{%
+ \@ifundefined{nwopt@\@nwoption}{%
+ \@latexerr{There is no such noweb option as '\@nwoption'}\@eha}{%
+ \csname nwopt@\@nwoption\endcsname}}}
+@ %def \noweboptions
+\subsection{Adjusting placement of code on the page}
+{\LaTeX} requires a larger [[\codehsize]] because
+code is indented by [[\codemargin]].\stylehook
+<<noweb.sty>>=
+\codemargin=10pt
+\advance\codehsize by \codemargin % make room for indentation of code
+\advance\nwdefspace by \codemargin % and fix adjustment for def/use
+@
+[[\noweboptions{shift}]] is used to shift the whole page left to make room for
+the wide code lines.
+It may be emitted by {\tt noweave -shift}, or it might be given by a user.
+<<noweb.sty>>=
+\def\nwopt@shift{%
+ \dimen@=-0.8in
+ \if@twoside % Values for two-sided printing:
+ \advance\evensidemargin by \dimen@
+ \else % Values for one-sided printing:
+ \advance\evensidemargin by \dimen@
+ \advance\oddsidemargin by \dimen@
+ \fi
+% \advance \marginparwidth -\dimen@
+}
+\let\nwopt@noshift\@empty
+@ %def shift noshift
+
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B shift
+Shift text to the left so that long code lines won't extend
+off the right-hand side of the page.
+@ \fi
+
+\subsection{Page-breaking strategy}\label{sec:pagebreaking}
+
+We want to insert penalties aiming for:
+\begin{enumerate}
+\item
+No page breaks in the middle of a code chunk unless necessary to avoid
+an overfull vbox;
+\item
+Documentation immediately preceding a code chunk should appear on
+the same page as that code chunk unless doing so would violate rule 1.
+\end{enumerate}
+[[\filbreak]] is useful for this sort of thing (see {\em The \TeX
+ book\/}) and is used to encourage breaks at the right places between
+chunks. Appropriate penalties are inserted elsewhere, between code
+lines in particular.
+
+\subsection{Environments for setting code}
+
+[[\nwbegincode]] and [[\nwendcode]] are used by {\tt noweave} to bracket
+code chunks.
+The [[webcode]] environment is intended for users who want to paste
+{\tt noweave} output into papers.
+
+The definition of [[\nwbegincode]] is based on the verbatim
+implementation in {\tt verbatim.sty}, which will, presumably be in the
+next version of \LaTeX\@. One thing it does differently, apart from
+the catcode changes is setting [[\linewidth]]; this will avoid some
+overfull hboxen when the code lines are too long, but the lines won't
+be broken anyhow (even within chunk names because of the
+[[\maybehbox]] definition).
+<<noweb.sty>>=
+\def\nwbegincode#1{%
+ \begingroup
+ <<[[\nwbegincode]] separation and penalties>>
+ \@begincode }
+\def\nwendcode{\endtrivlist \endgroup \filbreak} % keeps code on 1 page
+
+\newenvironment{webcode}{%
+ \@begincode
+}{%
+ \endtrivlist}
+@ %def \nwbegincode \nwendcode webcode
+@ This is just common code between [[\nwbegincode]] and [[webcode]].
+<<noweb.sty>>=
+\def\@begincode{%
+ <<[[\trivlist]] clich\'e (\`a la {\Tt verbatim})>>
+ \linewidth\codehsize
+ <<[[\obeylines]] setup>>
+ <<zap ligatures, fix spaces>>
+ \nowebsize \setupcode
+ \let\maybehbox\mbox }
+@ %def \@begincode
+@ \iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B smallcode
+Set code in
+.I LaTeX
+.B "\\\\small"
+font instead of
+.B "\\\\normalsize."
+@ \fi
+@ [[\nowebsize]] governs the size at which code is set; users who want
+to minimize code can [[\let\nowebsize=\small]].
+Slitex users should try
+\begin{quote}
+[[\def\nowebsize{\normalsize\baselineskip=20pt \parskip=5pt }]]
+\end{quote}
+to avoid code lines that are too far apart.
+[[\nwcodetopsep]] is
+the glue placed before code chunks.\stylehook
+<<noweb.sty>>=
+ \newskip\nwcodetopsep \nwcodetopsep = 3pt plus 1.2pt minus 1pt
+ \let\nowebsize=\normalsize
+ \def\nwopt@smallcode{\let\nowebsize=\small}
+@ %def \nwcodetopsep \nowebsize smallcode
+@ Maybe the penalties ought to be parameters\dots
+<<[[\nwbegincode]] separation and penalties>>=
+ \topsep \nwcodetopsep
+ \@beginparpenalty \@highpenalty
+ \@endparpenalty -\@highpenalty
+@
+The [[\trivlist]] clich\'e isn't quite a clich\'e because we adjust
+[[\leftskip]] for indentation by [[\codemargin]] and adjust
+[[\rightskip]] to allow lines up to [[\codehsize]] long without
+overfull boxen
+($\mbox{[[\codehsize]]}=\mbox{[[\hsize]]}+\mbox{[[\rightskip]]}$).
+Note that [[\hsize]] isn't altered.
+<<[[\trivlist]] clich\'e (\`a la {\Tt verbatim})>>=
+ \trivlist \item[]%
+ \leftskip\@totalleftmargin \advance\leftskip\codemargin
+ \rightskip\hsize \advance\rightskip -\codehsize
+ \parskip\z@ \parindent\z@ \parfillskip\@flushglue
+@ The penalty inserted between verbatim lines would normally be
+[[\interlinepenalty]], but we want to prohibit breaks there.
+@
+Note the bug lurking somewhere in this code, as reported by Steven Ooms:
+\begin{quote}
+I have some lay-out
+problems in the documentation chunks. When using the (La)TeX commands
+[[\hline]] or [[\vtop]] the right margin is always extended far beyond the page
+margin after the first code chunk has been typeset. I'm still looking for
+the exact cause of it, but to me it seems that LaTeX supposes for those
+commands that the line width for the documentation chunk is as large as that
+for code chunks, which isn't true in reality.
+\end{quote}
+@
+<<[[\obeylines]] setup>>=
+ \@@par
+ \def\par{\leavevmode\null \@@par \penalty\nwcodepenalty}%
+ \obeylines
+@ [[\nwcodepenalty]] is the penalty for breaking between lines in a
+code chunk. If you set it to 10000, code will never be broken across
+pages.\stylehook{} I guess this should be settable in [[\noweboptions]].
+<<noweb.sty>>=
+\newcount\nwcodepenalty \nwcodepenalty=\@highpenalty
+@ %def \nwcodepenalty
+The cursing chunk accounts for the addition of a mess of characters
+to those reset by [[\@noligs]] in \LaTeX2e.
+<<zap ligatures, fix spaces>>=
+ \@noligs <<make all those damn active characters ``other''>>
+ \setupcode \frenchspacing \@vobeyspaces
+@
+We can't make [[`]] ``other,'' because then we'll get ligatures.
+(Why Don put these ligatures in the [[\tt]] font I wish I knew.)
+But we'll step on all the others.
+<<make all those damn active characters ``other''>>=
+ \ifx\verbatim@nolig@list\undefined\else
+ \let\do=\nw@makeother \verbatim@nolig@list \do@noligs\`
+ \fi
+<<noweb.sty>>=
+\def\nw@makeother#1{\catcode`#1=12 }
+@
+{\tt noweave} uses [[\nwbegindocs{nnn}]] and [[\nwenddocs]] to bracket
+documentation chunks.
+If a documentation chunk does not continue the current paragraph,
+{\tt noweave} inserts [[\nwdocspar]], which uses
+[[\filbreak]] in an attempt to keep the documentation chunk on the
+same page as the code chunk that follows it. (The code chunk will
+have another [[\filbreak]] after it---see [[\nwbegincode]].)
+[[\nwbegindocs]] doesn't start a
+new paragraph if the previous chunk didn't end one, i.e.\ didn't enter
+vmode; if it does start a new one, it's only indented by the use of
+[[\nwdocspar]].
+<<noweb.sty>>=
+\def\nwbegindocs#1{\ifvmode\noindent\fi}
+\let\nwenddocs=\relax
+\let\nwdocspar=\filbreak
+@ %def \nwbegindocs \nwdocspar \nwenddocs
+The page-breaking strategy implies ragged bottom pages, so we should
+turn it on in general (this is relevant for the {\tt report} style):
+<<noweb.sty>>=
+\raggedbottom
+<<nwmac.tex>>=
+\def\nwdocspar{\par\semifilbreak}
+@
+
+{\tt noweave} doesn't bracket quoted code with [[\code]] and [[\edoc]] any more.
+It probably should do something nifty, just to make {\TeX} hackers happy, but it doesn't.
+<<noweb.sty>>=
+\def\code{\leavevmode\begingroup\setupcode\@vobeyspaces\obeylines}
+\let\edoc=\endgroup
+@
+\subsection{The {\tt noweb} page style}
+Headers contain file name, date, and page number.
+{\tt noweave} emits [[\nwfilename{]]{\em name}[[}]] for each new file.
+In the {\tt noweb} page style, new files cause page breaks;
+otherwise they are ignored.
+<<noweb.sty>>=
+\newdimen\@original@textwidth
+\def\ps@noweb{%
+ \@original@textwidth=\textwidth
+ \let\@mkboth\@gobbletwo
+ \def\@oddfoot{}\def\@evenfoot{}% No feet.
+ \if@twoside % If two-sided printing.
+ \def\@evenhead{\hbox to \@original@textwidth{%
+ \Rm \thepage\qquad{\Tt\leftmark}\hfil\today}}% Left heading.
+ \def\@oddhead{\hbox to \@original@textwidth{%
+ \Rm \today\hfil{\Tt\leftmark}\qquad\thepage}}% Right heading.
+ \else % If one-sided printing.
+ \def\@oddhead{\hbox to \@original@textwidth{%
+ \Rm \today\hfil{\Tt\leftmark}\qquad\thepage}}% Right heading.
+ \let\@evenhead\@oddhead
+ \fi
+ \let\chaptermark\@gobble
+ \let\sectionmark\@gobble
+ \let\subsectionmark\@gobble
+ \let\subsubsectionmark\@gobble
+ \let\paragraphmark\@gobble
+ \let\subparagraphmark\@gobble
+ \def\nwfilename{\begingroup\let\do\@makeother\dospecials
+ \catcode`\{=1 \catcode`\}=2 \nw@filename}
+ \def\nw@filename##1{\endgroup\markboth{##1}{##1}\let\nw@filename=\nw@laterfilename}%
+}
+\def\nw@laterfilename#1{\endgroup\clearpage \markboth{#1}{#1}}
+\let\nwfilename=\@gobble
+@ %def \@original@textwidth \ps@noweb \nwfilename
+@
+\subsection{Chunk cross-reference}
+[[\nwalsodefined]], [[\nwused]], and [[\nwnotused]] are emitted by the {\tt
+noweb} cross-referencers. (What arguments?)
+If unused chunks are output chunks, a filter can slip in
+[[\let\nwnotused\nwoutput]].
+The style uses [[\nwcodecomment]] for all annotations that follow code
+chunks.
+Fiddling with it can change the appearance of the output.
+Note that [[\nwcodecomment]] is used after [[\nwbegincode]], with
+[[\obeylines]] in efect. Since linebreaking can occur here, we need
+to change the [[\interlinepenalty]].
+A little vertical space ([[\nwcodecommentsep]]\stylehook) appears before the first
+comment.
+
+We firkled with [[\rightskip]] in [[\nwbegincode]] above; now we want to
+reset it so that paragraphs are the normal width ([[\textwidth]],
+possibly less [[\codemargin]]) and set ragged right. This is done as
+usuall by making [[\rightskip]] naturally zero but stretchable.
+<<noweb.sty>>=
+\def\nwcodecomment#1{\@@par\penalty\nwcodepenalty
+ <<add [[\nwcodecommentsep]] if this is the first [[\nwcodecomment]]>>%
+ \hspace{-\codemargin}{%
+ \rightskip=0pt plus1in
+ \interlinepenalty\nwcodepenalty
+ \let\\\relax\footnotesize\Rm #1\@@par\penalty\nwcodepenalty}}
+@ %def \nwcodecomment
+This stuff is used at the end of a chunk.
+<<noweb.sty>>=
+\def\@nwalsodefined#1{\nwcodecomment{This definition is continued \nwpageprep\ \@pagesl{#1}.}}
+\def\@nwused#1{\nwcodecomment{This code is used \nwpageprep\ \@pagesl{#1}.}}
+\def\@nwnotused#1{\nwcodecomment{Root chunk (not used in this document).}}
+\def\nwoutput#1{\nwcodecomment{This code is written to file {\Tt \@stripstar#1*\stripped}.}}
+\def\@stripstar#1*#2\stripped{#1}
+@ %def \nwalsodefined \nwused \nwnotused \nwoutput
+<<add [[\nwcodecommentsep]] if this is the first [[\nwcodecomment]]>>=
+\if@firstnwcodecomment
+ \vskip\nwcodecommentsep\penalty\nwcodepenalty\@firstnwcodecommentfalse
+\fi
+@
+This stuff on the definition line.
+Note the hooks\stylehook{} for pointer styles.
+<<noweb.sty>>=
+\newcommand{\nwprevdefptr}[1]{%
+ \mbox{$\mathord{\triangleleft}\,\mathord{\mbox{\subpageref{#1}}}$}}
+\newcommand{\nwnextdefptr}[1]{%
+ \mbox{$\mathord{\mbox{\subpageref{#1}}}\,\mathord{\triangleright}$}}
+
+\newcommand{\@nwprevnextdefs}[2]{%
+ {\nwtagstyle
+ \ifx\relax#1\else ~~\nwprevdefptr{#1}\fi
+ \ifx\relax#2\else ~~\nwnextdefptr{#2}\fi}}
+\newcommand{\@nwusesondefline}[1]{{\nwtagstyle~~(\@pagenumsl{#1})}}
+\newcommand{\@nwstartdeflinemarkup}{\nobreak\hskip 1.5em plus 1fill\nobreak}
+\newcommand{\@nwenddeflinemarkup}{\nobreak\hskip \nwdefspace minus\nwdefspace\nobreak}
+@
+And here are the options we use to choose one or the other.
+<<noweb.sty>>=
+\def\nwopt@longxref{%
+ \let\nwalsodefined\@nwalsodefined
+ \let\nwused\@nwused
+ \let\nwnotused\@nwnotused
+ \let\nwprevnextdefs\@gobbletwo
+ \let\nwusesondefline\@gobble
+ \let\nwstartdeflinemarkup\relax
+ \let\nwenddeflinemarkup\relax
+}
+\def\nwopt@shortxref{%
+ \let\nwalsodefined\@gobble
+ \let\nwused\@gobble
+ \let\nwnotused\@gobble
+ \let\nwprevnextdefs\@nwprevnextdefs
+ \let\nwusesondefline\@nwusesondefline
+ \let\nwstartdeflinemarkup\@nwstartdeflinemarkup
+ \let\nwenddeflinemarkup\@nwenddeflinemarkup
+}
+\nwopt@shortxref % to hell with backward compatibility!
+@ \iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B longxref, shortxref
+Use either long, Knuth-style chunk cross-reference, or short,
+Hanson-style chunk cross-reference.
+The former uses small paragraphs after the chunk;
+the latter uses symbols on the definition line.
+Defaults to
+.B shortxref.
+@ \fi
+<<noweb.sty>>=
+\newskip\nwcodecommentsep \nwcodecommentsep=3pt plus 1pt minus 1pt
+\newif\if@firstnwcodecomment\@firstnwcodecommenttrue
+@
+\subsection{Page ranges}
+The goal is to combine sub-page numbers in a way that makes sense.
+Multiple sub-pages of one page become that page, and individual
+pages are combined into ranges.
+(A range may be only one page.)
+<<noweb.sty>>=
+\newcount\@nwlopage\newcount\@nwhipage % range lo..hi-1
+\newcount\@nwlosub % subpage of lo
+\newcount\@nwhisub % subpage of hi
+\def\@nwfirstpage#1#2{% subpage page
+ \@nwlopage=#2 \@nwlosub=#1
+ \advance\@nwpagecount by \@ne
+ <<$\mbox{[[\@nwhipage]]} := \mbox{[[\@nwlopage]]}+1$>>}
+\def\@nwnextpage#1#2{% subpage page
+ \ifnum\@nwhipage=#2
+ \advance\@nwhipage by \@ne \advance\@nwpagecount by \@ne \@nwhisub=#1 \else
+ \ifnum#2<\@nwlopage <<new range starting with [[#2]]>>\else
+ \ifnum#2>\@nwhipage <<new range starting with [[#2]]>>\else
+ \@nwlosub=0 \@nwhisub=0
+ \fi\fi\fi
+ }
+<<new range starting with [[#2]]>>=
+<<add range to range list>>\@nwfirstpage{#1}{#2}
+<<$\mbox{[[\@nwhipage]]} := \mbox{[[\@nwlopage]]}+1$>>=
+\@nwhipage=\@nwlopage\advance\@nwhipage by \@ne
+<<add range to range list>>=
+<<set [[\@tempa]] to page range(s), marked with [[\\]]>>%
+\edef\@tempa{\noexpand\nwix@cons\noexpand\nw@pages{\@tempa}}\@tempa
+<<set [[\@tempa]] to page range(s), marked with [[\\]]>>=
+\advance\@nwhipage by \m@ne
+\ifnum\@nwhipage=\@nwlopage
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}}%
+\else
+ \count@=\@nwhipage \advance\count@ by \m@ne
+ \ifnum\count@=\@nwlopage % consecutive pages
+ \edef\@tempa{\noexpand\noexpand\noexpand\\%
+ {\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}%
+ \noexpand\noexpand\noexpand\\%
+ {\nwthepagenum{\number\@nwhisub}{\number\@nwhipage}}}%
+ \else <<use rules from Chicago style manual>>%
+ \fi
+\fi
+<<use rules from Chicago style manual>>=
+\ifnum\@nwlopage<110 <<normal range>>\else
+ \count@=\@nwlopage \divide\count@ by 100 \multiply\count@ by 100
+ \ifnum\count@=\@nwlopage <<normal range>>\else
+ \count@=\@nwlopage \divide\count@ by 100
+ \@nwpagetemp=\@nwhipage \divide\@nwpagetemp by 100
+ \ifnum\count@=\@nwpagetemp % lo--least 2 digits of hi
+ \multiply\@nwpagetemp by 100
+ \advance \@nwhipage by -\@nwpagetemp
+ <<normal range>>%
+ \else <<normal range>>%
+ \fi
+ \fi
+\fi
+<<normal range>>=
+\edef\@tempa{\noexpand\noexpand\noexpand\\{\number\@nwlopage--\number\@nwhipage}}
+<<noweb.sty>>=
+\newcount\@nwpagetemp
+@
+The sequence [[\@pagesl]] makes a range of pages from a list of labels.
+[[\subpages]] works from a list of [[{{subpage}{page}}]].
+<<noweb.sty>>=
+\newcount\@nwpagecount
+\def\@nwfirstpagel#1{% label
+ \@ifundefined{r@#1}{<<warn of undefined reference to [[#1]] and add page ??>>}{%
+ \edef\@tempa{\noexpand\@nwfirstpage\subpagepair{#1}}\@tempa}}
+\def\@nwnextpagel#1{% label
+ \@ifundefined{r@#1}{<<warn of undefined reference to [[#1]] and add page ??>>}{%
+ \edef\@tempa{\noexpand\@nwnextpage\subpagepair{#1}}\@tempa}}
+\def\@pagesl#1{% list of labels
+ \gdef\nw@pages{}\@nwpagecount=0
+ \def\\##1{\@nwfirstpagel{##1}\let\\=\@nwnextpagel}#1%
+ <<add range to range list>>\let\\=\relax
+ \nwpageword\ifnum\@nwpagecount=1 \else s\fi~\commafy{\nw@pages}}
+\def\@pagenumsl#1{% list of labels -- doesn't include word `pages', commas, or `and'
+ \gdef\nw@pages{}\@nwpagecount=0
+ \def\\##1{\@nwfirstpagel{##1}\let\\=\@nwnextpagel}#1%
+ <<add range to range list>>\def\\{\let\\=~}\nw@pages}
+\def\subpages#1{% list of {{subpage}{page}}
+ \gdef\nw@pages{}\@nwpagecount=0
+ \def\\##1{\edef\@tempa{\noexpand\@nwfirstpage##1}\@tempa
+ \def\\####1{\edef\@tempa{\noexpand\@nwnextpage####1}\@tempa}}#1%
+ <<add range to range list>>\let\\=\relax
+ \nwpageword\ifnum\@nwpagecount=1 \else s\fi~\commafy{\nw@pages}}
+\def\@nwaddrange{<<add range to range list>>}
+@
+[[\nwpageword]] and [[\nwpageprep]] let you change the wording of the cross-reference
+information.
+<<noweb.sty>>=
+\def\nwpageword{chunk} % was page
+\def\nwpageprep{in} % was on
+<<warn of undefined reference to [[#1]] and add page ??>>=
+<<warn of undefined reference to [[#1]]>>%
+\nwix@cons\nw@pages{\\{\bf ??}}
+@
+\subsection{Sub-page references}
+This is the wonderful code that Dave Love provided to make page
+references like 7a, 7b, and so on.
+
+This code
+provides a mechanism for defining `page
+sub-references' using [[\sublabel{foo}]] referenced with
+[[\subpageref{foo}]]. Sub-references will be numbered like these real
+examples: \subpageref{ref:foo}, \subpageref{ref:bar},
+\subpageref{ref:baz}\sublabel{ref:foo}\sublabel{ref:bar}\sublabel{ref:baz}
+etc.\ unless there is only one on the page, in which case the letter
+will be dropped like this: \subpageref{ref:fred}.
+
+To be able to use [[\subpageref]] we must define the label with
+[[\sublabel]], used like label. (Using
+[[\ref]] with a label defined by [[\sublabel]] will
+produce the sub-reference number, by the way, and [[\pageref]]
+works as expected.) Note that
+[[\subpageref]] is robust and [[\ref]] and [[\pageref]] are redefined to be
+robust also, as they will be in future \LaTeX{} releases.
+Incidentally, these expand to the relevant text plus [[\null]]---you
+might want to strip this off, e.g.\ for sorting lists.
+
+
+There are various ways we could attack this task (which is made
+non-trivial by the well-known asynchrony of (La)\TeX's output
+routine), but
+they all must depend on hacks in the [[.aux]] file or a similar one.
+Joachim Schrod's [[fnpag.sty]] does the same sort of thing differently
+to this \LaTeX-specific approach. See [[latex.tex]] for enlightenment
+on the cross-referencing mechanism and the \LaTeX{} internals used
+below. [DL: The internals change in \LaTeX2e compared with
+\LaTeX~2.09. The code here still works, though.]
+
+@
+The [[\subpageref]] macro first does a normal [[\pageref]]. If the
+reference is actually defined, it then goes on to check whether the
+control sequence [[2on]]\LA{}{page referenced}\RA{} is defined and sets the
+[[\ref]] value to get [[a]] etc.\ if so. The magic, of course, is in
+defining the [[2on]] bit appropriately.
+[[\subpageref]] also tries to include the right hyperstuff for xhdvi.
+<<noweb.sty>>=
+\newcommand{\subpageref}[1]{%
+ \nwhyperreference{#1}{%
+ \@ifundefined{r@#1}%
+ {\pageref{#1}}%
+ {\@ifundefined{2on\@pageref{#1}}%
+ {\pageref{#1}}%
+ {\expandafter\expandafter\expandafter\nwthepagenum\csname r@#1\endcsname}}}}
+@ %def \subpageref
+[[\subpagepair]] produces a [[{subpage}{page}]] pair.
+<<noweb.sty>>=
+\newcommand{\subpagepair}[1]{% % produces {subpage}{page}
+ \@ifundefined{r@#1}%
+ {{0}{0}}%
+ {\@ifundefined{2on\@pageref{#1}}%
+ {{0}{\expandafter\expandafter\expandafter\@cdr\csname r@#1\endcsname\@nil}}%
+ {\@nameuse{r@#1}}}}
+@
+[[\@pageref]] is like [[\pageref]], but it expands to [[\relax]] without a warning
+if the reference is undefined.
+<<noweb.sty>>=
+\def\@pageref#1{\expandafter\expandafter\expandafter
+ \@cdr\csname r@#1\endcsname\@nil}
+@ %def \@pageref
+@
+[[\sublabel]] is like the [[\label]] command, except that it writes
+[[\newsublabel]] onto the [[.aux]] file rather than [[\newlabel]].
+For hyperreferencing, all labels must be hypertext
+anchors, for which we use [[\nwblindhyperanchor]].
+<<noweb.sty>>=
+\newcommand{\sublabel}[1]{%
+ \nwblindhyperanchor{#1}%
+ \@bsphack\if@filesw {\let\thepage\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string
+ \newsublabel{#1}{{}{\thepage}}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+@ %def \sublabel
+[[\nosublabel]] creates a label with a sub-page part of~0.
+<<noweb.sty>>=
+\newcommand{\nosublabel}[1]{%
+ \@bsphack\if@filesw {\let\thepage\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string
+ \newlabel{#1}{{0}{\thepage}}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+@ %def \sublabel
+@
+[[\newsublabel]] is the macro that does the important work. It is called with the
+same sort of arguments as [[\newlabel]]: the first argument is the
+label name and the second is [[{]]\LA ref value[[}{]]page number\RA[[}]].
+(Note that the only definition here which needs to be
+global is the one which is, and that [[\global]] is redefined by
+[[\enddocument]], which will bite you if you use it\dots)
+<<noweb.sty>>=
+<<definition of [[\newsublabel]]>>
+@
+First we extract the page number into [[\this@page]].
+<<definition of [[\newsublabel]]>>=
+\newcommand{\newsublabel}[2]{%
+ \edef\this@page{\@cdr#2\@nil}%
+@ %def \newsublabel
+@
+Then we see whether it's changed from the value of [[\last@page]]
+which was stashed away by the last [[\newsublabel]] (or is [[\relax]] if
+this is the first one). If the page has changed, we reset the
+counter [[\sub@page]] telling us how many sub-labels there have been
+on the page.
+<<definition of [[\newsublabel]]>>=
+ \ifx\this@page\last@page\else
+ \sub@page=\z@
+ \fi
+ \edef\last@page{\this@page}
+ \advance\sub@page by \@ne
+@
+If we've had at least two on the page, we define the
+[[2on]]\LA{}{page no.}\RA{} macro to indicate the fact.
+<<definition of [[\newsublabel]]>>=
+ \ifnum\sub@page=\tw@
+ \global\@namedef{2on\this@page}{}%
+ \fi
+@
+Then we write a normal [[\newlabel]] with the sub-reference as the
+normal reference value in the second argument.
+<<definition of [[\newsublabel]]>>=
+ \edef\@tempa{\noexpand\newlabel{#1}%
+ {{\number\sub@page}{\this@page}}}%
+ \@tempa}
+@
+We need to define these.
+<<noweb.sty>>=
+\def\last@page{\relax}
+\newcount\sub@page
+@ %def \last@page \sub@page
+@
+We use Rainer's new expandable definitions of [[\ref]] and
+[[\pageref]] to minimise the risk of nasty surprises.
+<<noweb.sty>>=
+% RmS 92/08/14: made \ref and \pageref robust
+\def\ref#1{\@ifundefined{r@#1}{{\bf ??}<<warn of undefined reference to [[#1]]>>}%
+ {\expandafter\expandafter\expandafter
+ \@car\csname r@#1\endcsname\@nil\null}}
+\def\pageref#1{\@ifundefined{r@#1}{{\bf ??}<<warn of undefined reference to [[#1]]>>}%
+ {\expandafter\expandafter\expandafter
+ \@cdr\csname r@#1\endcsname\@nil\null}}
+\def\@refpair#1{\@ifundefined{r@#1}{{0}{0}<<warn of undefined reference to [[#1]]>>}%
+ {\@nameuse{r@#1}}}
+<<warn of undefined reference to [[#1]]>>=
+\@warning{Reference `#1' on page \thepage \space undefined}
+@ %def \ref \pageref
+@
+
+Here a a couple of hooks for formatting sub-page numbers,
+which can be alphbetic, numeric, or omitted.\stylehook
+<<noweb.sty>>=
+\def\@alphasubpagenum#1#2{#2\ifnum#1=0 \else\@alph{#1}\fi}
+\def\@nosubpagenum#1#2{#2}
+\def\@numsubpagenum#1#2{#2\ifnum#1=0 \else.\@arabic{#1}\fi}
+\def\nwopt@nosubpage{\let\nwthepagenum=\@nosubpagenum\nwopt@nomargintag}
+\def\nwopt@numsubpage{\let\nwthepagenum=\@numsubpagenum}
+\def\nwopt@alphasubpage{\let\nwthepagenum=\@alphasubpagenum}
+\nwopt@alphasubpage
+@ %def \nwthepagenum nosubpage numsubpage alphasubpage
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B alphasubpage, numsubpage, nosubpage
+Number chunks by the number of the page on which they appear,
+followed by an alphabetic (numeric, not used) ``sub-page'' indicator.
+Defaults to
+.B alphasubpage.
+.B nosubpage
+implies
+.B nomargintag.
+@ \fi
+@
+
+\subsection{{\tt WEB}-like chunk numbering}
+Here's a righteous hack: we get the effect of WEB-like chunk numbers
+just by redefining [[\sublabel]] to use a counter instead of the current page number.
+Since the numbers are all distinct, no sub-page number is ever used.
+<<noweb.sty>>=
+\newcount\nw@chunkcount
+\nw@chunkcount=\@ne
+\newcommand{\weblabel}[1]{%
+ \@bsphack\if@filesw {\let\thepage\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string
+ \newsublabel{#1}{{}{\number\nw@chunkcount}}}}%
+ \expandafter}\@tempa
+ \global\advance\nw@chunkcount by \@ne
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+\def\nwopt@webnumbering{\let\sublabel=\weblabel\def\nwpageword{chunk}\def\nwpageprep{in}}
+@ %def \weblabel webnumbering
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B webnumbering
+Number chunks consecutively, in
+.I WEB
+style, instead of using sub-page numbers.
+@ \fi
+@
+\subsection{Indexing (identifier cross-reference) support}
+
+\subsubsection{Tracking definitions and uses}
+All index definitions and uses are associated with
+a label defined with [[\sublabel]] or [[\nosublabel]].
+Either the label is the [[\sublabel]] of the code chunk in which the definition or use
+appears, or it is a [[\nosublabel]] appearing in the middle of a
+documentation chunk.
+<<noweb.sty>>=
+% \nwindexdefn{printable name}{identifying label}{label of chunk}
+% \nwindexuse{printable name}{identifying label}{label of chunk}
+
+\def\nwindexdefn#1#2#3{\@auxix{\protect\nwixd}{#2}{#3}}
+\def\nwindexuse#1#2#3{\@auxix{\protect\nwixu}{#2}{#3}}
+
+\def\@auxix#1#2#3{% {marker}{id label}{subpage label}
+ \@bsphack\if@filesw {\let\nwixd\relax\let\nwixu\relax
+ \def\protect{\noexpand\noexpand\noexpand}%
+ \edef\@tempa{\write\@auxout{\string\nwixadd{#1}{#2}{#3}}}%
+ \expandafter}\@tempa
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+@ %def \nwindexdefn \nwindexuse \@auxix
+<<noweb.sty>>=
+% \nwixadd{marker}{idlabel}{subpage label}
+\def\nwixadd#1#2#3{%
+ \@ifundefined{nwixl@#2}%
+ {\global\@namedef{nwixl@#2}{#1{#3}}}%
+ {\expandafter\nwix@cons\csname nwixl@#2\endcsname{#1{#3}}}}
+@ %def \nwixadd
+@
+\subsubsection{Writing lists with commas and ``and''}
+You get one of
+\begin{itemize}
+\item ``$a$''
+\item ``$a$ and $b$''
+\item ``$a$, $\ldots$, $b$, and $c$''
+\end{itemize}
+Plus [[\\]] is applied to each element of the list.
+<<noweb.sty>>=
+\newcount\@commacount
+\def\commafy#1{%
+ {\nwix@listcount{#1}\@commacount=\nwix@counter
+ \let\@comma@each=\\%
+ \ifcase\@commacount\let\\=\@comma@each\or\let\\=\@comma@each\or
+ \def\\{\def\\{ and \@comma@each}\@comma@each}\else
+ \def\\{\def\\{, %
+ \advance\@commacount by \m@ne
+ \ifnum\@commacount=1 and~\fi\@comma@each}\@comma@each}\fi
+ #1}}
+@ %def \@commacount \commafy
+
+\subsubsection{New, improved index code}
+There are two kinds of lists.
+One kind is a generic list in which elements are preceded by [[\\]].
+If the elements are index elements, they are {\em[[{]]printable
+identifier[[}{]]label[[}]]} pairs.
+The other kind is a list of sub-page labels, in which each
+element is preceded by either [[\nwixd]] or [[\nwixu]].
+<<noweb.sty>>=
+\def\nwix@cons#1#2{% {list}{\marker{element}}
+ {\toks0=\expandafter{#1}\def\@tempa{#2}\toks2=\expandafter{\@tempa}%
+ \xdef#1{\the\toks0 \the\toks2 }}}
+@ %def \nwix@cons
+The reference list for an identifier labelled {\em id}
+is always called [[\nwixl@]]{\em id}.
+Most applications will work with reference lists by applying [[\\]]
+either to the defs or to the uses.
+<<noweb.sty>>=
+\def\nwix@uses#1{% {label}
+ \def\nwixu{\\}\let\nwixd\@gobble\@nameuse{nwixl@#1}}
+\def\nwix@defs#1{% {label}
+ \def\nwixd{\\}\let\nwixu\@gobble\@nameuse{nwixl@#1}}
+@ %def \nwix@uses \nwix@defs
+
+Some applications count uses to see whether there is any need to
+display information.
+<<noweb.sty>>=
+\newcount\nwix@counter
+\def\nwix@listcount#1{% {list with \\}
+ {\count@=0
+ \def\\##1{\advance\count@ by \@ne }%
+ #1\global\nwix@counter=\count@ }}
+\def\nwix@usecount#1{\nwix@listcount{\nwix@uses{#1}}}
+\def\nwix@defcount#1{\nwix@listcount{\nwix@defs{#1}}}
+@ %def \nwix@listcount \nwix@usecount \nwix@defcount
+@
+\subsubsection{Supporting a mini-index at the end of each chunk}
+When displaying identifiers used, show the identifier and its
+definitions.
+<<noweb.sty>>=
+\def\nwix@id@defs#1{% index pair
+ {{\Tt \@car#1\@nil}%
+ \def\\##1{~\subpageref{##1}}\nwix@defs{\@cdr#1\@nil}}}
+\def\nwidentuses#1{% list of index pairs
+ \nwcodecomment{Uses \let\\=\nwix@id@defs\commafy{#1}.}}
+@ %def \nwidentuses \nwix@id@defs
+The definitions section is a bit more complex, because it is omitted
+if none of the identifiers defined is ever used.
+<<noweb.sty>>=
+\def\nwix@totaluses#1{% list of index pairs
+ {\count@=0
+ \def\\##1{\nwix@usecount{\@cdr##1\@nil}\advance\count@ by\nwix@counter}%
+ #1\global\nwix@counter\count@ }}
+\def\nwix@id@uses#1#2{% {ident}{label}
+ \nwix@usecount{#2}\ifnum\nwix@counter>0
+ {\advance\leftskip by \codemargin
+ \nwcodecomment{{\Tt #1}, used \nwpageprep\ \@pagesl{\nwix@uses{#2}}.}}%
+ \else
+ \ifnw@hideunuseddefs\else
+ {\advance\leftskip by \codemargin \nwcodecomment{{\Tt #1}, never used.}}%
+ \fi
+ \fi}
+\def\nwidentdefs#1{% list of index pairs
+ \ifnw@hideunuseddefs\nwix@totaluses{#1}\else\nwix@listcount{#1}\fi
+ \ifnum\nwix@counter>0
+ \nwcodecomment{Defines:}%
+ {\def\\##1{\nwix@id@uses ##1}#1}%
+ \fi}
+<<noweb.sty>>=
+\newif\ifnw@hideunuseddefs\nw@hideunuseddefsfalse
+\def\nwopt@hideunuseddefs{\nw@hideunuseddefstrue}
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B hideunuseddefs
+Omit defined but unused identifiers from
+the local identifier cross-reference (Preston Briggs).
+@ \fi
+<<noweb.sty>>=
+\def\nwopt@noidentxref{%
+ \let\nwidentdefs\@gobble
+ \let\nwidentuses\@gobble}
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B noidentxref
+Omit the local identifier cross-reference which follows each code chunk.
+@ \fi
+
+\subsubsection{Support for chunk and identifier indices}
+The index in the back shows absolutely all the pages.
+<<noweb.sty>>=
+\def\nw@underlinedefs{% {list with \nwixd, \nwixu}
+ \let\\=\relax\def\nw@comma{, }
+ \def\nwixd##1{\\\underline{\subpageref{##1}}\let\\\nw@comma}%
+ \def\nwixu##1{\\\subpageref{##1}\let\\\nw@comma}}
+
+\def\nw@indexline#1#2{%
+ {\indent {\Tt #1}: \nw@underlinedefs\@nameuse{nwixl@#2}\par}}
+
+\newenvironment{thenowebindex}{\parindent=-10pt \parskip=\z@
+ \advance\leftskip by 10pt
+ \advance\rightskip by 0pt plus1in\par\@afterindenttrue
+ \def\\##1{\nw@indexline##1}}{}
+@
+The information comes from the list [[nwisx@i]].
+<<noweb.sty>>=
+\def\nowebindex{%
+ \@ifundefined{nwixs@i}%
+ {\@warning{The \string\nowebindex\space is empty}}%
+ {\begin{thenowebindex}\@nameuse{nwixs@i}\end{thenowebindex}}}
+@
+Here's a more efficient version for the external case:
+<<noweb.sty>>=
+\def\nowebindex@external{%
+ {\let\nwixadds@c=\@gobble
+ \def\nwixadds@i##1{\nw@indexline##1}%
+ \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}%
+ \begin{thenowebindex}\@input{\jobname.nwi}\end{thenowebindex}}}
+@
+That list ([[nwisx@i]]) is created by calls to [[\nwixlogsorted{i}]].
+<<noweb.sty>>=
+\def\nwixlogsorted#1#2{% list data
+ \@bsphack\if@filesw
+ \toks0={#2}\immediate\write\@auxout{\string\nwixadds{#1}{\the\toks0}}
+ \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack}
+@
+[[nwixs@c]] and [[nwixs@i]] are sorted lists of chunks and identifiers, respectively.
+<<noweb.sty>>=
+\def\nwixadds#1#2{%
+ \@ifundefined{nwixs@#1}%
+ {\global\@namedef{nwixs@#1}{\\{#2}}}%
+ {\expandafter\nwix@cons\csname nwixs@#1\endcsname{\\{#2}}}}
+\let\nwixaddsx=\@gobbletwo
+@
+If an external index is used, we need a [[.nwi]] file,
+[[\nwixadds]] is to be ignored, and we use [[\nwixaddsx]].
+<<noweb.sty>>=
+\def\nwopt@externalindex{%
+ \ifx\nwixadds\@gobbletwo % already called
+ \else
+ \let\nwixaddsx=\nwixadds \let\nwixadds=\@gobbletwo
+ \let\nowebindex=\nowebindex@external
+ \let\nowebchunks=\nowebchunks@external
+ \fi}
+@
+\iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B externalindex
+Use an index generated with
+.I noindex(1)
+(q.v.).
+@ \fi
+@
+<<noweb.sty>>=
+\def\nowebchunks{%
+ \@ifundefined{nwixs@c}%
+ {\@warning{The are no \string\nowebchunks}}%
+ {\begin{thenowebchunks}\@nameuse{nwixs@c}\end{thenowebchunks}}}
+\def\nowebchunks@external{%
+ {\let\nwixadds@i=\@gobble
+ \def\nwixadds@c##1{\nw@onechunk##1}%
+ \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}%
+ \begin{thenowebchunks}\@input{\jobname.nwi}\end{thenowebchunks}}}
+ \@namedef{r@nw@notdef}{{0}{(never defined)}}
+<<noweb.sty>>=
+\def\nw@chunkunderlinedefs{% {list of labels with \nwixd, \nwixu}
+ \let\\=\relax\def\nw@comma{, }
+ \def\nwixd##1{\\\underline{\subpageref{##1}}\let\\\nw@comma}%
+ \def\nwixu##1{\\\subpageref{##1}\let\\\nw@comma}}
+<<noweb.sty>>=
+\def\nw@onechunk#1#2#3{% {name}{label of first definition}{list with \nwixd, \nwixu}
+ \@ifundefined{r@#2}{}{%
+ \indent\LA #1~{\nwtagstyle\subpageref{#2}}\RA
+ \if@nwlongchunks{~\nw@chunkunderlinedefs#3}\fi\par}}
+<<noweb.sty>>=
+\newenvironment{thenowebchunks}{\vskip3pt
+ \parskip=\z@\parindent=-10pt \advance\leftskip by 10pt
+ \advance\rightskip by 0pt plus10pt \@afterindenttrue
+ \def\\##1{\nw@onechunk##1}}{}
+<<noweb.sty>>=
+\newif\if@nwlongchunks
+\@nwlongchunksfalse
+\let\nwopt@longchunks\@nwlongchunkstrue
+@ \iffalse
+<<man page: [[\noweboptions]]>>=
+.TP
+.B longchunks
+When expanding
+.B "\\\\nowebchunks,"
+show page numbers of definitions and uses of each chunk.
+@ \fi
+
+@
+\subsection{support for hypertext with {\tt hyper.sty}}
+Initial support courtesy of Balasubramanian Narasimhan.
+<<noweb.sty>>=
+\newcommand\nwhyperreference[2]{%
+ \@ifundefined{hyperreference}%
+ {#2\global\let\nwhyperreference\@gobble}%
+ {\hyperreference{#1}{#2}\global\def\nwhyperreference\hyperreference}}
+\newcommand\nwblindhyperanchor[1]{%
+ \@ifundefined{blindhyperanchor}%
+ {\global\let\nwblindhyperanchor\@gobble}%
+ {\blindhyperanchor{#1}\global\def\nwblindhyperanchor\blindhyperanchor}}
+@
+\subsection{Support for hypertext translation to HTML}
+<<noweb.sty>>=
+\newcommand\nwanchorto{%
+ \begingroup\let\do\@makeother\dospecials
+ \catcode`\{=1 \catcode`\}=2 \nw@anchorto}
+\newcommand\nw@anchorto[1]{\def\nw@next{#1}\endgroup\nw@anchortofin}
+\newcommand\nw@anchortofin[1]{#1\footnote{See URL \texttt{\nw@next}.}}
+\let\nwanchorname\@gobble
+@
+\clearpage
+\section{The {\tt nwmac} macros for use with plain {\TeX}}
+
+First we make [[@]] a letter so that we can use `private' macro names.
+<<nwmac.tex>>=
+\catcode`\@=11
+<<nwmac.tex>>=
+% scale cmbx10 instead of using cmbx12 because {\LaTeX} does, so fonts exist
+\font\twlbf=cmbx10 scaled \magstep1
+\font\frtbf=cmbx10 scaled \magstep2
+% These fonts don't work with xdvi!
+
+\advance\hoffset 0.5 true in
+\advance\hsize -1.5 true in
+\newdimen\textsize
+\textsize=\hsize
+\def\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}
+@ %def \textsize \today
+<<nwmac.tex>>=
+\long\def\ifundefined#1#2#3{%
+ \expandafter\ifx\csname#1\endcsname\relax
+ #2%
+ \else#3%
+ \fi}
+
+\ifundefined{myheadline}
+ {\headline={\hbox to \textsize{\tentt\firstmark\hfil\tenrm\today\hbox
+ to 4em{\hss\folio}}\hss}}
+ {\expandafter\headline\expandafter{\myheadline}}
+
+\ifundefined{myfootline}
+ {\footline={\hfil}}
+ {\expandafter\footline\expandafter{\myfootline}}
+@ %def \ifundefined
+<<nwmac.tex>>=
+\def\semifilbreak{\vskip0pt plus1.5in\penalty-200\vskip0pt plus -1.5in}
+\raggedbottom
+@ %def \semifilbreak
+<<nwmac.tex>>=
+%
+% \chapcenter macro to produce nice centered chapter titles
+%
+\def\chapcenter{\leftskip=0.5 true in plus 4em minus 0.5 true in
+ \rightskip=\leftskip
+ \parfillskip=0pt \spaceskip=.3333em \xspaceskip=.5em
+ \pretolerance=9999 \tolerance=9999
+ \hyphenpenalty=9999 \exhyphenpenalty=9999}
+@ %def \chapcenter
+<<nwmac.tex>>=
+% \startsection{LEVEL}{INDENT}{BEFORESKIP}{AFTERSKIP}{STYLE}{HEADING}
+% #1 #2 #3 #4 #5 #6
+%
+% LEVEL: depth; e.g. part=0 chapter=1 sectino=2...
+% INDENT: indentation of heading from left margin
+% BEFORESKIP: skip before header
+% AFTERSKIP: skip after header
+% STYLE: style of heading; e.g.\bf
+% HEADING: heading of the sectino
+%
+\def\startsection#1#2#3#4#5#6{\par\vskip#3 plus 2in
+ \penalty-200\vskip 0pt plus -2in
+ \noindent{\leftskip=#2 \rightskip=0.5true in plus 4em minus 0.5 true in
+ \hyphenpenalty=9999 \exhyphenpenalty=9999
+ #5#6\par}\vskip#4%
+ {\def\code##1{[[}\def\edoc##1{]]}\message{[#6]}}
+ \settocparms{#1}
+ \def\themodtitle{#6}
+%%%% {\def\code{\string\code}\def\edoc{\string\edoc}%
+ \edef\next{\noexpand\write\cont{\tocskip
+ \tocline{\hskip\tocindent\tocstyle\relax\themodtitle}
+ {\noexpand\the\pageno}}}\next % write to toc
+ %}
+}
+@ %def \startsection
+<<nwmac.tex>>=
+\def\settocparms#1{
+ \count@=#1
+ \ifnum\count@<1
+ \def\tocskip{\vskip3ptplus1in\penalty-100
+ \vskip0ptplus-1in}%
+ \def\tocstyle{\bf}
+ \def\tocindent{0pt}
+ \else
+ \def\tocskip{}
+ \def\tocstyle{\rm}
+ \dimen@=2em \advance\count@ by \m@ne \dimen@=\count@\dimen@
+ \edef\tocindent{\the\dimen@}
+ \fi
+}
+@ %def \settocparms
+<<nwmac.tex>>=
+\def\tocline#1#2{\line{{\ignorespaces#1}\leaders\hbox to .5em{.\hfil}\hfil
+ \hbox to1.5em{\hss#2}}}
+@ %def \tocline
+<<nwmac.tex>>=
+\def\section#1{\par \vskip3ex\noindent {\bf #1}\par\nobreak\vskip1ex\nobreak}
+\def\chapter#1{\vfil\eject\startsection{0}{0pt}{6ex}{3ex}{\frtbf\chapcenter}{#1}}
+\def\section#1{\startsection{1}{0pt}{4ex}{2ex}{\twlbf}{#1}}
+\def\subsection#1{\startsection{2}{0pt}{2ex}{1ex}{\bf}{#1}}
+\def\subsubsection#1{\startsection{3}{0pt}{1ex}{0.5ex}{\it}{#1}}
+\def\paragraph#1{\startsection{4}{0pt}{1.5ex}{0ex}{\it}{#1}}
+
+<<kernel>>
+
+\def\nwfilename#1{\vfil\eject\mark{#1}}
+
+\def\nwbegindocs#1{\filbreak}
+\def\nwenddocs{\par}
+\def\nwbegincode#1{\par\nobreak
+ \begingroup\setupcode\newlines\parindent=0pt\parskip=0pt
+ \let\oendmoddef=\endmoddef \let\oplusendmoddef=\plusendmoddef
+ \def\endmoddef{\oendmoddef\par}\def\plusendmoddef{\oplusendmoddef\par}%
+ \hsize=\codehsize\noindent\bchack}
+\def\nwendcode{\endgroup}
+{\catcode`\^^M=\active % make CR an active character
+ \gdef\bchack#1^^M{\relax#1}%
+}
+@ %def \section \chapter \section \subsection \subsubsection \paragraph
+@ %def \nwbegindocs \nwenddocs \nwbegincode \nwendcode \nwfilename
+<<nwmac.tex>>=
+\edef\contentsfile{\jobname.toc } % file that gets table of contents info
+\def\readcontents{\expandafter\input \contentsfile}
+
+\newwrite\cont
+\openout\cont=\contentsfile
+\write\cont{\string\catcode`\string\@=11}% a hack to make contents
+@ %def \readcontents \cont
+<<nwmac.tex>>=
+ % take stuff in plain.tex
+\def\bye{%
+ \write\cont{}% ensure that the contents file isn't empty
+ \closeout\cont
+ \vfil\eject\pageno=-1 % new page causes contents to be really closed
+ \topofcontents\readcontents\botofcontents
+ \vfil\eject\end}
+\def\topofcontents{\vfil\mark{{\bf Contents}}}
+\def\botofcontents{}
+@ %def \bye \topofcontents \botofcontents
+<<nwmac.tex>>=
+\let\em=\it
+% used to produce an itemized (bulleted) list in plain {\TeX}
+% such lists can be nested
+% mostly useful with WEB
+
+% Usage:
+% \itemize
+% \item First thing
+% \item second thing
+% \enditemize
+
+\newcount\listlevel
+\listlevel=0
+\newdimen\itemwidth
+\itemwidth=3em
+
+\def\itemize{\begingroup\advance\listlevel by1
+ \def\item{\par\noindent
+ \raise2pt\llap{$\scriptstyle\bullet$\ }\ignorespaces}%
+ \def\nameditem##1{\par\noindent
+ \llap{\rlap{##1}\hskip\itemwidth}\ignorespaces}%
+ \par\advance\leftskip by\itemwidth\advance\rightskip by0.5\itemwidth}
+\def\enditemize{\par\endgroup\noindent\ignorespaces}
+
+\let\begindocument=\relax
+@ %def \listlevel \itemwidth \itemize \enditemize
+Finally we make [[@]] `other' again.
+<<nwmac.tex>>=
+\catcode`\@=12
+@
+\section{Chunks} \nowebchunks
+\twocolumn[\section{Index}]
+\nowebindex*
+@
+\end{document}
+
+
diff --git a/web/noweb/src/tex/support.pdf b/web/noweb/src/tex/support.pdf
new file mode 100644
index 0000000000..4d10d9ba20
--- /dev/null
+++ b/web/noweb/src/tex/support.pdf
Binary files differ
diff --git a/web/noweb/src/tex/support.ps b/web/noweb/src/tex/support.ps
new file mode 100644
index 0000000000..4d7263eeea
--- /dev/null
+++ b/web/noweb/src/tex/support.ps
@@ -0,0 +1,6156 @@
+%!PS-Adobe-2.0
+%%Creator: dvips(k) 5.994 Copyright 2014 Radical Eye Software
+%%Title: support.dvi
+%%CreationDate: Wed Dec 2 20:33:50 2015
+%%Pages: 7
+%%PageOrder: Ascend
+%%BoundingBox: 0 0 612 792
+%%DocumentFonts: CMR10 CMTT10 CMBX12 CMR7 CMR8 CMSY9 CMTI9 CMSY10 CMMI8
+%%+ CMTT9 CMTI10 CMSL10 CMMI7 CMMI10 CMSY7 CMTT12
+%%DocumentPaperSizes: Letter
+%%EndComments
+%DVIPSWebPage: (www.radicaleye.com)
+%DVIPSCommandLine: dvips -pp 18-24 support
+%DVIPSParameters: dpi=600
+%DVIPSSource: TeX output 2015.12.02:2032
+%%BeginProcSet: tex.pro 0 0
+%!
+/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S
+N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72
+mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0
+0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{
+landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize
+mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[
+matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round
+exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{
+statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0]
+N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin
+/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array
+/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2
+array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N
+df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A
+definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get
+}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub}
+B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr
+1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S
+/BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy
+setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask
+restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn
+/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put
+}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{
+bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A
+mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{
+SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{
+userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X
+1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4
+index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N
+/dir 0 def/dyy{/dir 0 def}B/dyt{/dir 1 def}B/dty{/dir 2 def}B/dtt{/dir 3
+def}B/p{dir 2 eq{-90 rotate show 90 rotate}{dir 3 eq{-90 rotate show 90
+rotate}{show}ifelse}ifelse}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0
+N/Ry 0 N/V{}B/RV/v{/Ry X/Rx X V}B statusdict begin/product where{pop
+false[(Display)(NeXT)(LaserWriter 16/600)]{A length product length le{A
+length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse}
+forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{
+BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat
+{BDot}imagemask grestore}}ifelse B/QV{gsave newpath transform round exch
+round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0
+rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B
+/M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}
+B/g{0 M}B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p
+-3 w}B/n{p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{
+0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end
+
+%%EndProcSet
+%%BeginProcSet: texps.pro 0 0
+%!
+TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2
+index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll
+exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0
+ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{
+pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get
+div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type
+/nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end
+definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup
+sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll
+mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[
+exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if}
+forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def
+end
+
+%%EndProcSet
+%%BeginProcSet: special.pro 0 0
+%!
+TeXDict begin/SDict 200 dict N SDict begin/@SpecialDefaults{/hs 612 N
+/vs 792 N/ho 0 N/vo 0 N/hsc 1 N/vsc 1 N/ang 0 N/CLIP 0 N/rwiSeen false N
+/rhiSeen false N/letter{}N/note{}N/a4{}N/legal{}N}B/@scaleunit 100 N
+/@hscale{@scaleunit div/hsc X}B/@vscale{@scaleunit div/vsc X}B/@hsize{
+/hs X/CLIP 1 N}B/@vsize{/vs X/CLIP 1 N}B/@clip{/CLIP 2 N}B/@hoffset{/ho
+X}B/@voffset{/vo X}B/@angle{/ang X}B/@rwi{10 div/rwi X/rwiSeen true N}B
+/@rhi{10 div/rhi X/rhiSeen true N}B/@llx{/llx X}B/@lly{/lly X}B/@urx{
+/urx X}B/@ury{/ury X}B/magscale true def end/@MacSetUp{userdict/md known
+{userdict/md get type/dicttype eq{userdict begin md length 10 add md
+maxlength ge{/md md dup length 20 add dict copy def}if end md begin
+/letter{}N/note{}N/legal{}N/od{txpose 1 0 mtx defaultmatrix dtransform S
+atan/pa X newpath clippath mark{transform{itransform moveto}}{transform{
+itransform lineto}}{6 -2 roll transform 6 -2 roll transform 6 -2 roll
+transform{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll
+curveto}}{{closepath}}pathforall newpath counttomark array astore/gc xdf
+pop ct 39 0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}
+if}N/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1
+-1 scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3
+get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip
+yflip not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub
+neg 0 TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{
+noflips{TR pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop
+90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get
+neg sub neg TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr
+1 get neg sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr
+2 get ppr 0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4
+-1 roll add 2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S
+TR}if}N/cp{pop pop showpage pm restore}N end}if}if}N/normalscale{
+Resolution 72 div VResolution 72 div neg scale magscale{DVImag dup scale
+}if 0 setgray}N/psfts{S 65781.76 div N}N/startTexFig{/psf$SavedState
+save N userdict maxlength dict begin/magscale true def normalscale
+currentpoint TR/psf$ury psfts/psf$urx psfts/psf$lly psfts/psf$llx psfts
+/psf$y psfts/psf$x psfts currentpoint/psf$cy X/psf$cx X/psf$sx psf$x
+psf$urx psf$llx sub div N/psf$sy psf$y psf$ury psf$lly sub div N psf$sx
+psf$sy scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub
+TR/showpage{}N/erasepage{}N/setpagedevice{pop}N/copypage{}N/p 3 def
+@MacSetUp}N/doclip{psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll
+newpath 4 copy 4 2 roll moveto 6 -1 roll S lineto S lineto S lineto
+closepath clip newpath moveto}N/endTexFig{end psf$SavedState restore}N
+/@beginspecial{SDict begin/SpecialSave save N gsave normalscale
+currentpoint TR @SpecialDefaults count/ocount X/dcount countdictstack N}
+N/@setspecial{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs
+neg 0 rlineto closepath clip}if ho vo TR hsc vsc scale ang rotate
+rwiSeen{rwi urx llx sub div rhiSeen{rhi ury lly sub div}{dup}ifelse
+scale llx neg lly neg TR}{rhiSeen{rhi ury lly sub div dup scale llx neg
+lly neg TR}if}ifelse CLIP 2 eq{newpath llx lly moveto urx lly lineto urx
+ury lineto llx ury lineto closepath clip}if/showpage{}N/erasepage{}N
+/setpagedevice{pop}N/copypage{}N newpath}N/@endspecial{count ocount sub{
+pop}repeat countdictstack dcount sub{end}repeat grestore SpecialSave
+restore end}N/@defspecial{SDict begin}N/@fedspecial{end}B/li{lineto}B
+/rl{rlineto}B/rc{rcurveto}B/np{/SaveX currentpoint/SaveY X N 1
+setlinecap newpath}N/st{stroke SaveX SaveY moveto}N/fil{fill SaveX SaveY
+moveto}N/ellipse{/endangle X/startangle X/yrad X/xrad X/savematrix
+matrix currentmatrix N TR xrad yrad scale 0 0 1 startangle endangle arc
+savematrix setmatrix}N end
+
+%%EndProcSet
+%%BeginFont: CMSY7
+%!PS-AdobeFont-1.0: CMSY7 003.002
+%%Title: CMSY7
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMSY7.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMSY7 known{/CMSY7 findfont dup/UniqueID known{dup
+/UniqueID get 5096648 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMSY7 def
+/FontBBox {-15 -951 1251 782 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMSY7.) readonly def
+/FullName (CMSY7) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle -14.04 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 0 /minus put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CD06DFE1BE899059C588357426D7A0
+7B684C079A47D271426064AD18CB9750D8A986D1D67C1B2AEEF8CE785CC19C81
+DE96489F740045C5E342F02DA1C9F9F3C167651E646F1A67CF379789E311EF91
+511D0F605B045B279357D6FC8537C233E7AEE6A4FDBE73E75A39EB206D20A6F6
+1021961B748D419EBEEB028B592124E174CA595C108E12725B9875544955CFFD
+028B698EF742BC8C19F979E35B8E99CADDDDC89CC6C59733F2A24BC3AF36AD86
+1319147A4A219ECB92D0D9F6228B51A97C29547000FCC8A4D9DAFF1B3EA76067
+C5493B69F73B89C8B61804A34FCEC826343337CCDFFCE17BF343EA8034BF95AA
+14C56862C2C052569AFB236E1F1795F05150C8F28DFEF6BF4BCBACB678D00036
+30EE84FEB44B1A8438185EB45654E6853C1159B073E54292D135F0961A64E8A5
+AAE49C4BA9C44156C123426212120F99F3E8B7425752A5FE384AAEF755A8464B
+51F015F9E2967477D57B22627D75CEF8AAAF0AEBD504EB46D0289DFC8D86C972
+F042BD88A90A53613DD93D8A7A8460E63D85F6C15C000C0AAEE4BD5130B6E668
+8C9B3F3FFD804745DA1D5EC0AB85C96E1724FA67F9324C59275415182AB48D57
+9722DCF602396AD4B5C075A5A89A5D005C9FE11273E5FBDDD1800F11BBDF6AEC
+6711C5633A73AC5DF038BA521AC492E138F7FFC7C5438FFD32FEAA1128C66E83
+0D3AA40665F05E62D7EF00B1B0596162C402A34B6BAE6300D43F3DFCC84860F5
+C0F0F1CE28FC60642BBFE9BC9102E80146774CDC88F9C250DE762D24A3484BCD
+1D26B6D9FE981CA5AAB2A4BEDC528115043DC18D7105735D7528C2C5DD89A812
+75B5D7B2E5A586FBB0C061E708F92C1552F64A296490BD0F20243986A4707FF9
+8AB3C917B8DB92F19DCA6B9D4A1DB57515E51DD85D5C9D2CAF7A036AA3F9E9B1
+5B5E099CC05A9126AB274C17D75CB4FAF78052366D2F21EDAADF84B22A2D645A
+3E65C4BC0F540B5D9609D88DD0E4CBEEF87C16447D43A5F98528FD45ADD10DE6
+41AEC411FD6929308F0E4F48A8D9C9EE386E920D41C1CC98A52073011DF5BD28
+5683F280B5CF7F27DC50930C81D344FF5A8A9258A207D2531AC21A735B14155B
+C22C752DD22AA33C52D6D4D053B3E46FD4C9129068DFF52695A3A9184D04E8EC
+93696A3FEC3AEB3814D9015EC14C22EC3ABD5070E8C28A3B42F5596D948212B4
+AFB9978A0A361135C9E18CBDC98E0D1E8BDC17E25DDB3D52E86127E5AAECC55D
+FEE61693190E378978EF1BBD4D1AF005D511C7607CCFA4BCBD3EC427CAD82809
+B725B25AE8A03EE88F80A7732A571A2317E0B6A0D072EE8CE2EB9E033CDCC899
+B64CF4FA1C708A885442062F08D3D8DAF44C066EE278714D1486EB709D327865
+A483F62709E89D08291F044325208EBA758DD459481334F5D9AE3BB61B3020F2
+A4538CFC2C94BE84C920BE80806FDCEE394230730E049333A7E16509207514FD
+695B5E0AEA9E4A9737311AA0B33B15F6769FF865D1ACB63DC6201C3F1062A3FD
+1B446C1857460745917A36289DD57C94FE6240F4A40FBDFC10E91B91B79029D9
+9F1B9C74E8E5AA011A0ECBEC660230AD5929F01D0325D15FDC0040406F124021
+02AE176F4C98BAC1706F03C2B5B40F325A50CA4683B2BB4605E68E72D0CBDC2D
+96B3BBCDD01201B650A7E7744D58D1E36D81FBF72E0A875FF29B4C109A1950FC
+9621B18D58806392EEE9841794DFD39E3C4E20D45384FE07F9D445F143B922D1
+AB350AA6DFC51FCF767B141A392D6A8B633AACBCEC9F56A0CF40AB08020EE63E
+08CC0BE01B40E86388A65F5869F2F4D022DD4B912031CB8CEDEDFC2473772569
+5B28F66AB74CD7902A0061AA3547D13C7F0C6EEEA7B0BD316694A94E4D672520
+EA044AB28D8D01076C486CE456EDA1811F7ACA75D27473080D27D3E681E35FC6
+447046120C6CC4C17674F0F051570A79DCA74848F3F300B58B19018430D99858
+CA5504084D6BB74CFDB635B6866974A9AF05DF201C69352B2663B0623E7828B9
+5EC5FFA8D8F10A7C28000F8C679B180067D5481D6315BF1C4194EB171C8F3CE2
+4CE319975B9E948D907F9F7EEAF07089844391555F329E331D52FF114668B8A4
+80704B3C6AC0CCAA2F5D043CE44E65EDA89A0CA854CFDCB11D549B7FA72EDB90
+D35353C34A771B1FAF96F83FCA5258AAB65384BAFFCE448690C1432A1F749C20
+5817205185F973FA098BA856584753E75EBEBF387FC155202885F5B67117DD7E
+70D1CD887183C5573B6FB607D4F6CC9F8B94B09B3F3AEC2EF1E6A320CF6D0112
+63046321941D1FB3F2140B59370AA9387E24D579D389A166A10C989497FE9549
+34E1AC2E546CC06C5308460DBEF3E1AEEB6CBB0FFDAC458E61DE3391480CF5CD
+34A647D4DE15B81131B7D1F9EED4C6837A32E89B0EAAD6A05F5F67518655E5DB
+224D4833CEC60D5DBBDB8A03FB1A9730589BB4F0FF56191D17E73B9562E0C356
+B188882B36F9505F6F42EB2644FEE125C2A7D12227ABC8ADB924E88B0A9E8DC2
+79762523B0B88DBBE6AC7968A46BD9E9F0C3F03F5F64724CA07782195F01F130
+30DBE895C212E0EE20162D863F46A674D85232FA0DEE69A8DF019794AF6873AD
+9CC2A5EEEF9393313CA519BF95C08ADF7A75B6F53EDCDC39851D20E58B97CA57
+A7523717AA1821DEA94C8A9F8B82346B16D92D15AEDC16F0011A45A44B09DE47
+08CBA46E8511D0C5CC83F952EEFA4ACFA7F3D7FA5E113EF6B70E5ABA6F1AD3B1
+E4D3B15AC6D5C3BC70A3946F411A7D965D6FA9D7B6C6ECE19B2C29A2FF476251
+EBF0CF3BF658A1D896323706172746F58B2DE49F8B7E431E20304A42694CCF73
+11C4E9E96260CC442E2938A1E27EE6744C7CAB01634C8210CE40488B9CBD757C
+4277B5E3E43C7560291D945F9128AF1F85924003418F96458ADDC5BB8EC431D5
+AC9093D20DEA69B92454613BC1A82DAD4FBF8E56084494D9D2FFABD82A7C9847
+171FE36B265B546F3072B0923840E6C6BB12CA53E05A99F0E8FD4F5109782746
+7CAB9B35B68050230736AE624B7862D1244C7D9BE4D1CAAE21B123D1E8372377
+F1FEF269A9A2EDF02CE0CC8BF92FD7EF09556987B8A3BF6D8C0A663DB6B9742B
+E9AC61A449106AF1EA7ACAD40AC6F59427CC51865E6A90CF2AEED8D6037BA70E
+4ADDAF622CDE877C98C3B2006B4721FC9BA18E30F0752BD4ACE36221F5CD1497
+8FEDA5D643BE2EE007970A68E53D85975116E6CC09F0039A09EBAF0CA4B0EED6
+A485CC0B69E526033FD1C1190BC5686739CE13D1AE8EBCABC01FCFF26141867C
+44ED291196E546369129B9F759FDD7DC21BAF0A528FC34BA9FA8937813953644
+C539F9DA4E55E83DB3D6DA309C562DA1330B157957B18F7618544AB738E25F16
+F0517CD13C1F11BB8EA056BDC575D77CDC526EF497639DD89C2098660C5C45B2
+D7CF715AC5E76847E0D3178360DAC1BAF6ACAEE72453B845B9F86621C166857B
+029CEF5AFE29D1EDB4CA3AD7D008B7550A779E0066D7312DD6C7AFE1C0BFFF25
+7B062B0DF30032EA2A2FE3CC46C96A3A0BA1888D1D2B05424A59ABE3EE928ED8
+B67F507EFA78AE128F58B54634C7F534B3D0F4AFC23E38FB56EB39CFA425FD37
+848545EAD03EDC5A9E796CEFB345F527615C785963F536972EBD9CFC4A6A4A07
+5A31A508CA147FBB762ADD198CE36DF86730FCE2B643D1E7DF0BDE800DE7AF89
+44A36B04193E44231E08919EE91A8B559646DC4DFAFF0AD891890A0A88FFA8EF
+B066BCB7AFCA409C51889E7FEB33F19A3CB1268BD0EA74AF29C1401BABD16F87
+ACF7DD65A8513DA9995C5092C36A774BC4260113360D29AF7ADF5D22B5B58E7E
+A9BEFC33B9A91D2C397B27A81087376CB623318A8362C3FA9CBE3026675723C2
+E711910DDB328E0EE3FCE219F44FE528B70E58B8E6CDB4AAB48237DD933D9639
+E9D4F9EADAA8D46537D964D75C27F210B0C2473CB60D65F61BBD91ADE01576BF
+77C49E31936138B0FBA066BE910DE1B1F0E4FFB5E81038E8656ABFF08DFD923E
+6BA2AFEDCE6998BBF7045393C34811501586A4846E5B942C8E99D4C481D3AE60
+2796ADBB5242D59F1116EBB828014BD903EF58B223DFD18BFBAAE4D348876B06
+CAC10B7AF0DC270E6702A3F75D4DCEF872F2CDB9470AC9A1DC1ABCB55636D26F
+9CB6BF27A0DAEB1F62AFEC12F55F78C9B59AC6DA9DB4B45444B0C582DB4DB8A4
+B31EF4AFB77988E92FC0B257374B4408406490D9AFCC495316D6C08BEC9A76C7
+12371E14417711EF802FB7151B3F6A2580C97527C9C3A0FAAB8D62FD992AA18F
+EBEB36F7910186CD5F70A55DFE932757C299D9D2289796769A00A0C6ABD18F82
+E0D4E95D6477E67B4C012DBBD098FE20E2F15C412DD2AD5471A65EACE05B3A1A
+0C9C430BAEF4887F2CCE668116B87FFD9DAB4B9B3605CD26E6B12488058AFA30
+8843791A95BB322DF5C47387F3EC72343855D6B23D72144EB5EB5157B8B238FD
+6C71DDDA64C9539F66A7DD569FFF43DBE4A8F0608A3CBD354DD9BAB5E3C756DD
+92C3C1B3E169D86A2230299432488BC04A87E08A80809F9968676DF9157B1C91
+27C664ABCCBA9997FAD8966F766B325086899D1FE44581FE07C97688B3E15B0C
+234A22646C32BB965B9BFD2CD34854D1488AAF021E169BF9CA9665CF040E25A8
+16156C80A2F47397CD370AAEDA731E0D14FBEE1E51A17DB972D96DBCCE33F937
+5CDBF1A650BF1D3536BA4CB7A1CACFD5CB457E2368A660A62AC26E64A631B2BA
+6B08EBE42E02D9B1B2E95BF9F0A6B59C96A122968FD46A4D17BA3D018CCBA0F9
+80BA3C1E6C683111AFF79303CF64F1D2CCBD7571C6E09DD9B27B8E101BE219F0
+E075880A0E367885AC94143E777DAE455B990383100EADF786300602C2CE28F2
+4F44662FDF03BD39A5181912D8F1243C36FF88882CFC4B34C1D4EBBC01D96A7D
+9CE5303042D1B21042E4FEAA455F22A01333FCAD7E4AACA5D3A5386331985F6B
+9B247EC6310BB07507321BEF3E4ECFC3B915AAA6E029B3999644C987640863B0
+5DCF58CE479497AFAD1208FEFD1796E74467E9F7867C313A3412E6923F4C9144
+C69EFA17965056DF043DB465BF2F1E191706D3AAB47E6AD5C9767E4A73B29F2D
+E2E579D0262237568F82B360ADB6D0219B7535EFD02DD0688CDD23D84FC4F308
+5D2D0010B1A9F4F0321A00C154672D21708B66B91ADCF98BAC7A2F94848E9A4E
+86CC82EDD0399BD9F13E43359E71F80086B9B0C3B6D08831D4479ED83E7892C4
+90C477BD1F06DFEBBF60F26516EECDEFE4787EEA8683754F2B257D0BAA607DBA
+35EC6D1618C2FDF3881827F92D793ECF152D761F2423A96210F582DC9B90120F
+26A33025414716A5E6F56D712E31BABE5047EC4855B767AC63D793995C9E074B
+6E35C7E5255FBF4C3F17E7AD7B2A6C5F7459794FC94306B581536910F244BF5A
+3158E821CE75F4B0565EBE985DF24DAA92F9C1D848EEC6B88E21FB6C51125872
+1752F7352291960E5BD36F78AABBCF6DAA4D07AF56E4B6058AAB13D41BCDAA14
+C0D63C6807FCD0E2B4B9CC892F224843173A75DC53A8F0FA396959C2E2CFE3F5
+9B1C8B62797F34E7A0BFCF0787C73FEF98442234A617CF161829498035D30B29
+ADFEAABD0B496E8A2E764D22DB7737F950FC5982F1C5F4FD414C1B0202F40FBA
+62C81B8F0E836CD73D79366FD62388B437B81FC673442EE34BF27454F72A08F3
+389E60CE28A050601A42FB4491C60DC02EC008E6B9DD2495522BBEC7293E2923
+120584E88412DA7137397B41A28706B1CC6BB0C80709A2A4BA79822D245757A4
+3EE454198942ED2316FAEB981F7615E642167620EBDDC5B271E273216EB119C6
+4F2F0412F0BA6E3BA396217597575C6739194E1F839232FF088FDDFD3695A5CB
+9A0E220389938596D8BDB183138E1F73F64512E4FAB5E1328F9B42364E3113B8
+004BE2CA0B074EE271BBE0260D31CE555D535C16EBB528747EBAFFF253E659DA
+3A377CBE0B296276AACF0294CF90FDAADB4EAD5E2F600E5B2A018DEFB86FF61C
+84296480A425687CCE37D671472537E897AFD4B8C6A6175E1ADDF9AD24DFC5C3
+A73E18AC2D9B28BDA2F17D51DB3521945850DAF0EE48B0FAC271544C1B4F3B2D
+53BFC8DE32BA366FB1FEC0DD6C0B1FEA374CBE2B96F5B235A1D83A240DB442C7
+1460980A3E5B96AE3D5784DE2C2DFFA671E0A856DB2FF4130E5905F3D5338856
+C11A468D867D0C6EC585F1AD3E7164B8598BB59973B9A952FAE819F052A6554D
+EDC342BCCB0525905D1D27ECB9EE43847B69AE116F494CB2DBBAFB2773F1A3E1
+C75FBDF8D66FA5AB4005757D631A0D9424FCDA91A1D2AC6FCE7CC7A23E84C65B
+3E92BC684F23467DCF8521E0E27CF1441C487EC6E3BCA0AB54BB137E83776009
+833D772FD225E88A8BD992FD69819B3BA90BAAD1DDF16E4326190CC4BF9C30F2
+AF7CA1FB38E6387D9745FC5E176B248B1581BF7A4CA2FCA8E423DF340EAE29AA
+7E07A25FF838F67378F9A6A9A0B404E01E86E64FEF71DD3D540D4711AEB1974D
+E2E0D485DAFFC74BA6B8E9AFDA245BC8997BB39BB6BD52B496A09C68F7A8E900
+8DB3007643416040FCEC85B407EA0A946827771FBBEE49A3DA5542CC5173A31A
+0280AB8E922C23C1BDD88D70627EF124633C318E7C9ACBC14AE216BFD41C0B6B
+3A0161757913CA1F7B6626963C09936A52E73DD9B3D86DEEE73C0293A646FCF1
+21D4C33DFF1671DA7A53E77E20233EDE51571549AACB7968602CD03EE67ACACA
+B231661CA9DA2BEC5795A83DFAF675E9B052C8BDD51490F7874C91EF5ED2E0A6
+BE9CBABB98A950F7E55DDA3823036437C11F614E27DA5BB8BC6D955FFE54B825
+0201275C2C49A3908BEF1DB3D87792DDFFED23DE7FD9CFC284F6255C77E54A39
+C2FDBCD28F2938E4CC135829AC1867CAA5705674062C9639FEEFBE49D6108091
+7C58585B80464F7E69966D7933C7019BF336B88B9E0E7073A85EAF297B71B303
+31EEE9121347A482D28CCE942AF53E94F88A97EF2F1860A92CE29A14495D67B7
+D37E207D42F3891E0423F5BCFFCAAC057FEC683696ED6FEEFA65C8FB6F1312C5
+24A1130192B4179F3B08DA1C951D988894E7FE7CFC28C56992A1CA82BF8BDBDA
+E021F16E630FF67201BA4DF5F3F4D6AA65B8347FC1575C142C6C1868E8472BD2
+CF191137AE1B36F32FD84DCAD50644AD55EBA2694C93BDF984A5C9E7C92B73A0
+26769F00831537266FD2E711AB3F8AFC5F3FDA3C9E6439FFC48C3D1B5527FC56
+1FEDE991E66E8465C0E395EAD0A22A2FDC001E449AB9C5E0EF187A1DE9B74696
+BEB6A525DBF3A60DA2FBF1579150DEE1C5D1B6F55FF2708CE23289803CE123BD
+C81E25DB96551A13AD713D5C7BFDD3F2E1D5C12463A195442B51909CC1724E50
+A1F6F4EADB3B7355908F36F88521F333C4E7C70B094209D1F883B961DFAC32BC
+8C5A2CAF77CA5E6AAB714CC0AF2B42FFF6F73301FC71AFFA9B33A2153F55C2DB
+C1C111874DEC37CB746BEC9A3A9A37A2DD098CE7C66B0FE38460ACD77A47D53C
+1550F857FFB733B5A8D02FB56790A09190B29CCB4F4A3058B1C82F0CC5E1B2EB
+2F8E06F2DE531E1EB81326A8EF0F82843A4AC59D267EEE45730895752820BA93
+A129C22A78C1AB28BCF67AD5DF372FECC9EE6719A02E499FD5CA866688E86089
+7EE8E5912087E0C4588DE38428114785E0CFEDB1E2EE24CC067D107DFDF1E2BD
+B1C4F9C6B740F3DEA0BD315581004E851ED5A9F66C4F9E95DE97D355DB06F482
+A43B565F1255A85710B15A281E2F034B1C23FEE6CDF3A043780CB6AB18A016F1
+9EAFE545CA5A5B5AAE2459D69D2151E99D029FB5C1649B9DA784BFDF7D177385
+4D8B16B9922D149FFF6B4F99311D52BEC9A9FC098E7192180DBB38767DA9B9C6
+E8CFC98615219EF3AD4A8157D14C72BA3F91C8B78381383E0BCA1A5319749E08
+D67D1208C693A6640D1BD6B9285AC0D3110CBF8F7747AD12585141C3248D0BB5
+BDE892F91A4B3291F21F30294693518E4629A3ADD7C8640E424FF615602C603E
+1E14DCB3B17D34C090BEAD2A523E260A599522329B698729A635CFB15BE7E79E
+6A34DAC7C3ED57340821A4E7A0C7F88F64BAA69BB80DFA8B659F4756878E3044
+E1DB7EE4FE60074AF97818B3D36CF51110191B4E10655F52CC5D11F56517CFF9
+04BA2676F4147DC8192C98C555B001D54301853030B2CF0C068ABE831158B1A3
+F30593ABD51F5996CE493E0622323FE93B292844521051C1D3799C07DC879EE7
+9D047DE1C7127E2DC6F94E30C34FF87FA03DB3A3D597697C133CFC5A9448E067
+51777DCFEC80352A92D9DEC0A2F40580A0242C063CD1086D38FF5C6FA1BDB0A5
+3EDB5499AA2322CC73A38FC826DC202679AF4A7B571509B715CB8BD1D0C5D1E5
+9F5B2D6DF5E9
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMMI10
+%!PS-AdobeFont-1.0: CMMI10 003.002
+%%Title: CMMI10
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMMI10.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMMI10 known{/CMMI10 findfont dup/UniqueID known{dup
+/UniqueID get 5087385 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMMI10 def
+/FontBBox {-32 -250 1048 750 }readonly def
+/PaintType 0 def
+/FontInfo 10 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMMI10.) readonly def
+/FullName (CMMI10) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle -14.04 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+/ascent 750 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 66 /B put
+dup 107 /k put
+dup 110 /n put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CE3C05EF98F858322DCEA45E0874C5
+45D25FE192539D9CDA4BAA46D9C431465E6ABF4E4271F89EDED7F37BE4B31FB4
+7934F62D1F46E8671F6290D6FFF601D4937BF71C22D60FB800A15796421E3AA7
+72C500501D8B10C0093F6467C553250F7C27B2C3D893772614A846374A85BC4E
+BEC0B0A89C4C161C3956ECE25274B962C854E535F418279FE26D8F83E38C5C89
+974E9A224B3CBEF90A9277AF10E0C7CAC8DC11C41DC18B814A7682E5F0248674
+11453BC81C443407AF41AF8A831A85A700CFC65E2181BCBFBC7878DFBD546AC2
+1EF6CC527FEEA044B7C8E686367E920F575AD585387358FFF41BCB212922791C
+7B0BD3BED7C6D8F3D9D52D0F181CD4D164E75851D04F64309D810A0DEA1E257B
+0D7633CEFE93FEF9D2FB7901453A46F8ACA007358D904E0189AE7B7221545085
+EDD3D5A3CEACD6023861F13C8A345A68115425E94B8FDCCEC1255454EC3E7A37
+404F6C00A3BCCF851B929D4FE66B6D8FD1C0C80130541609759F18EF07BCD133
+78CBC4A0D8A796A2574260C6A952CA73D9EB5C28356F5C90D1A59DC788762BFF
+A1B6F0614958D09751C0DB2309406F6B4489125B31C5DD365B2F140CB5E42CEE
+88BE11C7176E6BBC90D24E40956279FBDC9D89A6C4A1F4D27EC57F496602FBC4
+C854143903A53EF1188D117C49F8B6F2498B4698C25F2C5E8D8BD833206F88FC
+BD5B495EB993A26B6055BD0BBA2B3DDFD462C39E022D4A1760C845EA448DED88
+98C44BAAB85CD0423E00154C4741240EB3A2290B67144A4C80C88BE3D59AD760
+E553DAC4E8BA00B06398B1D0DFE96FB89449D4AE18CE8B27AFE75D2B84EFDB44
+143FD887F8FB364D000651912E40B0BAEDDA5AD57A3BC0E411E1AD908C77DCE3
+981985F98E258A9BB3A1B845FC4A21BCC54559E51BC0E6C22F0C38540F8C9490
+88A0E23EA504FA79F8960CC9D58611C519D3ACDC63FB2FBCAE6674357D7F2285
+4BCC9F54D3DA421D744D3A341DA3B494BB526C0734E1A8FC71501745399F7683
+FD17EC3044419A88C3979FD2ABA5B0130907B145A8462AAF0A9B511D2C8A7C7F
+347FF6AC057E6512902BFD2918E2CD31DE615F5D643764E900B60287670AE18F
+FDE15545D8BC69591A8CBBB275AFFC9B14BD68DF0AAB32268FB84844D4DBC7BB
+C591C1AC5102C50A9C7BAAA848DA88B0519F0F5F0813BF055CF0E3C86F633A04
+B779D2E8E656DB1E09A66A85FE21CA8BA5523F472A229E83F2C4E91ABA46C733
+F3C7B5775B06C97782BC225C46385BEBDC61572458EFC5CF4190AB7A9C1C92DA
+29F84BAACF552089195966E3AD9E57CC914D20B6962BE80429A16D4DF1ECAA66
+36C4343FADF0B2B48F12E2EB8443C4AA29D00949255F3968617F98B8ABD4CC12
+048B838EE243A21AC808BD295195E4AE9027005F52258BFCA915C8D9AED9A2C0
+80814F79CF943FBE3594C530A22A92E11BE80FCEC1684C4F56712D5846B0749C
+9B54A979B315222F209DEE72583B03093EC38F7C5B9F9BCB21DBE8EDDAE9BE8B
+75ACE6B12A31083AC8348EC84D1D29D2297A266284B7E9734E207DAF59A25F4E
+4AA38509E993C5394FED76E6A2F25462685C4C86C6E8CFC9863338EC1428BDFC
+74616BB1BC8948B0ED4C87C15B4405F3A7796F9DB3798FFFE8BD0A94E834817B
+D5E9812E308D0CC920470A6F2CD088FCB80462BF7CB3F039A7DF3DAF5B2B5355
+E083A385CD2EAF0FC181E40E96DD7E9AB9EF5C7E6866A13B8A54718E950FE097
+EF0951A357114F18CE9933D28B3A77AA71E3CE884661F13284BCED5D5FD1A86D
+543E588FF473DC2CF9A4DC312500135F29C2D0174B32018C8DBD40EF9A232883
+710A1F2AB2CD11312300ACDF789A9B7B93D2035D81D1C84984D92D78A53A00C6
+EDA94B24BBAC1AD17774A4E07E6F74ABD90415965616AD540C8ECD8C3A44EE4F
+7F4F6BB6238C5062D63FA59B7BF08BE93FAEA70A2AB08FBEAAF7DBF56B95FD93
+03CA406543BA6C9527D0DF01F5108D31A51778A5EB1C93F27B72B46146A353A2
+01CACBC829603B9989A87CF64528682CCBA0562A8165B185C58A5C6BB72F5E89
+500ACCAAB8ECEFBB2640E99EAEEC4EA979AA793D013D61D8ACF8784FF8D9398F
+F6A252A709324FB39509F0B3A4E725E82F53543383C6765BE556CC897C758208
+AA3AD37B0406E4A79F8F0A6C1983FC73E71CD858C0DB66ED66D5D992978614EE
+1EA91EBE191E082EBA1FC040AF19A2202575C2EBEB8058833E3520FA03D2F915
+85C1ED337E457B9FEEB0C6EF2735EFDA6E0D05FA641BCF698AC6B97751E8306C
+4DF00A39B8581FF53DB8F8525FDB196D85950906CCB59B8EF171349AA3B567B1
+6A00819947A995FB383C3C1709C9A2C113B2E40BB832B7D4A0FBA0B16A2C455F
+55809CC425C403E9668DC66BE45B71A81C332FD4DB279D22A2959962304A8F18
+085893DAC61317D24A8F198FDAB95F3B86F0AFD35047B868A9A17037A2829A02
+BAB042F75F349E197A7EED41984C2859754CAFD0251439921C248B463B516951
+2E1322C80D73F9CBCAA63A585450275AC2492E4D3FB78E800F788254DB5E610D
+CF788DF5C70FF99892BCDF16133E34B24B77C8F097F546B87C603DDB8998B66E
+BACB68BA27462AF54AA405682EC96D701F0D474DECD5F95CA2102DF639EB169E
+D518162C2BAE45FF698B6DE15FC6E7DE48C336C40A670FD26952A6BAB09115E1
+991F0073419F2CC2A1C08BE91096936AA0C37E4ED3CCCEE235476074B8FF1125
+6BDE3701F85532D8BB64CCC927CC335281C95EA689706F0AC717DC2CF680C754
+E5EFD7FA4BB8880B2B727A964C876D4A223069D4E6001771F0E23EAD2A4BBC80
+E76675297B2EF05F52BF4E71B3EE2BE3048CF088C79540113C66AE98B2FD3CB1
+B0741A215FD070882C52765009D7D711DAA2508F19AE7DDA15229A856AC49BC3
+4DDF40814FF96500E4B9B02D412E94623C5FDCC76C0FB8E42DF56A904FE49D65
+1DA7C53901B2EA71AB658A464D3ABDE27D9DB8D9E0B48F64E61A2495AD5D8DAB
+B5E72424AD017DF37964AF911BD7FA21A5EB4775DC8E95EF0C0EB856B00D89D7
+8172A1DE8530767D317B8256103E53CFB877E10686A04F5A08F8DC58D843DEBA
+FD5F40597588663D103689F6EB3EB14D06E18C8078F2538B43E712DF491FC5C6
+AF639256C8C6134B64D560D8476DEA6329D995E46CC4BC78841C59E73648B47E
+BFA7DE0846422F738454AE77E822A083405289247BD7C478BE4974F742CD6051
+E99FBB1D1B3FBABFEE855174734EE45E87D0AADF32B1283B911162A9955847FD
+38944D70584FAA6B1A7191C5C134B73F98EB632B69E2F0C0F94156787C34C8A3
+7622A029D58F9626B74F8A8A1F3803E0BC20E0EADEB1E99B70F1BD9F980FB751
+2A842843DE42EB142A84D5D3138629AE9EAF6F3479C423E8829C8816FA6EFA27
+DCE5580E65AA9854B1C64163DC318420CD993C15BFD76A8BA1182860A6B03D6D
+22B8CF43CFE6C8AB27C64842E239CAE707D3086BADDE1D7C94E3BC96319470D6
+8D26915C575CFDD03271D6BB9DE86A0EB6EEA6E768B224A626C62A9AB48A6EDB
+44F70BB5AF991CDF9736D65933E81CC57A78F623F33EC9AF535F2F25FA4EEC90
+D50DB7E87F31E971A75A33A301CA6013EEC5A4E179D695B33DADF2C98364434A
+42926776000B610E17524162253F6FA638D6581C18F99EA0BD1D2E24D2424ADF
+C05010D08192485153DD03930C7BF45237593E484F9851E6D464FA10FECA5D9E
+0C8CCC97DE029030900CDBB491C5CF226DBF903CFE7735D939C3FDF3A20B70CE
+66579B28B99313FEE914E295388C7BC8E055A2E54EA3A8206D3C8F4F7C0BA5E6
+E519419FD8CE215F7B8E9BEC604A9E3FE272A0328A24E31997C8A91E0946BCF1
+6943A97CBED2AB9FC636B49828BBB8B89E0BBC2653796431224895ABA5DAC41E
+1854BD9764E86147FD7624F736F40DE3B7582EDDFD15C2BDE3F22B5A54D7DF10
+B87A1301CE85CFC061689A890A321412A13314AE96DCD3EDA75035FDD8F4AB9B
+897A2C68263A68457032C469987970648BA2D88B1C5375DFEAA35A917B8A952E
+EE670427942AEDB3CB599C5746180E392837D371E15D860620ABDB6AA7772C40
+A5E346661673ACA530BE3D8E3FFB895E5DA3DC23B1B43C080C77F7E47847F0F3
+F3AA5CA9E4BF75FC5EBD18D19F21A7DAA3B11CABC6E4070A15F7DBC8B05EB6AA
+A02EF1B078EB66D61D6AFE41DA9B36FE7EC9EF94D1EA26282A9871E2CACB3126
+2AD49C2D9B50A6E47D8F2CCAD50992D1B430979A45FD9E76182A19964BB2A1F6
+51779A2B258DC1DF4C2F3074621286831F3848AC152DDD2BA561E6586ADA88D3
+598A2CE2CD048F027CE0008B828BD915887D7785341E8305DF2346ADB76BE99F
+87B02173BDC334E9221C8DF54114A6B24C1C5340299512FA6C8C51AB4C8778CE
+178CEF531C6D1B5FF0A1BE8EFF767F959BD4C345C52699A29A17B2A230842BF6
+4B011217D6D24EDAC3F6D53482786F1CA33169B90ECD499407D37CE9B70DDF78
+7B7547B32952535BA9ACD1E244447AE3FCED3AF28717083CF9590A09780984D6
+AF0743C82AE4FB3E2BB2856A4153A3967A023FFC35382D6C22D84A924900B6A6
+3DDD400E6D2418DA6C27F2FA34C075C902B89EBAE658B3C9A18EEE449DA5A379
+337DE95CB7AB3F0970CF1A5D8FAD8090E495570FDFB2FBBA79244780D8035547
+C5A55BB21A2270F724BF5D442CDC5BB9F09BE0CAE59B1C2270F0BDACE698F2C5
+DE8F66BFB9634904B161F5BA2B1950048300D69BABD312D58D89C4ED527AF7BA
+7DA2478EDC2CDEE3473DD8A8ED9D891CD1FC21F23013228BB3281B71FCE959BD
+6F8E9059D682A7FCC5265A0620992D4FA8D78377EB34CE3ECA070EE3707239BC
+98907DB0120CE42ABA32CF97127E28382BDDFD685674279F588D4F951216C355
+821361790F64C2CC720DE97E8ECB57326C43EE47367628E05769E106868B54F4
+C33C9951908DF6FC4F5ED2C7787BD8FA591BBB3E9C6C1DA94CC5E38D9B20C886
+7D237572FF46DD896A4D6163408EA6CEFAC398EE041EAE29D577E75326CA17A6
+B072D47A7B13EC441CE6DAA042ECD02134CBFA6809A435050413817193DAEB16
+A5882C8AEA44BCF36E74E9ECCDFE7E19FF5A5DD7A94E5AB4F8702C3DA7F42325
+23C808670A0490F5B373DADE40814FF9650241D3D69C91FBC5ECE728F827D9BF
+C928602E05477903449E079164CA39859C4BCA60C579F490AA455F82B5050BB3
+969AFB478E0D4A257B3356EA3CD62051FCE6C6B1929CFF85BFDF166BEF658E10
+3A55E007F38EBBB248B3F0B8ED1925106B499B762E45113AE1AC9DE09644C84B
+9C08034B297314EE69BC32DB6E7D7FB9913CE5AC17E7335979E9DCCE2BAB3725
+1976155551F9706A576FE0E3ADCCF72C87683291528ECB749CB0ED291966E239
+B5E3630676BD409E08F85BC1AEC9A2D4135376284A96EA24431243BD6FE8B966
+95F11A4BB53F392E0AEFEA623064FF8A7002367B0A515635CB2D2DDFB9B4A8D7
+FE721754E81BBA548848A235B91AD4E4F7DB19CCE2F61D277FC00AB956EB93BE
+44AB4970CA56BF59506C94ED160FB1E25D3DF2988A532BDB787BFB8539D22986
+FDC378AC31444E63C4727FEE121A43751043849E6DCAC5B59D0FC703AAFBBFD4
+E8B7C268F21615AD02CE9DABEFA27B5FE6A6441B619539CAB1F810F1263447AA
+633F5DAF483752EF1A0421740E3A811D2D2898CBF53E7F686C9223FD7235F02D
+6F90D2D48CC20AB87778DE3C6FB335E0F0EC20B5DC5B65223FE117526DE2C72F
+FE839DF93CB2A7D66CD900CB325F891E311BEC932F703FB4FEFA29DB8B9C88DD
+375EC71B3D58C7BC59ADA91971A3BDA1ADEA629CE6CC92BD542CDDFAA7706FB2
+6CDDE2DF07E56D6741916AE8E8744339816F3E6C38062747AA9FDA2A2678A6B7
+EFEA870AA3A4D71B25EE3013EAB1DBA34401B867C7A41AE51E0421D41D3BB83C
+E120C8FEABA6E5DEC53A689C21426D4BBCB68CB37568761C360E6D4E3596FB7D
+F4DEC7918E58C0293D12D6DDA7E9DCDAAD7C939F55CD1BC4A228B31E9A904156
+DA6B40B08E6ACE674618B768DD681C772A3E55FE096CF949CF3B0460ABDCD891
+D17B37B355B29AB5137899C036F31DA026244FA25FB798FBE5105BDA29F46538
+D3D3AC1001A7BCECE64DE94FFE6C354166A0F97256137BDFA07F6E22A3D1D2F4
+9588DBAE95E895BC5E64DDCBBAA8D0A22C229B42CB717FC711E7E9DF793DF80B
+9F14754585A3C7E17F37B32924B9F9870DA8635E3E18BD1DCD81EDF01834D9C6
+B33F23C956C2FCBFA47D84422F583459D827D1E120B97694D12F1F54D02379C0
+D288F7104F3FFCF4F76E3494F4ACBD1BE3A15543CC680924C78A473F8E311ADF
+8FE00A04C6C393DE61AD3EDA5BC031E2353076A2489391B52632387CA28A7B93
+FBB065A6EF3658AE80B1ADA47E9B2539E73A71FA75645F85ED8ECC257FB4CF26
+B6C912DE9D0F9899E70BECCB934AD32CF49A093371A9F73DE6255EBC39DE1E7F
+00D0CBDABD4D0383977E694890E71FBE5C376BE5F3A80C28987417504F515C50
+909F3D31178BB9B1D085BE514F71B910A9085BD6122DDC72A150BFE266920E49
+5661BCB4BAB51D6DEFE32B616963DBD989FCDD1637B294CE4E288655FBEFA1BF
+7F25BBF8CF17C2D5FD161A7C2CC9CC7490D9BF15A1D35B3BFA43ADE256E88BDA
+BD490D92907C57BAC408A575EC84D6AEE070148C7C9A91C03B09FDBD792E8FF0
+C0B886AAD2EDD86541E5E579359D40E3AC312ACD3D8FD49F71BD533DDF8859B1
+BAF17F1884E331DD07CEEF93B71D492AEBAADF7A263450A7A72210CE630A0D37
+BF024BDC09ACC882816B8C22C62AE38A3A8D0F6EBC2B1B2C0B8161A8B076DD5D
+4B779C0788546BB4CF57332230D237856B00D79C28A7C01D11F44B7304F69075
+94B97A745DA43D1BE561372CE611C345A843834E46AD9DDB16CABCD3FA33D6F1
+F6B5C0497F5EE5400B305CDC16A7EC286AA4D45D0EEBB9DA06AC9C5294D68EC9
+E4DC3CA2B92CE8FC0526184A86EDC7AB34D67E60AC12D9CA8FD300235EC968BA
+92C6FBDA47572BC5600F25249F60AD287CBDAE980E747FCBE7EE5CD323E733F0
+63553B494D3DDEB9CC1480B5C3BB79A28E419AA65B18CB297AB383419E890E2A
+CE6F98C9900CCB4675280A10CF060B8D220DDA1BE55DFA65715EABCC1AFAA271
+B1F8732341613E17B231231A0D24D4D7FC198AE04D89A99C4536217769C6FBD9
+5EE24A6302F97438F7C0E311C878F674B4477A5ADA3952CDE4055AC408B8174E
+86F8FB797646DFFFE0ECA25D1BAB9A9F71F3926D3D85AA63E7A8C931D71E79E0
+AF1EAC26FADE468F4FF7F3861D14C10E3BE1F9EAFD6D3A544E8108D5DAB5B180
+3950C74818BC8AF4758A108F462EF1826647A49667F5E482038C54716856D9BC
+35F29922846D2148F92F943E951D7438C73D6A60459A8003174036C64E1629CD
+155D47FD04B03C023AD67CD5A70C98AB556EEAB8C48169706E5B352F6505D580
+AC945171BFE62E81F8F500438AC3B64D857BA5BC54C2C4BBB237F8FA51296255
+E66A92A61FE13FDE781D393557EB72CEBAD86511035F775FAC39A0479CCD400F
+226709118F887F47CC2ECC8F79816D4A945B2845F50AFD62D8C9A9BBF4739496
+9E644BC9F7B04803B7EE75A09EAE94365F6F374B4FCEB0B506C76297564B9B6B
+8B812BC3A33929AA94692572B010E6210AEAA312BDFC88BF302244AB9D587A9B
+919823FD01DE12438D960944D1977800FEB49E638C32E5B188B1CA033E0C37EE
+A142F746367888AA119535F0CCAF7EAA461B790EB089D2D6962E28A398439BB7
+9C9943654D7A2D765B46BC0DD1F915327F369162E1BA1BA83110B93F442905E0
+523BFF5E279508A98568CD5CFD18FABBE9D17265A9081E7BF64155A2CE3C0DF7
+88D00671AD65654709589BAD7EA65BBA811387ABA5CA0BC3F66D3D48597A0D1D
+2C268375DF47CCF62166262AE4840AB03BF49BE67A05EF66328EC729F03CA5FF
+AD3937FC053E223303565DC771ACF32E63DFB96D5030E787961D72D02C195C66
+B48E9AF0309DC169CFE8D16E2818DA94693A18F027DEA0D91051800EE6C54285
+AB0594D87D05EB4CB44FFC094DA0072AE7D4BF2F4F9BB812FED256B937BC2574
+8C529F97AB9CCACD8DDF1ACABDF29591D77A705747ACD59DC3C4BE35B13F0833
+7FF3A11D9B3FF1932159BF8FCE44C4986C74340A346D7195D155FD47AD519E27
+A24A098E364C1480B4B05F3457ED452CDBCD3F7AF61A81528C14848265F0A18C
+7203506FD03909A7E604F895F2183F01DB04E4D8BE928E09C85D8DDF4DEAFE49
+7E1A21B2C7152B07D00436033D6DE4AB442D376B3C8BF57A96657B85161744DA
+2F22B614B670F17D123D214CA49B150FABD18506E52E4A1A00AC0E1ADA70F91E
+A467D951A69E1CADC5C479FC6B8859DC1A36DF86FC1BB235B2AD62A38C4FF38F
+26C706147C089ECD5D37E276E7339EA7FEE5079F53E7A9AC898EF5A39E2037F9
+EEC0C7C4F51BF3FE55AE2B88DCEB8AFB9DEFB5D3E6056EA31F761F64BE1D761A
+8EBE10171819DAF38E783EEDD57578549EDA769F9C7D8F652225F2BA0D72D743
+4A13C9567714B61603E4D93C9F23532BB8E7CC9F63435B61C3811DC4A6D6C359
+86D8828B5389063FF96A486AC3CCFB412E785B6A4CCDFC340EB6C1EC0A77FC2C
+03A8BCC71688CFB2EEAE00456188708B45036C4210757CAAFA9EDCCDC63E8584
+23C49BA147A185131B43C01778DE397E38643B4450EC4BA1C1BE46B056654C79
+888F3FA6AF36D54F56A9180B3A4C5EC8978770E99A3FAAF6C9DBF6843BFAE603
+37F5419DD223827EB96063F6BA9B8F9DDD3037E73D2749B4FF52C5C8CF63E849
+E780FA9A99CB76408E62714D7A37213EBB1DC54962A852946D53E91B0AE7A5A0
+87292EC59E086A340CE80AE721DB7AF4BBADBC0C558884B60F944852A8D48851
+3D3F9176C2B0C27486494875374BB24F55A03A2C921BCC1908725681A015F38B
+589CB46F957493BAF77CF528C444DF73E2759B6FA95BDEBAB7A9243B1746E4D2
+93F180E56F2DDA2AFAD203A018FC3D18FB810776007AC8565B845A18B70A099E
+BB0DC8801714879EB0793979FE28F957B4CC77BDDD949D63EF772EA7CCCCB8F2
+2E7C0E11B59A02D4423F53C8179B1E28F757E053BB7826E8322377060F32BDD6
+49AA2A81A208672C28FEFD241226735921BA68E8184BB2E47AED8C27212B5BA4
+5C55A9C78A7BF36BE9849A4CD113E499483F9EA2214DE3
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMMI7
+%!PS-AdobeFont-1.0: CMMI7 003.002
+%%Title: CMMI7
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMMI7.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMMI7 known{/CMMI7 findfont dup/UniqueID known{dup
+/UniqueID get 5087382 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMMI7 def
+/FontBBox {-1 -250 1171 750 }readonly def
+/PaintType 0 def
+/FontInfo 10 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMMI7.) readonly def
+/FullName (CMMI7) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle -14.04 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+/ascent 750 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 107 /k put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CE3C05EF98F858322DCEA45E0874C5
+45D25FE192539D9CDA4BAA46D9C431465E6ABF4E4271F89EDED7F37BE4B31FB4
+7934F62D1F46E8671F6290D6FFF601D4937BF71C22D60FB800A15796421E3AA7
+72C500501D8B10C0093F6467C553250F7C27B2C3D893772614A846374A85BC4E
+BEC0B0A89C4C161C3956ECE25274B962C854E535F418279FE26D8F83E38C5C89
+974E9A224B3CBEF90A9277AF10E0C7CAC8DC11C41DC18B814A7682E5F0248674
+11453BC81C443407AF41AF8A831A85A700CFC65E2181BCBFBBAAB71645535A2B
+6F0F22458E1429F4A67307E01F0BCF6F337E0E2AD89658D880B04C26306F8179
+C8121B958459B923AC3B05B594D8AB95F75870019130442FD29578D44F5690BC
+7281357A5041C8A809A59D0DEE108E2A07D406656BC74A9F3317CB887E712318
+46B2ECAA341F8692ACC2D14ABABDFBCAC6F35858355F1D3228B0223EC73AC56F
+3C987464DB829F243E304F4C59CDE3EF6EB53A4EF9BA91510CB89A3407261F58
+A2AE66880BA98FC1EF546112892494C85A2C39F9DCCAC5766725894A7AA148E9
+42360AE64BF3A4F1F9F0A0D0C1AAFDC4D50C52233AA595B7D0CE557D4A010D86
+6E6B76A7E9523E8A6633DA9348BC3F59302F72F492A30782AE7EF220516893D3
+DE836CDE311DED9262AF01C506040541EE84AAC539B404B23033EF56D4BCE6BE
+B05F79CD633FE75C6728114D2749E39FD7454050F67763AB636377BA8E1867C3
+996C7D7D4A4A02BC49D1AD7FF174C1F49F1F205BC9D5AE42BCB02CF8554E8F5A
+D1876C9285B6CCD7B8C165F75843B0AA11D8462B57077AFE75BAD086E9D9F91E
+30ACFF91776132F3CACAD1CA5E08B17B36A0E45ACBAC52393B9AF9089BD821D9
+CD5A9CD9BECA59F7445D63DECC1B4502D299DB85B6E2EE7C69A1DAB91E22A3A5
+89B524FA20AF6005E7A586B90A2C6E5A93C9EFA4ABEF5F7E4C7B81363FE8D2B3
+0AD637FA863DE787581ADD7CBE463F7866C40F4E280260ED0E9C8453E5C7E668
+FFF058B9742DD3F131C264F8FA102CD0DA05F3114D13D34D422799181453FE23
+2FC6EFB01BE420C930B879D671F3DFB036197874725220644A5A52DFB467BB75
+8089E4F40CE9401777B9FE1D0AEE02E782A6EB2A185A454AE9394094CDFE7CFA
+C03C23A78EAF242E4F811E4C83B59EF4DC5ACE4AD37B41616B46C263358710B2
+6137314545CA6CE89119B42A3518EC85C68DC07D26839C68B1FF55C4A9CD518B
+A1FB32F9C475BB6110839FCCB94156E7B3648F27245A00D2966FC4DDE3996BFA
+F463A663CB6935B596B1582ED0ABBC648AAA8A86068BF0038001C753C8BAFA0D
+2058041DFA720B528E2D4B16196DB1CF30C779D3F4800FE662D5B60B208341F2
+A66EFCB8448C2FCD12DF0DD899911A8BD96C9B670054D328790E5D388518B146
+8CE92E368EB1DB3CAAFCA4834CC9D9D9DCC80FB1F34F39DACDE643052C977A7E
+A95C5FA8DFED9B4DCE769E4E46256D6DA8FB18FD7FA4E4CED5D486803538F3B4
+6D3F5B3C03184F5C26C66DBB4C724918EBB6A89C4602E4EDDA81EEE2BD18B683
+FDB459F2CE0A9CED23DC208EAA8BEDB304B00E093DEE926A7B32FDB2EC70DD85
+94B9137856DDDABB402B2C76DBA87149051ADC6007018EBDD571BE1D092EBD95
+76D4E063AD7D5F62E6C26EDB88D38678F2806A1F4900B0ABC4ED034A818119A4
+E618F1A902315BC98F26775E59555A3DCEA1D0F8B20A9084920ECBE3F7F245AC
+1182A40B518B194669D95DE968542BFF80FDC89669BC256C44CB66A2AB8CD7A9
+E42C69956CCB6BDE8C09AD22EF3196939B3B84EB23A6E071A36D702909E019FF
+058F27562441EB5CAE87A4407F67C4390810BE89BBE867D636468E73677B84C8
+5A1228DD7DC8EADA221B1BAD5F43E832F20ADE7ADBFF170AB306F5B711816FD1
+39B7882556E30F002977FB88D8B28826A75DE0D20354A2D41F2DA8578376F7DD
+F27B0F59D4DDDF5790E11E3957491DC74EEB7625CA49FAD90FA47AD8E0BDE824
+FF326A84846A47A21B70FA549BEE307F9C6970009F963B49A504F0115777826F
+1D81203F655C242FFF15BA97E3BDDFBF435B10E74CE8543C98966223818839B3
+6BF3BC63F882B0AD0FDACA8C56A570277952E1D83F18BEDF084D2AC004E2B09D
+70DE1740D7D220E92B54D2FD0DDEAF1E08C41FD321A8D474982DD105B23166A7
+AA9E0129DC88065B1E0F9382BEB4B4E1DAAE3EA5489BDCA921AD5A8175F2841F
+9400478DFA99C5E5553F383882664D73FBDFA29BF32E52C28DCE80DAF4839434
+022FA515679DBC13FE98968D2894DF5DD69C49BD23D00F5D858B69D1F220F968
+F0700E13873579B3CFB658972098DC61F1DD580105BC27795DB4AF11A871CCD6
+2E1B9AF7F0DAAD4CE315379A7B42CECB983DAC5A2B9426B4E5E0A7F7978504C1
+DD7E30063AE3CBDFB24EA2BCCDC478AB82084FD30A4793F4707D9F8F9647B413
+F8A5C5AC6D5EA0E35628CE1096A434FB8286F4617CB4D0AD30A4A0B255A5A356
+25AA5A947FD3C4FA44B4AA80BAB44C48CC1E2C6D0A711365A37A58C3483D07ED
+301A83D2650A2E8CBA9EE62FF5C2736EC82C1402959F64527F9B640619F112D9
+8E0F4A8A3078C72ACF3F34AD855AA4008C96E30D9E8C414607C34E06E29AC5B9
+2EE5DDB823E8C3EEE6A8DE228313D476A7F39B5DFBFBDEDDF7C45C1C88EE6D01
+7FB4F7BB2CBBD5DF7F0CBD98DC287FA6940FBFE1B3B136613A3CF16634CA7B90
+53D5FD5776515EFF5D37F8FCC62D8BEC8EE2216503D54D6F2032D3C2BF861E15
+FD1B45B71576F15852EEA65DD372E911EF4CC18283CD2FF4196A3F1A9D81137F
+F1820EC604D6C61AF318C6C5AB6DA1EDF305CADEF7CC0183B86D31310A09972C
+A4BC37D110C77ECCA614D1A281EE1C2040B4A5ECB31A3FC61760F608E44332D1
+D2C53C7891B505A3020E9E4915F3618588FCEC80B9ECC5E637D8D0F3C94B1F2A
+C53FC46CAE0AFAA7E12266C212A73AAE60199752C042BD55A5DF1CD07FBDB830
+C83E7832D8554AD9C9CAEEC7CED1DAEE622090897641CF2E5B34A353D83264D4
+4687522DB290D3BA927BA315EA5D25B0D7B69350C6C180AB0C322B05E01F7C7D
+F2F48651567F0C1B49AF3950E43C94D78F7B184BF2946B924BC4279AED28F3A0
+17A7D8B235698A516D3FB5DF0B18A422B2410C385E7E9439C6D60917EB3299AD
+E31471616251FA40C9FA098109BB31A54D9C03B2F12947E4E9252A0851B81C4D
+F39E7FC44752504B589C3911571B1D3EC3BD1E1807F99CED1DB20270E483A805
+CA2A016E7283550D1B1D35C226FAB63F983CED41A4D02A2F228FA9EF065027B3
+CC69D6F2E278C0A2D238D3A37154B0D22281F62C61D9182A69657B027BBDED64
+11E261E47620602F865221A534C5A32E2BF5B93A187911A146F2E96538B47DBB
+7BFA7EF406FE940F4DAD17E6E4B80C4F031D71F65657C2F5C8233EEAC68DE8A7
+E1FC3055C122C1795D0C71A0284F89A9BF04837F61C9E08DB42644A490C97D34
+A5D3CEE475B8D578205005A0D68AF94AD27C0E855BB8EDB74775690A4EDD6543
+BCC10CF13283D6FA8A7CF3FE6C4F96470A11FF0B0160D3F9816B13B0BAE0D8F9
+B84C7631063FE658D13D108D6FE24A89799FABA72E6A6D1C943922CBE676C1B6
+11A4106ECB4F1A7F8A84B2783C2E6A109C58D63FC0B74D8C8A1CB62D527441AE
+E656D94B1AA8581B4F07B653ED6486AAE1F8ADB30FA8D8914AF24721C74B0908
+D84F2EBB91144ED4BD7EF533F2584048DEE37E17CDE5FBC2992A6F924FEBAF07
+B626F988599DECDAB43C931CFECF99FC6EBB72F8E542765C26295902DFF60B7C
+7B9ADDB4858BC9D808B7F0909690CF8DFBC59A786D48B891937C31A219842A43
+234425B4963062DB4C4E9F534C77F4243408805B5A6B8BBF428632CA4AC03A7A
+E336DD181CE0CF3E742079E2919EAFABE16A63299771BF276EFA8D85C920F995
+5B9D4E8F1ADFCC5C29AA89BF90C186C5DE7679906B2FD4DB279D245D27D08837
+D3A8D541FE37415B706EC585C05804108C1D938E543B8B63E275EE85CE9DD843
+0A8B9163144B77DA1A552A25D5E77E94F29CF252BE9950F4E627D5F72536B6F3
+3278D4A45D10759F16AE42BAE8460865FEE84537F8EC9BF4813570E883B826FD
+1ABF3F4E66DB6FEF8366E07BCF290EA67D39C9D81B2A7EA48E0A228FE3D5AA50
+1A56CCBF229C9AF2537A8FA70EEF41096ACED34CC7BEECA4EA1F23B39FBC39D8
+CCEA93E63F508CBE6722C11467A3D0D5C4C52031DE43C449333E4295104651CE
+E13B821D7904653346067E971BE0042C571ABF40C3A1079A675FE4264B784D46
+1B8FAA4CDE9851C4EBF69ADF51A7B68CC8706C08D13A44909D4C1D78DB0E0B2D
+0E0318304B229DD2FDC968027CDFF65722059C62154304D6F9C3F06DE22914EE
+928B7D1BF1FC7E74B4D882998D59BC086AA2D4EAD0AE39F6B75B5A3FB9994506
+E21731E1A15F0F2D12F88724BA72898197A80FDAC00243A3038871EBD2F2BAB1
+C616278BB78490CB86F552CBE5DD0862F3793D72C68AC16AF8E38FE1A523A5FA
+9B0428745B1455671CFA1F6BFBCCF9CA23C833113C2948E7A6AEFFF1A83509FF
+C559BB5EE7F92BB43F7F37A371E661C826F63DD0C1B25E34A8119E71EC82FB66
+23C7B126FB6554E7560B1B69F2EDBB742F3B20D1648C151C37A8570CBD330A9E
+7592A8607D2D727F3AAA0FF2057DF4E2A4C7D3B658C6CED38824A770420D89E7
+F6AD385DBCE9C9A9095CF0042052A67AB804A6675BB9373A99390CBDFB715984
+A069DE543E4C6ADD7F1EC7A15392EF834EAB4584679A43443953427DB13E6959
+0F2F5061C99C6D00FA5327FDB5330AEDE19A53DE3AE092634DC6AEEAF63A5BED
+990F8A117AEB1CA0E7F7DBE02CB3D86465F1613B976D1CF6F3A1E69740A2FDC8
+062ACC45EDA6B863B60015F276860FB79C31D28F97A799568E66D0A8757B2C41
+E939337B467303041D0F4C59390B2E41E5F298F275DCC699D27C459ED4D5ADBD
+02539F00095D7E1872862142B46BE06513D3EB1A406E6BAA64BE795122100F09
+C37E5D1834218EC1D11B031C7DFC9F5AB071A8F4DC08203821366959E9191D4B
+289682D915AF28CE5858F83338DC51B6B0DD052A181D9133FBA50CF18F70EE65
+C33726A0450EBA9D0E0C3662AF6C2121AB7911AA9880D6BB6811D6D7515888E7
+199A0E632104059A88C9D85B19BB35EDF4AB95E1515BB2339572928BD5FE8CBD
+2D4DAF55DCFE29FBC4C3D56336277BA0C9A889A129F9FA7052AD1420B8705163
+1A808EC1284C888D78CEA2B4BAB71AD76289F5F4986008FA9BF328E8537E6C91
+E11DBDD8447E1C9ACE18DB0EC3D5742C264C8EFA445C5D16C2930FB43669774F
+A2CA52144D99EFA8FC427DB4128CD4C036A8C611B087335C780740FAA419D39B
+5DD68EA89C95275F9254D947EB3683D0130255269B10C6CFF29EA0BE484C9949
+96188FCB747618A8044E2E37DFFD2DB8ABB621B34DC024259340677095B6937A
+78EDCF508AC91D4CEFD872AD73F50582DC8807143CEB9F109C84DC5DA30B64E2
+E56DE973088A9D32583D6946DB4F3523902FB1781D993B89D5F56D79D5D98CC1
+7FEE73FC3A7D1BCCE90179AE450829E228B4DEAD3B2B4C79A400CFF899AB26F9
+048B0875EBC871AD23BA96F88CDA8B87FE5809A13889A6AC349ABB25E54ACAA9
+C213C5DE2D01BCB9CC0D7BBD384D23AE12E289FF8FDF1F611F5E14D4B20B15A3
+42D9B3B37A83A9CA39B5DB6C8316C51B70F211530A56CFE54D63E88169CF5233
+D1A7B2388025B3EBD2BEE0716C3A2D589EBC7A42B3DA602AC4E2FD9C9052C922
+711E44408DEEA1FE0C9FD50A39AD46D437F61F284A2EFD42EF158EDD71A1486D
+4865D6B5E20E60F4F4FC3D646909FF1EE2D7573665E4CD8340A1B232CAC0202C
+C35BA9BB3D2267C7E78518F6711633F888EBEF72DC750AC2CB362D528CFC8B2E
+A1AE1C05456F50EED8CAA768DEF47FF85C4322F02D7F9D188C6F285C674EF589
+251B0B913339FD701FDB281338D96704ED7ED908BC113B4275A24D058955890B
+12CCDD5572D63688426B0E1E9A40D6AAECFA5555C1CF9DBEF8C04CE1E5A63F14
+969D39B6DAE8A91F6AF4CD1E2DA89A4661DA34E272B6032C442C031F081F5DF5
+858F4620885773D8A2B2F5EB6DDA74C1408DF279900450E4A3E80BA9A9B1295E
+F24EDC3F6EFD81A741EF74B0202820516C4FB720687BDD915EB2396128C3B262
+20E3075DA153D6FD36E1C05B855929DAA4DE694B6F15EF2145C63250B24B031A
+4CF0AFDB225E91D99828B83BD90F1702D3906D45872587A3A116B138AD9627CE
+E778A949C392202823C670FDBC56F1896FFFFBCF52C4B400F67BA36B5FCE44A5
+F18EEB8ADFC088C99DFF8E0A593E81A5ACA2E3693005F723C7D3E0AE2BDD3805
+8C6007A00542DEB2539709558A88B21003CE4B2C7817AF207ED576B25A41DEA0
+FC55A459BEB00ADB01309B35920F04F84B7B64F95AA99EBCB843A06CED900D99
+97BEFD7CCB9F4D85876F10160C8D63E2FDE82B7A8D945F37CC9933ABE0FD1D76
+268296B1A5AB06B2E814691128771694224781171DC6266BCC290FCE1AB59416
+85530368115BABD4F1DE45952918D1945D51EB713C283DAE8EDD559F437CD886
+A4B1DA6120D685C284673A3EE489FC1AE4297A3623B339B7D886B6B4B8F9F4A3
+7BF85E320A52FDC6323B51879B98A14C33C567BC069D9B44616514EE1BE36F90
+EC5FA33E1B6B0A46945D876EF0085E74935DF2560A03321861A752E59742B9FC
+5C501FBC64BFB1602459885B63873DC857ED37F8BE1A9C6E9517B9BF5A6161BD
+DEB6DB0381FFB34A8A96AB4AD48BEC40D4C198ABC599C3758AFF638AA75BBDA4
+8545D5F95FA426FB25587301A43E176F6CED7851E815AD907F2443E70740DD2D
+4FBD5D978B9B37F59D6DCF0ADD0F90825DD23558FCB858513602C8BC82BFA383
+7AA6DCEA4009961D06DF233C5381A7F9541259926446B2F03664BC5978A1B6CD
+EA6EBC9FE6100A65959513EEE32E69D47B55BAF30A893D77142F943982019C01
+715CE29923795EA01C58A798979939B507C5B29A32881877EF7EF0C5CB3DE591
+6B9A6C3F3FFA847F396A396F078860B59850BA4CA3115CA2376AEE6B30C05DC1
+6F9DB6781ED0F9D45D10E096C33B1B7CD12A9D57C6E49AD833C4B093DC82811F
+16B3BD902BE764A1680831EC5A6C1CED84AE0DC0A65678EA5270BF20931E6409
+7AA44EACB22CCA11098F8A51096BE83A1ABA56C9EED4195D5CCF24FDAD92E823
+C439DAAFBFD652157D728F2754F28304710D3CB33763156D76A259D446647A11
+493FAC70DD28063A4CDDA162F72542368E1AC2826C4BFF7109208F66371910C1
+068F21779FC39DE03AECF1C9FB2F417930C22791961D801284DCC89B0833B6A8
+D63F153ACBFB7B7D547924613BBCCAED37D90BAC5B0264ED31C7B9DA5A2BC620
+9B20CA48424D0FF58905BCD6190BF4B5FC6ECCA1BCEF13426920197CAB41C4E6
+E82E8EE7BCB23C6BA6F8B58001533B225ED721D6CE3D6E89116EC33CAA6E905A
+649F8C6A1AA187A48E20DB864596481976216DB78F0F57543DFAE3CDC0A6FC77
+2CAA49442527A5D94DC54BE93C875690CBE52EAA4EDD9F2A511361BC0F0807EE
+96AD0D26B62D809E82EC14EDB158EF48A748A6FE0C3A7EE5D4479B35425F35AD
+3EC7444F6FA75CEA5011AD571078293448A33C7647611CAEE87974B0A756DAC9
+4E1BA78DEE477FA59AD50BF5C52E068A5E044A4A4994D5B24CC5045F768A3C51
+D4F65E2A5AFD271A7666C6835E28C60751EE528C0742433165AFBE71562A3016
+F59676D56B0B5F7E4984D664BC3ADDAF24B4205752EE21D4B57057A943018466
+09C3FA5D2C5BCBFC22A643586BC9E7A965DC34C0A7D76A470B0602AE45106417
+0701ACD2C764DDE218B924E38B5A13CB82678372E743A8B3CC300BCBBB878978
+D9847F0640A031D5E76B5AD07699C3B2FC6C1DBBF79938BA649C152FFB2B5BBA
+D18B9570670B99907506494F362B124790A17D4F415D8447ECF70B67DBD46643
+91AD465A1852B804CBE65206EAAA38FFD2B4180AF00DBC6291C9474BAE831466
+A9837BEE55AA0E15812D87E7033BF2CEF3BE10ECF668D3B57D6EF1D4335152CB
+08DA4049A65A51BCE4BC82BC80EC26012417012D6C86EE5293F1343F6AEFFC30
+998F5CE34DE6ABF67EEDFF71511FC9462AA30A36A54C347BF852749FF906C73C
+7350511DF420128BD2E6441C853BFF55899534D93A31C4B721622A9AC308CC38
+057091623FF825987AFA03ECD117ED711F193BB07457CA841A6CBDDAEA94E3E5
+921B7307A98A7A6FCD90CD09AB21868D1562FB2992ECA158DF5E9E5E5C66D549
+EDAADEC517CE9D10A93F0A132481B887AF55B32F5871FA9FF1605339B00EC64C
+E10570DA68796CD8EEBDB75C548442C10B3D8B07698C3569F4D385DBDE0267A7
+8B7EF2791FF56DEDCCCC80F2B114F08F1AFC29B5166F9CBB2CF7C0716D862195
+B39BCF6A81928E3C83497F03B43B0CE1F73DAA641E19DA487A5238FAAD459330
+28244382F21C57CD2364EEC72281433B4A591E35C1AFEBD1E40431913A7537AF
+CDEB0201EAC9CB87B28E1B2D6A24EB2E8FAB1C8967F7CCDF91E1B5FDFF977F31
+32D31D
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMTT12
+%!PS-AdobeFont-1.0: CMTT12 003.002
+%%Title: CMTT12
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMTT12.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMTT12 known{/CMTT12 findfont dup/UniqueID known{dup
+/UniqueID get 5000833 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMTT12 def
+/FontBBox {-1 -234 524 695 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMTT12.) readonly def
+/FullName (CMTT12) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle 0 def
+/isFixedPitch true def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 66 /B put
+dup 69 /E put
+dup 87 /W put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CE32340DC6F28AF40857E4451976E7
+5182433CF9F333A38BD841C0D4E68BF9E012EB32A8FFB76B5816306B5EDF7C99
+8B3A16D9B4BC056662E32C7CD0123DFAEB734C7532E64BBFBF5A60336E646716
+EFB852C877F440D329172C71F1E5D59CE9473C26B8AEF7AD68EF0727B6EC2E0C
+02CE8D8B07183838330C0284BD419CBDAE42B141D3D4BE492473F240CEED931D
+46E9F999C5CB3235E2C6DAAA2C0169E1991BEAEA0D704BF49CEA3E98E8C2361A
+4B60D020D325E4C2450F3BCF59223103D20DB6943DE1B57D05DA0555DF933BB0
+7B42D264831116C06C79335D519461E7B0E870A6715E3D74A08D1BCF86E3BCC3
+A43FC6BAD1C68BD9D4AFCC06D845FD1F1E70D7A47F0BBCAECE8396E04591E5E3
+4797F646AFEEB7DB548183F0B74C9BB6BA2AA04E7F5950EC8AE97C741D4B2C5C
+A8E7A8DF5A36A30B5A7592D95E1DBC63EF33C92FE459792CED29E2B8B6919251
+75EF62089BD7D44A6E1F9B62EC802FBE62B821DA1C3B2DDED45D27964AD29ED0
+9FB7868F3A8FEADA87A8E42D52C1EB7229D7C79B60BDA263F2BDB025AE14A507
+098FA274206BACFB4A0A7257D5998EE8F0FDCA79CB61DD1FC59DADD11E16BF02
+ECDFD706CDA1E72054D4EB55AF7BA9F19955886BC0BD6E0E3FE3769C94AF3581
+DFB2BCD67FE2892AF07E858A01280194D8DD7332B3D0A585C87FAB056C2EAA9B
+5AD48D1C9F00CEF8EF0D1408DBE1C03D04B231D7B8D5D998FE0CD7EE19828EF2
+F988EBF6DDBFEE00F04A4A1F4E1A55DED7EF3AACEAB5005F1962C724A017C914
+2936E2E0DF26A55ACD7DD836C6035CBF07981C1BCE3615064F0540A1034C69B4
+E3908E76EF8925D486DF0B4A8E1F02D8AA99585A7C31847AB9382F83880C1C21
+C496AB2DF8E7BD4643B28B704B5F6B53429D3EE940A79135F5BF0396E5B46F23
+42AF406C26D12BEA7A41F332AEB75DF43C15334CF4651A99F602036946B1B91D
+4BB0D2E51C20216D892C8173241AC8FD15A37C3CDD8AB4FB67D8565AFA61C068
+95E3D6E46D7C09BBD09428207D506AD43C693F3C3D787F6A5C39084AE45E81C9
+830900DB50DAD10A17E118FB5E9680B5194716A788FF7514A1167DD1A305FE62
+C7DBA30E569DD3565AC9C80B112E221E3878624A015F6224597D02C9A07B368C
+F9FDC817988D12CB00ABFAB288C20A59AE40E7A75C235938C47F77261BED14BB
+6574F633BC4DE9E8AEABC46E0965AD69748C315B6DB5F264D5E7635BE37E23FB
+873E2488086BA27275142C774A4A241F92E8ACFF0F25E81E2565642D88F77DE7
+03BCCBC437BB1C9EDA969E92CF3423203EEDE585A9371A00BC54DD695BA12EC2
+461AD673A27B24AD38903C82D0208B10D78F01780B31793DC3588AB9F19E7123
+D6B46ABA3A72F6F7261CA2274AA3EB9EB8B21E190EF9E63BD18362B550CE5AEF
+2C549D287572DD717264EE11BAF82DAE986C13C6ABE4780078244D7BE7119E94
+325AD0BAF860F539FE738FF07ADB87F9B8BDE6EFD70FB3A2BD48C8A83E4C0A86
+A64BE3F5659B7A5513C93663D3F178AEF685E424E3E9E91115ACE1358EBD3CF3
+25D9966DBAE54B4E5F84D18147F528FEDA20FAC9B8E97D9F31901754EC8D1EE8
+45260CD817B090729DEEEA881960AA2328BB6DD66E4B7E2165642AE3E0297DA0
+C9BC42F199B383F0128A5009E74775ED366DFF7F8D82ADAF14C417B98CDE1454
+8332341365A96C5D3436F63BE7FC1339109D6F3D387C032A1C7463DA969F08F0
+3D034A8CCE155D86B9208B64881343F5EAB503D8B379F34757601515FC1AF7E4
+E21C8811F9A46AD130B06112D9ECF232C79C55A32F9A32678C3C7A65F759A425
+F7D24B44C9E6DCBBF406E7E1E0F6D8A2A3B8EE331C4E9E650017FCF9EEBDF3B0
+CCC4E491357BCDA073AE32350D04721294519EEAE9A7B5FC45BEDA547F25251B
+4A5B130943F11D8505C3F75AA569CFE3936452238CF1B8CB4FAE036866EB9749
+AEAE038114576702BC45058F9B1E2CB9FEFCB766F811A29A81C4AC9B462675F2
+849B39199A37D6755E761111DEE4C0FC168709AD4EE609CCAE8B6018BF802FE7
+D89ACA409C3AD4C2ED4A37CCF6C1926B36D17DDB27100C5B8A3B1F84DE92223F
+34BA6EA2732B8CEE09BE17C4BAA0181CF2CB0D24EE3764C0242849F8924E4173
+C2D32E3DAEAEB1EBC7E98795FC19F7E0C833F441CE0215EEDB5F21
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMBX12
+%!PS-AdobeFont-1.0: CMBX12 003.002
+%%Title: CMBX12
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMBX12.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMBX12 known{/CMBX12 findfont dup/UniqueID known{dup
+/UniqueID get 5000769 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMBX12 def
+/FontBBox {-53 -251 1139 750 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMBX12.) readonly def
+/FullName (CMBX12) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Bold) readonly def
+/ItalicAngle 0 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 45 /hyphen put
+dup 46 /period put
+dup 50 /two put
+dup 56 /eight put
+dup 57 /nine put
+dup 83 /S put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 101 /e put
+dup 102 /f put
+dup 103 /g put
+dup 104 /h put
+dup 105 /i put
+dup 107 /k put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 112 /p put
+dup 114 /r put
+dup 115 /s put
+dup 117 /u put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA
+0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93
+51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71
+7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551
+E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078
+0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273
+C01924195A181D03F5054A93B71E5065F8D92FE23794D2D43A151FEE81296FBE
+0CF37DF6A338C826464BA5198991445EC4BE80971DB687336AE8F74B516E333D
+2D8AB74D362C559AAE6ACFAE49AEEF4F52E28C869222C1301D041E7A0BC1B608
+1BF728EF9E98F3A12EB2714E7F16B14E055FE1FA0EEFB058860ACADEDA9D0E4C
+42E3C6F1E4869471BFAA3760175F3FBD842755A9D7847EBF605F18293B42F557
+FBE2715002669091BB033E1AAD657532F34F7C66E4F04D63ABB07E6CB9D9AEAE
+78EDE8B79DD9BC87A1FF445EAA05B5572BB880E69F4DE1F82D7F0E9980AB0C18
+22C448B0B1722D3CC33C56FF287CECB80658B3AF5E7675BE82CEFF3DAD5942EE
+A03C955FF979E41E54BCFB5316A9AB8945C403A73180D0961416EC9C92F49811
+4B91BC4C788392994587517718521E416D469F69952149FF7F9224377EBA1065
+4A727BF806A112A7B45B0A1BA1D5A23683960575368D9EAC8C04753BF7465AF7
+95F25C258C63E4FDFFD0B412FD381946AA38C0B961652BCEC30322C47BF4755D
+9F91880688AF066E32FFB22E1A52DE741307AD3ED830D6BAA1D1F562919666DC
+5E8FD9862AC8600B0AE0BC7FC779252AAC57248744ACC8A8AAFA836BCF09B0DF
+9253DFBB1CB77EA8A59D42D1B18FF25E9AED72FA62FEC3F126F030F5D7DED9C3
+CF60FE890BA4A48E39E687BFFAEAB96AE542A6387F6624486037C8924002A511
+BEE5FBFD780AC1D4BEC3FBC47A930BAD0280D444259528B6C565DE11DE36BB65
+9BADC55C1EDA1A80458E98896D782DFB5C137897419602809F9BF8CA39F00C68
+EFB9E076FB324C2963F23CBFED28B9EF70EAA4E4B903225D1F199A7162AB239A
+D92D71C18B1B682D04C6A48926275BCB16D413B2A0E953E1257E0B12D8B717CE
+2EC84CFBC046A4338A69F454A469B12118E562B4F56C5FFB3CA5D357513E6FFE
+947A564B229C7FD873057D5C7CDF03E958294A1003B37D8DF565A70A00A3734B
+0138AE5277D383D10C2BD853EF806D3CCDC47739F0E374A3DF3B63638B949ED6
+4EC25869DC1C0B1F4DBDFFCC97382841D8F10F3635C792139A1EC462FDBA379C
+BE0990CA2E70FE73137AFBBF30CA54954D7E7377CC50BDD780DDD4C7FDC77AD2
+F3EB1169F14A0041F18160F43C24FAF556DB5D621709FBC544CE55424F7446D4
+6AC07A51C8CD5161AB0AD5084A96FB35D77F1CA155147DEF8D7A590EA6939514
+D4A226588295CE0007BA8A550895511C8D80BBE5CDFB8A50D249C3BDCA974415
+F5557914A9B805782F399E4078DDB6264F1A49A9A5BA45E284A5196E9828EBA8
+481D357B8D9E6ECA631A6204439FDFACE7D7E6A2392726107CB7D2517CD19A24
+FBE592C119626DB221BBB635B6EB84845C16A9585282E34958B961F4A543AF9D
+419B6A9105BF185FC767712D923437BE08A9C0EB92AB6792DBDC671029B6FCA6
+7F717FCE379C0F3B51C6CF042A762ED04898FBB4B0105C3C4ADDDC18C51BAA3B
+70A93666669547081D9246732CFF74C83EE90DA17F5B4F8BAF47FE4D81590988
+2858C9B96071341FA0A0D23BDD4947FC9BC2297913CFBD4FD6CA4303AB3179AE
+0203F1BD502065F90CE9BEA3B52DAFE4A29446082EA0E6B1D7AF1F31D0AD02CC
+9A7FACE2CA86E5FE0F6A425B28A5940ECA306891CECDB3CFC7A5BBC76B5D9E8A
+C754379ADE80B4D72CE493010317BF21A0CF4A0A55C1246218839DCA3F4D626D
+1F4161D38F54AD5142C1CEE95C61D8BB10FAD4B772F4955777AFDE8AE5A837C2
+A2BBB11D0BF5DA2E63D0B75ED421DBA9C789B281B01846B65DC572BA69591969
+21265DB722AE86BD8CAA3D887C975A617ACEDDFB7AAB341F47532AC0F354A530
+7662C089DA3939588774FFA16FC4A52555DED6D6F51DE718BF5F345C23C90198
+17B77CB8B5D53A5CE7A79F3E286B6A59F3F6178AC8BF15C0A15C1A8A95D03B60
+30EBE53DE328CE085CD9A1D49C69AA299C5B58B24334A546F6E274C1B534DC8F
+3289553F560C2F81E413ADB92FA0E7DD1C2F39D5FD268EBA97AB7335ECF28257
+96B4EADB7D0778706CB41C7E9C882760E7670936774A1088FFB2011115FDADB3
+B69EBD5108760762521C25C968C3E282DC3400001AC8FB1EA27FF643E3025950
+1D617BB8BB321281708E496277E11DD3AE0023DA9F25AD06B39C7CF527FED27B
+57397E88D3DF70EE4FCCEFC8A0927D6B05517E571B3E70ECC99F3CBA32CCD4DE
+B8BF22626B6C94FE65598A88AB90D238461EBD9A098DADEA4091AF1CDD7560EC
+8E1B9BC2321686E1759E6B8A270C8CB4A254F7368039602EAEAB86ED21CDED91
+8F2DB9889F46981C494C7EAF5E819B91C129F0740B8002B510014985E5791F59
+B16879CC6521D8E9F1C4C1890AC85A78022BE614BEFF318AB2616F0C3F02405E
+BB425D1555472A2642BA7686E431DC3FB8A1688B76660D9957C3FDE8D58109AC
+21B1234C9DDF3F0FAF93BCF7B2F88A001F23162E1A13E5E9118D51B485B70A91
+D0CBC39CF44413FD8686D9030782DAB58064F5B987E0402AF5B264B17BD31BD4
+FDF63951BECD73ACA6138854EF35B062D01F33073850D9C09A818828C581241F
+A625AB3638081DD0F00F946BE5450D38489CECEA4E66B4D85CC8AE0157E2AEE4
+A22A9313829F24D573101D84CC1784D1CED7DFAD5DD966601370C6CCBB723082
+A86BBAF0A5D867D0D2E3CA16E14E5109A29EF02649C47E12E88B3B397D65CACA
+DEB9940B92100744D686066F8250FF30E5F13D81428EE238A2E4E07ACE0F5C38
+7D79D4A336D0D26AF9C2B84088ED8ECDF94A1E3FADB45AFDAB46CAD6FF950B0F
+07AA2CDF82374DA76C56D29C80138841EB13F0D02ADD32F88B23E282ECC845F9
+BB9AAECE9CDC644AC2D49577A92307A83A99434F6493156DF25DBF0FCF2EC21E
+8C50A312C3D19E0609C0038554CF4FEF3ACEB7A833FD54B06EF0D617C2971C89
+E4C06075B09B84A4F78A82152B9A9C540B1D881313C2C74F20ED064A9606EC2C
+B56D7BB4797F1EEF4A9B13579CCF311FA4A4DFA62D80FDB7F535CC6526D1AAE5
+45C008EAF024B48C377522F74D939A475970533E645B1BFA81997549AFF26F67
+2AAE6C2EFA357DB3B525276EF330905688777057F4E4CBF584520A534A8587E5
+5A8360891E75A15205E8ADAC4A4E5A6E27D0C4A7D492216E4BC023AB027F37AF
+A8DC7579BA50204D5F45A51460C5BD8A5A7F87668CA6451137F2F59E117BBE28
+5C40820882A5546FA76F0CF49F8A6EC445F0647CC3227C400F56E7E9B84A6975
+E85E243CC1666DBAFF4E07EEAF3AF71BDACB30DAEA792F2B8504CAB071544F01
+5D66243D529C479D276FE22F7E275D9E7FA9C6EECA18716B2F213916E32C1D94
+6E32397B41AC6779543218E506569E3544803BBF9B404A983EBA62A494187B30
+8D3DFA4E1237A2E5E08224A60492C09ADAD8775B7CDB830520829BA164209ACB
+BCDEB2D574CEBFB7AE4BE72DF4EB1945FEF2458761AD8DCC0D378AEB7DA002C6
+9C14A665DAAA532B0ABA98D7BFB5A6151FF6703385AF7AE8FD315A492FCCDBCB
+B825707F9566B3B4943A3C61C3DEFDC31A843A2D67AB06891F3E110DD8C73D3B
+B5E4151B51D9F13905D7D94DB9ABBFCAF35F43B6EEE256B1A80ED6D1739D8D5E
+8C767F6F0E8704C5345D028A2A6DAFD9BB7AA048B8B895FE9423A7ACE858BADD
+595CB074A128DAFE08FDFFD6BDAC0114159A702FDCBF8013804B0CAEAD7AF38E
+FAF086A3248AD4FCA1401A85AE2F72E3E6956DC0996FE8ADB18F89B14A208A15
+13F81AF73D0DB72F78C4DA634ADE3C73756CAE6AF2E149C26316DFD93370BE1A
+FB4A79F77A67C07CB0A53C78367F21661D4AFE9E27328E077B522B50FD9AE2E3
+DA087BE481515B5DD7BF894A96A84A6C78874100505B7DDE1D22EFCE8D58B3AB
+313AB5495F72E2CA4E6AE22C0CB854302B9990372F1661D9F0A517F90686F248
+C5643008B3D29F7296E5C8FD4049886662EFDD4106E17C879F5D41CE84F87E89
+F6A3117C968B95A35940CC29C43E1E0DEF51C1E46B676301F40D59615C3F73DD
+DE37B72FF7105DB84227DA5241583272AB1C3CD97AE11C1EE98FFDB5E5F44844
+8FC41BEA5C54B26341AFF6830D9D0A5A2901B0653D8BD0746838194D240FF753
+E99750D3383373F453723D86BE97B571B8B84D8696089B5CFDD53E6C562A2197
+A8C4FB0CC690C27761A816B441029D3D306245052E0C41B53025D8CB7267CFE3
+C17FDFE348E765326F91AEB700CC49162DF748171214252CBC821493DD01AA20
+417D66DF47EBEFFF3E9BB2B0A2BE7D9B8C68BD570FC2EB0FA54CECC318F04C43
+19598BDE93F2F13DC7847354C99059AB20593EE51E94F9D4E9241869D605AAF4
+9D9B5FD88C3798A039A67993C5EC68B6326B132E647F67EACCA7F7AE7F718D85
+12666E90D7C73EF210E344964A38228B236679A2B18F5E081234CAA2458F8D83
+3F0CA308D19663CB12EB904076EF88E556407C33C9380A6A3D68A9EFE65387C1
+A1BCD2D26DFD2AC0881EC30E81C0A4E76C244A2BD822EE88C4A60B480D107E68
+90E419A1F512E865BA922A7830909BC2611A80931CB2E9344529586726614D94
+3AC5200FB9FF68AD9686506C5EFA8788C0AD0251AFE7F95E84683380CDB421C5
+B1A783B6D5F3A6BD1BC1C14B363DB01C87C0796DCDD5BECF41A1A9F43183CF6B
+82C2AE49F0BFDC5DEF7729F2E638EE6EA9E4D059EB9BB1B992AD8C82D501A550
+1BF73CBBFE740179B54E193E84A55DCD61B343C1852780FFB44248FC9426AC94
+AA2B3FE20FBA30F6C4D1E0FF3EDCDD8C0F57CCB50CDB0EFE2E04A8927E239C1D
+9B026C7929BB48461D4D695FFC766C8A0E545B1BCC2AA068D1865333108E7985
+2D93F9B00EA0A90939D0D3840D59B6CC0CE2C147B2E1A9A4F14270FE3ACF51D5
+99F7349106165AD627CBBB0ABA01ECC6D3A14C1DC1ED23A9DB9865BB4396C51A
+31ECD001EAC94B33C34E29C5611148EF3E55DD61813470B8F3CE32564C749414
+3C93C77EA5A3538A0B5AE3FC4DA32813B06772E0E48E25BB39F3F6FDCC077E86
+F86FA50E18FD19EB2F37311CE87F18F3BC85CE7FD71CA92D5C3264E34E04A2E5
+70C79D99F54D6C6D9D527AE45EBB48411221134587D2253E7C8ED7658EDCA34E
+5E768DD14E0200470F73C44D006CE8CB35DE1CA3EC10ADC668B0662A7774C891
+84EC95A31DD872F0728D9F65CA80940080E04630BE4DEC77A2C49E3913C39978
+BF145F8832AF2C4385EBCDB15F9D32C22CBA0CF950877717D6F1591D7C0B8047
+8C9BFCB16AF7124ED83137695F3D69228DB633053208C29E0ABA1B06A7FB3EE7
+5625CB44927E2DA6E038A6E62DEBDA2D96A03177982D8FA33BAAF4426E05F4B7
+9C1748B3FF7691F9888E7FF864A10B9DF761A41E6B5CFAD2BDD7E1C4924AC97B
+F4B352705316DD1A58637CC12D71C18A5CA691AB2AA8F171590EC24582B1123E
+94D4DC587D8F99E18A711776BF4013C96446BFECFEE4C809EA94B169088024DE
+0CBD20199A915AA406F0BD5F3D63D1467C49B4691AEBBB35ED6624F2D7BB74BC
+E80FD92B9FD04DD9C2BE9B6FD29EC7EC07FAB447511C61DD299C783BC09AE2A4
+7B3CBCA6A20C6631D06D0B2E2482A50612BB7C29B7E7D0A205EB0E8436702581
+596BC996ABD58CD8D5BAAE4B1478195CAFF98FE0141287296C4EFB8D2E7A8442
+F0A3AA9F9264329982532295A176BA1867EF732BBAC49AF485D9D0F7130F617E
+7F7DEEF935874D55A22240F8EDE4F247D5F73481373A392D40A8076BD91079E1
+1CE5998BA13D48D56B49A92B4A18430E316405D2E2E391B496A1934671FF1785
+AF42BA3B2D14B8E04014437FD194455C50289DFBA61B5C377BCBDADA48E82DEE
+4E70EF5E9DC03064907BCB8BE4D59DE069FB0C0CB140DA54708E630767313F9F
+744594AD8A499CFEF733E640A11FD74E46A749F9C7D18D49251BF85C6EB4668D
+67598C31A8F90922FEAEAD4B83B6E7184567DC798E4BA1C4C9B3461A478D63CA
+054F13B502DACB674EB49D6BB935E5EC82BF99FDA7D47C581AD7F940DF4FC6FA
+6C6D25D647033AC69505F0CAC58DE99087F365531A6283CB89CB644688963C3B
+8B2203A94294E58739EF23C7803630A1F9121D62BE1977DE2F41687C8CAF87FE
+CBD7AD3B98E0D95C8C6E1A7CCB0E09465AA874DC90A0F5DB2C5E7C130297FD39
+EFE63B0350B5139D09E6864D22C3F1150B29196E40EEF9723E71158B7ECFB8E4
+C426FEDCD439420B7F1C251FADA347C9A2C49738B5A17922E1EA93CA7B125B76
+57449EAA9C1D591CAD327D0E98EF2D44D614EE9ED49DD31ACAC0B956620B6BA5
+5BF6D08CA7541059D5ED2EF00AE2EE95488F5645BF6837D9241C0D3959B7580F
+C9ECB2BCF3E65C07D52EC9CFB21C11CD4C883E44C173214C900C44D2E1E43DD1
+CE8DFE3DA93C38B548BC4EC46FF91F30CFB97525E1FD4E77686433B20BABF8D2
+848C1CDF1BCF185CFD7A81D2D4BB826E837E2AF35CFC4F419F698DB0C43E9F9C
+B0FB628AC9A3CBE9B1FF4A067016E70333E78B32AB2D89C483834B31F5808FDB
+77492E099F1504DABCA5722C7860CDCEDB2DDEB512FFCC7D287F4945FD711F28
+87BC3D36173566B81FC2C1290C717A09697DAC6072408E20926D39270121CE58
+3EF97CE12EDD7F87F2C8CFE36C3C0400869C0D813B71C425343EE0CDF717BDD8
+409D5297D0F8F7FDEB0257C0A391F5635E0DB1116058942FF3E7C94D5F2873A7
+A3B0ADAFC3835AF2BE474E6741319BC6695FB37F59AEE388F81F6E66F910000B
+72E6BA7531B4378CEFEEDC79CCF4947BA1703823B5AB4F4AD73D9615C66C489D
+99D68E49C9BF765B7FC547BAB9640D51D5A7A2396507AB5A4DFF3D14F52422CD
+8FCFEAA06A56C6C7FFCD29C9A7A59DDD2A909A9363FE5F1E9629616D25ED38CB
+E754C059E4379318CC491C3B1A90128693AC53F80F8210FAEA7EE638902A7D3C
+82B95B3F5AE340EC1B648DBB9FB679D6E80B7F426D8671FE7136D97F51E2D2F3
+C9CE9183E4061CA40091A2A70DBB9ECBB19CE3F65ADD0FB346B54BAB182E2CD0
+EAF4C0F402C25573FB344EA771B297BEB615FCD0595172E84ED2A62FF8962634
+23C19076C2A9ECEED5135994EB397303A9619C76DC55E032DA83FBA441BD484A
+59F70A5110A8927F6239A14D4E223E189A5462E4A92EAEFFA4B961A2A32B320F
+C2B4E8C1821FA67A655B5042C15E4DE1FB3652B55078DB123573C4E986B19DB0
+1C5131F3DFAB271C30A5476B4A19D8FC922E31879C34BAED94C07A4841B8209C
+403369FB8E842610D1EB4662B6171A4465FD0E819964F62EC5B0ADC92F08CF90
+1DE0B410FFBAD16F6D355E8AD72CCF67961EDB6CDA82398021007C2D0462E893
+75EB0710AE4A6CDD15077C9DEFC5774EF4A657734D703CE42174259B58E5277E
+0DF26BF59AF8D1A3E7DC12E3C12AA4B67CF35B19962F6950C2020B698D971B35
+82FF84E72F72FBB0C54A112BADBAE6C4CAA358BDE6A705AB59332C3850CA3D25
+C7564499BC1319121CE0D93218210C68080AFF33420E3CB3A48BF9EB66BC07C8
+A79D8CD8E78C200FF7CFA3DAED0B9E87E6141C88B436D8FCBA50AC195FCBB9BC
+9512B95FE3A37FFAAB39850FCEBD4D50A243EA416E73F53B4B00F3B6EAE0CA06
+0693AFFEF215D00BFCAD02E45496D7C8F5E99EB9096FC4300D038C1AFD31EC4C
+5ACA6B72C1BE7204E37A4CBBCB1EC26AB87F2FF82DE20601025169A5FBD2D060
+62B5B2DBC288C79C33B596832AA18D730AD572C6EDFABCBD36DEA87C0F323C3D
+6E537AD3B43C6F3A905597570A8C6B0B4A5E08C08A430B643B6ED36DCAA09B41
+FEFDB90E10C8A8B74EB358437D0CEBB9E03109C593BAC09CA996278246E7CA38
+4F311F23DC5A7F7DB374E0E3D066C874EEE28CFA47054DC41A389203BFB3D601
+BC9A4817F8DAC250A102E7404CA135B33DD66F8FF40D106F52081FBA3E79CE29
+FCA5C502B38C86D8D507AEF30436472D2381DEA09B8B3BCB109BCD72332A9483
+E61ECF0F89A85BC37B8C10FF3F7C0A84FB8D0F4A7898D3F8B06202FF8DCD698B
+56544751347E9AA35209B18D3D416E5E034E36D9C5FC0B33B7AA0D46F3A3F925
+7FCE00D42215F7C2717D78C7BEC199043BCC3D4CEAAD87BFB1ED2F719ABED65B
+EB6A783BD5E0935B9A5FA7F899D25750536B99A0113F16C45E5CD4DDD975EA74
+596C6E35ECDDACE357F9EBD01798566169C00EA22408D0F4FF55AC05313E7D74
+038FB6B5EC916B21D5F65E1B3E95160A471CB7DBDA69610467149176EE154B5C
+7754CB9B0197B63A089ACAA2F261E02A726B1ED33D19A1FBA9796366A8A8A68B
+8CAE6C135DE5112639D055A8FE22F1DF2524610F4BB4A81B08DF745EB2C005BC
+3C75F49F3B81945768DF7387E169B97F2D97D237DA0E9333F57CA9B88C746B9B
+7B4400828A0B8F207A9F3365F426085F664F120A823F5D4E9BE39309B588E413
+B2BB052FEEA82898611E212539408722E7BEE17F1C0DD5548283853F124CE54F
+DB4F95273C48599D3BFD0658FD23A688710946173DA830B62ED1EBE7F99DFBD6
+C6B89A3DCE2972FFF9FED7FB2A8BB9FE8FF631AE353ED88860A0EB1309226B5B
+E7CCF92B139FBD8D3760486151E6E1D8A8FB29AB75C41E6F9BBEB6F1919CCDDE
+8DD5AB6A65107EB060295E849D2D6E60580AD2C02DF12FC823DF9F935757A77E
+3F5E4BDF7EEFD9EE03ED598DF438A929A368E4AF8D03BE3B79D5B92925EDCFEC
+4CF10B3566E183E6607A9D5D8A8B584D34EE7C673955B3DC1AAD1EDBC150ABEC
+E085377B9E8F43224A9D0C3AA793555C3F66D99F7FCF0C62FBC5BED46EB0052F
+DB8A8CCE5715D224FA06816AF233D30285FAA25CD1995AB1C6DF94BB44011D24
+BA389EC53E7FDFA26F06BE5000E1F3E7B1A485830238DF86A0826526743E3B11
+487CEDFC450401FFDE8FC4E8355C878915A3A93996C2DAA81A81A7E6D2AB3FCA
+3F2841D2CF158601213FBB40EA4FAB368774A0E639FC78E8C2AFC5E1B08F9D1A
+70226CC188C5A317CE739326C15DE95846595FAB5F4469132B50168311C90013
+BA9F32CBC89D7776FC977774A310184D7C9250D953931DBF3D695A193EF2083B
+EFC7486F753F84F4C01FD31CC2344D2F4DCAC01ED5D94278AA9DF63A87BDDFC6
+5E3297C73F8338C6189EB1A766894F262A1AAB9337B079ED5C7298C66163DB28
+549BAB63F3D657DA44C6E832B8FB2A57460EEF0AAD362629D1ADE07AF89B14BA
+4331C2E521EAF3BA71F1FDF6B74B5A905B990AEBD3B2B6F8FE69B65CFD4FE59B
+19B74B739BB59A605FA5E70D833F055E493BD8D244D1BE00036D00D4340E8776
+F51F81D25E7CE1066F96D3968894E949DE618685C02EF0B5060E88D848BF9409
+AC34F2219E4F2AF2CF219326664044EA6A3F7747839BC470680F16EAC85D694F
+D67A4660D3D7AB03FCE66079CCCEEFD07D03F9DF346CD15DB284DCB490764677
+3AFCD9710DE1EA4AC39CEAD6CF59C6E95B2938A6899096AD94E2C804E74AD781
+89B3C6767FCAA5BB25A0C22BF93A29C2CEC62C300DFD95D8129E70AB4623178D
+F35B4B52E4EB1A354A9671CFBB2B6D543171CC9CA8985F15BB94DE4C76809E29
+711E14A3CF8EB7179E2AB1E6DD1E56FEDAF53561D04A852C999042AE4D014639
+9F2036D05EB66C514BBA47E0D1615E43213CF3270E28CA59C8D671FC93E6DC4F
+DC7895041DABEA2274A2916FD80A8AB435235EFA0C42ADC3A7E560BE0E19D026
+C6F6EBE1519C4E38568EAAE27B2A68F13FE94727E05E4DFC5F9B45B9F946AECA
+954CB8B160665B6593E31BB27998A29F510AA5C149050F995246D48CFD2E3046
+4D61CC66D7E1EB08C253C081351D47D7A625D0922B6AE8FE0EDBC35732699C79
+2C8FCF0D9303A7DE0D34D1A28D6FAF68177FB23E919A8CFDC30B947D419E0741
+96D6A3DF749E5B27F4EE58749352C396A2161EE2F7F145203A4AF7B53149A98C
+BA98B1D9553584918AB2A4B7D83991FF1EE5A4AEAA5B722B5D60C918973629C6
+A22B23D2574425D472778983A2AB0B07FB0B076E31F277C8AC19927F4287361C
+DF7B786E8B5F21FA43A0DC05C3C7613A61D191F2EA60FBEE725F3944FF81F342
+E1E3C6DD4909DA4E0E6FF680976175F722F7BCB6D41819E4A1E2C7D3A0AAD672
+E5470D581598C43427BAE4E06A3EAA331A2E4D8CC30978D629CB0513E3FB9EE8
+4D70B881F54151D0357E5CE28EE4ABC81450ACD3918D26A168AA5429C8A08E4B
+6A3C8173C94EA22FEAD8EED6B843CFCBB5CD1CF96E970B5D125D5595CFF29830
+385526E233037BC2DCE87245EAD5F912C0D5625BF26C432C7210871670FED94F
+73DB2EE957A6D2B7A03303C1824D6439B643AAE4F75B779D1AC78344BDB2F332
+B98CD271ADF18ECA8FB51E3257EF3900F7B24206B187E37AD646F1086282D211
+F7CDAE2A29873876593088CCCCD4D9D8EA663BB05D3FD6CF8C4CA27EF3428921
+EC8448168C3C60F3C1DC2E36CB6DBBAC24835F9C2DDE4D662D99AE0DA7A33317
+91355449BCE5F7490990E57B733E1C39E70F4B67E2DD738BB3C16F9FB5A6624A
+60137EF56B60A3CF80ABFC7BA4363F3940F8A4DA65E81DD5E7D72359B95913EC
+28CC664981A26AA9EDC90F7CFEE0679A58456C63DBAE2808C4A4983640F3406A
+35F48EBF829EB1329B49BC4C470FAA0D9A5E61E23278413205453DAF9BBC7E0A
+D22FDC15F38EFD7076F6C1F7BBAF779F368CCED9BF54D3808233FDC5BB600287
+D19B06F5ED0AD1889F2A4F5A658EEFE3FE5A74E86A5E845A4CCE45D9A274484C
+F89C02A1E51DA1728D0742EC26BFAF66263B30C478A09F35E26EA7C1EF870B64
+12B516B91B35E02138D6EE2A757E6F9C216EAF7E3FCA7F7A80CBEF35627737A8
+F40FCC27C17180A83115E6B70A263EE4D2207DE81FA2F938E4286EE77A6D4BC5
+A77914F2ECAA92FA1E3DF6F45658325948CD5B74D11795E98CBC2F2182B8F020
+D9EB376C6DCB7EC18BBD9C9B2C710C7FD9BDA0641A4EEF9EE4176C140E9E61C0
+9D9F0B593D95C07176B81EC1D8CE5376302121F1A329DE5BDFB5C20A0EE2EEA2
+54D7A69E6E431813F099FEAF668338C1A5483BBA74C9D29885E3BD512559A45D
+A97DBD1E9E9F16F9D54E681DE1C4198F6CDB9767568FCD71741B3A788E148586
+709037283014BCDB17CC1BAFEF9F91284DC52CED762A10D4C869EF73819E9BFC
+288D0BB896223767038DF7B4BA241FE3D148BA62D68D50B107C165FD3E4A69C3
+D8E971BBD5FE576EF4036533875B5B12706A5137F839A486E5461354ABFA8B77
+03D121E0170F8EC24E36AB94B1A0C099DC0F223FCE1466126BDF37F4E1165093
+3924E765E540ECA2526E5E6AEBF713469A5E67DAE66E158169F4D6D933BD4F51
+3B2038C449C79C9900239E39022F14D67DB752C61E14FD66F2BD1FC8AD40740D
+516E062A2B53C1E4CEDBA43EA20839DD9C4741209849E8B71E2841C739A97B07
+3D90E720F1D41294C70E4B430529548FD74DEA5AD2846785B6015D91ED97C5D2
+6C197C7C84CD088106D0C91CD5B23E9B8D86ED4A3450C9B079FF2965D0A11D82
+A382B0B7321E10CECC525BABD7A43CD00B082D568F34A8ACA756C5F12D045B4F
+FB6240E5246039B39E2C3AABED3B3AAD5BC47B353057A58F4217E0BB460458BB
+C0D090CD43820FCF13EA2CC91C36EEE43CB4152E4F6D122F378130B64B2F4664
+129EC23770B7A162A8CBCA6FA4EDF9DAA6671EACF2D9C5BE02295DD0447C59CF
+E0E790625C84EB1CE5FEF409CA896BBC8B981011BC7698A755AE654AB2B0187F
+F092098B3C104538CF26A1AF3716934028ABB362C09ADF8063C7B8057A481A38
+1DECB03FB03FE41678CC6D75B9D1E1FEF7329CB09CA82018BB9F5D33FB335645
+4A16A97F4321D699EA18AAB1413314EEFC39C5405B91759431745622114E849B
+DCF9FF349BB11BA4D227648A6CFF161E98E25034EEFF2A7F72BAB61BC765630B
+2CAD74461FF85DBEB32E750F734912666C75C305D6F07CC4FE71B15BFC0128B2
+719E33ADF72AB2B1528E517E97CF9EE8750B04AFBAAE9E58238A37C327F195B3
+99F0E3E4F8B964B78DF90CB2B3BC926B031A4209C341960792610CD8B958ACA7
+49FA47E55571F0334688976E5807BE58F1535DA47ACE85D976B30CE5AE91CDA1
+AC9C4AD4A36BE9CD8A5B11ED444388A68F4AAE04E89B89D6691A09C8E15894C7
+512536BE6BBFAFE7A0D2B0306C883B97B3B2CB9369704CE85FE0E309B218DBE7
+C06C139242F7571FCBF7008080BF067A0934C7F9A9FF577FF67E17D67C1141AB
+B9AD2614C479F5BC6F4BC1A6BF6264C58DB2E36847EA434779B0825AF7345AE2
+7B0E2F4A15C7E6EA8E4C8F9FD614ACEECB3C3B156CEAF8CB34DD42A8A6A3ED1F
+FC3A6991C6F133E306B79218ABDD593A33FB748FE49FC7880A20FB8466D0991F
+C7C00758FFB9436C68A97D01A35C2B77E1083CE5AFB6EFD685EB7B20E0168FC4
+FA5E0A199760353647C3B0BBC1F7C06D6536D4F92D2E2A234B816A3152E9724A
+F427972BC2517988DAC491CDC5E4D29181EE9EFF07ACA0FE458F7A087F4C96ED
+BB8855AD5532EBBF25187C1CCBB9AD56C1AE3023409DC1668F04D9191C1B0747
+3919F51C55E69EBF5DDFD161C962D98F654C9B535112823C4AEFE42B26BB7020
+BFE73E41416EA9638210A73D40BE188E9DAD0C9B661EF212EA9F39AB2A0475C2
+50DB96C6834EB95833C1FD4D42CC4A5523529CDEAE9DF244F94FBCA4CA09ADDB
+0B8154C1113AB1688AD38B763B9B36CAAA77490F88D98A893BF642836CEAF6E9
+8835C11A4D2AD2F8EB20E269583C466D96B21AFF8BA75D7E766DB15475E31FA1
+8BA5BFC3C4E96C9D7581061424231B3C21003B6250CB71A9033181564261E8A1
+AE0FD34B0A9FABF1FA2D9B428B932120CB0B80ED3FEFD08A3BADBA4784313146
+9CBDF52AD39C81249626ED19E9200C9608C93F5EDA48842E6BD74311D5DB3F5B
+4C743C7D8A12A49A6DECDD0477595B789AAC43350914F15B86A89720D30B767F
+B13CBA0D5FE0A0C22C2C44DEEAAB911B169F58039AB084A94B3D3839A8BBADBC
+9D557250A4F46B05C28AC1F5F6628E06D15740F4359127479DBBC85AEBF1B8C4
+3759BD0D4A4C98715EF4212EAC7E40D15D4363A495506B030AD90B0E662504A1
+40FCAE6FDAF99CEB0747D1CB287B2D482A2163EA3F860FDB1FB45D476C8F1C01
+13CD22AA1EBE854C399AD2B546D2DD5E8AD912B51F09E3F41B9CCF36A11486DB
+0310C647B06815AE4EAE035C8E9566A28D9AEC9E6E4C827AE857BC3D8B793463
+74FC41FC35073D0F5F79E444C0B82A1EEC7274C61E6F3CE12AAFE50693FEC720
+8C8E2CC2C0883D861521E463A52061CD16F2DA18115C0C939FC2EB4B1E6F48D4
+7F29A30F6287911365FC5BD74A5E4A0D9B60C379BB755A4AD5C5969B12EC270E
+AC38B54CEF0E9D381D5F6D9B8AEB37A67943C8DDC5B4051B217BDA995A504326
+72645CB04CE748648C2EEDA0735B5C11F0ED35A9C09FE0A022E65BC0C22F78DD
+9B563A53D33ADABA1394
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMTI10
+%!PS-AdobeFont-1.0: CMTI10 003.002
+%%Title: CMTI10
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMTI10.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMTI10 known{/CMTI10 findfont dup/UniqueID known{dup
+/UniqueID get 5000828 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMTI10 def
+/FontBBox {-35 -250 1124 750 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMTI10.) readonly def
+/FullName (CMTI10) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle -14.04 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 45 /hyphen put
+dup 46 /period put
+dup 76 /L put
+dup 82 /R put
+dup 85 /U put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 102 /f put
+dup 103 /g put
+dup 104 /h put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 111 /o put
+dup 112 /p put
+dup 114 /r put
+dup 116 /t put
+dup 117 /u put
+dup 118 /v put
+dup 120 /x put
+dup 121 /y put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CE32340DC6F28AF40857E4451976E7
+5182433CF9F333A38BD841C0D4E68BF9E012EB32A8FFB76B5816306B5EDF7C99
+8B3A16D9B4BC056662E32C7CD0123DFAEB734C7532E64BBFBF5A60336E646716
+EFB852C877F440D329172C71F1E5D59CE9473C26B8AEF7AD68EF0727B6EC2E0C
+02CE8D8B07183838330C0284BD419CBDAE42B141D3D4BE492473F240CEED931D
+46E9F999C5CB3235E2C6DAAA2C0169E1991BEAEA0D704BF49CEA3E98E8C2361A
+4B60D020D325E4C2450F3BCF59223103D20DB6943DE1B57C5FD29DA32D34C95E
+2AB2ADB3F60EEB0600C8ADE15A2380DE10AC5AAD585FBD13097B1A7E8E210D4A
+EE96785449E07F0C8EBC2EC5EFBFD0897DFDC15E5BFAC9584D8DE95C5AB288CD
+8AD8B9BEF0B8E5F887B3B0B331542FC8184DCCB753DB6ACEEF98B85756B988DF
+CAF1AE0DBE7D37D5F44A2E760AAE3A5197C27B15E32275A64946C3E4D0476FD2
+7FDE148C788DD2106F7C825E270588AC05B57E625AB17BDD02306F9E5FC851DC
+32A5A6EDC43C770A71419B2C0C8074EF3F222C8A2097CD81A91F333A521B3A09
+482A4FE1CB231CE344AD126AA284C3280AAC3AD162CF0EE241BFB4C8F20502FF
+118507F5D1B5FD898571015E73E5CF2281085072E00D401F6F59761EEC3E8381
+1F26F75DB66C504AB6BABA87D121B1E7040A07AA2FE01F80DBC246CC03C4B2DC
+C2A715980C52B7F96BC1A78FCC7F4F52EEED5F705E08FC1E5BBFCAD121FA88AA
+8EBE58172C162AF409DBB0728F14923ED02A65EA24E5D52B6AD07777455A70A4
+61833D3789C719BA92E901232599767E423D5AD9C807670BE0E7B5CFF8256A20
+C7BF7214FFE0342809570F5966A2C43E784F35015D9040BA34FEAB6A6F089504
+3A40A9E9D711A2721D3F4998371430FB3C94BFC619559B97D49627BB630F4B70
+9D0A8FE4E916235335C3962F3CFDB04C4A3CF714DB5E260F4E66FFF2F27CEF2A
+D4AA26BBCAED23B8BDC98F8F453BA27AD7758537561E766B82DC3032E92A9EB0
+125D98A22C5466AF069BF72A9BFA052A8628FEC6A6AD0B711DFFEDE3AA2D7CE8
+34EA487038EF50F953B8B4471CBA6FC3C53877EC1BC94582B1123EDF44B4056A
+30F49394BDE22CDAD7F01951C7013D26979277D18EFA594E8F4F2B5E615187D9
+39E842EC28461B9ABA52020A127D2CB9002A673A435B13C10602EEFDBBA6BD49
+9DDEAB9E68D655443A5C2492BA061C1391A51592BA8C353A6F6A0708E8860184
+2B5D031D2CAB87D618E9F6F7A0BF3F66B3FD5A25BB91F7F1F5F99CFF56EFF4FF
+0A35C55658001ED2E97B26C869292F6274D433A5443179DBB8EE987196306348
+3F9E87C6422AFFDD30080C9AC4EE7FE5E2DCBFEE4974331F4AAE479FD8806D4D
+9C2B85FC69EB0453AD827A1E767E5C484BDFBF5C8D6E2B3C96298B390F22D757
+802643A79D5E29CF3AEDF0E12CFBECA4663444FC87F2027571DBA9ECF688BF28
+FF0DDB3AEDBA0FB28447CB4B5D5205F40C1E7A525FD7373392EEFFD910AC82D0
+98E71660A1B3227C4A2592F3E853CA4CDF64DF19A52582E167234F4036FAAAB9
+5446BE102DE2BF43E82F0112C2A20F15A3F92C6571AC761665A905362C4F8BDF
+AC8705519C99862CD9C0D75113C4AB5FBB83C880E46B82715B5628890D9103AD
+A2329638B95D93C4DECDC5E6C588C9D5183EE6FC28FAF9825F02DCA567306D93
+5440987A81B51EE7291107A08F201C609FEF91A8F0587E8B13D4BAF74A5A6815
+DE9E4441F46AF8E1DDDFA2D611C889614040B144A5EC064DEE4638C04EAB2E37
+4CA8F50FB8C4D65BB296DCCCD39F1F554CFBED96670A91F515CA10EF896874BC
+8EF48C6447752C70FF5A06F928DB55586354076773BFF7E94C4C3A7A1C1F421B
+A9B4E3936EC26E0C19BBBFC90F021E877F54B62108F6DD1C7F6D5B8E64FC9362
+E173F01BF2904B7E5A08B3543611562C2714099DE7D4FA330DB148B560A9601F
+42A84452811CE213DCE782A0D7809CFD954D6BC1EBF2BA4D1B18F50FA8174C96
+3E0120E266AD5DDB40B3F6798AC28CDC5C3C4BC34583528F5B5DC8A222B80B59
+A3A93DC715D061EC6915E6E6E21A25425C25E8747C60F170D61047108826F96F
+7830E220C108B441B6EA3198E33C49BAD8D43086E49F5A2BC7958A1A8CD011C4
+49045193394696EC3DDD0BE084E8F2E9F0B9496F035C0DEC1CE11409DF566428
+D50043CFF5CDD1092F6E0807E660B68163BCA738E8D98FC6EE3F713164CD204C
+0BA84FFF4F33F47BC31750B448603D7ADB9AE92FA91AEBBBEC0DCD66980E6955
+CEB425ED07115B24E40F53B29B9D840842EAC691B4F591F866DF27556474B485
+1C6F53DD72499847109B16C7093984A6B8487D4F3870DD517945CD90E648C1BB
+8A6861E540FCF9D75B984B5009B5CC760CBE297042C240DD624111670B703388
+6FE6FC0E89C6B4C88F51DFF3913D0CC1FB4770C8CBEADD4B86393605C0B6C468
+83CA5594754411B6FC331EF56D7CD6D247FAE42E966583C29239A8F862348D29
+60B177984B6B957E733DB4D275015691D91443BBB13C2DA96097A29733CDB284
+42F89C85A7A743338C9DD3BBC4EE53F695E5163E6E1ABE5791ABF100B198B9B2
+1C21E2FA2FB4AFE7F9BB2D381260CDD3A2CC05BF513AA1E80ED69FA27BC5ED5A
+21445BF00BC2F997B356D94AF13736C6D3B0613EB6F4CD96A685FEB672661DCA
+206105EDC3CA07900676EB2FAB37F48D2E8207BDE1463894DA3C5B1488AC1EE9
+D39DAF691648048F5D7A384B8927F8DA2BE3602669F71D80686E427F395134E7
+7ADCC611BA91AD4B7A0237213C60CF2C905359C90795230344FC3C50A22BD44B
+55B2044792509F50F5C21F53D9F9E9F063ADBED3AB99E2613B23334FE8DF70B4
+6120F2EDF69F50BE793EE145B9FF9C73179DE640FC2ACEB5C6617F918CEEB762
+4CD81E665B2E544864D13230B058717B207D3CC5D6647D5343DB4D0356082392
+871EFFA896631A7E0D6477942B632074A9A4EF7B09D4701B1639BAAB4E03A40E
+9B54A7A4F845CD63F88831EBFA4FB847847CB98F3455CB5957F2E0A0F5623645
+DBB5C5564C7F8B117D6E27E65C0F3EA81AE67B4AE4B201E7C4FB0A8364FE53F5
+41A7CE8F834C2C4B322809B353A5E63BBA7BF3B7DC1A85EA700BD287C2BD3FC8
+2832B0BB4695FC937FF5EF06FCD87DCE6DE793C2B1EE10E6450352C17726155F
+220D550B1759E15AB2C1D5968E52C8080CD280E99D3CCC0E80C2EF8BBFD96001
+A226FEED7311EFB4B67F424B557A877379A15BCA54780F0CD2CCA00400B9B39D
+981C6B552AFD2506D1B23618FA9AE6D8143CD7198A8482CB416CCE62B992347F
+337D505A4078713BBD91E5535BD58EF0351EBDCD749CC24D4AD39F8CECD7D6C8
+139756680A4C03A58B3374CEC658D30160AE4863A3938A891BB59CBE02BB451B
+1BA4B2B6E68AB61DEB85F95E3C909B8B66E220B9F18280161C279F10F7093CDC
+100A53D542F071CC0A5AF834DC1D18738F5DD62A5573E884E1FFD22BD810828A
+1EA47F8218C15A2E97CBC609927DA3CC2B802EA4A0D7EB57627C135E3B065905
+F97597D818A2C5CC6F328AD25AD11FA50F1E4FE637980B7474D6F85A521892FB
+72989AABEBE02A2D0EFE88A6F67AC29F5D8DDFEDAAF465C439983C6B84389FF7
+A6434462BEB7B07DBE4BBA61ACD4A60C55B5C0AAE527DE381DFECA2E6BAFDC8D
+310364ECB42CAFF72BA93C067B2F02D1CA7C34AE7CDC46787A0E234C8BE8A928
+7A6F3DDE0338FAD532A9886E8E3525B85DD39364AB03EC4C0DD25DC179CC1989
+1BE232E387E857C78332D834679195E10F1E7B87B7966DA3B2238F53D1E13FE2
+8F55ED6A92A750C7250C9B91E29796621E7E9520373214D7DA81B2875A986D33
+80382AFF6DE1F829F048E57664D9C4ACE91E4684A51023943A4964AB5657D610
+3A5405EFD4CFD1EBA684243E15093C9667797BB47617B66054EE02C41FFEC45C
+C1BAE8AD56B00D323FCB1D2744F061FA16E161988741A319B1564E04BA210996
+4F9F02A3268CABE450D166A763F5284954564A1C86B76544C5F5ACDFE0D758DB
+865A1CFCF9FE8CD5F9C3B2998C56468FD52DF8EE60C6935A3D221EAEC7714E3B
+301371C7DDA0B03A2416238F2B47BAD3A2C5021C886DF51C695AF9C87A864B48
+3BB3FE0B355EED5454B59B25A0D8A1B8CBD356C24F64D9B55E16C30C011365C9
+1E0380753BA3EDC0868788D5F50B9353D0227BCEE1BE36998B2622C0759BD66B
+E4444250589F9CEDE766D8B940770CB6B89503E925B35C00CBEC2873D2DC4A29
+0823FB7A3717B69A7DEDBAAECC067949932728E89BEECAA91DE3AF9BF070B9C0
+30EEFA8C0A55C8388CAA2F0515915C98E67FA095BB98967D14B0DCAFA9622E4E
+2E0EBFC768D80585ACDF28D8A5C2B6EE2FE7AAF62FFB90F569F84A0903996DF0
+C1D5723366C436E4088F3E2BB9B47F9789052A71CF5C49908CDC1DDA194BFB89
+14D7E3D7D4D72A150FD6FFD8303E9DE5A97A71B808B8BDF2AE466F31BF5D7A4A
+44F81230BBE2B456A221E2F72A8B59F8FEA8D31F8A005A5BD93B9F49CFDC3DCC
+CE2B67090460F632271C7157BDC2F05BC2749FD562FC28682A616A52D1B67654
+DF78B7843A9EC26A7DE2EB168F874904C2915B97534B2D4D9F74A9573A771D34
+9F7BC855E8F794621BF6AD471BCC347E2DF5F620F5C209E33A4CBF1EA85AEA87
+4492A77342DD33EF615FF34037D660B713C908786D9022051B825226545827A3
+2AD1B05D654DB6E6D261B4E8AF0933AD1F0FCFC7201E1A7C1B4199F160C38676
+21ABA2DDF1CEB655B3EC3226E0B122976EEA998F7A5241F062E54AD1DFD6ED26
+47C99A439E0AE95415059179867CDD3F0FF751F3141309F40E00A6C7C28433E4
+F649BCD5DAA64177580E05C495EE7BCBCC5FBF104DAF360CC2711386655B26F9
+D349D887EEB32ADE595241560FD5924A1745A22E6A01DB9C285EF14596EBFF0F
+03F36EB2E0A7C3864F819EF7B0855121292D49482F046A55CD7271FE03F02EA5
+886864D9D8EC22A68C23089EAEFFF03DED6484D8C341861EF8B6FD3C5BDF5AC8
+352DA4E13A1E30D0CB71E090E9CFB9AB2CAFD0CA7C34AE7D8E3B2EB4666834BD
+9CCD1AC2108348AFEF6071796F4BB2FFA4A67ED917E76A109FA2DC2A30D744A0
+9AE653A748C1D18FB52595D84E87F1C1FB6B2F32667FE203262C66627AEFFED3
+92B23861E5EB238BB4EDCE09DAE1C65BAFC198CDD1B45D42CDF93E16BB82D35F
+821E9E49067E966AFAB2AB52928F8DD6359984071FC37AA652FB834A09E5BD93
+3AFAE161140E74C6531E413E8FBBFC42BFE8A464B71EB1D8CAA93B33D7BCC3B0
+47C7EEFCD3E9FCF26FF9441DD9BDE68D77AD7251C06BBB9A2103049E8827CAF0
+F26BEF33F656A690235DEEC623CC519AFA82DE2AE16FB99F780FD7D8290DA40B
+9B604AEF36B529FD184239E7D50561A07428D28E51B55546590A1AEAD4B7F2B1
+AB8C5B9022C1FA03E33F8F409B24911AB8BFCF6EF4A8E415263C789F89063E71
+C0910DC20347469380B7FC1EEB87D4CED7F4A361E58B61C91AFCABA35C03F978
+B9FB5257C31657EE48504C355CE893FE3C553274C641DBC4004F5D5B879CC5ED
+D3F21F867F6DF054127067DE86189F0B59A1B90FDABCDFEE61423609D888EEFD
+F4A1367129962110C651D9481CEDDB8C5C2576A59AED64E95F7ED042AEAE2F7E
+81AC0C408E593DC30DCAC334EDE9EE27D932B98F040DDCD195D6155607DD2038
+970EB78221A94C52BD4F0EAC65F1FC10E5DAA93C17266F351669CAE56F42B68C
+6D01E1EA03AE554D63CE76D800FDD9CFD89F80A241EAEFF7EDFA41794EA25CE7
+97BD5028464D2CD45B53834B4AEF8BF0B9E7C6ECDEACEC887E8790A47A93F668
+A9095E5FA1116A122C0E5B74E2226C654D3187C6CFD8807917820423DA3EC1DE
+AA020EEEF2280C44A15209EE2F3FC1776875308CEAD38571E7BF889F287E4594
+971A83605E0B4169D4A23EE790515223DF8724054EDAD905F57918FC0BC64F96
+514B4BF7DC9BA79E763C22C977FB6146B10D26FEA1BAA7BAF21312F78D1625A7
+8E242D743471DB5821408AB786E4A7EA9D35E30E85533C617689F95758FB2C7C
+392E759C299DCCE36689686DE0C4DCE32649493650BA194A6208C5EAB670B170
+3F2C70BF0EF0E3BE2FB0A79224FF4ECECD6BB3388C6D06867A0E5E3DB93C1B2F
+464C23E44D3132E7D4086E3B59B1D13F49EB4772DEDF8EDC4F603217233FB7BE
+C13C28648E9AA51D53F11FB896839F97AEDD8834BCA53CB0021AE91FD8E95E2E
+F8A094093AF556B9639F508A401542B06821FF9DE1A745FE9AC5CACD5E8E1053
+911442FC15CA5333751ABFE2C617D38FA1DC332BFEF44AE569DC631C93EC54D6
+261583A695F5A392867A57F59B741EFCD2DCFECBC55D1EA5F2317601C9DFE9ED
+D1EA466210FFA905A8F85BD58B98991BEA58DFD1CDED5C9B086D42CCE632DADA
+147941917B879139E016B0DDEB8446BA017FC8EE5A354533D667B0835F5D027D
+C2D580C16B80B3D05CC92C0465CAE077729F0A15B2DAFC89DCD349B3F81D0516
+C65526EB5C10E45A8A85D716EE35FB9AB201FD7C89ADE5AD925A174169DA20FB
+61E96C73A143DF964C20589EF24A0FCFE6195317F2FA0D2249C0D8E649C3D9AD
+FF13332EA2E4C9CD36D8443EC8F027B61CEF92C6A6B72DD4ACBACC16E429A9A3
+F5F29C1631360E32F8C1C93ACB22F810B86D2969A7480F486F62F8488BEEC74C
+2C1AF13BB92BC578E8CD30BEA6BC8CB68ED730F54CED0167605FA76AD7B7E88C
+7AE7688E598F91C471BD65A542E96D64B1EAF19FB4F1234308C48C2DC86E2193
+11ABDB4C6189C6F201627C693691A86DD07FF55C30FDB3F72381E09C6080FD7C
+9182762E5001E30F52A216E0B71E4D2D4E2F3B20F95DF3A11FDB2D2B5B5FAA66
+C46226D5E0C77066349770514E5675550FAC9394FB27CD2C2F974F1FD58C04A3
+1EF53A8AB3B2202CCA1CEFA66228E1480A0709436C44BD3319C40CF888AE4692
+5DBBB52B15CF3A518F627F672135A24D5DB9B2EBEF04C860AECF231EBB5A3BF5
+6DCCD5E72FE4B6DD29E896691868A7DE4120AD06AC573F5608B8449B38E71CA0
+EB5CDA3F942482EA7973661170F81DC88D54DD5B92323F46F833DFA757107E9E
+F62A47CC50FAA1B68ED535C3E0E1073532A05ED339C8D70B3B9864808ABACD23
+AA95E9FDA43D54C66A675FA074E0A5B8777D3C07850A09087F36852B5351F35D
+8BC4DDFCA35CF29CD5E3DE118A741FAC4DED36847F2E2C6CFE08669301722D94
+376F540982958074E7F1383C409652F6C99DA39FE90B38221E75BC1ECB93ABF6
+B00F410A0C5651DB418566AB350FDA1789AFD88286AF3BCB42B98386F7BC144B
+02DEB8940D20A6B3062F0C4244EABC50923390064F1D027A8BACC3DE45156E56
+4A942D1B87F1C4A76B0D4D6801AE792CCAE3009BF25368B31B6AD5476FBD3BFF
+9759EF463EF5E78E10B7BF64005B2ABE0E8813950A08A1808587A98E0021D0DD
+751AD515E8278F1A0759E85D8A084490BBB0F8206484AA36388B1013643D3198
+3509078847BDAE08E76FA5BF3E3A73C323CE093DCC148E3C02C2DE1E26C94D5A
+40EC8308ECB02FF7DD04EC1005A2A0DC74D4E587F10A3EF349E828F69FD38962
+2F0C74D5DAB3ED6CC9F97008ACCE74C086A503948DEF1AAF58FC8BEC703CD360
+D32098A56AC776B1BD08442052A2A4EF6C8798F7CDC102AF1A2009657254762A
+0793F79A39DCD6ADBAA5EC84A7ED6018BBE727E5D477893D84F157074B24C13E
+8D4881C7DF8ADC13EBA0D89745EF93B7616EC5355600BB0D2B630AABA3CF2946
+AFFD0B2B724EF0F28393F2034B2E69DA5061426805353EB4D80E20739BC4C510
+6C45275B8261DCBA10DE1D104B12F46ACD230977EE7D7D1D35D2814139E38C4B
+CA6937CCFA653349B1EF64A98457F7B4B5D8F2978F16ECCEF7054905863AA46E
+DD524CB33459220C71E9EFA7845A3A760A507B3D3ABC525B35930B613710A13D
+098832C58EBBC8B0CA6AD516E6385792C59220331D0922A1F6F838A8DE13C337
+900462F952EABBDC2EB1FBF94A66186C177501453CD3FE3582073DD86F04406B
+41B6AEB440DA475E13240445D46726A6D45185D56BAB8807CEC8A8F7CE1AD149
+7CE2E1BB5DE4E5B9592241DD136479A65905FD0062C91DFF7349874BFEA5D9EA
+2F610ADB9AE7757B2307A1BB9D6797D9F9C4844A59841C7C7682105E23A374BC
+A91885E7410F56F60C29AB8B417E2D6092F8BB70A2DD5DEDD4BA1077D7CC62FD
+EA43428C6F79C332342E15F75B08A1ED360B3511F823E75AD49BA7AE63B19238
+2AFE8FAC2715E2FDC895E95036D23127557837506A3B542B0E4651CE2B89C252
+31EE8ADC26E2C04E8E30A9CA12F066CE01953BE7867171FF6C7E834742C36C3B
+58E74E4B482CB85FD4D24DB03D753F260A585D552CDC9E1941446F2F5B45FF24
+2DA4932B973139F328E7E92828B900BFD398B6F41DAA0D6861C66AA7F5E3299C
+87A5925CE0E0F9E09AAE0792954A1F2C0AAA8288DEEFFE579E38A3CE8A943EB4
+55322A87C1634074EBEC25F724DC1BCC1BC10458CA6C4395659B0DB6B612C151
+557CC669D8DC37769E59A5AC6BF061C79FEE265DBB59520EB8FFEA273601D1E8
+2984B8AE31AE343F37D03E2BF97DC48AFE50BB6138C7B9F9B5E28672A37BD8F5
+8F8C98DC43DB22C6537028798198E2D3B0453ED72487267D653DD50F1BBBDA92
+833A987A95FC1F275B90B581B4BB62B6863A4CFAE37F715EDF3EA5A33679FEB6
+4847ABB4B3D170C275B9F1AC3156D731198DACE0B051674E85B758500AC9FBEE
+ECC75EBBD85F8D62AAA328FB09C6526F853077AEF7EFBFC2B6A29D6D508B1E19
+EAFA4C67EEE44045B9F15B9762B3DDF5CE5C18B23A5C2F73A1F6DF7F8679AB78
+843AA41FD2A7DC02B45B729EB76C66A89F5F76E5C4A0C0563B1EC5E75D72EE35
+A7F1FC89216B60D82F6F2B8DBE85E4FF4D63712C689E696F60B52AB622C2A4F9
+37C380775EDB72638D3F81F61D8D730640A031D5E76B5A50B324FF8CB6D27941
+08BBD40548A9CC009B87404941B1C18BF3AC52BD2CD78C5BF77DE0552ADA3E14
+BC0B82F2CC37AE635B8762953D0CE34CB2B48DB39EAD4D6A8939194DB0FB0DE4
+2097ACABC52E9DB146BAA3A8A02B7C530BED308AC87039858CAD24FFB5D67500
+0565199BC15C451E1A15CFD9B77CA5DCB240685CF1CDC59423D16196A1E3266F
+07BDAF48BB644BCCE0B7AAEDB13362CCB1538C5D06638D680963B578D2574388
+D48FE717B30B53AB4C9D9AEDCF0B554E5B60C93FDCCF55E13D39D1CFDD9459D5
+6F76AE0F5DCBB866F3148AE22AC1F787677CDC3C2F1C7E8F26A28904EB2D5986
+B5BD875EE980E0393405F629498E1D77C0C11DDA2EC873CC2BD4C28604E04467
+79A2AF636279A8B02475144354DC5F63288B1C652C79BE189723641634CA6C9B
+6C1C7A790B80DF1048260298DB6F05509581C1D43FFD59C34F8CB805BDB780C5
+02C3AC7D3CF9940D140DB3ACF03150A9821273E36336E975D68FDF0EDB3A2C78
+66C9DD71593AF85079B20B98B5E873C5C5EA0B218CCEE64FF6DADA390B4641F2
+7001DBFD5615A35253D968BEC1722CE2A13645590B04C5D3AD5C7BE95535B486
+F8C805A2EE1D38F2EA58597C4526D5861D0184F4956DB9D9BEEF25BF02427893
+F786226FB30141D2358C0C3FCFE8EF0A4AAFB5CA8C59221CF0CE2BF5C2478B9C
+D66C6DD022C3DFA2EBD3E4BCD12A3E6DA962B53AA3B1732162C5A829AF0EC535
+D0777DACA2C8796A78BD525785E5034C5A4CB78AEB1AF1861BBCA30B1F839E62
+930257A5340527D9658BB19271DE0E17E64F46D9A250A2A18E0FD974135FB8E3
+A225C505B9C7416EB7A6786D306C964659BD0E3ACAC93C4FFB01307D91B1550A
+20A090C72AED05B4A74F5532A769FBF7A7ED2D55C9AA222C7DBA8D2CDBA530E9
+795CBE9515C3B0D00062C0C5D7494F83CD31B99110EC6E12E6EBA5C28FAC2B5E
+3D99FA2ED03C476476D21348AA585EDC3D08F9B4EA6CF01B74E0D2C8EF28E6D3
+B8552454698A220A4A107E01940961F1589EEC9C87A286ADA62CD96931421DD9
+8CFA4A0B38F9518C4F050B07BFA39842B562CAD6FDB60F649E7A76356865E5A8
+D3081EC10A2CAFF9CBD106A8632651B80CD64CB48043322A44F3076A505460B1
+3C00053D8F1ACAC4984F6B3DB8D1C871BF609DEFAD7EA90D57E257F4D2C388A6
+D994C6FC93ECF13F2C8B305876FE263A3BD1ED1D3661BC841E70680FBA10C178
+8EDA8105D3421CF0AEA5A31B5CFA65DF3DB858BC36E275B8656734D5659F76ED
+E3B8954FD46E296154A383239148B3069CFF8B4CD411F2B81567DD56554994A9
+2A1C2C7B62FB84CC343F14B2C5627C3CA50A06A0D9C94E03557DE89E869D4596
+1C0E072F283E9B213E23B3CD838CAD85CBE529946A965AD3FF5D4ABC65FE6E91
+47CDB9AF7757DE581BB0743F8B71766581D27A5ECA31F634ACED04E12DB04D91
+D14DE0D2C4EAC162549105DAAB7DF61175F015000AC20414F1EB604CB7A7F5FB
+C4EF86D19878D5E75120D6B916573B635DF0A3262BD990B0849E50D3AD0BDFF0
+A19CE86495C760D926DE543CE80CAB8F407965642C10C65E78AB7757E75DF93A
+9F3628CFA73A322D4268A399AEAEC4BB868798AFFFF6890EEDA14F2D8FC95796
+F73B45039389176F42752C0561AC2AD9F7A2C4E7195D34CA26568F78981B480F
+94D87A519BAA52E8D1C847E3E12B493D30939636AF8ED7ADBFAE1CA3AC4844A6
+C796E47157E4F6ABEEE0FAF205B105063D1114DE7B470793CE391C20D7EF6830
+6F71A881A2483C28B3360A04AA5DDC6CAD239AB33E8DE6B672C42288383069BA
+7DCC02A63EE07DDC62BB8D893CD4C5DD231F0CEC9B2B68B30873B09BB1B95756
+95FF12691E4DE6D9C1B6B62A0ECDFB5FCA3AC89533C3FF2BB0C5BC048B3BB144
+A9642D2C23A5D100AC74C8169BF950EBD0D623D3B12B7DD0D9DC432FE752F91B
+8C1EFEDE847B9FB6853A07F7BF96E10A2ECEAD2CA8E55B40B72B160D4853B77A
+8FB1E30E32B72D49BA04EAB452ECB769881E9D94F0A8AF6EA265639DD47D6451
+89162EB4A741E46AD7E08DA67E610796EF90A51188989A94BCA73D14BF668E2D
+32773E101247108A342F71845FDD11512574F2F2D56150AF7C3572CC752736CB
+92928424F58C1C4C20E47FA196EC5FC46BDE3437A2F7FA284297B52A2D2259D5
+58B4C3406EDA877765CE1205D2BBE509B11B3FC976A928DCCE64D468E938BF7C
+A245ABF829EDEDAF65612B50D3F2CF76635A42AF3579A2827D09B8EFC3ABB94D
+FA04BBD63184293319074E6CDBF497FA69D3FD282B7D2E96C436A4E3C447B6FA
+6C7B5DB4598D8AF04ECE6BFE118EE80B22797CACAC11C15042648E53474E43DA
+3C3A2B1359ABCB9D94EC36E7D6C8E24D3D8F8F633255E3A9254B82D9EF6D214E
+683E22EDA23418648CFB576421E575F08F325CB37867E3AA8EF77DB1C13494A9
+A5EC6259B53D3B37E9D1C8B0C91BD846636B19AF26D5BA6114E210FFFF32ABFB
+BD5A4723E4FFF0A5D3BE63A806F74C8051795C7A4F03D85DE8D9BA387C0457B5
+FA1521EA8C71E8D27A07A276545E647B2FD802D19E5AA9A6D6CF9E33C0339627
+5282159105563D522B6357BE2383E7A539EF7ED32BCCB636650DB281E3AFED99
+24237FF46781B603CA1F5C99BECE3EBDD52EC1DB3F02532BE24AF706F238765B
+91ABE3A9FBBAD9547E7AA9FF5891A024551FE45B24D62B6BE6E7E0A899F6C4FF
+817F72762ECC0EE633CC6900A9CB3A5DD25629DBF2DCBEA6360429BE1D9B6D5A
+3669931B132141921F090557E1CBB726595E2DA54DD26E2C38E4A35820448945
+40DACA669362F4FF28E16E71D472E75457D34214E9CE049FCADAB97A5A6511FA
+CBAD12DA3C2BD2F0316D4B542A9921D4DD4585A61714AB81694941D9E0BE5C1E
+7F892FECAE54BB038DE31324AA2CBFFBB43A1B2E27D6A96BDC99DABEAE2459B1
+0FF2231B065D29FE56757238CB33A266FC66F61E4F1F96D2F3AB38B8770EB897
+228FEFFCA3E7A5ACF2EDC8A8BC218134571455E76CC07CCB3A4A706826B0B6A0
+07D6446CDD5E5E97ACE3DC8B3A7694FBA645AFAE422C85CBBBF455909CD77A93
+18EB022D050F6F2799A4A5418CDEE457623903078AA403EEC9AE7B60C091C4EC
+97DA30CFFAD9CBD1316668D05BEA9A5F9059DCA98025E1AA0A792D2D33CADC36
+6359D6230F194BBE663942D40F9A0F8D1670FDFE26270EC7AC1762034529A52C
+47B14AF203ABD5891099397BD9401FF9A7D5DE4F31CDDA34F87091FD5F6B1E5D
+6A1899B61E79564407868CDFAD67BE6F150663A988FCA5D9159931E645D774E4
+6FF777BF3EB95462CC696280E0E9F1C2CF39DB04679555FC360FDC844B3E2BEC
+8D75EBB8FCE89DCB8928AE97D30D3F185C552FEF86D4121A51E75D05F43E9F28
+E994280672DE8A5AC107C35C6060A56CDFEB7391FB52B41D3678EC6F242CDC11
+4E03E17133FB5D132D9FF5CDD23752CEACFC20ED2F844316F5098E4EE9328F3A
+F2B650DABB0E06F4AE0824B3E4624A0959EDB6BC263235E02FBD18A4E5EE04E0
+5CEDB0088B247EDC96EF9B86A03FE4B544492AA975489BD8C3D40743C93F158D
+F9F1E58B9890BD115CBA34F09395B06D0B2C307EB64BE00ACB6201C2B808AF86
+2B3EF4E1C75716370621BBA370165D177BDF364311E93BDC67DF49A4565BF2F6
+C8AAADE63A712E8B3B5084B2E49F61980731CB694EA3BD6F79B88EEEDC82D8FE
+155DCDF072C4A17C872DE72F20D4CB2AA612F6AED5EFCDF58A554F43360DE449
+3255A9912ABDD92A83B49EC2722E3A4BD5E08B1A24CA1553E4FC4D1FFC34B7CE
+0F020D35651B0CDFD5D6FFB70502A24193CF4D5FB7D22C44C58841372603E761
+332DA6BF791FB89271570798950884F0AF4396120AA987D25C1CA7DC02943C0F
+A7A77E392CE93BD636F067C8DAE51ECD82B9A049609C7382435FC9ECA0219F34
+7F65220E077F3B1E925FD83533F74288B5496A7368F701EA40FD2BA8D2F04F0F
+4646F8B76ADB7F8104678F009576543408B417925E91B65C9FF25586875E91A6
+709F662F43F77971E0DBDBAA22B7EBA487FEB39A4E693943F0F0D1D2704A3709
+0340AAD38D6DC5184E07AF236BC69EDB3E4B83CB94C8619224746169F38D2BDF
+3EC3947BD5D1682F7378CCC006FDB84508CBA7A642430AA85F83FAFB2A80D9E0
+74512C212182415D48D027E62AAFB8A165790167966CA801B111AA5DEF0430B3
+3D15CB081D7ABE5A0BDC3540197C2E6682B89B1FD45AE6E1BA5FCB957F0F3291
+87E7CBF10CA0F10F9E8BA2741B431A868A4A8D5EC423985F63F76FE4ECEAC41B
+6FF8CF3518F1321E421BF53AE99716B485BF4B901287B73A5F6CC4D2D0837F6D
+D14F00AB998ED630CEDE548C5EF7ADE1C37C68558B1AC33538C11A6AC9373C4F
+DCB66B6D97BACBC54DE1B7AC735F1DFA83BAD86B759210C4441AD07DC5147F20
+D4233E8E97E0EE5B054E35BB1E4A4E68F4C74465FB77CCA13AB7290E9851AE1B
+A17ADAA7CE1F0B63D474CEB5B5D3DA322C939650F35B0F908E9DE9E5ED9AB420
+A1F9E43B8763A0530D8BBB8C07A9CF7E3E07C4D00E12F96D4F68900350D63A4B
+0A8C5FB0FBB7228B41838D1486D332BCA58B400689D740CE2682AF3AD7826E50
+079BB9496723C61485A6E5EFFC056B29F8AF0B64412C697C333884391B38B6C7
+408F8AACB7120CFD98C353D76E289139172279A92773BFEEB09BB4AFF479C950
+42B4E88B99BF458CC6E0EB7D460ED56C3982D5E9066F3775C55FCE598823EA20
+A214EB658F9EF8EE6078D2A391DDD9821296D4600013FF666495F5A5313218BC
+5337AD549709C833FA694F785B4E6AF78BBE74C17CEFD4414BB362426825BCB8
+60634977571B622979F5B4102BFB408098230C07851A97EA9E56E946AAC5E47B
+C6C3AC81F391448FB84E269FE7243E955115C18F230D42E97EB4C274F81D6FBC
+8B21C1DD0A6822A171825EFE0572659E8DE69A8A739485DB06DC8A16AE326FFA
+9CA4629C82380B2708A9579E1C2B5B53FEE640F06B44E17DBE3520F4D238B7ED
+A1CA4AD4F963211905E1C9D60447863BBD344AB5621E3379B8D9717EAB4CBD52
+2B85AA6685DF7B9129A91621DFB11ADF765247DC04615321D0D1440E1D0CDF21
+00712AC98A1F58929B42CBFA5AC8535FB2B81E5749A4CE8CBA59746C4467EA5A
+0A05D863C921DD5601397837A656967D0647BC4CC6B35EE6EE23FF367E93C336
+22FABA3A80751635AB1F6AD0EEAAD69BE680BF12103ABFCB7398106471058277
+9C1A8610CBA2A76BC8CD2D94DC8E95800FC62BAE58E5C8B5CB181071AEA1E84F
+2CD1956FBE305AE0D7BEF76425C7819C936626B5D0123A49A204E734ADE5BDDF
+F7024E8AEEBAE8EE85AFEB67521EADF982EF932AA773FB07C563CCBA5ACB5364
+DBB8E7F84A7B2EEFFD2FE243797BB9C6BC0870E52C36949262CFD5C98D334D6C
+A1B13DAF18238032DD0825D7F05E8C2FB5924133A4BB590376834D651F8CAB2E
+87EAD8212BCC62F158DEA0F1E48472963BC4BF68ECC10D5E65463D3E01DEED52
+A6A2D4FF67809BC5D03C69E8C70BFAE98814420EF2C0573CE0342FBF5A68AB2C
+5981066208FF196DCB116701B63CFD8C48D5618C2FFE2151F2593A8947EA210F
+1CD0CCB2339CEEF26A2AE15F857AD3E26298C29FFC7B1C9640C7DBC67FD59947
+14FAF860E02EC2A848FE450F55A67EB12D2062B867FF1DE6C2D24A39E51DB73E
+AFDF18418B241DCB72ACDA8B527753B9B6300FB788DAD04BCE94D110F20E56B5
+BA61CE7BE66F10E80E169E2A544F9ECDE8D7185675405E6E48568E1320D540FC
+F31CB04891164E15CE93A8ECB1CC7915F3E1BA6F91D32E6999521654EA26C012
+552E67FC012A61C89BC8DE53DA536C8462459D897B1F656FECD5A7622402F713
+C0A33D7CB9CD363A215AC1C21B46775C479FA205425A2049483BCA38E1F614FD
+8503A7F277882759468F1BFF2C1ADEFF982185FE27925603F796EBEE9F3E0A2D
+2FC083B1C3D4006E7DB6A215655EF488054E938F0FC4D2E0433A5D7024A998E0
+F09808DFC02CBBA68698C9067428B2F84E34FA9D456CA12D8559CC81CF4C49A7
+74AB3B9AFBE43304A309E4DA0ACBE2061129D366417A2C8D9B7E895B51A99714
+FAEE1CFCCD96D2389F492FCF79AF6C78233D5CD3224DDF47C4927491A734C92D
+9F8047AB7760C636594B6DED76463078CD68DAC39C64EE36578978AE8B3553E4
+30B136CBD81CFC829D42E35779BD7ABAABF02F1D2D4207E50FCF163BDF416A76
+A48139FB526693673A41D4BF8E7A76E6555CCA7AD22904A80393010C5ED9EC12
+A48A3B438AFCB0A5C1C60FDF12B8D0476232C5BFFC5FA125368F843F3A10DDA3
+A2B67DE64CA97EB68304846ADA7EBEEB7C3E9ECC2D69E924B7FADD31CB23A828
+D30AFC8E895DB50845FB6F7310F51DAF4053E70E809C6ABDBF9737B24BC9C22F
+DC119CED118CF6452F57BCA4F04FFF21FEF4E9F30E36FD2FD5576B22E21508BF
+28BE5E31FB9D3F8F10FC009867D53EA8F60AB24DC7BE968570A3C7131A73F3A2
+5BFF440EB52F4B43D39A5886715A2C733FA5FF0B601747A4908AA2F6E281A682
+A09D8314C65FA4AFC75800136EFD83F7E6FFA5B8D0B3A0DB4E2824F8BF6218E3
+2F492ECCB90697EC67CBF945F6A4FFD7460593BAAB9E8FCF3B6906366BFFCDE4
+82AE89E002A38F18FD74D1469E88C061613707D658F59EF0C341273E5A1E79D1
+0573151A69EA500C27ABCB4BBC85899D71DA327AD2B7F4EF31710F8B8F12A277
+8520BCDDAE8223C19497C0067DEBC8A9DBD637D3819CA070410BBAAB518253EF
+0E0D2C96F6B898AFDA200EAF949B1006D43F77DB0B744F35AB4D50586EBA5037
+4CB2B0EA370F76FF066508A0A63CFB392C37B9EAE7A6B80392C52B8526CA48A9
+BEB5354E304A23F846E28F5034C5BAC1821B7C0C79D4F91A89F7B352F3F3BA2A
+EC4890792C0A7C90661F9238D9067951AEC21A496F2CEE542B47378C18CB914A
+69922B408BF4B18B245769DAE9BD8FB79EB371BD11B1DF165AFF60692CF3DDF4
+C4B7807CBA6D25E25F3A1CA5A8E7EB271E69A5DCC410C9B29BE0EBE7744186E6
+86FE9FDA54032A3D52F6062C3A6479932D30CEB52C477426F087E8F44CCF79D7
+53B64FC9637F2293C79BA75C7E649610586878A140545FD666CEB7F2F238F696
+E5366740D421686433B3B10FDDE6BBC46FA5AE88C339F5D14E10AD4600B1087D
+EF3726F005372A04627086493DD788EC639E8833F009909A03C766C43D37BFF8
+5B6F2A
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMSL10
+%!PS-AdobeFont-1.0: CMSL10 003.002
+%%Title: CMSL10
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMSL10.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMSL10 known{/CMSL10 findfont dup/UniqueID known{dup
+/UniqueID get 5000798 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMSL10 def
+/FontBBox {-62 -250 1123 750 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMSL10.) readonly def
+/FullName (CMSL10) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle -9.46 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 83 /S put
+dup 101 /e put
+dup 104 /h put
+dup 107 /k put
+dup 108 /l put
+dup 111 /o put
+dup 116 /t put
+dup 121 /y put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CE32340DC6F28AF40857E4451976E7
+5182433CF9F333A38BD841C0D4E68BF9E012EB32A8FFB76B5816306B5EDF7C99
+8B3A16D9B4BC056662E32C7CD0123DFAEB734C7532E64BBFBF5A60336E646716
+EFB852C877F440D329172C71F1E5D59CE9473C26B8AEF7AD68EF0727B6EC2E0C
+02CE8D8B07183838330C0284BD419CBDAE42B141D3D4BE492473F240CEED931D
+46E9F999C5CB3235E2C6DAAA2C0169E1991BEAEA0D704BF49CEA3E98E8C2361A
+4B60D020D325E4C2450F3BCF59223103D20DB6943DE1BA6FC8D4362C3CE32E0D
+DCE118A7394CB72B56624142B74A3863C1D054C7CB14F89CBAFF08A4162FC384
+7FEDA760DD8E09028C461D7C8C765390E13667DD233EA2E20063634941F668C0
+C14657504A30C0C298F341B0EC9D1247E084CC760B7D4F27874744CDC5D76814
+25E2367955EA15B0B5CD2C4A0B21F3653FCC70D32D6AC6E28FB470EB246D6ED5
+7872201EF784EE43930DC4801FC99043C93D789F5ED9A09946EC104C430B5581
+299CB76590919D5538B16837F966CF6B213D6E40238F55B4E0F715DBD2A8B8B8
+80A4B633D128EB01BB783569E827F83AF61665C0510C7EA8E6FC89A30B0BC0EB
+5A53E5E67EF62D8855F6606E421BD351916549C569C7368AAFB714E22A023584
+8B1D6B52FC6F635E44058690002C6BA02CEC21C54CC8875B408A8BB84F445894
+5D6B3E4841CA20AF852A660FE9C832F773691DC6F7197FF3DEAEE97418A5ED2F
+F2AE65300416227CD3BB03C29003C770CD7D2A7A2E4C1DCA193651C2CDDBF93B
+966938788694BFB562AB0010268955FC3555E5984CCAB0A9B7590C77C9BC713E
+A29E5BD7193A4E971D1752DDD0F0AA4648E7E87BBCE66A1E836C715C408B07A5
+9EB56BEFD4596706CF839BA4CFA90CAD4038C1E006B51913279A2C31FBEE5BD4
+A7D74F9103CE6124F5B439CB860987DF44FE17EF88EF1BF62C67060D25696BCD
+94ADF08F04E349CEBDF9D3389D870D94CC05E393B3F4362A13A6A672EE5E8F5A
+DFE7046AFE3EBAEA58FFEBA4A47BF61F92E2003756DA643CCF2C9DFCCAB62669
+E3C2A18D690B64D907F50BCA155A85E47C3A6954C6FF7ACA36D8DFCE777B7929
+5F5D5F787B9C247ABF13D6D7B4A8F06BA25CCB342F8A5071325CDA86AD71BA23
+8A9695C7D1D50D0AAC267AB7CDBA7AAF46A264B7B081B7E79AD937FEE4969FD5
+155A99E652461EFFB4BD010E5885631E2B2497D6B8C43CE77D7D47FE201DD46E
+4482FFDCE150A1183C22C004A0AF0E1F42AA6804E038E1DFC8B0A3CE26B52038
+44D2E7F759DA5C252489E5525963D68BC27C82247BEB18818C7D4CF0BC5CC97D
+8C701034B8DF798DD4CE36C3F8B1FD40B2DA14EA75583852875031AF8C909EE0
+04495FDCD04B05A5EFEBA56A8CAC1F57F1B8AB91FB25C81CD51EE69D6E0F52CC
+A0E12CF7E3187D67DF71A599FFD895FAA7BF80E2E6B96592BE77AE96905BAF0F
+F547355A36C443797DDA7C414AA606CF9153E03450B77D1BA4088D739DF55F07
+111B9E11AF37F45B6EDE6D7AC126E05886A57C83886DA87761BE600DEECD1344
+8A82BD652BE7ABFE6A0F50ED7C6F4EE12CDFD80CA7A5518692F267C51C3FE76C
+567BB8DDBE09A2AF901F79AD02B435287CB8057B3D5EE6655071F67B00438728
+C4C3EBD648BAF650993AFE5E2B29074A99ED0FB725D9B8CE8B0292B08A280214
+C3AF252BEEAD30C88F72E322FAC3E9D78A1038F5DFC41F7BF1AE3744A0677094
+51B77C2D630B67853FE5E975A395C06A4D4DA744040B272C2B88D8B7ED3A2C01
+66F503C9DFD3C7DDAC865900D2A4F2CDF517F449851DB1963468D0266D7A3E58
+9F6B2A1843E6444274F16A9930302DACD8D2BC4588765099A86BCCD8A31DF0E6
+2853114DFF2D19F812F19AE6C2E419D7AC1BC024D1195074FD0C6717BFB389A4
+4D5428E7BB2E4F9E9FDEDED7BDCBDD3460805AEA0B5F6460C2FDF19273CE5BA7
+5D3AAE0DB94C6AFA8339646191C23B0149E7CBF136FC4C844E025A38935DF256
+0A0A6466A45EE8B9B23B6A055856FB084F87C73BA28F1883E3B184CD813C72F9
+233B78CA4E125ABD26F29B92CD9DF39D6FDC2A217E2B6B45D9B0A4D536790A5D
+BC0903069565A442FA7466414D948AC432C6B75D8D0E1DBB217CA3DC38A52DEF
+62E9D5AE9E753956C13819D93148C7683BE4F71B80BC066D8C19FC807FB1C086
+B49215DCF56A91A42089F0D063B9981925691F7DDE3237403AC714F5CC3ACA88
+DB2F1DD205578C00472FD70C8BA4F752E3923ACF3164D442A6B639902ED060D0
+C5777BC20F9A3BDA60FA3BC986C38136FBD2E8F910E32EF36377C9CC187F4AFA
+CCEC423DB925B378522B748BDF12D523804CABA83CB5A7ED69FAB9AAB75EE8FC
+38D9866E3754C4E2F2B9AEFA804044D878DED0E114EA0E9682FCF38F6628E63D
+FE1C1B5615E54FAE8684566EDC4B616F76EEFD6207E0386F06D3BFFA26425F24
+303CC7C8A8D7021E7D09B202616988287838C3DBCE3179B4FB5C726E603A47F2
+8248CB508F327D1291CF3F08F7C88298DC2D0F778D24304EFCF6E074182BF5B1
+8E6551811FD6991971692108E289B61053D6DCBA2925B3903E8916EBD09D97A2
+C6D08E89DE4C0CDF7185E1E00DF456B249F0BFC686E04FDAAD2772DC2C39DD53
+9C23A41471267F53A87E5C2B8CBCDB66CE0B9844BC506428E6150B48D2FA6363
+4FDB2CEDFBAE0B7DBCE4D83E29B2955F8966272CB865EDB360C8A8C19EC62A29
+03066483E4083524A1E8D80FE3867BC1AA91753C26ACBE8489AB0E3330206212
+93E07ED473DBF457EB8489E66FB4B8ED8A9EA8911CF9308CFE3E6D6F36810EE8
+91CCB11BD548617B2C683C354452B9229E7C9E68828BBEC324420DF7C188CCE0
+FBB514547553A7E9B38AC265783891F42DA472388569C8E7594F7E8810895A27
+06E456902A8D9F65CA808F1FD475D011C4572F8A654BA01D67942226A663D179
+95149FFF41A9F55AE84EEB9A6A39C017D7E4FD6EFEEE7FF3CE847CDB064A4954
+9DCD273B810E0F259501BA4003A3EC1ABA6E13D24C0B57FF82D6DF077833B6A2
+7EA54801BA81DB961C261689C0887FAD83771E55D3D137AFBB21779397E11972
+6C6CA922F45AFA5C0526863A5AD8B9C0775CCBA17FFD37A44CED4710884DBC31
+5C9D3F5441595B86CF7CA2EEE42AE87896E9E60EBF5F35C2B7FDBF9A9CDAE262
+3F48396F0F741E9DDF1D4FEF75E68AFB020D06CC29B3A7B2ED819D1AABC12B91
+CA2A65F1AFDDA2F3FB322E0268DBBA024663E49EFF076455338FE31A16B04EC1
+797EAB0B49AFFB906A0690A1E8E2F5314773E1CCFFF43E6FB3875AC907F0C5D0
+DCB9BCC127014D472463560CA0CB1C2CE614D94177C7A52A5B089316689C8112
+CA57E35D716D956DBF9013B1E5B9626456B1433C8C15FA906458F957133B9E19
+8D46DC3AC015F7602538C2AE3927C6DDBACF38E59220C2F5AF36B68DE9117C51
+04CF7DF32B1AF55B87D1D8A5F4BCFEC66F63B32B6548DEDA3AAB06C5310E4757
+78AFF947DA22809B360FE535506A554DDDE5A6F2411246653710ECE5CD3185BE
+730520A766C47E1ED01890059882BE1432586864E1A86A7F586438C8DD35C00F
+021A741ED47E0F16DB6070ED0C50038632CA4AC2975578A8372A080CC0447C79
+CEABDF2BCD5E78564247B0F0025F556DA8FB62125227849EACFB724A4AE3EF57
+90C07A5B27D2E59425F56BF8AD84C5F5310FEB1BC73D536339FC2E6A5BE2DAFD
+97FC835E0D52F680F80ACA37DB498AACF152B9B44626CD89E3302C3EE1623EE0
+F998FA78305960AAB9F483F731F5F67A8C963C23DB8E48FB804EF8B86FAFE7F9
+4C09641915FA7E3930AC922682313408BC1607C76751CEEAFD660206A39CF394
+40ABE2A313AB7D5FD6444E219DC5C26734D322BA268D330AC17959A390D6C8E7
+3A155095BDD66516DAD5D65519A7FB871ECDA77061EFB21F359158B4470EF79B
+362C35C06B85C9A9505C8361939C6AC013F2CFE8EEF46FD8CB4452AAB3EF1FA7
+DC066557BADC2ADDDF7DDC2A0E1DD4A357E27A2073427EACF9B9035DA5272136
+7DF37E26D96ED4B2ACD60596E039BCB15E259C72FEB3344E3EEE3D4F17DF4233
+04C1416BCADE80BD483DD8C9AF979E1C7D50C4CF015870703F88B92C4FE46AB8
+DE6717B55C460C805B391B84333097E116F4A51F631FAFAB34CFC925BEE8B72B
+C9FD5F5A79D8F2295FBFAE649DC6AB47794AC7D73431FFE5BE992F2B5AC67049
+B5208251C0E442385A9FACF25E3A98D7F5D4C2A1ABDC600AABE84769CA83350F
+9B87F71CEAD3600E02FF9AC03C1B5C21C84F911511A0CF0111BAC7605EE31229
+3C526A79D943D92E1CC3C38ABE82D560CFD4172F318030852A5FCC0534B8B3FE
+D7365987C8B48A072907B26CDC2108130A33233E8E0BB5FDF14FB55098A10EA2
+B51AD9EFB119F82B08D256D396D3263FBD9DBF172D43A90ACD1A31F3E89E8571
+74BE98B9560E2CD661A2F93C69FEA3FF26B00772AE2C2C24B98D3D122EA2AA8A
+44652CCDF4EF4F01CA7D62A976E23E8A86291F43BFAF38FD9C325E70F9C36CB5
+A181DAD30156E98339E6A0498D3420B7BB3B4E651A9090D4A17604AE386273A8
+3D4AE8CC18345E6E19DF06BA848F203F74B161D6A8882991CBA7385F308696A1
+BEEB0130D938A764B98A2001A38489B1334025EA848CA44A116D64926D460D64
+01159E77EA7ED9ECE7BA77635BE564A4ED89315BDFF54ACE6AA1A26591D13CD4
+6D6425CA7933769B842192858D10998509396829263290A3A7CFEBBDA3EE6CDD
+DF1E492AECDFF7941B53573F01F623CA0A5ECC9D05A3D0954F7AE8CE94AC3B2A
+CD4E27519B2E16F033EB732AA024BBAF74626DB55DC74B1FDDB07FAE98B4AC5C
+683CFD8744F361838D343B657EBF52DEEE7AEA7565C5BEEFE455DDDBC4DCCA7D
+87D6D769C5ECCF14118A14A85A86865777C8E28F953160D5E82844AE54D541DF
+550D5F1519E183E0C42BE88F0458CE8087F2CD4B1B49A8E9E3D127C4A4CB74A6
+2E73BF4CC317781D03FF04BC36AC0E4AF99E2ACAD20F6F8029DE8A035DAB40DB
+17D237850BCDD05931FF4B0FE2D0B79EC5A88FE0236271CCB075BD194AA25AFB
+3FB93A5206F61A14602E4EB6F1C31C654527CE0C02D04314DF9AFD710D0EBB9E
+F8721B97F5FB18E27507E1F800B5509A58A1A8296C72B7B73F99B6CFE42E9C2F
+B63B3555475E562672645CD374BCDE937A9B05A157FB3E74C8297507253E957B
+1A9DC421946734CEFA3D5EE357DAC7E9DE17A5BDDEF6B2D2A740BC58128FC514
+61154664412BA1C05209EC992A77B7CA45AB7C0EEBF590A5B5652866008CDEF7
+124A3003AE6A7CF9DF3C72750CBD281358CD2FF25B162B78CBB971DB3477F8D2
+ECA3EE9CBC90323B2C236E375337EA0848CD7CB5781A2B0A42DE7E4D99DB2746
+0B26796CEE129D23C76794B7CE21C13C7D4A998B752C8CF43A4821B736EBE246
+D2A2BD7BA3351FBCD1B0A501EC1EAABE60D06DA2FE39BE1F0AD629769FDDC933
+F9D02F9686EC8C2D7455C26AF4DD3F6860B2289E3A30E1C254AD17D731CB73B2
+BF4DFE90CAEECE3ED0CD3FB4C8F4C7BE1C056AB4E9B95781A8968E3CC1010003
+75DFBC4AB9F6B27C5A9AD88D94441A8ADF09EB275E5F0E5E6F3BFEA0FA8C308A
+8593ABA0645ECA8FDC3F0E264B35D4B0DDB86B93CD8A047FC409E18196B501C3
+B003622999C47BAC04FD1ABD8AD359C977766E9643EF3BD6385306B08EE3E13E
+7DA5A06AE33D17A3D574C6390DB6E9429754B210F0C349C359559C7EAA2350BD
+F61D4D8A92B1AF697BC620FA0351E67E0D9F41A95A47EE0BF210C2C48691901F
+F905F65693DCB85BE412F097480F6A7266AE0A928729DA0F691CBFFF3B276EA7
+322BCD2206D96E3DAFDFB992CA8F2955F0E8B882729DFF840569D12E4DA1775E
+523AA734552AAB6F2F16B89B39F1A3FF0E07EA08D13E612F201716C67F327017
+6C041760DA30374434808273062C1FFA2C47B3FB578807BC26537F542040FF77
+66C995EF3E8B08B09FCD3EE89C30F157158A739606D2CEAA26694A4F1CEA6633
+B54933141CB85C60AB262E2D4E824A3B85C2BEF810DD774F296AB37D0BAE7182
+5648CD18556ACB124246A75474B232D712C2358908B5D9A76F82C626BFDE01A1
+093B8FA6AA0B32F2CDEF737B28BC0448FF816DDB5812131DA0DD5979D77C3838
+B978CC3F6778A4BFCE9A7087EFB19749285AE4C92B99A6649DA349A2E0889D72
+6D4FC664522F06C8C4D86D30BA43ED4E42211217D01636A4E17E2A132D26F394
+EC34EA12D84594AED9C6CDBBC0908860F39B240FA7D7B3003DB10322498691CF
+A294C0FC7ACC0BAD1EED3E9D60AAE3F7429695892D1A21CEBF062C6129B33966
+8B2EF6E932F9891DE6028B81C5E9B23278D35B7F0D83989BCBA25E20E9D503DE
+144DC485F09A4EFA1268AC5E4B551C5B2F1D51E9B9B9C0FEE585204F869D0BE0
+7287D7570A12940A47C1F51AC6134F03B415C30E147C49F89228855D093EE55F
+172711F37776E97A99CC4B36E2F10713E36FB279FD3FA5A0EB9F3938F42E2BB9
+254EB8F0C0F30391735019E02BFDA21D9813C6A22279B898EAF01AA892B14DC6
+5912B9275167AB46EBC420836CC1A5F38A4EB47C039A7BCA62BC3FCE4199FC71
+011DD6E5FFA0F3D7F04AC02AF91B9249B9F993AE346572329DA852115BEF8460
+B94690E790003586F473F37EAB5AC2922F5F663EE2C3C0C336A8DB71650631AC
+0A923A389AC911CB215EC2EC7D50CF8AEFD59EBFFA53A9F1FFB7E6215F17093E
+3975F186FE23BB5FA5474C11408FABD223E1E6F62035B5A5C1AEFD8899F00FFB
+E729C2D5FD551E80716CEA4E8281660286A802AAE8D5834F37F2EAC46297E57E
+993B09251DD7789D3467417E393B7DEABD06676B96241B0E43ED1A1A9FC3B12E
+0D34B2B0792B79AA648FE9450C3B209FB6D7D91F50C52A5DAB0BC81A8B698BD9
+18946EFF691912D7348D48FE68CD876FC6F71F81165D0C3272DA1A992308D9E0
+ED6D0A4DAD679AF495F62B78D462B463BD4A40931172290C615B3B3B6B47E45F
+CEBB85E0A6AB6832067CA6D403C239530D07F199788AA4DD52553836851C5228
+1072406F6D7323A334E7A7FCA588897C4FBA6D4F7DEB65525EFB74E539C988C3
+A685A98752F7198E77E456A545F0D23A1BEF81EF58B02D289CF980A3F17BEC8A
+6F83DD90C4A917EB0E5E2B444A608E2E9D2FF80620E16AC1D7775C0A10C1299B
+BEE0E1AB24C50647E5CA1DA65CFF3B2C295F0644CA7826E1DC6FADEA93D66A20
+DE852F20AD224D28DB900519EB1569837139C833F24B799F7EBE3FDC14235323
+1D0BCD4991C861F38DF413A5A5588B73AEC3BBFDB885CE17BB3E97B4E6A79761
+93EC8418C2BC4725CD61B5E30C07352F647C3FD50083878C13CFAC241DDCB082
+E53703D182068727F9EB6FACEC25F6D901D7309ED7370867E34E267519E22D62
+4FC7093448BD0D6B1C43D318A3E14C92032325C132AE0FF7ED707E1FA4A955FB
+F5224BE0045CB14ECC321D0F333FE24EEFCC504F7C756451D7693C3E6CA87526
+4912E1B6DB935BDE76FBFAFCA4ED473F1D2618812CFF25A6859C626A216603C1
+361BE3E071FCFEC2D4BF2FEBDE07DBD56A1BFF8303901168FA06488BA6B76F36
+95B0A90D7724E9ADB567C2ADC65CF3482CF47FD1D16F70AA19A97D0F9EFC611C
+AEA5E1ACCDA7FB2DF05E9480936281484BC329F0B771775E73F7FD72FE3F45F0
+50ADBD03932B38F37A8F0A66B2F739EA3AC8811C8F514E68C5643E4AFF485C81
+88475A523D7FCCA5C8809BD49846C77795A38DC6406082000236A4D2628B5932
+AB7916D44EC2210CB941B4C12515E844F0D26CDF0AEAD63BF1491BB50ED4D6D2
+739930E80E26E9B425C25033121899AD22102AE6868648BABB7D5985611C95E3
+5B8D365C7D034BA22E904A0ADB0132CE38288C127BBEA0825E600D18383A6854
+EE28FD1B2F57AF704854AEECF985EEFAE0521DB38B0A7511C803CE8AE0D0BC02
+50744F806B8D771AEA2192F982A46222D0BBAFECE94AD9364FF06C1A0743139E
+E707CDB1F328794258E7B65C8DEED54A3603A207E9293F1D0AE9380C346ED826
+FB86BF48CD0CCCEA4AE48394690C580DF1BC1D18D5D5263A2B4E2F4E76E97E2D
+7B116321428E4418EBFC552EA884495FA49D0BA43E50451601EC4C2ABE08BF6B
+4D89C8002D2D6B2E6D776FF2B4E19BF8114A8ABFA814C3D19FE883BA4CFF5F55
+E2699B224EDA1D73C4FE549E6FDBF7F03B55E169CC7B3C114716B076CD2127CD
+EDEC692864A8F284F068355D23DE0B72098F15F36BE977CAE1C93707E9B016EF
+35CD7C9E3C0D2E280E9FA779FC88EB4D8869AE19372C67590D4C50B186CB4957
+4255CDFC8626DF97A3BB3CD57E6F5C0753EB791BEB1D89D9D08A0CDC20B03887
+53AF5658F82A3189C68BE1CE912E2DF8AD9DD14DC19B73374D3A8D91AC5C0BA3
+5B4E02A20F0CD2AD2BF9CEFD5BAA6DA6F67683240FB37F982E4BF94D01EE4B87
+48849EEC3605F4F238EEC0CE5F8F0404B54EA14197C4512D693E7049FE2554FD
+D6597924287E5F7BE637A45BCA0B656E72B4DBF038F34C200410A5F13D8F41FE
+E4F82A0E8AC403CF55A7CAF1592C8F3677AD309BD02D7F1A024EF4D12D76A4DA
+3B1D7D70E5F37F30DAA980F14794B958BEC5E965947CA8701511A24C51B068A8
+E16E87E6E0122772F1B7889B606BB34C3292D202790E3E44D08B2DD1524CC5E4
+C5B5A0F0CAC3E959911358176443781BE957B29766D3F6C4F3F00E472DE7FF45
+C0823A0ECD41DD85D331FD6382EEF94A49C025AC9343CED0EDC96B340B9556F2
+FFFD21DBF54879C80C3AC86A8C60F036818300CBC2BB89D244EBA39909FCDD25
+00DE6123A2EAE20617D6AD25352BC89188D9A0A637899845684FD148F6D05B43
+1BE58EDEFDAE5F13B8F490D8AB779DEE843349F10385DBB9B9AA1FFB29771131
+174FA14C1F2FED29A9144C17DD38F24E2DDEF79AB75ADAE4751BEED51EF8001C
+5E746F2B18E06D788F423D51F80AEB1757E191DA795F73EA9D3745CBDB8402E1
+1D68CC70E9D870B1C13F1B6571426E682ECDF0760703AC3CFF878F886817CFE0
+91B4C254052177B6803EF7D2AE1627051931AB0F40897063F7E63A531F17369C
+9200AB01F2BD55CFB0593E7B3F0C95ADBE357B47DFCA6851FE0BAFCACB518174
+C1DC98147B32E53025C75BE70696B8BCD0197B7B55F9D3F86B3514B70C6E84ED
+37E14AE8E7B028FB7690B49C0935FF8C4E7BE20FF62924F8FF1E63087E80AA08
+7A4813ADD73264EC452EB4756E3A6F6EA483B670D26AAE5C01635E5BCF7B68E3
+4A5EAE7163959BF4B6CF07676410526339F2227EC18F3AC749994B9CBDEE72B5
+637CA69C3A9977A371A8F3976F89C396F5AC146ABCA81D1EF54D63ECC741B8F5
+74F10D8F45621C4D4387F603BF2C6F28C186CC1B459092A6DDB2BA582B46F966
+BED9A58C136B21C4E5A8AA454E7F9E3A959269241FC28B17C4ED41FA25C0DF04
+7A9E19F35C8581C352D4938757B80637916554ADB3ADA7CC900A43EF5EAE9B7F
+FEEC9F03526E71B41AB44EACF4E3FAA590373E5F9B79AFC4710BC3605A617385
+5D0E4ED5CCB5316D786A1A26A0CA791C7BA57E6D095BCF85376FF355336A70A4
+A2D0B8897CB47DED9DC84DFA177703D22D5C28EAC8703784882E961EB913E8C8
+3D61D4BFB90D80375D6AC9F865BDC55D002901133240A64036A8C5C3C17E81C7
+0CB2DBE2F4033941ADAEC107E9AEC1A0392FE24EE04C9FF9F55C1F5060B9C11E
+952145CB32E36484E89553FB76133B17D4D8B8CB93E0E1925A7F35D6EB9F442F
+B7D750722FDD21A48FABB0CBD361283F1E169BE8046008A03C94DEA662B7342E
+177AD179F908A16912757AB45A236827DF7A9E62B91BFFCC2293861AE948EC6B
+118AC7781E06285B4DB4383BD10B11B6158D8FC5AF66DD3BFDBE2B672A475155
+18A1E12364CCC7ED102F178B45CB26EF751052E5F24D63F4B89F83DA2D3F1647
+080F68DE59FFD51F95C863EAFCC8A23CDAE9F68895D768DCDA1E8DA17AAE7718
+3C14FA5BF5FE32A6287E118FCDC09B33E6E2FEE973B4A4F7926245A24A341A78
+43F2BDF8ADE02E6A2CE8525A3B4AFD65047B07F719D53A568D5F681A036859B6
+36A782FE709EBEB5D4664171F86D877EA8874B6ED980AED7965211F0B19F77F1
+4EFD94AC40971FF56B7986B447CC4D4AADA4C3D8789AA4AF6E6123BE7481E1E1
+583BA88794C57BC119352C57F3D4647AB7AE2C2D62D15168B275BB266EB7171E
+69DA6272F0C3CF9A44BF9361112CFFF0B3D5AFC45E6BA6AC8180786CF5E37D44
+0B450E00B37A91F28773FDDB55E7D6ACCDE2F23A812238EFA885DF3596629B41
+5399AEFC1983609BA4BBF0FF0567F6225364C66986F3F2A0110CF44025E049BA
+67A0094237BFC2A2D12709540CD2E9BFA05FE1BEFF6B502C644C3B0B8161A8B0
+76C96D707C71BAF3C2BEE325B8EF357365F561F181BE78A739F12A2DE0719F3B
+052E743C1D4541E7086700
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMTT9
+%!PS-AdobeFont-1.0: CMTT9 003.002
+%%Title: CMTT9
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMTT9.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMTT9 known{/CMTT9 findfont dup/UniqueID known{dup
+/UniqueID get 5000831 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMTT9 def
+/FontBBox {-6 -233 542 698 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMTT9.) readonly def
+/FullName (CMTT9) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle 0 def
+/isFixedPitch true def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 34 /quotedbl put
+dup 35 /numbersign put
+dup 37 /percent put
+dup 38 /ampersand put
+dup 39 /quoteright put
+dup 40 /parenleft put
+dup 41 /parenright put
+dup 42 /asterisk put
+dup 43 /plus put
+dup 44 /comma put
+dup 45 /hyphen put
+dup 46 /period put
+dup 47 /slash put
+dup 48 /zero put
+dup 49 /one put
+dup 50 /two put
+dup 51 /three put
+dup 52 /four put
+dup 54 /six put
+dup 56 /eight put
+dup 57 /nine put
+dup 58 /colon put
+dup 59 /semicolon put
+dup 60 /less put
+dup 61 /equal put
+dup 62 /greater put
+dup 63 /question put
+dup 64 /at put
+dup 65 /A put
+dup 66 /B put
+dup 67 /C put
+dup 69 /E put
+dup 80 /P put
+dup 82 /R put
+dup 83 /S put
+dup 84 /T put
+dup 91 /bracketleft put
+dup 92 /backslash put
+dup 93 /bracketright put
+dup 94 /asciicircum put
+dup 95 /underscore put
+dup 96 /quoteleft put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 102 /f put
+dup 103 /g put
+dup 104 /h put
+dup 105 /i put
+dup 107 /k put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 111 /o put
+dup 112 /p put
+dup 113 /q put
+dup 114 /r put
+dup 115 /s put
+dup 116 /t put
+dup 117 /u put
+dup 118 /v put
+dup 119 /w put
+dup 120 /x put
+dup 121 /y put
+dup 122 /z put
+dup 123 /braceleft put
+dup 125 /braceright put
+dup 126 /asciitilde put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA
+0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93
+51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71
+7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551
+E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078
+0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273
+C01924195A181D03F5054A93B71E5065F8D92FE23794DDF2E6BABDA4215500A0
+42D1A3D0D02C0C98BB1D6ED0B7791274C38B038FC7921FF1FB8FAE7258C09259
+4B8E1BD9EDCEDE9ADAD9BD9598EEA9691589649A9A21539161E374075BEE3457
+689F308A4A7AC9F2FE4B301A6C36B0442FB92E3B002623493DC087800B5A0521
+0DB96A23175AC584DE166F59142779F26FEE9783E28DE49FC3A8D6583EE63FBA
+610DA773CA18ACE6F64A4867A1A7817120ABF9DE4D17782866E6CB6B65A9F6D8
+3667C8D3E61E5356E35343FDD4C6436DF73934470916CB5F0ECEA6BFF092E735
+C7C355B56189D1DD5715EC97E50145FFC17BB1497315A9585D713A7A6DFC7933
+995468EFD0F59E3C15865B87925A3F2930E20D5A35970E2C44F1629FA16E00EE
+EE21EFC50D49F5BC02300D0A7BB85E649CB4E2E828C8B1C5469463013E71D723
+2CB11BCBAC191AC751A2AF7FC228395CE9472DC1809052012AEC2CD66695DAF0
+4CA04234F0187F4116C93F59A7F1F8123DE87F111853B785A20CA8B49B3B0CEC
+B11AD345E1A11578D2EFEB0536D125237086CC8CD9F34A5137AC5DDFD8746014
+D74AAE8239B81ACF65F379CF2153B06A238A2D767F294CAE0D79228F0B7D45CE
+510AC9657A1776202FEF42F96D476E7DF407786AEA12DEA0013D3B4C5D0640F5
+BC5BB72C34066270399CE595827175B23B25072723BD24E07F6BCD9EF0175DEF
+93714BAA53960F81103CFB731CED4A267B53727BCA3C97B0BA5004055D4EF0EC
+F725658E53AC86E4061B489AD4154915C3981B3B703E1E2A8D390CCECCA99385
+45EBE35441B062D7D12DAB2B31569387187D74A4043FD71F1C6D352EAE0F6757
+4345FBFB6DB15CAE47CAC4BAE47AECAE5FF5EC19057DCEFA1B23F47364ABDF47
+088A7C6A2AE26B10459B6D41CB69182FD1472F326CE3A15B59255D1DE3B616D8
+9D1F12561038839781E657C896B8C58A32DF5AEA23732A0966D96C68C988ED7A
+09B7E2C8F9F3D0D56879764781566299A4EDD3588BDF70E3D924D25074F30988
+E35BDD827AE4D0B4A06F55A9976BF0DB3C0B1D09CD08E8CB168B50617691638C
+0EC1A791C228177D4FFB021EC3DF5082CA3487AD2EFC8DE9466A690ADDB4C52A
+FE2A6DB4CC275CD33D9136E735279FBB2008D59E667905EBB04326EC33C98B2C
+94744B7F540D86E90DED64572ECF1EAD3A58EC101642B245A9C7232DC8FB8741
+03F97883BB32FB955C22F878FA0FD114451A3B3859B0B5537AFAB73AEC7DB2BF
+409E1FB41D473714F6BEA73CB085139879FA31710E01915C2938C37BAD6D7D71
+45B897E00857D3931A489EAC7B42BCE4E65F73F67FE027CE482DC47598ABCB95
+39E98DA8ECA3E23F0799D5963ABA6E2984DEACBE7B46B40ADC6213E0F4D08971
+58F68C946C748E4B4217CBA2391BE2086C9758F4E32C9B6413E48D84D33A6E85
+84747029C0A9C9B92841D217A902BA8EB333999D62FDA9F82BFC8ED11F67988A
+0CAE42182E414A9766AFFF4B046A09D476F8E3F15A8C7829BEE982D8350BDF5F
+F215F2BBBF68D4B567BAB798B9604C79306C475926E9FEC0F07A99F43473C6FD
+B15AC29C3D07FEBAD1BAFF75AAF2FBE94F104F1DBF838044FAD94B661B06AECD
+D9AEBD02B60CA4546DD6B5B5C1A3833ED07845671CEFCA8955CE0DE5DB8FC93B
+3306683CBFB8E5B79A863DE78D455DE9D592043C2686F88A43140F8B9F3B553B
+7047420E93E753829F8D47AC7621CFE3626F271E31F0019CC02D0B57F67BB47D
+8CFB63E902EA3231C00EC66EEC0D30FE8394558BD3535C888C4CEFC6EB72E737
+712ADC6300162D5D79BEE0CA1F6E4127A0BC90656C01692F6D82C85550AFC97E
+C2693E379160FDB9636FA41AE9C75B7F6643B05971C6D67CE30971D590FC07B3
+E0B36B4D1C7F25110B5DA2130D574FA292B47322975A2BADBDB39AAE69BDDBDA
+A880F9AAB580117708C79204DFFDC08BF4A48919B5C22228845CE8C3109E93AC
+2479E523B8A1C12A6E541118F121DC6B4EAED83491A03192D5C3A2A45D1A2467
+757E7B377C635CF5CAE11A7CB49D49F3A1BB2286090B5F0E4F89869D1771D50C
+54B5C5E091E3048A2C194F0ED00DD64FB95BAC6FA9D61ECD093ED416DA3A4981
+DB07CFF17C4F55C62DF628EBFF06FAC3F3D3F91C30EBB34052BE1A08F5EDA4B9
+08977197950A282B84E21D43C64BE3AE4BCE22C70E7D392DE09D89B7F23351AD
+6AD37225C12BA79EC9951F5DA1E505DB26200190ADE0E549305B7530CB86EFD2
+A896F13A97E51754F70B609CB4511CEFC38BA579C071E9510A49982389980DC5
+336D6C4A2DB100DFEC4055C7AA9C55880F94FBEA9EB280BEF66CB8E1E38A359D
+E5AFB12B540CD599085ADDA7FC2C72E7C873015773FFEECA2C596B75BC39A3EB
+3C43FA2E53C0D7993042F3D652BCC483E48B7F6C94C3FF6D38E276086A6AE67A
+E5A571B9C72E0D7824E0BC2ADF51A393B9E334649F786EC1923C854382B89627
+1B9E701AE5A6C42E672B2C6A33C8BBCA8F69B9061E787D6B92183F20CF4C3903
+FF5417427B84798C82BE28D2C81624E3920CA61EC9EADB364B5A6E50E49A1A72
+A9A090A1FCD84814B8B2708AD787D2B5015DA1305874F58C5EB62F843685FCB6
+465FCA80176CAB2B2FE65E0A270BCE1E3DB97564BEDFAE5CA44395A8DF4505C0
+3E103CC3B914359B2870DA6CD30382EAE8949131CFE31E9E75C3E47A3834BB32
+CF183D4A8B9001710D0A11390C9DAD116196568591D38C2AF4ADD852F31494EF
+573462759A35415900360882739789D6B89ACEFA251C5ED90ED704DD7C3C80CA
+9F6CDED69537D201D520C99E69EEAD5D3C0EB84C166660B3C190166D93EDFE6D
+15BCB6DC5CDCA825E48D33845CC2FB15291AAB823F25CF8BB0A1EAED8BEC524D
+D9CA016027141FAC9D35B64FB9C224552F29EF6B32497254E319090E698FD8A5
+15491CDFE1B988C79A0E3B9D01E12FF084E9FA86CCAE02A3EE6F2917B61A2CC1
+64B8CAF309D1AB48A34227A7729DFF99CB6EC282E3FAEDD2673779AA7E4C1789
+D93FDC37FE95F087C5F88F53D30A2DA9C913BF205FC6BDD060A40184F4AAEB3C
+D080D63B89CA3DEFF310D09EF0A83F3914BD5B7932980ECE139EF0313C20B4C8
+576EE0FE3F28FAF4D3CE7CD0890BC824A85B8EF4636BDF1EF1BB519F93D36540
+ED09FAF93FD71992CA2CE2E83F5355162ECEB32AD218092F45D5A61A44E67135
+EF0453589CECDC6962D0E8DA7E7567603BAF50B2C8F1CA65EA5320984E7D69AC
+9A7D3D7F92565D79E8C9DD2D92CCA7DE9CD058545E9F98AA47904D70E1897099
+3C4C852B3BA131DDD348433C336BDF5FBDFB62120DDEAEB3255E3207B0C84A0A
+1ECF9EC869DB9BFA3693B03FCB27C5A5D3CDD62630DEDE91B4DD5B9784BF0BDD
+FC6EEC3FA7ACA9E15FAE47CDD9B7FCD2BF0EFA10716F08C0AF25FF67CB6F9598
+C607D2FCA452417D2C69DC808A9441A66492394C3450BD30632AE739EAD654BA
+4343459CA36B6D5B2C12C39495952F2EF93D82C73E33236785A79609E260C4E0
+CF3A3C950DE71DDC3939D42DB1CB1CA917CEAD56979A70F8F3B207C805319FA7
+3C000AE2B21D711A6D78C7BFB901334DC06F59EAB6D94B507734C27971F8458D
+D00193645AB92FB8FE163D5C51AE4F40BDB4F2C51691E76EE0636F071F37AAA9
+BA78BD12459CA499210EB0CE2F8BD317387797C33F5933AE7A6264DA06B4A6A6
+1188326147A16B205D1F965872DED7D8EDB3294FAD2FCDF0D423329E9CCF879D
+4E0B966D509F45527F7609DD09694D286F6FF7535EF8971B7DFBAF608A19D442
+C133207EB1152ABBD11C455D0977F66A9B73E51381D1CA4B66E87C0C7175A63D
+80C699A052F00C41DAEF42E7A40E07B1B14107AB0787E24E17C1462960E3C54C
+AE73BE4924464FB177EC62F116B2822842541543EFF7ABDDEE197D6BD8F8D4E6
+59175D8C5957550B70BE775AD52FFF6E7C00DA7CDC16E1DF7446BB5D8FD82647
+3E9F87D5EA365C82A2D991321ECB14A9E3AEADC5A56665DF7072D6DAE402BCB6
+14D92B17F9E063E4E9D8D239C91F5C7C0BCD2FBD936C9D4A0B57659420343B59
+B395BBD1AB5B6003F653699D57E7581F9813CC98D4F072FB78899D6DECC42D34
+F2787EDEA64058B46C4BFAA2BB96E9BE5CACE8D91E4C080ADFC0FA0D4A29C6B8
+54FEA9E11DBCF53D9CA40A21AE5076451EDAB3593E56B6D453DC8EAB8C78B588
+34D4C4F36861B5649BC1E9F3091E704BDA7613ED45C911DFECA74EEA05165191
+825F95A947CAF382FBAF01F3B8B041ACCDF39718D7DC5BA6CA12BB20EEE96439
+BF2E2628AA3BD2C91998E6247A690FCB0CC95F286F427345CC4F1115BA3A6E54
+4743355F2CC991CBDFF5725902C1F5A6DEFDC8638A26EA456C33C27773D6214F
+66536CD2E44FD253531732D5A8C44B336B1BB47B0477350EB8CF74889B93402E
+2356A9CAAFCA562315D8E0B3F42F08932CB87BA2499A875AFA08D11DA73B38AF
+F46D03B7F639A8D7BF88CF07FFF4E91716DCCE6E2CCAB60A64D5E40EFD8B336A
+1BFCC4CB04F49DE1FBDE7AA5B2092A6EDBD913D161A3271AB6411622D0E14416
+37F81E0102F5B0F2F9A2B27819E4BACD7C50E29D6291AE5B0973C657761545A6
+741729620EF2BF1046B3913399C10982EE5F4142CF461EA31042E432CC79A1A1
+39C607D22E45A6DEC008CB4BF6007CDE9DD5802B49A62C8E02A6D448B64177CC
+887AD71D171B99E7ABE2085B37D90B3BD8513995D9A57F53184DA474F6DB5E49
+B73E04CC214EA5398DF7D7541F94E623E8687B511640457A48A68E9D9D6584CD
+15B57CC044D8091C771D175F2EEDD411099BC8F7B4317DC503BB5E405AEEB526
+5E6E1B1F2705275D274E012A98F66075CEB90AFC648B964DDC0E9C4AE7B24CE1
+80B051022E5781A533A21DCFB97893847D685137EAD85BA708A7E118C72FA839
+A9E460B5D17365A0AF1F53A98319FB64A5819B087F554BC056C4BE44113A5404
+BEF759F890C1CA5E7AE156F4F8106FDB4F8DFCCC640976983EADB30976344048
+2A86D7B2AF4A01CA736B98D52ACE392AD4BECE7E61C710B08B66F01857CA460B
+B8376E257113E10F6DEDF14CE2A4E6A99ECBCD302C36CADB713D849EAE9EB598
+F29DC98531D793B79F83091F9B136809E006F34E423D528CC4309AFFB3EEB47B
+9A9DE4D5B25CE953345C326BCBE2B4912641780637783084D3D12693F8135483
+CBB0AC4EE0B5610D7CEB7DF205830BDB9BB404DC1B28FB0824CC187B26C19A91
+DA0025EC739BF3993700101D042DED86D67F5FB87912CFC51AA7DF53F2162D62
+6314A2CE13810D0B8D81F45771391A236422CFA0F35F7A0CDF14ACB2724AA57B
+7C2C28D53029B1146558610E0CFBBF72A85AB9BA308F846228F299F13F68E8F7
+D963B2EE9EF7D4C21690632B640BDDAD0556EFA4EFBF035F13377ABB5CBC280B
+9E0C12AACB153C93351E5BA95A7D149010E204950A59C7FC6581D9703468C1E9
+EFAE37E7E6ACB892B3F8D1248D9A4A72F642FECC5E0B25C15EEB921EDDE84D12
+0E524FE6133C4921FF4921242392C12FBE69744D53739F7E849C1B96C4020AB2
+1FF10DEA608F111749E2FBD8DBCB17F353DCB3075B4F4B8186963EFE95A76A10
+85AA5BB6DB4095291974221829A8E436680F4860E01C3843BE5BB3101D0869C0
+EFCE08D187BC04F58C7A450A59093680A0F09E8E3F12DF5223E7EAFEFA01978F
+D8354753A68022CC92C71F2CA732DADAA8A466D4AAE5999B0DC077715671F518
+E6277741F44AE798EE50DF44CCF71FCF8BC71F76374005FEBC4883C6EDA854B0
+88C0C2B476709AA809ECE41AE786DB1A32B3FBBCC14921673578D3514C8CA842
+E1FF90BE33F7B93ADF6BFB8B1AFBBD080783BEF056A6BFAEF676F7BF9F2DFCC8
+01D255A9F0391951210D60D4D4DCA93AA858B38C0D7B8FD740D5FC6F277C2A68
+54CC2DE1F40B6347201FCA2A0A91822708D820CE645C3E4E5A09FE25721AB33A
+97871ED448F38FC5A349D81F402B34461D840D5768BFC6849439AB6115104F78
+B87115B1DAE12542EA898F86ACE247709817850B067F537E6137196101D46DD2
+D842EA03EF4501E34074E8458E638ACC4EB349A7430AB035BEF2DD4CE00554F9
+18F9FE32A55AC1E7E50D64AAFDA278D77A7149C59DC5B1E3064A4B281A54C9CE
+A5EA94ABEAE4C6D5674C208ABC72563976487136AF2E21F835BEFD232D7F0D13
+1D19932367F51D5379934DA7F1635AC51EE5CEBFA63D4D32F018DEF13624EE62
+31DAE68A08DBE3B4FDAAFC75291C8C6CC7A657E3C7453C7D1461A36E88E633D5
+408253B673AD87A9FB2D0F56DF1305916D14D5DD62051E27BCE09CEE9A1F14AF
+1D7164BA5FB6E6EC8D38750F7E28BE330909F303ECDEE692E347DE13C8C2F82E
+29C8BE6EFD76546F362A12A1C2DC12389EA95ACB4DCBE95620F0C193EAD91B33
+BAAC5801AE827B9AB3FCE5D11D1D7854F8FA8A31670119CC0CA98628F801838B
+AAC7EF90AC5466BE69CE3E3CD9951A5EB9AC08014285422F6DA6F6E221BB30F8
+0042A11F2E4B765BB0D142AD52F4D85785EA71B2E1CE20728B9E9306CE93268D
+99B822A5AB5232EC7E26EE1160850AD3905864A01357F22722B6A54D4EBE58CE
+480EAD9FBF068EE965AC4B5FD2FA8CCB91ECFC6E90B9C49268CA0B0FDAD23ADC
+D5A74B41149BB08454054C451AD0DA4CCF8B60F2EBD061AA03A011D548B6B481
+FAB00AF9225BB5463F27FD67333FB51F8664536267E95CFAA0BE3BC1B8F889CB
+587A3A4FA2B45864F07E11372C9507A625C0030EF7030A0B4D931BCC48F6DD51
+A4D1F63FDC4B59C1CB18E6242E9F4B4B8AD9755B870FE60D640181FB7EB8120C
+C56F51DC8C47FCC6318C2145EDCBEFA7BC4253315BA67FD2B3D4AF6A9F3F229C
+AB75B592EADE15B1FB5FDBA1C0F786BD21A51506B7A2E42C2D086BA6F84D1B3D
+AC7531545F0B01346831FF36A52CAC1E390F99AEDC265B44B0FC9C581BBA6BE4
+48B723811EBCAEA5FEFAEA7E5B987F2C7B3E9A65D2D14A7B74F099401C57E367
+385352D0776D2A908F7A5A2E4D4160946C5591397877025C8C387CA413EFED56
+8B142E8341E349DB4DBA422A4FEE56A573972A0C66590175158E48850A9F7F38
+4B95726787B8F969FDBC97491CC81CABC976CD00A27D1DFCA7CF467A956C1C6C
+839817AEF8794B6151FAE9261119DD5DB787DC9D3B420FD325ED6599FACADE0C
+320D54C2E0D296537E22C1783670A9D9BECAEC63853EC2F05A990260DC189D63
+7CCC0BDDF2CF7585071ABAC14630666737041194D0777EA4292AE60BD7F7100E
+DB568C90F0D899EA006CA423CFFD6EC70A5D3D8AC43C747DBAD3B02219E47D8D
+DE030631F4678C357A58ECC52782B31B50CFD44EC33F41585E51B27E3997D33F
+461BEF897220AEC80007F13C5A1EE3A0430CA899047DF944831F8B010A7DE74A
+BFD26001472DC00CDC9F17CC435F61ADAD4E9AE062ED477FC621FDDF9242C449
+1BB3F77FDD1519A251B663A693D84B42BF0962F537757F38CE5C5D56B98AB10A
+3B70C8AE8D52DCAFCEC22E7B09D3C4EFDA1841C74CA975E4F8294F7BDC796500
+0ABE197ED3737A65F7BAE601C91DB3983EAE11DA3EA18ABBBA3650DC361C2E77
+EF9F97618B0C337A906FF39926D2B0B7883ABBA650816C4C6B34EEA836994EEA
+AFEDDE56E0099D0E09EB88EB093544B9BF4871200746A0409C475FC4232A38D8
+F3105B0FF44E4F132378DD12D9E796412FD0F9478322215E9F59E69396C35AC4
+097C4995B2C3BAB2DD04B1A7097DE16DFDD76465E79ADEEBA90489ADD0914EBA
+53E11A43ECB11D072C68D2131BE1C7C43CB9DD5FBA0A67BA43D6851AD4CD3BC7
+39AE2E22CCC183A56CEB71D4F9F578518E376426E42B6390426A8434B5A83E78
+77A5B9963BAECD5FA5521C2A29418764E4EC1A72462B04957F823E2817A7F8D0
+1512919889500024B1C42EC107E8B8533C0B314EE4E23313A4C1BDB009A20114
+2248276B7E4F8924750C8361FDB1FA328B434499FE5DF14B96C1F5D03F1F2702
+C77057AF82D3982C5EF8EA40D0B923249FD9810464A9EF6D1A99402DDF08120F
+FE77568235A193F5DAF57231E5095D4EF505A0FCD8E538D53C5E23E226B487CC
+568F94438B050A4ACB53340A4054B02E8F4D8BB42E72FFD1124BFA91C22F3F76
+3F3015809D6EA1CDBF7827ECF8893F550132A618BCA2B9CEC7A329460CF59E2E
+3F0E70D05F42D3E37130429C984D24F49529F647CFCB675C7CB79749E35DBA8E
+E8A0B56EE8FD852899BA52B789CF2A5D4F1C948FD5F5C57DC8475E65C83FC690
+28EDD11C5A7149D68B924EF92D73A70D37AFBB433D1563A034361A4415C1722B
+7599BA7ABFB5D0189D9071AD6FB28ED80984B44BE2C04371BFC57AC36B918096
+0C4D04ED59C111A6468D2DAB84018930FBF7D9E7B3B43B5349C4B3B7E8542409
+B5EC9BE8C9C04FEB470E28D3E2DA70EEFB29BDDC4ABDBAD78386FABF443FDB1E
+9458FAA05E9362979CB79CF51BF3FDBFF05F8B410D76AF9D749C161E5A224793
+9094F212E87A697BA5BCADB2F6F8510242AF911BBAF8FA5C17172A713FC97711
+D1D1C506B49B6FF85A713D3DB9DA5CB6FD031CBC44A898B16C18B8EF65366132
+4006962C078E68558FE7F2879518335A2E23034A7B8A6771E95A869B11D908B6
+2530CE5551A6E270F91BFB06EF448C22A346B7D011F62241A55B7F7E886C21B8
+E41BB806659B0DF80DE854F883BAF1E21902619AFB6B248DDC7FF08AE56706EA
+1CBA3C9CC443721F7E365E0CB81C1D0B453A1FF8162B5DFC6C4FB7D613D7B93F
+E29E4B38DF51B1CF584013D6BB70D422848585317384B2FE34B0A3E7B091B8AF
+86FA106BBEE6B59FDE82656847C78E629FAB784FD7C610FBF9F0D6B763748D4D
+C90D2B3EDB4CC1B269137D8FA881FDECCBDE9FF84F599911A4A8C777624EC2FD
+40EB0A8EE71E6F9E99F0315B549A7E51FDBA35B26CDDF634BDEEF6F561DB4298
+A80F2B7B3BDD68B2D13EF31DA56B1E609CF5ECE6E43DBC72B344872C7A729F70
+1E846C63164A69E30112E34BC0BD001F97EF9BFB5BFDCE7E7DD10197EDA39BDA
+3859C778E31A9D0D4F6772DA9FEE3CC4BF32A40E607EEA5AB07359EFC5E44C16
+610C9F5D8915B05E06D934D6173B4671B4BC19F871500AC983540103495D18B9
+123793DECF15C3CD213D5D57A2669E531D44635EB81E999755FC6111B8166C2F
+A6482D10F456A26D7D6EA00D07F542F6F2466DC6A688FF2E4B595F95C9C1059B
+0462324ADF96BDD8C1BA32ADE212F9A779D7C9A87A60A98AA539878CDB2C9CD2
+D05F1474A16CDDE4D3BF0077B86DFD856FE19A9D56F0B30D8D2944E103DDD9F5
+477F6439724B553AE611BCC2422D59F5F8833C9401D4833917FC46036755080C
+06365D46020CA44A5F0E968B0C590E87CEDFAE3AF6F04E603B921391789EE9BB
+E647B340C98BC48D1F95164DA5A769652DF1AAFE1DFB1DCD5BCBC33C744E29ED
+6BC02DF741FAFC241B94E76C507C04141C0A5A4604C18FB6E15549FBA306FC5E
+40690EBA17551BBAD0DFC3F0B11EB92C3DE5471FF5D5E295473FA870E538F218
+A8C8B728851F072BAB4ABA19FD87F630CB7F7F3633DCB5A011D6B96B40BB6221
+FCA90142C929BFA81548D93A4BF8A45FDE9FE4263108E6435BBF67B764506DA6
+6981B41C87035623AB8DDEC1FDB046D18DDB2BA476F2968B59A85A295B41A6C9
+B3593FADD77A7F2D70BEDD7A0C5A378C76D9D39DC672DC5733AEC958CBFAA7ED
+8F5F9812DF246EE3040E09CD1B0C94F2D876B17818FA33A9CA5B5DAB4A546D3D
+B85EBAC2B452F6E780BFE9E703CB8AA0135094671FE92F6607B04E0C965A741C
+1041B8A59CAF3778C7327181ED2CB210ADDBB5D2C0496D40268E7C5B41206419
+A02D73CCFFD3B2F6856F00598577E8E2D12AEEF7A22B1639E54E8D59997FE5A3
+763CDF1006D3E37BF67EB1C8C1EC35BC4862F26220382D3FFA3ADCCD25887758
+9CDE8E6380CE3B5844FBFEB1C1B4B12B1E6DACD6952BEBC9D7BC39DCFBB8B36B
+10D8791174B20CE7FDDB84E43F7B8431E9CE957D7774EF445540FB72FA772D17
+DC0C04101CFBAE78D08A21B108391523B024D9300564FBA12E1601A64C5BE673
+5E3938A25A7C6C94D7A3E789B9DD3F4F5205AD538CE134F6F0A38065A870932F
+DB33CD22E129F00F092296359E066E4444FE8E19768A1320C1A96BA6268EC037
+1F105785749DAB69BB9A5FE6FD492CCCCCC7E91445B7A47A0FC675D47E45EA68
+97FEBBC25FE0335C0C41CFBD53A6DDB7EFD2845B039BE0463D2D73DAC5AEF9D7
+5056B8400576CD9D8E0E2FAED625395A9EF46AC3D8756AFA777F42385C62D7E4
+DE47177893F8C30100E3A95A88DA9CD787AF10B98A373882CD9FC8A8F3215EAC
+2065C13B807345F777423E7CF5AFAC338DA83C60E1B8B44CE09F41E4489AB271
+125C0A495B91C549E5345BBA213B3DF67CBDCF87260BDA6DCF88A65D484B5DA4
+92932B8D03284DCA19410F948D3FAE378D63192A150D1F68B2BE085FFAA40C9B
+B689B6D734D965CA949273AA7ACA492050348D623924EDE7A7414BF639EB111D
+1F77CAA169A6EBCB15182FFE72C7B0C8EBC18E2506971F1E3118FE002CACE569
+7BBB01B27459E9170094FDD8784E5C2067E4206F8D4FC644E412D7370C16E9D8
+3EAD9C2BFB193CD6AF8188993F3FAB7DDAC6D0BD19E0C9C968742603F4FDB07E
+45617BD2C4F2EC9E3A40C4467CC7AE5E50BD38A875CAB904B4479555E6D6C829
+4A6E66272CD25D5BF05C7D9F8105EEB6AD2532820E34E3635684E15C7172E179
+52BA7737D4A9C3D1CABC39FA756406669E34C6A03642969DF0E842E49E39C39A
+91959907ACF346087E175AFDD421CB74BD26BE5EA6E9777CA6BC9871AA031DA1
+E05B54210DB0231E2209165A78D15BBF8F086973F099DD446A80B36577675B73
+5BA4F1B1EF400EF783F4B4D0ED4D70B881F54878E8AAE9E455D662DC9AD78F82
+3B871065B632D737F0BE672B0F77E6E03980B2745E7031B71671B3D983AD2E0A
+F83C1F91E427DDC07BA100D742828E6097D5F600CD7F07F7C2A283B094C7F12C
+701922BA37950B4A81DE30CD9C66CC0514F24F0D9F56951F3123AAB586AB7EA5
+DEE197A79B3D6123BAC5EE9F5D1BD504FC7B06782458D16DDF0936CE420C6B30
+35C358C846C460C055ED42F1BCB54610EC7F9D0D3A719DE29C38BE710E8E9518
+9929C046883F6245458610A696C18122E377E4FB9FED6451937A547B050C36BF
+63666A74D9BA9D65BAEDD10AB3AAC2689B52CD9A667DFB34D5956360F32A54FF
+FD93997A857B979B231D246CE252A1D3B9F34DCCDD81BDE75FF25E935A614069
+343EA6B342C19CD922DF9EAA855DFA8B0E80636B04608AB3DD475F4EC97BF542
+CE8A2B6650F43E29378B0156CD886043122E743802EBEE6DFA509AE0B8F4B61D
+22BFFD4EFECF595A0950F092841233ABA4D628B95DD364801DFD444D3C52338E
+75091C0775630715298559160A24B4C2B49EAB6787FD591F764C6B5C97A10A70
+9502B3C35C47B8DAFA92F702A93C872DC424EAE7E67C894B5202CBA85C8429D1
+BC070C316C43FC50A8046C4A3C21DEC9668F8571F8C23DC032F0FFF91A263532
+8FA97D6A38F194E93DC1BF725F574FFF409BDEAA98DC2736461164B6631FB91E
+1E2C40939F73A093152DBBFDEF61F8D0107867E262B64295C617B42443C65102
+35189F6B19D2BD6F3404A966445B8709DF077C9AEAE7F4458DDC0D3CF9AB95C6
+AC29FBE021E17A61F547BB75FE3A610A0ADEED819A5BFC19BEA087A2E4D31221
+DED7AA13FDD13235C6670504CC7E932320DF993C5A8B675DE2BF020DE3203D04
+5B51FDD0EF2C3F7E6EFA239CA76EC343146AFCEDA5402FDE629D304A4123B305
+DD23755EEC8C7081535363ED0F948364BEA64CA6D4AD9D6F8761D903011119E8
+84B548D9E49152879FD7DDBEABCAEFF8791B2939996F56647F70ECB6103C1567
+8BB4000C944C7AFEB7C8A529C3E984DBF854B58AAA3209E8E366877855A449BA
+44E0D0D3F672F9DFACABA24E8472E3DE46050A4CEBAAE39DB4A5BDD77C3BCB24
+EB90D2796BC94683935F209762D1FBDFE1C7D140E46C49521942056EC5FA0C8D
+377CE689C8DB405C44643DB2586D91A8EAA0A749EF6055AC0EDC45E9C4427098
+80A0CA45D1441EA5B25679B1C2EBAA747396B9C255642EF309196522C038FF7E
+2DF37C60243B99D69832E0C6BCF662380891C3C2D89269E888FBA1E2E247FD18
+1E1B090CB6829119A7F54E7473B686979326F7B0856632A54FC32311049346BB
+C99C15441B2ECB026B36DB0BBA0E2FDDFBB6CF6BE997669611267B266E533EFA
+F212119A39E2D343934E3301A051E66CA8CACC988418E0C18DE48845BDD45173
+F916D909270CD6D2076406A91F12A96A16A0DDCD5FBD9128B5D970E7A762A173
+10155B53D25ABCCA982CCD59BE0ADD089C2C14E044910B1BBD6F07C04F86C4FA
+63FF940A1540535C2F0450CF7995DC6A9BC9C8FFD50166649E3C7949BBF66DFC
+0B3E576B35D048C4DFAF41B77E0C8B05733933D6B0EC509DFC856CDC26F2F833
+7E2E58ED0545CC2D3F91B040136660B2E5C8F75A8FBD3AECFCC3CF3C4AEFEB70
+9BB571CBD6D5E0CA3818A8F08F2A3CA0969CF73CF8C043B69F37A4443E575E05
+D9360A2AE0135F3C9639D76B13B8D8EB64CCE253996A3033EFD35EE716C9B475
+258F7369B04E939DB01849839A64BD50825B9920F9A09639824AB0D3E54D5ED2
+A710AC5AC35FCBFF1A7242B8AFC94CED8E7B141D21781B5E9B97CF1804F229F6
+250F79AEC28FA27C2008F7E7B6463504A1EA635567F3E91C80CE1E6E68859489
+436C06E599AE578B9658771164B1C8F8BCD23BAA8BA947FE553B4732F9FA2ED3
+1AE7F577BE287E672C035AB8E72F8DB5E31465076B7F2EAE0BAB0944BCB75C27
+FE822D07AF694958420D7F15F3A36ACF7A1C9A92FABC46BF297B523381A3D910
+B00C03DB2ECE60F63DE0E1C2DAA756F337D7C2E961EFE7730ED8844E0E95868E
+20ADA11055A4CC2C4632832574690CCE7A8462EA4D0A2EF4F8C354D2F3034DAD
+9A0B1DCEF4BB70D29D598F527D333A0D3A73D1DFEC7B043774CBF2B49C055462
+2820092AC798A3887D577280F038301F44440ADF5F5915E1D560A5E1E3AC31BC
+ED5A53CA33ED0ABC1A65D3135D7A4C7AA26DB122E83F83A5BD4E16A79BD79055
+934E49D59702A6B3E3562212DB0D2FD4ACCF75B3A59D2F196E1277A61CA1ACD4
+53BD0AF9857EBAA8250D5985B171A446D0B15E364FC43F6D468FA073B85F892A
+3071651E480775B0365C76B5FBD1BA770FFDDA7EFEB032090E6192DC4A98F8C5
+A0A5533F22B82159995DFEBE6F68A163A5EA2763619EF56D64FEF9727533B061
+0C306D3CA6C585EE0491C8D95A5E340B8A2373393FADFCE32F4D00957662E6A4
+32895DFEFC20206F49D863E4C21AFEFC9858193250949D12A2611C56EF4A16F7
+9386D8DF7D1F5651ECF8EF632D5AB35D204F4C94088E9087EF80ECED40191E8F
+B3EC55E81D38CC91BF432C44DD33CD58CE860DB6D27669861CBEEF9412412999
+1D4F1A70F412173F348423E55977550B4C8D04461FE539B0A69050A1D46567C9
+924261D14204E9BB65FC448A5D51C4C1AB09203B4CE157160F1219189FF54777
+4F2D513745403C7A9D9395A11171377DA8A05EFF2CBE0BA9FA54C6109D43E9E9
+51B5EB5A7338F48AC520296BFD2EE545C5DDBC359300F48062A4E36B35F3F293
+E48DBB621DC1057A12D01C9A4E2AD5D9DACDB718D61E2B926044F08622A9599B
+FECD9E31AFBE2AD3DC4A6C1D4037AEEEFCA5DD3A3A6F8FC12F906AAC34EC89CC
+F92C44477983A10FB7CE6CA3606FAF25258A6FB58A9FB1C0EFE4D1E725C0B9FB
+DA6094A41A29317EB96EF0E7D6FF340F3AA197A3B9175D7E50FE0C62722D3246
+DE458E4BE4DC7208EF619801D3D73547075E9752B2F2301259930CC3B5E8618E
+C4FCC4954EB0ADC590F78F68AA9B5B2D1CAAB63B269C140AF8D161FA8E78B7D6
+BF33268011CFBFF47721DC7E04D7A216B3739FF116283000D454CF7CE04B0F16
+3793087399AE2CD49690C44F8CD2B0DBA5DF316B57F3AA9A66A0F65768BDC385
+3EB6BC0F5FE11B4CA86499BC1001B0BFBABEBC9AB3E5229FC92738D87874CF58
+557E726D6DA8BF12029E24E2AF6168E3F13D7F1417E6DF7D8B39787A77B8C2F6
+EB60E78575AE12E42BB9AF9ED2AFB6F3265720BAC268D1C6331DD05B4569A4D3
+CF7F5D5646855CEB8F0F792235480A76AEEEDAE699E47201EE91B876215E6F8C
+DC05CE3BB69C07BAA0BAA8CFD3FE8598F71FA32619C55DE2D81665AE5853C70E
+462FB90A5996C26A0E4DECA41B66FC114D21069AF9DF16464A91EDEAFFCE8183
+594685DFCDA6C29B9EF44EA9AC718863FB3DE47DB97F9E0B42C1F2D4D86B1625
+83C3181D4EA935C0C307876AE65353EF54A66A10B0E9EC655BD8E2037B7DA1C1
+E5C376E9C56050228C56CE35E812EDB26DD94C7C42E9B5EE7EF9B2A7EFEFACA3
+04DF83C1777476FC200DA78DE9A2814D8CB8E1413C907E828903C137F525215A
+C8FA7EC814658105A0A020E4538482F7B347FEC0063BCA81C516171AC6108BE1
+588999F7F459E5B21E2BB4F54C8F2D6FB9F4D651A849B078D2DC108E6A2EFE4F
+CFD6D4B29C00DE49573135553DEF1C32CDC0C16627823D5996416932EF4189E2
+E6DC38FD749A32AD2AA3EAE7DA8477F5AA151CBCA3B1C804E80AC00050BA8027
+5F5F4984F20F9631B9A3DE81567B1EDCE9B1B218F9ADE39D9FC85B24C801750B
+BD84EC20AAAFA54D68C00905A29D33212E01BB2AC2C8A2025A31A5F5E8D1EF38
+E4279B55A1CD38A36120440D7F4AB8EFD4497BB27C99A12A3DF6301BF4400F5A
+89913C1CBC2FAA8B370AF6463FE4886729B7C1BD6C9740B7CA8B64950BE7119A
+675EDB295962427256D2922D6FD40E9FFF971AFFC185773DF868C82593CD9FA6
+EEF84D9322151C1BE8969E0E15EDF3B9CDE50836B37383E40EA13A5C432E462B
+B0B741B4C411A98E326467D77DE336AB42836754AD83EF5B8B09A55325D048C9
+E80C5E02552915000A2CE9636B68C71642FBCF7C5DFC155BD3FD9B9AA9BAD862
+0A097070549C472D3ACA26290A16128634D4541B0FF4FA4D67679318D6CAED47
+3FD289DFDDFA33F4BA65EFEFB82D98D9884C2D7CF0ADE7596058C2BC49EC141B
+4C13075BDC71E17BC7D96B4C47DC30F66572066DAFA6E8467481D16E8AF6FDED
+CB7BA0D353501C8A9163F8CC471DA83D713FD9F1E654B69341A5CC3E9638FD5F
+F02E58B0884D454FB4D02AFE75357AF11B4B430002D0A469781F1281C22BA8B9
+4A17EA7A28ACD013495C823EBBB3650FBAE5A4B714746318895A3DABF932D845
+AB1E57FE5CA00564405DFEBC143DBE82F038DE1CCA1E8B154A11B45200693D9E
+FD2EFDAAA3896DC08ECAC86A429D2F3D8FF0BF7FCAEC65FB0B7EE8C39F140849
+A60170A5DC981D6280169C7ECD54C7F71DC00C81290E7186F29EA5AFFE65300F
+7124408987B57421B9B57F792915C8D2DE198DA2F943E0641A8704FC0B84ACE2
+D580685AB944A02676AC7ECF825A291AFB0708B1E3BCF2504442BD2EE16F987F
+187981A2F76F919D4C53D458C2D733868ACD95657C6674ACD513E543A4E271EB
+364E84131E6D4FF01001D9D70BEBBA40552E83B960B624C72D8629CE99225EE8
+A3B77487BE3637B1423E0F8B6B7C766ECF066B22AE841997CEB5E64127B7D17C
+5E6295355A68BFE772282E54E773465B1C49200BE925A30E4F31971B59622D37
+48C33E5C72FCDBAB5735CB0FBE9D48B1268B7AFB245DE6EEE4BA544DB637AB9E
+E9B6FAA22C2463754C653AC25C884347D940A4640229C21513E3BF1FFAB272E0
+0CF09EC78001C34C2D41AC1CFD967BB6DF6CE713D194F2BA8DBB0A3F9F2F2DD0
+044AA1910950B4ABBEFFE14BEA5B6460BB853CE329605E8652FD64E94C74FE2D
+C237E18A42C47DD0FA1E2BCA549B40AB4FE0008005CA8066E09327082866B12F
+2294C1EECDB9AC0F47148D6B0B480E34D300EE501D2AF01A5CC0B11102030648
+B65B330AC0E7744C7230D8BD1988F9C750072F89D9D677F3E087BC8FE6A74868
+05DD1C7C091D8B3CA2D593B23BB8EDD2159446D9E826DD030398AE3D62EA2834
+8896A27E343B095D6202528BA2C58D676727C1AEB5191571105177B4F1E8F1C5
+653D62804830BFBCD4BF178A70DF1A14EE96F73038F7C3833BEB8D1BEFAA3113
+1949237E082D4F6A7F68C021B8D6F65084F61554C754A35589C3870342A5310E
+67E85B0C98F3F5060ABC03604957D553F90FC5DAADC5DF81DAC7EB1201C7C7BD
+3C9A52B53D74216E5244082D4B24A6E9D119F956C17E4D17E6A1920B5F641066
+620BA4D2E4AC10DBF95DA79D949C6CC64769816BE58B23D2A50E91C8A9691DFC
+CED29714ACDDE0A2AA4A5E62568F29BDA67287EBFD6236D0905D6725BE102BD8
+E28FA3650260BCD7F8E44096DBD33A76D830A58436E6CD6A496F6B1F5C79CFE2
+C3DE376CC015E02D932BC9191C3777C7EDE1229D9E7D5EB2E5E44B4EEDAB9B29
+B394168CEBC2F4282ABF08F8387D42D228C6892828054A80F487899343055849
+49664B6FDF576A852AD24BC0953ED6267263ED9F72837D547506C2B56D614203
+774BFB3857657D49CBA22C988FCCFD52BA914CF7E6C8A514A9DBF72043B4DAB6
+ED56B47E0310F23F0A3584B764314DEDEFEF2677D65602DDD0C29C92C33A95BB
+4FBF3116FD9557CD3EEF24D8E8176B4DD30FF414130A3F44DABD3D30A024D7DA
+E5C9720E1C9B82EDDC4030D68C7668A8EB567CC78BEAC75D3F0B036928740825
+96E95DED2ACB9E4CB113B912CC6FEB30FC68C7775AE9E763469E7061234BC403
+51A7A17AD09B384E3A73460B6CF69D5DB94122927B446C0B4DB3A6FF8EA9E844
+478EE9D4AC9B542431279EC9AA11A16AC9A4C0A13B30B83AD4FE82077C026A57
+B048A170769FA46D735B6615D8C7848D8DBAEEE82FAE5BCF7DE73AC18EDA48CD
+AA2E64B002C91214A2A784A527D88169C62D731B49DCA9E613556C2CC6C6E6D9
+3CDE03DCE88B5C8D37E7BE8AAEE50EF2B0068D171A4C0FF96F901EE8083E8BD0
+0B108257F9905DB23F39060AA70D43EF8473EC053D5AEF7AD81B5087958B974D
+E2CA39119DAB442E0B0274BDDCD1C0BD1D2176F52754AB2602CB2C7FC62A47A5
+0559E793DA77C6B0823BE94C6D0E95079E487D13A02B3A93204F028B5973CC4A
+1AD9E476461F2A2BC5B8602D0AB6CB603D9A6F4B24009FA9C361B256CFCCA237
+8CBD9A6E0C091A7A2F6B6EACD9DFA2795392DF3B1E1D14B2A32A7DCF8D0A4DD5
+D8B56B79C4A085791BB013B79AC01AE83CCDC0C00C971C327A97CB2F0E7E55B6
+55D80CB0E361EBACB0195BDAF934535E9CA33F834B13DBDFCF5EB71E5E756C72
+A5CAA60D609B4DEFB90FC156BFBBBCAC174B375C6256D5A28EB7D7FD7F8A98F6
+2DB730ACDC04BD58E87A6F04698015AC46A043FDE0682882D72412345E486AB6
+ACD6F2BA5B044E9BD395FE2FD7E7488204EBED26C6C5F7EF1179C5CC6D18A08F
+F8B17CB299947AD34AF2D33DB26477ACB9FA0CBE01EEF447F105F522788CAC1C
+A3539B412647F41D58D1732EC4922FCD3CC5CEE1754DC0580695EBF753873809
+B3BCD4EE5483410C3151E3D4AAD78B57683EFE3690D514192587305EFE935D2F
+D77B2DBAD1EE92693F415603D0723E98F8420CC1DBC41FADE03226DCDEFEFE0E
+FB1404543D5863B4D0F64F6864A041893A9298751E54FD208DAED41D8290E208
+EFACAB9D3871527AE3CCAC9B28D9B1B08935533B8287D90A2B9F7E08225BBFF2
+249ADD0D7651AB852B7C4548402582DBB27529167111B5E30935227190EF5748
+817E859F3D76B88802ABE17ED74DF24D0E560BA287175E3C614BE1C95824BE65
+2572996AE849F08D830473FC7F51A3111A26D551D872B007318637AFEAD2E916
+60FF7CA1E4684455C20E1D627CF89A3765E7D1ED00BAB0EADF403BCD3BC89209
+DD5309DC1D05A1A4BD4BD6B945772B863CEDD6522FB638B8E6548C4FC2322F60
+B113F497D495BF71F985D1A0B280784C32E29E9D4DD35014BE29D3611867EAE1
+7E0692D2F8D4BC242CD384BE4027DEBD5886BAD327BBFBCE0511F0535FFD030D
+748D483526EEAED2AA840A307EA19B3FD0655CEE6C3A925F16E2FAD4862E0DBB
+97EAAACD2EFD85814420487E092F08BA99555A911DD39F0AEFE1981B2510B6B1
+0B7AF374ED7861E0391C94112650DE905AAC7EF92E9E010B38333F65FEA8847B
+7EBC40A70415F0CB15F3003E8B5C1705E2A4FCF3F7718B56541CAE264E122A38
+EDAE23A9A2690A90CEDB2DB223E6E1F7AE9E38FCC059DF6B0013D0CE31A35893
+3C39B5A9BADDED772D5968ADCEA22995E59A0ACF3F886B5695F0533E8378D74F
+BEA1C7B17ACACD2361F7AC0F36FC445D2DFC346A3D4F5B88950EF9DA684FAE26
+2E43D2D05623029213372FFE4039D587FEBD7EE50F9A2609B4CDC05F78D35DFB
+995100EC27271E987D90D2E8EF483CF76CDA5A09A0B7B592C97AAD4D7B7154E3
+4DE7DD07FE23D5DE182AB5C3A9D7DAD4849B7E058457429EE565B4C4AFA40FF9
+78077B5266F65623160C692D066209E6F0CFB058CB1A08E456EB8C62966FBEE8
+989D3AD6D51A81A28DCB4EC5C55AF5C223728557BE8CCC1A811C8FB75DF43A7E
+35B9C83A20C9E94EEA6AF1192097D093F03A4FC3C35F89436393C9853312846C
+E0A9BA692F47E4AABABDC09630634BF94F7253D25B036961B748F790B34F3E6A
+1978882C87D6718702E4251BF144F1D8510A4BA9A265F950C09BB111213E7386
+78C6F174C81E98D54774343C6FF3F54B21DD7097DCBD7EDA23A69CE3AF596620
+79E005ADBF394C0E3D96AA330E2D68A5062643E7EB522F4CDC59276BFFAB8EA3
+760767161EE5412BDDEFBB4966BFFC21D75887B13732B9CCA30211EE73F1086A
+E29A739124B0D0EB7EC9AC78D380063A2240FCCFA6434B8EF2D64D852EFD9231
+8C35BA8C19EED41ADCD2DCFB924072A999995D4DD9DF0E664584DEEED64AB198
+2D5F9944411C7CD31247FE83C4CE102EA6C5F73536705BAB703F39841E382526
+A9F18F3BD704C67FE7EA8EA61DB1B0497436E6A289D8A85A7A903F4411CD67A4
+17C05D6EE36681FAC99971423EDE0856CC9F13D0B931DD6FA82A6FDD8E9CFB56
+3795E838B5EB8C8716CCF4EDE9FD9BFF0D39C3E8D99065E5045CB8F037FCB2E2
+703D973E1499BE0487F2A0E5D758C32ADE9004684A3A576DD2514B703849134A
+3DEEEE8E31514BA84EBB23A9FF63C955FCBD40894577C788A1BA27D9714D7EC4
+557F6940964E91DF8E192EE892E482A53AD81BBB859DC6C3FCA2957974D5C140
+3EA94C9B96CCFC88C5059C863CCCAAF237F53C3DBD7D1903E5ABE3582E0D26E4
+56907ACAD4D56E6EFE2D6CAF5D26502A8AA3DB4D378DB9908BE2E33493DD268B
+47DAD87228F0930C33C77ED7BEA44A3BFE91E667A371BC1720C6C89474A29ABB
+D33E86AE38DA1AA9AEAFA7CFA70D9D720D7AA09442080E1F44BAE5E044ABEB57
+E2B9C5333741D37EEB99CED5D803ADA5C8181761F45B9B18D21F391CCE4CE451
+BB675ACE66159FC6C19853B24492A62DD89C24F399701B60C76081970055D616
+670AAC77F66B0EB583FB5D1F8F48F5FDF6E57AF484FC4C32C67F2A46CCE6D823
+D659733F4995E8EA17CCCF0DBD6204AA45A2B3DD69C47DB7E2EB8B1B8984379F
+35B128224AADBBB3E3456CD547BCAB3C78DC5F55048242F1A973C9D538D660F7
+4E724D0A41844571AD9141CE949F16BF4E5D93A16DAF98DB46AB26DF3A4ED09A
+4AD6A0CAE90FC05117DE2B8A839F03E3EB7DD6B7E26A3E069992E9C0C1F0D680
+C2C302DC6FF5630C82F3E33B2F066A226366280B5C6A15679673A022CCA11709
+331AB13F81F6166F7F4949D9A29C9056C9147F537F889BB84F36547E859FF4F8
+A30B9CE9A94597F764886F4BD4CBD8835C565EFE6AC212A20E02B8F341408C1D
+5B56E7DBD96C4FAC43EF699277DC398086AD6148C71D082065296926EA00E0DC
+01C4AF201365B754B14DD0DC8C039AA68934BA8F00FD019710D68BBBC84A6ED9
+92956E21CC9F47AF37E0F68633CCCED3ACE0F7C559B11B356CDB8F9BD36BD64C
+9F38132B706E69BFC0E312F601BCFD379151D9B5BBD8BDFDB1C9913179AA9EFA
+5956768BCF44984356B8086CBC2F3FBD743B12BA81BCC001BF3893A6F5CF8046
+4718F2AC850A03DA5022472CF32997B526849577744CC541303A1C4DA1FD252C
+43EE0DE89849CC4E2E15FD570B7336E36A182A898F77C592DEC60E9E0B278F43
+6E4EAA822AB6DF0CA390B1D991ACFBC30315D83785254F9F28277E58D739CD13
+360DFD764F9116F6063EF8F4A820D97E7E58E3B44D901B3209A3CE17763BB567
+585ACEB22B4F93254096C3CEC75013D2AC8DA569AFDCB286A19F7A0EFF0FBD2B
+BFFB5163DB87F0F37F3CA7AC66573FABDF753D9CEBAA361D0029A44309C13B2C
+601E79D78EAA1DD899EEF9B59E1F83F04FBBBCF4FD29156B9C10DA4CCF8F1FFA
+DC449BECCB5761D24FED596C9D34B093576880A985993EB40576F2C1952469BF
+5F17C62046B4494D36D84456280884478A09D8FA2203B8F2A6E6D574C3FC4F79
+55A0BB010B62423B767C2086D47F2E2DE9B95724CC6938E2B0EDB8D458B3C92C
+3F3F27DB16C58D321A721437476CF4BBE989E1119619E601A6D9147955211C56
+7ABFBAF46C5ACC007AF4DB6A7FF446AB40527D59888D3D0FB9C3140DC146F2FB
+F36EF680CE68ACE95BEF6C5CF1ED0EF226FFF525FFBB5BBBD3BCAB9842E422EC
+D4284E08E3ECE1B5FBCDB3F536F6EBDCC1A41DF9438F8F9BF10E3BF7BC49B141
+2DD9C623CF65D29EBD67F96BA81CB2DC859834A45788DA0B12A698F5F97C060C
+286C2CFFE0E31FCC409A8DCC570468977E2F3F5FF411A4EF1F20224E64441C55
+6CC36A5438BB15AB826F7297B08D2315718C02B690E3AA2D689D2D8AC1AEFA27
+62C1E4CF3114254159D5C8D894CC50E692CF863E6C347CA86F048C7502DEF227
+5F3E83CCE897C69DB5C3E7C4B7CD9DB0E5B777F4CD86E7CF03B35E39BDD525DE
+A11F632DF68B65D863F30ACE081905DE99FEE687964825C1E7F14511981EC483
+B8897A72E3E4AA3EE892E66895D8C1857EEABA65D2C33F199C3645346B2C7169
+EFB7F8C3D490C6DDCB66B2B212C67BF20BEFF7B471B5AE96E17B920D9343AAB7
+6B109BA92449C6DF6E591A1FC48914B2A2602B6AB1B219E30D022050067565FF
+AFA0F554E5A7140E47C00FAEFB8D547BB1714320149241AAD482CBED45EE84C6
+7964F341A263D447E0605C3F12640C6175B7263704D1884CA414FB718348AB0C
+FB0EEF1189C0304A5DE23153AB7E9C8F9B894F06D04B2700070FEA16813E3171
+8A0053710772A1394B2492687E308D6122DB6165E222167541EBECD68E6AC145
+E1DF1550805C08337B1017979878A4ED5EF85398EDAF84E93EC30525BB2DA6FF
+B1A4802EFC994E55474CBAA878A38339B483FE5D6C85F0C7CD4AB7CCE0E1CE02
+D0BF17A127EA17FC048D19D616CBF282A9CE2BA572DC0DDE126C3434AE270E11
+4FF9AF7B63E817DE371EEF9102B37E69FBDDA4E2789F3C37C6DDA28A9BDB40EF
+4AB5A776CEB1196C25F4C8D7BE6C44FEEFC515677D49072266FDDA714B863916
+A833887224AF788B37DAE91542ED1D95C7BE294B64D18AD2032440B29ADCD4B6
+1783E47CD4B1F396BE67B76BEEA7B6232BA11619B001A4EB5BF988A99594E1DA
+A5D7C27762F704CF92802F4FC738C3BD38B2EE2BF518AB86A2059F8550B6595B
+F191B97559DADF54BA85B472D1BF4C0C4B4F1C3B3824FD295A97228099DE5E6D
+6FFF4A97107AD28799EDAE4167DAACCE7571D6DD5D38B11BA7DA7B18334BBF94
+C2360EC14916462890CBC982C3B3CEB8781EBB045FC3152258CDB5F6EC680BBF
+7D0C1A40D817ADFD9F2C33F466F1B785673725F2D4A0DD3DD53504EFD89F1433
+6207D0630CC3B3B03E7EF02307ECE3FF85E0E09D1BE9F1557A5DB22B3AAD31CC
+8DCC461A6A10C339F3AF621E6DAC
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMMI8
+%!PS-AdobeFont-1.0: CMMI8 003.002
+%%Title: CMMI8
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMMI8.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMMI8 known{/CMMI8 findfont dup/UniqueID known{dup
+/UniqueID get 5087383 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMMI8 def
+/FontBBox {-24 -250 1110 750 }readonly def
+/PaintType 0 def
+/FontInfo 10 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMMI8.) readonly def
+/FullName (CMMI8) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle -14.04 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+/ascent 750 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 46 /triangleright put
+dup 47 /triangleleft put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CE3C05EF98F858322DCEA45E0874C5
+45D25FE192539D9CDA4BAA46D9C431465E6ABF4E4271F89EDED7F37BE4B31FB4
+7934F62D1F46E8671F6290D6FFF601D4937BF71C22D60FB800A15796421E3AA7
+72C500501D8B10C0093F6467C553250F7C27B2C3D893772614A846374A85BC4E
+BEC0B0A89C4C161C3956ECE25274B962C854E535F418279FE26D8F83E38C5C89
+974E9A224B3CBEF90A9277AF10E0C7CAC8DC11C41DC18B814A7682E5F0248674
+11453BC81C443407AF41AF8A831A85A700CFC65E2181BCBFBA9B440A6DD72BF8
+97084C906B05FAD969086ED21AF0AA1471613182B26117D7494DD9F9270EF3ED
+8DA4D957225F75D060237B6DAAD5A0AE3E702B3D1C437835B93B8AF1F9E7D966
+E739CF3AD5E256F90286A34069E5BB4122F94F18F3485658D0D25B938522A879
+8215A417CA2CBD20F71C5C5FCDE21EEA7BB27876D93BA667868A419287FE59BC
+F538980597DBBA743DBBDBEBC61E3286DA7977833DC8BFC5E52FF5DF5EFD9A92
+D070EB769E31E760A50FDE012DC0057835E8B9B046FCC83F1A0C40326AFB4E3A
+0CC3BFA35FCC64E32854F32EB7DF10A19F95830136BBB8139DE1663B7FD790CE
+464EA431AC109FCA0E03F3E0D355FAE20AC8774D6B1CE233C27680C77DDA7356
+560A27C75993E8C980CD1E3B0683F7E8A05119B3AD567DAB4851B66E418687B7
+F9B21B3BEF607918D5973421B68E65DFD8B6C8DFDCF1CAFE2637D365148EBCE3
+FA4CC00052A2A522205EA3AE3461CEE02042E1A3F11467CB6C8C849B200CCE3D
+0BC188EC7B934CBBC0AE2BF5DEA228181DBF0F774119F313516E7D97FF532621
+9278F856C166CA6547504F34991D588A0631A5CD06363F3FEE9FA0772C783447
+ECD0A200929CB58EBFB6B72008E4082B5D14AA560C24915B9463A92F38237886
+C35CBB2D4DD6D0CA8C1D4EC46093041C6181C2F6586EE3E7D4E647A107B6DB23
+DAD9AB5A0C2905455FE58075EFF6B48597078BFCCDD84812B98986F34987CE49
+7EFB19814F2A58B0233A59331F6F8EB66401F04EE7B1ECAD9BC90A2BCEBE213D
+DDDB1F75C83609ED6A669A0CED58B2E269E76ECF73616D94F13CF827C9BF354A
+E82202988DCFE856786B8AE569AFF3105B55C72C58D310FFC0E10B2ABAC8DB06
+40D5F72E54770E9DED1AF4616008595B8481E3D9AF4191CC9A5BFD9DDD01C9F1
+FE7165D21E488DB40879E863D470CB31CA06E5B5F1F8C3CCE04B697CEB0F3557
+ECAA358D2EC2B370519CE06138FA702314BA01F1F33881825EAE1230098BB3C9
+59666983275CA4E8D9DB34979F86535577E79393A72F84B0F768FE8C92692907
+15E9FE9894E98A0EBEA490CBC8C7E5A9F3E43B24C2C5A4BCD71DAAD3CC0B8B82
+AC13933543E295C163F61C9FD18371CB514493F90BF7FB460C029B8DD2E2BF05
+FD66B451DF277864DE1EE42100BF29E01A50258C2758F3EDE211BB3457B8243C
+20BE72983FD6FA2581C5A953D94381E32E80D6D6095F2E93A5455C101BA71E8C
+E560D4694E4C167EFA25FB1E9D214AEA745CE34CAA5468FAEF8F6BDB6C6BE8F4
+3D58836C26A2392E4C4DECE284A90DDB3858A16D6135FED655A600929DE71605
+6CA32F6851A2A6F71A9DF3D5D657593BB729CBCA2F4B059365B7263DC08AB211
+9C547096E6427F6AA53CB2EB87DF0AFE2ABCDBD15D7EF228D3396413B83C6B4A
+79E41F9BA55A2688F62A10472675E5658F151F9FD6634EC94EC0682C17448024
+CC1633077C07A93E4DA8749D974FB8F4332B5DECF97D749C10DB60D4C90ACBFA
+E65AE928C88BAE19234690EEABDB30BEDCEF2660D7464D5071058C30C572A2BC
+7DEE5384BD7614A4BEC4C84E18CF7EC81C810256E8CE6520466C033E2A36D3D3
+5D6074B3857415011D8D9D49A474D994571CDBB89AF92BEA879BEBAF67663F5C
+17ACAE809C2231EDD0A76641BA52FA7B19A2798D54A4A9B62C42F9905851229F
+2CEE0191C8AA5AC12BB0CE9E5E3E862683AB57DBB4AAD6AC0FA8BA4F408D41E0
+755F72B82B7C18EC6B13995BF7AFD66AF4BA0EA7523DA8B75EE751744EBA9CA4
+4E8BC1FB37734503A5B24FB9F2C2D07A47CFC477F02413D55BD7DC180B0344E8
+50248801FA6BE26C97F397797F5F9DF762967E7CD92CCB8B2E587C92177619A4
+BF8046CBC72C6E69DC78B8CB6B7381A290080EF59F5B9F29C1167B261C932E9D
+010D2D14BB425D157F22BC0305770AECC5BC80000F8CCFB9930255A68F299ED9
+D3B5B83A2CC00E3305EB281E1A7054734661B175C6CA0AF168790985F173DF03
+A8693B677BAFE23C3CF833FF6463B136FC370E4F0C29E322DBEF637F62C33CD9
+B0A8338FD67EC628E3BF2FCBF7CF0347D5CBA1DBE6DE878DD670176B85F69EF2
+3C5CCA1BD2B8A385F113EF1CE522F5A6AE053B9C1E39408C9459DE3E7FE2C4ED
+77F026B0081BB80D40185458139C16333EA27F43EF1204BFBF80BC5301B2A3AD
+B10F7EFBB4F5B7E04DA1167F68BB6D4049440B0F57385FF0A95E72760C6A12F8
+1335BB31CB74081FBAA319180DC00113CF50CC5A41D2E751E055DA1429CD75BB
+0060C21CED634FDA106C49A12B356129D010E29F2919301AA7F80222AF3905ED
+672FF85C9897A70241E8DDB9A53034B6BB44E140D9E739848E7A782F24B98AC8
+00DA09EBE4532787E5CF3ED815705F659D8E52DC2C2D4949374A3BF192BEEB99
+1D9A90A4F3250BF8A1FD40D91F5B34AF2CC561FD02FED712500B24330D87DA9E
+4AA46B6E34BCB40B1F73A1DDE07E002B9478E9651D2BF85E67585B6ED812BE03
+A594874A235B1C1840C4BF4BA6D863583D8C12DB49EF7F8CC24DCBB6B21FBCA9
+378F3E2DC406291AB324571F76E0805DF8826090F0E8B50599CA58D124653D16
+16C782B01C91A6F3DA6346482E3163D28D95EA49866360147296838A3FD0CC53
+920F91D895F839CB61FFD2FBA296CA4C6304EEE579782AE5FD33D0FA652BA7E2
+CEC7C01DD0D3E0D56E6177EE5F609A396F7FC8EADABB465DBA7F384E215C4DCB
+E64F807A50A461545107F9C3F7D7CC7D33E6EBD6D9228B1DCBFEF160703E6129
+0DCED8D45DD54E2A36E698A616E7906A50901E453BDB2A363EB77144E9EA6F2B
+6BD927495EB0EBA5755165707CCFBF8759CE5856881117C7F3EF6D494EDDA7EF
+E499BCA56C86467AC573DA9C2724FCC74BEB331E736FB093DCB67DAD42296655
+415D110F2729BD1D55E5C9CCE2E724116F45FB2E66AE0F790258851A5C808762
+68B8A110BD326F8D3EC45004E7CC08DA42F6CB80A6B6E7C286F139534A275BCD
+2F812993DD9C9A1AEB5E7E4BDB4805DFF3A7030263AB060C9B74F0C25C5B9005
+965284884450CC2815DF28D5F9B0496DC7A3AA85E1E42741E1538797175C28D9
+FD904699C771FB066397FFDEE8E8DD1ABBDF67E6BFEF95BB700A7C1BA91354C5
+42EC3864F6E19B379E79A1CC3C786C0DA146C6B0B8E507ED58DBB1F12F613A98
+0E1F8967991427A22ED323901C4B83336CD343212131E8B59C2F5D232702ACC5
+7891BFD4EBA5D0FA35AEF9F3520CA82D121BF6885BBDAF15248A9E4649ADB94D
+0735CC4D14E1D7275427D00C8E709579612F7F74DB6FC218C10C278CC63E2AE2
+37EC996B10C0229D687F0DB5E38A8C4DAFB3DD8A9E7ED37186FEFC97790A1EA6
+636A88FA9FB4D282234BAAD301A1F3AD33F252C5EEC49410562FC52809CEC466
+A0F6D148E9AF19D6DA2337C8283FBFF6005C37AAEB0B7F7217A8DC6F949B9984
+72DEF163E4D5ECE4288404448C96A7FF0AC76F732D50AD63A1D286C9180E80E7
+C218B1F48E3034FCABA6BF262CEECC284AC29E9F3CA1CFC1639A681ED66C1FBA
+666F073D45C84A286E05FF809D4764FE819B6A330E73695CCF2F448B4D4EB4B3
+F63E94EC289807A2F9A1159CF328C002B467B19D6E9454CCE36FC19E0A214190
+B251818DD456EF658B0398E275514B72D9C1DA5F806EABCF1DD56BC025D69FC8
+A0C2FAAC1892B64D2AF79EA2F57F103CA623E440307600D50E783FAA998EBD40
+51D23A0CEFF8D8649B48B982DC38D613F882DCCAE5F51233A641B3CFD783F830
+D984F116DEA3ED8F0D3369AE629A006BAD4523F8E3C7C6B39A6C972508B67AE9
+32613F28CCFFC4BBC86CF31A0C25C786554F7A1F3DE97F5CFD1A941F775067A4
+784385E2D02EE1FF886701B1E87D966D3F500E15591A5012E645837FE2DBE3E6
+A3D375C6CA0ADBF96B33EC3FCFFFD888D7344B31D40427B8A8BED0FEC6FBE038
+1FB5F0714C4B5A0E607E215B5B7F76ACF0FEAA4C9790EB7E13C0E3933B7C63FE
+5B934EA34F4B741C3667BF1735C685CECA63507E6FB9EB06AA010311F12AC1AB
+4CE3FE8D1EA1EDB3C700BEBA516FC71D740B1CA1A60D4578003973CC3EE21DB1
+58FB1CF7E2EAEB2A4A6C742EBC3575EE6378531C6EFA6E6986E68B8E25CEEA67
+A59623FC1ED2ADDA9D72DBA627D179E47DC7F5551E07EA4D54ADB6CC8109D340
+7279F288E552EFD79C17DA3431E53EED66D16F24BF86468C2FE7EFF421560500
+12FB048D6CE2F370BE4E560F8B4AA12362ACFEBC839351C1D5100C625B14CFDC
+747B66082D4AD5474A63EA0054E9C3E6295AF6B133348487B0471395857F4B73
+4BF8337DCE2FE2E1A4EAD7E7BEDC822BDDCE42B79B308C11897C98E3ADE253CD
+09CEEEC0CB1DB66AB072E36E1E04911F40B535B0FD85982C21B8A587D65C38D2
+DBC5A07A0A26DFFF7460F10781069490AC1B611CF7312A14B4AA6005A4582C5D
+336BCC30EB47749193BE8D457A43F54204B070DF5AC2057B6437E23705C7FE8F
+7BB150560F7044BE3E48EFDDA539FEEFB0D2A7856CD4E405FCE0F5EB190D91AE
+578E2EDEB9ECA218573BB1A8EF116043A27DD17A4047BCCC7C5F3C563A910778
+45ABCA32C7347E6180ACC86F9D665FF025DD8AF514FC3724B5C3510F3C37E0AC
+5101D1667C6ED4E8F37F06CC2BDF66CB5A9FB7C52CAD26344FD1557571336A1E
+1E340EBA149B4EB99016D1A411FB874914AAB2A415CE3F5FDFBBF5AFD7959B9F
+CB127BDC68D2A2F3F07FF3D4FF32046C0371CD2E68A6471E46B08413FC3C7A80
+A107EEE57979DB387B2206D2810DB310B7232B2DAA385256C8A58964B512003F
+A0C24ED21809E2576229627278118107B9C32345C1EE8C0CFB452CA362379369
+31320DEB5371037AFAD093B61E8AC7A6DCF7D49C7F8EC32DC0ECEAFD7E892810
+039570D2956289B15E078C2545911BF535F72F7DAC619BBDEEFA855BBAA81704
+18F7D351B0936357085A32157AD8E27438A58B2397D69264E748B0B8D01B33F4
+D04DC59326A7DED39E247A1C1A1AE49382BDBDE9478A1CB48F88BDF14A268B40
+A40B9FBFC4C87FD3DF1EB2464C3C14E36CA41E09EE0A9B75FEB0769F9ECEB1BA
+EBF73B818427FACDBC33BB95B9654F31C59A766E931C698A8608F15290FCDBD3
+5C535D9036A19CB7B55BF54E96F9B2206DC71624E2E55FE632FDFDEC8757AEA3
+1D83D190ABED5E7A7AAE2F41FCEBC7C18626BF58F9E9F02FBAE0C8AA85E9DB21
+A3D8907522DCBAE4923C6A2A09FD2F08FE32215C544AB577B337D929E625E704
+E041C2381AFCFEA37F3133B6CA20093EFD457C772E428325E56C9CBCC447EF9A
+05A8C3F28017DD4FFACC51B38E4896C5044266EAB4EB7C13FE855E790DCF8A17
+B61B1D30DD866BC57397EF6297C4891451FD6A5C6AD6D7446F58F56A68650908
+224D9F4C31C6906FD29BB51DC947465B808438E6260325752808963C808A4AAD
+60422ADD62CAF315F6AE92FACEC55D5B682089AC0BC051CE1E2C06A3874736CF
+0DB5F7C8F178479E4F11665402781D80397C75456F5CDF0A4F382A19EC6AD64F
+71A9275264800E178F212269154DD8352167C57EBC0A38BE794AAD1601C8E541
+7E1AB8E969A76E1EB4092644958FEA2AD29635E70C4DFE2EB0D9B3E1644FAAD9
+B27AD5466EFAC724718962B62E7B8C32F412B69DFFEB792587D571FB5C591D95
+4CD441662CD1B07595E245FA537FA9EB5A20A97E5C9251EED22C9961B48B25ED
+85BB7524F635F9CBA3714C6D60A6BF920C45A64F4C366C1F9D22F53084997C9A
+EFE2D79FBE3347111F5093E271DB7E3770B35D253DAF93653F6A23FA145AD775
+AF11E188EA0428137D9A14542E3EDA6F7B2E5AA86C9F3D3649A85ED2F020C696
+01A339FE6D7E42BC548C8F92A4E3809C67A986C99418772403D16D0E8662595A
+1F37563671D6DA0F36CAC99DAA8FEA215DF7D45E61314915A30A22FCA86A50D5
+2FF2EF08E240F9FAC030D92BDFBE40F1972DF413E6B452024CD11792BFDAA2D7
+C82716528AD4B3D637BB43E748336DCC86A952BE96F1EA423E31340FCACDC1EB
+02EE932F58734AF3A5B2279361B63F1D824EE3BA9F4D2EC7B33A300A1CE8CA43
+24616444176DB8099D85AC68329B1F85E4B5B16F3B396FE2AE7774F3065D0203
+AA140DC128D6F935C44733EF585F89E8639A2096A225A2E5E49D447D8AF9FD44
+CF6C1BAD5C5E5262AECC5543EC8199B00B72BE32A0F110F64A1D0D5CCEF38FD1
+155D6198E9A343702F8ECF5052333272CAC2FE016681E12745CBE14E1065EFD5
+407DA3686080989F6F6D650A9F1EB3A813B070C30C0D3B4A1E9C206E2E4DFD51
+D8DCBE9AECF956640A2E79F1B4FD0EB8E0449AE1B8FFEBC43275743B4D7F6605
+0673B61EB3189E74F51F3780A91E6A5C6464C8CF7D563D9958D46F39B1A12087
+6BBD4898BA9ABA468AE1F24115891FD3CBC2195F75958E26DF8BF1B93F7B521A
+C12112237AB23A8E5A7B7D0DC4C53692B35F3CD813EB463C0BD3A6486B0476C6
+3B36DA71FE512E5745D097FD4AF5D056E434DEE2AF926B2EE79F7FC4FEFD4130
+BB4B4BE01E5C720325A4884507CB51CBA4FFB615B78A4182444F0ECBE4161A58
+E86FE1DA2E39C2BECBCF1F1D7B9B776A26078FC252128FA8108CB83F673CFD37
+CCDA493234FB93E1550EF8D2DC049ED95B00A8A57834B024B277D3DF062E748C
+B61F183F2D72AD075474F8165528CE75E4F40B38B0FAAE45751C1907F8D31619
+E88EAB02EEED415F3EE3BC5BECC6AF565D34E0BA2958FF337A2B06012DD1858E
+C53DE52C108BD5AAB76C882198C72CDCC958D68EA8FD26F76F04EC1A08B2AC3F
+A6D0E8724D2656555DBC0C8C42A3E22ACA7E1BC8E9F897D9AB692E0FB9EC32EC
+59E31CCA4516A3C3BFD5411BAC3DEDCE374D48681CE7D67DEAB93F5B5C5290AC
+FEB29C5EA2C98095692873D36C7DA24847B66F31E4CA4C7AE5C79D7CE4F0532B
+78620582E3731A2A6533A03E7155B33E7CD142FE79F72721862EDB24959B9783
+F834CB616FFCB2A23497BA6D99AE34DC459A2F7B3E4DA2B54BED118ADCD92178
+66C40F4E60F6E1327D5DBCA645A2A7C770807E6D7E47E1265C753F8793BD2D1E
+BDCD749CC24D4AF9315A93F01180A0F9A7F420DA1B87664DA5FD967131273271
+9DCC45C3D57EB9B8AF14771E8E751D88B98D2FFDC72F5011D402EC34FD010ACF
+D3B0660304725191D64FEE106253FCB3470F1A16EB7B45C1489D3534BF94F740
+C2781DAFA5E8A9E7B25A85BD7935DF3ADDE08C960E283D8FC3976FDB4085DBB4
+B6B35FB239C28C785B18BE4FC98F3A5F410F562DB5FCA04E8074E4E790F4265E
+F88117B3D0833AFAE6E8B8A71D7731BA6F14FD6F217EDA3F8CC687A494FC3914
+B84FDC37C8C335AB1E7E0BEC7FB6B7A595C50CF8F0080C8D461BCB8B579A5155
+F963B6587873FA31C3A6572740C63EFBE58A2EBB723B7517D2A243F6CB08A038
+54F4DF0F6692022B2EE8C6F6B73735ED3166BAC58D9216A06EA6FC7B63B20031
+D0F0F99D83D9030B413C2360DD2C553E34BD67851B743C3FDA676AD63C5BD759
+9131358C6BCDF05FCC048F4EBB9005899ACDD8E9EC9BB8C5A08E83485047D263
+0ED69B4D1869A38068FDA03524022A1D32FA2AE0BF728D2A654E52B6A6C90A3A
+725F86627D7C3EC5AF5AC512976D35FE42AACA3FECB401788D0BFFD9F4743BB2
+EC5B4E7891F216DCA5A69E917A171E0069A03FB214ED307DE947225049D46E0C
+4707503F09811A597A9113921AAC23AB1CAA9866F81A02BDF349FAB129F23E86
+E384C043053055938D42ACBF9F0EE86CEBEB011BD5BB7D5930759026189A89A9
+B624BC5B352DAD55CFCB8BE6CF6F215CCF778E33BBE1B009AF1164AEF12E6291
+751E80E442FCEDD8DD6752CBE0E64AAE1C9C5BEDBFF946CE8D7834A341ACDE6D
+3744C8A0C37EED863F57BD52BB891022295C56FCBE4123D95A13DC2981E906AB
+3A0E488D716B15D8C119353B99D6F71407DE884477D5C0185FBE439F9DB2A096
+6A4471E9486865DB9F8916785BAC2F6D68C48106F8C627E0A4798B1D8D03C824
+2BB8050C1434241EDB339EBC59D4CDADCD043B5D746959298F2C5D76D4A57059
+3843A6981E6747DA2CFB54F0E39A144C4F7B95B1E3F1F77E0BA2DAACF2BDFC77
+B10AE7CAD85CA900834C28D00F5D710A955F0802D7082362A4B709A9F2D0780B
+3DD79EB0AAC51F2BBD695A035880D43735DC093BB8E1F201B48C7E62BAEBF384
+C6FF853421961C6FC140123CD3C6EFE6AFDBB990A4F57ACAE0D1AB11171033C0
+F3A18AD4E1A6D27E0F5825FDD93A97E9F01F899BC6AEEBC0
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMSY10
+%!PS-AdobeFont-1.0: CMSY10 003.002
+%%Title: CMSY10
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMSY10.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMSY10 known{/CMSY10 findfont dup/UniqueID known{dup
+/UniqueID get 5096651 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMSY10 def
+/FontBBox {-29 -960 1116 775 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMSY10.) readonly def
+/FullName (CMSY10) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle -14.04 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 0 /minus put
+dup 15 /bullet put
+dup 17 /equivalence put
+dup 104 /angbracketleft put
+dup 105 /angbracketright put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CD06DFE1BE899059C588357426D7A0
+7B684C079A47D271426064AD18CB9750D8A986D1D67C1B2AEEF8CE785CC19C81
+DE96489F740045C5E342F02DA1C9F9F3C167651E646F1A67CF379789E311EF91
+511D0F605B045B279357D6FC8537C233E7AEE6A4FDBE73E75A39EB206D20A6F6
+1021961B748D419EBEEB028B592124E174CA595C108E12725B9875544955CFFD
+028B698EF742BC8C19F979E35B8E99CADDDDC89CC6C59733F2A24BC3AF36AD86
+1319147A4A219ECB92D0D9F6228B51A97C29547000FCC8A581BE543D73F1FED4
+3D08C53693138003C01E1D216B185179E1856E2A05AA6C66AABB68B7E4409021
+91AA9D8E4C5FBBDA55F1BB6BC679EABA06BE9795DB920A6343CE934B04D75DF2
+E0C30B8FD2E475FE0D66D4AA65821864C7DD6AC9939A04094EEA832EAD33DB7A
+11EE8D595FB0E543D0E80D31D584B97879B3C7B4A85CC6358A41342D70AD0B97
+C14123421FE8A7D131FB0D03900B392FDA0ABAFC25E946D2251F150EC595E857
+D17AE424DB76B431366086F377B2A0EEFD3909E3FA35E51886FC318989C1EF20
+B6F5990F1D39C22127F0A47BC8461F3AFDF87D9BDA4B6C1D1CFD7513F1E3C3D3
+93BEF764AA832316343F9FE869A720E4AA87AE76FA87A833BBC5892DE05B867F
+10FA225E233BCFA9BB51F46A6DF22ADCEACC01C3CD1F54C9AEFA25E92EFAC00D
+7E2BA427C25483BA42A199F4D2E43DFCE79A7156F7417ACF78E41FCA91E6C9EF
+B933450D851B73A6AB6AEA7EE4C710CB5C14270D1674FA334686653793FCB31B
+491E870D3C2BC654D2C1DE463EC9BA29D7371AA1078800EF93D3F66263A2EBBB
+F5723697BF7448BD0D2E301544BECF497FD475B85DFEF52AF4F8F8BE445CABE6
+019318806D10C5952157FF8F8286C1EE701545C8F60EFA854EAE66835A2046A6
+915D395F1E0366EFE0C0391583FE001FF16D82A2E2DA5F57754A2C6F69306E36
+356ECF8EFC3F1188AD6FCD2427E0580C97A5B69B4E0E09B85EEDE142F5ADD2F0
+5DE51D6DB72B127412A0D57106C19CA493048A4F815129ABE767D51715B1515D
+9C21067CB5BC88741B7298C83EAE36A866DFA87D8981F179B1C31292F56BBB64
+3C430779468AAF07C8A8B4934E1E775FE3F35186BD1FA6EE3689C1C750678AF1
+FBF9B23195A124C5C991FE670AC0C86FD39D2B07B9A319E74EFD498B45820252
+720ECDF7294F7B0B137CEB86D33BFCEB8606985A3260FD669E461C8BE94216C5
+D434FD8854F44EE66E5A289A9F9E32BC36AF645D53F96652602BAED418C8D726
+BD04A1B4617551FE4DEF54083D414F7DCE004E6BB2DC9C2EF7CE232B254BA2C5
+7DCBD36C2072ED46FF711F121A701E2284BF1B718B3164382B8F453D68FA0377
+DFE106503B8401D4DB87F5402A3AC9A442FA060B0610A9524D530C7157C26B56
+AC970FCC1D5655FFFFA39246E6420CF97D08ADFB7B05822679BD40C638DDF0E7
+A97BFE8918B611A145AC965C203F1428812F9D340AF499B3A915B22BE798594E
+0F520109FC81E452180AE45B170FF999C5FC2761C6CECD8742A5A6FC97F16743
+AD4EFCC6572A6D3F3E4E330C5CB2FF6FEA48A5B64DD3DBE943BD9918D4A18E18
+CBCF598AEFBB6AB3CD2CBC9BFD6099272F6543F3E532E0E21E614BD2880B1023
+0AC234CB705827BF016DB84E00E8C255FDEFA0101A842929540B7B4AA8A089BD
+5EFF05B72356B6BC3727817823B5CDBB1B963103000D7F2A4E2A1472FC3E614B
+5CBCB6D6D784023173DEFEBFA8F9ED87EC1A0A9EE98CA59CFC964CF943DC683F
+E9E00DA718C4425A705A69D99988EC6F152525C790912C2E46A2381A569424AB
+54DF4798BC2D7E7A361E7991641D4B756CE2A7FF4A2848927092C59C2C4B8809
+E13AB84FB6B111E680D7FB9F2FFC2C5C66B0B501E4447C2E46C10E2F6124476F
+A140C404CFE2DC9E0199BF61E035CEB481D438139A9630934E541D261FFD2906
+4CAD99E20655FA746AFB81EDBB5601F5FD6B1D6832A01D585E2C55053F6A7378
+4DAACCAC7608DBDADAAE732D66B3E7F87E79756337C1A961E53A4651BE7C77F4
+038B89C87F650C54A2A90EB7F1D525BB353F33318551EE8D84A6A83C718EA5A4
+B2AC0F7306B1E095819B87015A90CA3ED739B09061782C28CDB36BA4BD5E5308
+5CBB70414E4112193DAC4A1FA30996327230D1E021F3CD8115E12D239D93FFDC
+B645910EB29E40D830E7BAF2DB255FD7C4E776557BB38157917D993EAC245837
+A3B515147043574157B8342D829C7228CCEA843ABC89D1785A9672A5923FC4CD
+2F3FF27E6FCACF84E2D3136CA2C0FD3EF1EE7354CD04C38B5FB874553646ED2D
+CEDF7E362EADD04B18051F20A8FB0DE18E152385B9D05F98A3A7EF177824E246
+455ABE69E2F700EB78185CCFC07E3B4C6FA301112528D977367D30D0D5D59EDE
+FAEB706DDC970A9E296236C725B2B55B09B9C336B8E23CBA5FB8692D56F33B03
+16294E5FC7FAA42E96395A57CE51CA8DDD77442F142E2E576B778373FB31C81C
+16840BB422CA827E30A81829648BDF1CA36700EA32AD888D097C1FE0A05B2D9F
+483AEE40269DF09AF0D1AD3DF80C45DDC59C2A03FBB661C79B87853737C6D352
+67626B657321B16198DBD6DB98A092F17878AE4698121E1006E53D6F9B0A3BE2
+3FB68828EF854A0CDBAA68B37ABCA6AD4A3D809AAF0BAB1697A81FE59C98C472
+1E33CD70A75A22C249DD11D76C2575ED3370A25892A16D2FD569CDA70C130770
+93F493C7D47D6F9A5424A7A542BAD726BFC3AB225DCEBBE6AC4BE006F8C7C0EA
+051424B08305BF2D951AB2986AAFEA04E078CA79B399585BFF0F1ADCED02E15B
+8765EB6BF6A8E4D0901EFF2C3AA104924EAD9637A35D877E0C51A3C37DA78CD4
+8643C8CE6DCDDE3F116A6C2390F948E5371BEB5AD2E87B41C5F01FB5C196C436
+6E256A88D082E3F46E4EFFBF605B2EFF1E9D9AD5EE4DDC323A137CD9451EDEE0
+06F7D82898D71FAF2362C0FCF1F726F97F820305B7CE20728CA08C63575083A7
+84BA28B7DE2B916432475510E274C12FFD1660A717F51DACFDF0A102D85224E0
+D6DB607BB72569ABB8A7BC6A10354CBBC01732EFE35B72062DF269CB25EA3DE6
+DC603B04C90C5912D2C38D7A5ACDCDD3F6F116D884F0D8C528F69D5D47BA20DB
+0A9E585C7D8CC3C324FE8A1DF150279F7E8FB43BDB720E624E5E9918032C02CD
+8020636AE5C38DA2484B7F4B34163E0D0A561B43B80E97746DC05C871AB620EC
+C5D47101ECED4A7E25F291184BEF8B80024AA7BB456C1B83A907652B331DEA34
+754226C39C6889EBEEFDAD081E01EF8FE47751987667836FDE4C8BB8A3FD4406
+1E643B4EA37BD370734D1A2DB17C2F4B74B4ED75098B433601F75A88C9A37A05
+CCB157EF6E32023BFA33973F3E655A4D58289136996FCFA61EEABD70791B6523
+1FF5DE71AB8A17038923118A5EED8D59C4C58D246FFA9BB26472346B40C8741F
+153D19CAFF20DD2A86C6DB89154A630FB1761929FC3F0448EE2F089C1C953E02
+905BA8DE75D101A982A611056C4B237596C10951DD98BAB838B742D3CF7DE718
+617DB72E5268583223E37E029D1C8FD3F1D21690151F76B76C52C725CA135CA2
+8666553E863CE188BFC9B99AF56AC2DB5BFEBEB12FB563D00244EB89E478657A
+98AF2E1223C1ABC25A4500E8119B86EB3C26B8A2F3505A3E5610F89B7C34E278
+53FA0A54A7F46D84A35EFEC36AE660A9E3C37EE3864106702DE5AF6C45ABF64B
+888A4A51323138CE77DB935576FE6B4824B6942DF80625098CE1B5B32B234F1D
+052A9D6039697118A9D793793775D8729D8574A2E74D7109C7B7E23BC5E2E87A
+CA8E019203952A4892544E1AD3D4EDD22971611358AB230E9A2ABDF00A288501
+A01B67C42B33F6B78C39562DB50F4663B922D9BE0D8A150311AE44B83C1F129F
+07337323E9A23211EE58E16043E127C6F9574019179F5635648A011266677B56
+B5D0201A4E1470B952A1579B57AB2329CD4C615395023C653F784D36B5EE3672
+10D191F29EA508CE84763CA4CE7C2C5229E38E241255A5CABCD6C7CBAED901A2
+CA53B5E24111921CDDF83578D33D463D70EDACA0E470D8F592303FB6BFD68B4D
+3F3BE2D7C5EC8BBF10C90111A33E205F2649B56E8443F6FAA6C721C66575AE12
+D4C40F1F46CF9E9DA675AB5D5840D938780CD9E4AD6736ECBEB6A4397613586F
+849B51048AC5F9405E03E14540A5E5582F61CDCDB57EDDF95A8C6705F433EE16
+648F098C03DED8A2AD94AE3DE202D629B9422ABB031318D48F2C85F9DBFA17BE
+84708AA3B6C9F81F4508F7A5CB7B6646AB8722ECF817877B77D473F577556DAA
+2BA0ABACFCF5DEA7498C47328E873019A956FBB250FD9D8885D21D368FA70CBD
+2709D2DA44EE7A9869963EAB48789541906DE49FAE785ECE1F18A22C7E7ED204
+9768896B78E9EB7A2BD6EEC1B26083940656ECD689D92942CC8AF05CBF82AED0
+B45A7DF4DD7AA6526FB597322560B9ED3087A65B5EEF1371C328A021411BFE3B
+D9B5088B2F1AAE381FFED52D2D1E02CD0DA78683E3B06171CBE94BE9760005D7
+135893D7CC2DB097F6AC664D9594CF1C650F84DA80D2EDE04802DBA33CE3DAFE
+EB7A37E8AEFA4FDA6252FF21E8673DD98E67124D5DBC7BACF361E57077B71939
+C1D1FB923E4E35C075CD1BCBE0E80DAEA1320D55B43EAB45D9B26C366B278782
+7519FDC482D98839BF0DF2E7C3A56A1C1A3FC0E57A75CA414F6536C1FE8EB7A0
+4ADFEE3BEDA0F53BE8CF5F64230784A797133E8CD46BCCB3BF38BCE38A73CCE2
+9E073ADE792F7128231DDD1F63E6156ADB2609C200837C2E8A2D93D2A7BC9171
+050C709A71E44E32B1B03C92EB5CF1D3BAB1C38E027DC4ED9AED633D98CD7486
+3F773ACF8AE332631CF2ABE6D606607593FE862ADE31803964E3F4DC3CE3A271
+C76BDD95C87CDB3B87BC26FC7A16D567EEC62E6FF0D471B4853DB8A94D4CACF8
+843824F818083F10E88D52FC4253E8203292CB40F1414AE7E51DD7347007C342
+CD70E8E9F2D2A13D71213B841DDEAAB208AD9EA644591C15DEB084165F9DF24B
+B91D3BBEEC2E34E38EF16A0C3F00700A7BDCBBFED2EC0D09601AD6538288DB50
+3478B051B5E16B604A0341FE621A58718D960D699D3FAD284310DCF54EB13175
+19A75A539EE98E804AEA24689D3540F0F12951A3C01FACCE9A7BAF4D0DAFA946
+FF65A4D2A4C39969607272C6886F44E90ABE27CA3A1F12A29D9B32E60E8E34F0
+17C5FE43D0E69A99A922D98909B2BBCD145E59A5E7F5426B3988F73B09A525F6
+8BD4915663C1301323180E760BE81CB874B020FDA3AE63340E4261E4F3E4949B
+CC0966BDC4426190BE9F5D77F76A72AD925662E5FE1CEF9CCAB68F0BD33DA003
+F11EB91AC4502FBD6AE48DA0F9D07C35B96B103E379B8A83A05FE728F1716194
+1F650F75BEBADB2E3810388F3E2DC7B19F1BA9E32925F2FD9F19F4E8701F3E4E
+4069125D7C401144740691E7A460021A47B1E27997FC1DDABEC5BD0EE0B20194
+2D579C7D6727AA124083242BDA46D8E116E2751C5F298851A62B60AEBE82A929
+9B9F2492BA35690D1EFD16215B8EF14E7A3803B93C28FA41D971B05B6AF3B593
+E74AD1E68A5FCE12A86E63B78BFEA87D3949FD164F12277A4688BE96356791CB
+8671C49365608F3EDECC109321AF92B4C29CAF073DA3A7D73E913D0D83FAC5EB
+BD884D4C686056404DAAAD6F82F94F803FA1FB0DD8908D1DF08FB87A8BB83027
+04DE0CBB1C6FEB6B517FBD7CF065120079E608CE41893C2BC96A347826CCDFD5
+C69E161217F2127A59F1A6F22037641613F191F22D5B4CDCBCC2EE5615623404
+ABA7BE6C5FE475481615B2AC1A2412E54688DD21E44CC9AF5F16E634AFCA389C
+4D740B7B51BB141BFAD1080E7C726C1606A28ED492E6BDE9F800EFACD1513909
+84E98CEB6A0B7A2A6F3E1D1DCC3B2552795E0932673E59ECC56DDD37A1D52BA6
+C3F0E905978AB568941A163F4CE3AAB5C5B16F86016EC47BA6F3F7AAAA77C3B6
+09C8C3ABDB6D514A76ECD37C37AA88B5860630B3406B494F7725975596F84777
+D9CF48686EC9C5DBCC1D78513F591C7C10AB9D153B3D41426B7BF668B0D04503
+56BCB686258462C1DC61095724B9F3312316262FD7C1AEC6E54DE7E5A7BD8EFF
+035299B8FD8A4A7B0F51404F4A760F4D8B4C0FB7A32FA4B2383AB6E9C78FDEDB
+FE6A5788D38A6701B123630C2A6D820A684166FBBC83DB17069494FBD411B333
+CB37E2491C5BD035A33867A6D3A3D420CC31ACF43AA07182CAAE67E40EC63663
+B678F71D4C6E0EC3A0AAF904CD3AA66E0DE5E3CDE049E94249B39A1C06E3CE9A
+F974B2484BB2CDA14282B9511E505B3C89F9C802218AE40D1A7541335C5736DD
+CD565D4B9F4CC78F3A393737EDB4FBD0DA299E21CCFEBA5478EEF013F0552A8B
+0BB11FF46CCDB784E8BDCF730A16363E66572049E42C695886EAB42A9AD9094C
+B635DF4B5B9BD9B9AE8455DFA3EEFC77653190F9A8B1E93B7281C2A21EA7DDA9
+33484745BDF7E3DD63C7AC66C286C9A5A698A5E4D7A91710B7FF943FB23609B6
+4B442F83CB795788FAB5E9CF3F75D5487DA26170E4561C7941C910B088C3B86D
+F844B0F340CF82786A3FCF347048463EBD2006281A816627065DDA6CD4D3AC5E
+2024BC96C7D896381BBB567951E7A1F29D4E95351298B000D29E5F3D0448CB5A
+CFDAE1BADE9403B90371C3A07D208948AFA022A69C519434B6813086ADF518D5
+88E0B92072A44BA1B3EBB630A13B7AB90992E85B6D67361C8D96F3E0D826FF37
+17B67E4B1EB7BADFD98D7F4FD17BECE740ADF13C141EBF0A91CB105DABB32FE0
+55086D56A0D358841D15FD349E6B95512E4EDF4C430216FF85C2ABE995E4B40A
+A6044CC8820AD885C07E052B3F91C2E9A1D163BFFD210F7BE95B923E2500DB50
+2075106DB541C267BD450B25B670CE80BCD068D4DBFF2D82634175B61FBD3BC3
+406131F44C7D6F18D375D1F2270829DDF29DC14DBB58A30AC193245D18DE91F8
+AB88AB548D8138605BB5A50073295534E314366E26665AE70482B890E4101D6B
+60E4F3B37ABCA1346DAAE8FDB8DD9C832EFF3E73BA470E2BACE7B8515CB43388
+C27AF99FF9322175CF8D4947E6B3846AFF5163E972156847F58A66660EC8A3A6
+5FB47C9F637B4CBB4C73B6A080B0CF6FD1E9665E92032540570FFCC747C67C50
+822811AADC404BC7ECD1673E8AA6C3A2F1D82F39430B58C29145E2F1B679C46E
+94EDC711883F1E4EA84117A54757E8895A40401A26E1437B39A2F65CAADD6E02
+D71FA8AF7453668DC613F326A3344F74AD7AC67569AF399385500ABDA5EDD3BA
+343CC5EDD4B558467626850E752B9959FEF1454E53E7A3DCBC2255AD8F6AB4FE
+894455118A61C58840CB68A925ACCAD75CEACE863D806916228F0614191A1CD5
+DC9BAE256018615AA3725834519449B0A88B4F396654E74099C007930ADB1327
+DD119BF799FE3B0B223E1EDA04FE2DA7A1C879143E1C33B6C6344F4BA033AD6F
+8E88C33DEF1977796B454BAB2494C930F492A518E8198C708A75FFEF8C49C324
+A718AB59B889DED521229E741FFE53F98EBE88B0405AD523254FD3FA4BBE96DA
+DA1C27C1C979A0DD4E61C3B1F4C4DE01E42F1C4435EECFC02D97994BC8AF5270
+E7CB1458D76ED0229C5FFB4A23B8716018F9050970895D51722CDE8F2EA3D947
+DFF374D84915D5C5D16463A6FFCD079D1ED416C4347BF831FF0C4ADFB61295DC
+4D5785BB0852BF472CFC97EC174491CAF961AB90629F055E75DAA6D9898E8653
+5BCF379816CAE46FEA62E7BE8E9B953466E51828172C4DBD0E1BBAD1CE28B5B1
+02B3E36403BE80B49A47446A6677FCED438F01D60EB10F478C89528FA337D0D8
+88D3FC123C076507ACDAF783A9A6E24ED73BF24B6E0F11C13E532DE5F70B15A0
+657F5ED27D204449A841ED19E01432CFFE928E921321113780D036D34F2797DE
+D4459CFD15BB117B5C9745EF3CD2B296D91FAD48C80B136D94476967E255F808
+AD2B5D522ADEC64176833756510391815A1D4A8DA1D0AEE7CAD36A1D161889F2
+3347D5B6BC503300FDDD48F594F391D5FB42C42113C538E707C16EE24A3F375E
+7C506E8F49CE50FF9DEF3B4A4C1BEB3848EAA3477349833BA22D2A9012287D8B
+A8C4CB4307A1188ACC0E6E9338E1559BE5FAFF381BD82A6C71C267409468B3C0
+2C1A29F4281D565836EAE57F680490FEA4A952FF64C8CD11C377C294DCD1EC25
+CEFB2B6DCE959D0208F85B6E32E9B44FD455F9B134A5306D95EA29F37BB8B86D
+9E592159338E1293F449380E13C21AE42E6D6952083BFD432F72DFB7B6F9257F
+5784C683A6E9ACD72334E0EA8060A81E14EE32300055040E24B49810DFA1468D
+A962DE1D1AEE09B49109257898F155A63A83D514996DCD2F96BC0F52796267DD
+DA6229F5E9024F78B02154C27EFDB9B6E09B131C9E9E4DB41A0FAEDD93A17E66
+11A2D58C918F665AB77ECF4D059CA0E6273FC77765C3E943F31A237BDEF1A735
+FFD31EAB88550DE10F9A77034ACB155D085947312A063D6DA7080C457601646F
+7B4FF501B0B33B163A70EFC77CCF6D2EF060F21F46CC928AD877FD2F3937F1AC
+057CF070D3B4F9A86EEB6B24B8A287AB9C097D47695869C8EB52B84D815AA6AB
+B06AD85F81B6747D34D833BBF91E669FAC3BA3DE04F09554A6188672888BB9B3
+3C1895ADFD24456F4FF3CD018AA87B2DC35DAA7589C72261E6D0035832655F73
+71B09F8D98AA894DFAE3D6BB5D0B6C03C4F25B4EAA40BBA61CC1C35729895503
+56EDA3F81E74AC0032BB5B000673620827777926AAC56BB52E01D31B9C47B5A4
+C6A04A785B4AAFECC11A6E3D4CA140F51B032BA39F3B9CD77EF7AF250B732B16
+2598F78AA005D8938E7B04FAAD2DDCEE87E6E4F578174BECB4A94D1BE792D097
+2034095A4ADDD24CC24C1379307DDA53F0C34F45FBC99E32EC90994B249611BE
+AEE1806D80BD022A8C491EF89EA5A98559DE4FBF8CDF929F2F1A8DC2FFEE2485
+5C14CE2737C81C907D873D79EB8EE5DFFBD72BD797C67436E9DAA85E7B5F8802
+3EA116F59E5FC8100279917BABDD466C6D1CA83AF9493CDCF2AED9AE83E02043
+F0E73245BD8640ED6A7660C9B541DC48F7AB182DBA353832521D2D5DF2AEB915
+044ABF160FDD0723D713D1563EE0FE854FCF2F8F5C3768C0F2544D718C7BF104
+E7DF8D12E9AA2D700D660460D3532E23E41FBC47ADE174D2048E2E5D4B82BF80
+3ED36A14D6ACB1C04F822ABFAEB37CF47299562411DBBACF
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMTI9
+%!PS-AdobeFont-1.0: CMTI9 003.002
+%%Title: CMTI9
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMTI9.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMTI9 known{/CMTI9 findfont dup/UniqueID known{dup
+/UniqueID get 5000827 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMTI9 def
+/FontBBox {-35 -250 1148 750 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMTI9.) readonly def
+/FullName (CMTI9) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle -14.04 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 12 /fi put
+dup 46 /period put
+dup 58 /colon put
+dup 73 /I put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 102 /f put
+dup 103 /g put
+dup 105 /i put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 111 /o put
+dup 112 /p put
+dup 113 /q put
+dup 114 /r put
+dup 115 /s put
+dup 116 /t put
+dup 117 /u put
+dup 119 /w put
+dup 121 /y put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CE32340DC6F28AF40857E4451976E7
+5182433CF9F333A38BD841C0D4E68BF9E012EB32A8FFB76B5816306B5EDF7C99
+8B3A16D9B4BC056662E32C7CD0123DFAEB734C7532E64BBFBF5A60336E646716
+EFB852C877F440D329172C71F1E5D59CE9473C26B8AEF7AD68EF0727B6EC2E0C
+02CE8D8B07183838330C0284BD419CBDAE42B141D3D4BE492473F240CEED931D
+46E9F999C5CB3235E2C6DAAA2C0169E1991BEAEA0D704BF49CEA3E98E8C2361A
+4B60D020D325E4C2450F3BCF59223103D20DB6943DE1B57C50F9043B95BDF77C
+1450E422362CCD41FB4AF30F73B66A85AC8DDEAFA65B4FCF0033D034E111830C
+ACB981C2AC41AC32863D02E6D9CA81F8D407DE4AB20B4CB6418B8067D694DA02
+6E76FF50A7197281B7E8E700C4A8824220374DE1CA077D50A8B751391E35FAAE
+E0AB0604164A16D476EDD5E33B08639DCA14796F27A20EAA52D0BD8B61065AAD
+083E4AAF626C2575C56F87AAC636FDC2E5ABF623F2D916D3CF5CE8703D297151
+0A664F40B144A2F3900D053B709210AB8678EF35301AEF3696CF17A5B41B588F
+539243F32FD78B62A0D80B17F1028CBD7234BA7513A4809B584092B95583CF1B
+664929C33846E8F59A43220F79D8BE0DA051D17D09C1E9DBA6C60BCF99BAE773
+3E9439791901546793B3CDF014E6AD9AA169483DB87A6CE4104A8B25AC117504
+8D6DF6052EF491D510F67D730CA315915E77290A40D3F8EB8F004114BB64C5EE
+9F1E18A47A785A04D4EE3FCEA794EB3438CBCAE35242782053277EFD6B67F6AF
+97D892DA958EDBFAFDDEBEAC4451EF8E00D6D0E7E60C112F74999096428AFC5F
+507D0DEAC778A81F8F47FBB1FD8C22FD22DF2AD0C9BDEFF2633F180E0186A9AB
+B0680E661CF083B8DC5635D7DBD69A17E6BF1E86F7C19FF7E48EAE8D35F0B698
+F990DC16CAE9D6E9D1C323FDD183096BE0EF3BCE379CE5E5CB0F58E4516C01B1
+55004C20A6F2BF430D59368AD4F6D398B9A27B89DBCF70BB8A36AA24496CA621
+0D28748646257C95B113209FA00B4525C582A8B223C64B658DA11CA08CB64F12
+8BF230A57B4DC2FD0AA8C486D7B151C9713B12ABDF174ABDF52EC8034B0858CC
+6D389B503A320AE42AF3BBE33135032FE83E6B7AE0D713BA6A56230A50C22FB8
+597A5F21CDF98D70423E8AF8E3CBCE4756DEB5695D3A5E7C47E6EE62F4D06BC6
+C9978DEFFF773BA6CB9B92D2B2638FA3A1D92806EAF9A9A9D6DE09D81FBD8622
+AA7AE1FE01A1390427D270287D4A436A544D4F568640100F94518C113CCAA34B
+28791F62F1C5B6207165A847AE2A9F1E3AF8B96203DDAEC2AF8F3450CA2FFB5D
+E55DA538F39D6A5F13963857E2CE6D75E510E8287D4DDFE5FF5CDCC0FF51E346
+B8717B28181DC56315751FC861DE7CAFECE8E350CECE6B324879ABC8D8206ED7
+51D1D299BACD2F7F6EC2F8D3836EED6CCF09C205A7A76B82FE1AAFE0833C7693
+FC7E22D373C10C34BC0B57382312646763F593AA91D90F6CBDB096CAF9F52C12
+CB6E75237566C5D528DB58B92D0C7E16D6BB2D097C1FE565A07076209AC4DEE2
+BB6147D06D65F403B6919D65D1C3D9D0FFFC0CEA7FE0EE002AA0EFBFC120A724
+CCE85B3419C44ED7216E4C714FC85F72CA933D3707D2EDC6AC02335D4770B48E
+0B64716C0E1B9DC8A4DA1BCF7B47FE7B37F9630E55E9868AD41AC770C5036E78
+4D8B24AF41E90CE8358F97CCC43295371B73EF7E86BD1647EAB2E493EE912F74
+EBDBB5CAC34EC1044114FDFEEE2FA8E3574F4D1E3EFB38C3BCDC341A0E53044C
+0A19D619CB789E8C10100E413B8057373E6D77709B8019841DF04C8B27700FA8
+B21E2955C9ADD9CBCECB52727BFF0E48029D46C695028CB3A7EA779EA69C8763
+2BA38F274B4217F4D5C942042ABC9E4C1627D63C0BA9B1E03E9E3C7C8CB2812F
+503564C0C02A6F2041D4CD59BFD6E465CD060D655C38FC5499F06E0323A4F359
+37061EA5248B3AD809D16446E67B0267A3A929FBEB0A93DFEFEA3E8D5B7C564B
+95AA458F532CBA8770DD90AE6D3A0BED3BA140A4AB6261CE41967038861D947F
+20BCD353B32618537EACA0F1CA5C2708D67D46B6F9B6D4F12081485AF0699628
+05AE00F008AA816DB07710E06AE2DBFA830C34851E5C63A7E9E02404ADF1DCA7
+2185507F0CEAF858389E4F8DC3A1283FBEC373FB4A1720BA71F993D432425C2E
+D0FB5A6FBC1E1904B959838FCCD085AF1778A5E3EF29166C6660B797C8ADAFF7
+1EEDE9BD371E11CEE77D70008706E0BF2B6DA250F9C6A92BF91ADB7D32CA17D9
+776CE695179FC5D1686E86E2B4C3E34D2741CDA86C0F343E7CDD52AD3059A8C8
+134C7DAE20076E5EE5990CC56EF8AF66131243212C40480BBFDEA97FE0558ED5
+7AECD669BA1AD9A50F1C0B21D75AD5A11FF9F577153C12F9789EDDF81FB683B1
+F66244F6FB2DC1FF2B3BC8CDC6990E6C4CB835E552E2AC9A7540DDCFAD1F931C
+44815C59118C7EB3C4CED4DE0D45C311D69576D5E6DAE9DF8265EC6E566DDBA7
+22655E765C074082F346AB496F08F4E598D6D35472629273128157FA8608DD96
+0CC4A3B97B430B1DF8EA4851CD54E742AC0170215F86D4612129F2CC3874D047
+F485BE77D2FF57B8899E1E667D41E519948F0E60C5247F5483D20CB108BDDDA4
+27F15C14A35FDC3CEA924E051D711D8D4EE36E7735E6DB443DBBD000A4CE0635
+2727EF9C1AFC95E876A46FE001EFF903D64A2C1F00D734D32FF4A6C8E3956DF5
+5E676815AA165DAA9E0AF2D56EFFF32BEC9897F45E40909F2F39BAF85A354420
+5E6CBBC6626B98FF1A9BCC1F76D9AB0348C8E7540E42EEF3F3351006CDBFEB01
+0FED065EBE147B5E36BB659D6AA429E6BF8121F147554BC0959E6F45C6990AE4
+66A74CEBDEDD67A559C3E4937F50D3B51E7DACCA53A2DB98306E7AA86D21977A
+A4CB7592590C94C8479530239945471408FA1F774CAD14F58AFFB59D8CE596B0
+8DDC2E8CEAC94156D5FC69D70F2F779774503F168C48594C63F3180E8C93F423
+7F1F1D44CCC5E5F766D7BECC470F880611C545FB3F4C0E171A30516DBD6477C6
+2C478B4E3C2AC2241C68124C4570D476B1A18E7D093C97D16999E06CC1C8C485
+15AFA4836718A40733ED145DFA4B80D3FC3AA074665316786E65706DA958BB71
+67A4EE35FA629FE738CEC51D4F51431BCF8B14804F2C83453566253847077644
+257AFB4D3D13CE77C9CD592F6C913F5AA3064E88779966EDCA52B2D9469FE48A
+C8F6E5036AC9B0671508DA664E3F24BCE551D22434DBDF58196254D7D2C7C308
+1A6822F2F21BDAE029F7F776C1FA7BA9CD94CA7D919B4E7BCB9B885FD767CD9E
+96CC1604B95F0A8715837D7C27BBA08663FBC0DA33C2962577451DB48A4B76F4
+8A4B66E7D2A2E465789D1E6B6D5F20413D84A47E5788CFA97BE43ED05FA176B1
+F535C65F8FE60C72BE326737154602688AB71A8F12622648031414AB80C46289
+1EAE582B933C87122DBDF3E3F1C4F4F5175E88AD0EC90B33CFC13DA07CBE8C49
+EB1E86E0DCA68AF0BE3814595A4B2A4113FC8654A032BF00DAE293B4F2CCECC6
+C0E804B658720C67DC156B4785D9A15274F2BF38748FAC7936275CDF42915CBD
+FB21A739B80CE81B3897539492F113D589DA8A6C7B38621C8354625DC8B40FC0
+7CFF21FD2D09E41AC9E99CB18FB9C92BB735C16FDEE7A8BB75A2258E76195AD2
+1A88B0D64C130BE88CB2FEE3C723A46516DCE8DC6692EE27C6D8469FF511B7EA
+F1B7EBA054708112981C79CFDCDD40BC55A1778FB3FDFC0AAA7EDC425FC2938D
+694802705011B724423608C7BC1E803D344C9B5BDE13005D06C3F27DE0371EA4
+0F836D5C0D6C0BE2D27700B08ABD09783D329EDD00415387C97C04F89607DCAB
+62463E6A37E36C3A1CD92158353D45B443428177D1AE501F1CC0B50C100166B2
+98C4824CAD58B3A396D097E2850B39130E743CF3CF59259A174586B9361D8F23
+6DFDDAAC5B40CBA0495A3971399A95BAAC66CE5B472669E2C31ED0F2BE60E787
+503EB379D332055EBF839B25802E076B1BA8DE3EC59782335AC80D1CB950948A
+5EEA00C5F5829EB5293E05B982032207D41DDA035B3CAF26802A61751B17D0E5
+170C99F6A0EE0EABB1576814EC3B4317A89C7F11022A0695FA3C2B2B80A2F73F
+6A3FBD3A2B8C4820E7705CCEE368CE580434F3EBD2E9DBC162CB482278531546
+74355C299E321C47D1C4C6D48C5100A4B8B2A16DD422AC3365B37A79D936FB24
+786E9AD00E8E2666438B096BEF243BEC5C1AE35A9612D08CF7776E458265FC58
+0D67659A4D5AB175ADB10F662536C8A9447DCF5173E620320A43B2AA5D5B5C34
+78265F88656D2125C6E694AE4750193B05ED2A6DB4CD5A81E48B9912E25710DF
+C66A0FCB7920479DBBF739D4BC746BB03C2F1FF89288DD807E805957EFB929CB
+248F64A431C995F0300C0F836EBE1678C28DEA1F45034A4057520D17A25180A8
+693BB0FE3FE6308A332A7E54A674B497471E2D13756CB0B991C4A4F9F4851A9C
+49DDFB13416722223559BF7BBE8F1499BC93DC8BAC757E42E25369B182811ABC
+FE4F1CBA5E5BC15ACB6344EBC575C2F443A508A46ADDEBF7C34D88702FE46A8E
+D96C91AEA3EB989909A2B22E86FA80721E68A1385239B4883DC065A0C08ECCB3
+693B0D13CA411A78C13BEE866D8AF8A634B81283B77FF62EEF25C5D48CCB10DB
+BFA10E3066C116662395A6AF0B71D23C4047EE0352F4E02CCF28F959FD4394EF
+43F0761B73B8D726B69D5111CF94B720D461E0AE42C974F2EDA6F7883BCC35FD
+093304225534D8043D934772B0FEEE6427D0481A6CD8BD614669B875E1DCC6E8
+EC423D9A0DA290D8571E97CB6CAEF274DF823767AF4E0576588CF2ADC239FDC6
+437910EC0C2F01B4DC773E73C7FDE6E37D3E784E0E5B655600FBF3FBCC1FDCB4
+CF356017BE2A663DD7983A46482A4C1B42A067381D58AB1B332CAB8E5C83FC78
+1F0D9DBACEAAD372991BE3074D9911CBAA95E776008644F203D6B2EEAAFCDC57
+C53DE48816934BF9D70F90F4186F6268522D260512492305533C1B0FB23D4726
+6ACE20B872517CA01EF5EE275CCDC3BFE45C19FF225550E4E73B15E9BEE3CF21
+1594CC1773CDAF0C659F3EDC2EA43C25D00AA68DA8D39DC46A1676099496DFD7
+1155BCBC439742A80EC917BDB6E7593639CF1217C0265BA3183209DDDAF50E71
+FA061C8978583D93EBD97C70A890230AA7123947B197E9536F0DA91373DECFD9
+BD4E1C12B086B12077EBA19BA50B786AAE9244C60020F406AFF705CF029B43E8
+D70CDD5DC7A61A75858E03657264392D9CAEA8C515DD98C2CB9E84BDBC6A62D2
+36CA59D774BD889D64E6C9A0E043D04744D3D807D3A1B1B25266F0D9953266DC
+662424A93FFEF40F47097F48D1904A1CC00030155AA3D9B07D281E055E6D033D
+745856D9465D7349797A07396AE9026EE96DB8BAAA081D64EE4D86ADD8C4D1C1
+CE8EDA25CF3242047E18E4C9870320052ADF3EA543D32E6EDC93264DCC2E5A1F
+458369CC5CD73DDE165D5BF594C81FC992F35DF29A57464A0C6D72D5E7A92535
+3CA14943640A67B23935409206FAAA6A11F598BE24373E7BF54A2B3C34551080
+1B4DB4E3135AD0B61CB1C12A5154013E11B33393A1C16D74B16BB4D8E7B893FA
+E6AA0C843BA5DC50FBE07407D8B16ED2963E36D021EB433609053BD19ACA31AC
+53B1360A48F71D972E669D5357C22A33A7211F3380DF41069AFC7ABCB3300D72
+FA1E9D6F2291E147988003554D2DCE165B5F316A390500D0273E83453381B13A
+95D6E6F3300F36155573B8FB32A1691F6A9AAFC39541BAE0A4153C9F6B181B89
+43D246EFEB5A2B5F66FC60A44E2E1A6D972C53B1E930CAA18A5B58820D8D2EF6
+C1E798E9B744A31FB980C77D36728AEE6E682EA668F32E0C3EC70BCADC32A8D9
+A2597F1A4AB9565FEE420056E8A8B0004C006AD981E94A84CB30ED6FC9642D65
+0FADC7C9950BD962E0D86543EED6DE476E29A525183E52A8C97769E2FBC4149C
+53A13C54341A9F554F0178211FA1E4731BFB84C11E6B776335F1F42864C70E9F
+4C3F71F7DED7FB704A05FAEF7A2186B2C9C2AE9A3BEA55EC7F3334699BCD3D70
+A675D3D1EBD9958BFE62267CAC06FA97421994C17D60879D8B847B39D5379B2C
+079AD7BDB6FDDC56106127147297932F788184B0BBBEA5657DC92E4D6B097F30
+97149A14677113EC8929C69FC93CCE56C068C015F46029110C7DB91DFE31E06C
+CBB475E860D068ED6BE3B15B5C6F6F0D1D5FE6E7E4E47392C46FAA9CE932F928
+FF628944653962EBFE4EE5AF7522BACB33ED77387B0247C146B81F7A860B84D0
+D372252C89556DABA34913010DBA3576A6E13E3A184CD18D53FC758DDA762338
+AF195F1F261D5F10AE0E733ECB98BA2F81F7B456A75D862C69D623CBDC50BE99
+E3D1ED35ED4AEBD6CE39723F459AD508863C020FEE61980A17D41BBE0A54E120
+1EB69BE8C1198663596A3678F11BB8F28D7BF5F713AAF61866B6C172EAD9D25F
+02289C719F2C121A09DE6D8E47001FA41002DE821E739567F5D45F5C65D2A0D2
+65D011472F8AA705C7BC3E0580BF4E2E007EA98AEAF9AFD2F25FB20B08EE26E2
+E8F94A39F6240409F44E85FFAC9A46A2EA23A5A5F8BB0DBE50A7A1A9A6034D32
+B777C38B88F25D392E59AFEC304C13CB1407C70B7DEC884B5B7AC97440CC198A
+A949ABBCBABD1442C67E1828CE582D77F616A49BA12BD006CD541F707ED05737
+FEDED2D912D3C1083AA726C21C396EC6A36EB6B9219F2BE7EF62D09E487B3FD0
+9748121C531F7CD54DD98622C4C945E5B04ED2FD66D20873BB42C5391627B074
+7DF90B81ECC6AA0743F25247978CC09C28C4F878E29A5070E4023BCE95FE0ACC
+CC01D0EE219FA8344E8F6D7D43475678DEC28FCA370A417D2192DD293B13E507
+F20AEEC2B825BD73A6678698858CC4B3DFA40DC96536735CFBBC2CEB5CA6A396
+C8D387BCB4D6031DD45563921409C33F3BFFE220D7A255AD2B422AC9DDFE7A13
+AFFAE4D39E8F285A4877D1FD83FF8BB9BAAD29C4C4DC7CEEB139D4CC253859B7
+24221EBA02F074C94543E32176588F50D0ABB9B0AB449E21E01377E96A487B39
+E45385A6A12DE9067750598BD5A12DEE276612012DC4226B14B0B289C9C8EB08
+49B5FBCA42865EE9ADECA117AF8B2BE60A2F825F51B3FF32DE769AF8A9F0708D
+7BA0C614E8B1CAFB429B6407B3BDB582FC49D3794A0BA6932824A1FE44429731
+5F1C8D2DEE93EFEE11C29B1C020196EEC515336D8FD1FBD73FA4F2B454066970
+1657B1EF286BB2DE8E5ACBBF40C992F9A22255B3D842E68346CF43C568E1DC7E
+389CB45E387321424D7950AD8834BA43A128309ACFB55FA8D30C0A4E13A06862
+0BA93765AD3744B7F0502EFE5D457D7CA7E988968EF34E2AEF0D1C5C1252BA48
+E4AFEBD828CD1DCB34738801458A8E4F9970DFDDF7973961E756ED7DAD161736
+0F774F441671DB46F07E28F57A1EC5FAFA529685CC5D419FA0ADDF1030B3F21F
+AF395EF405CFC8FDD30B79B80CFC1708602680E9985C38474971F5A24FD0C415
+CAF1F98938F27BB1C805F0617DFB86783BE6F3AE6265DE523D2781E94B042D16
+36DCBA12FAC0BA0B2CAB48F31FE24BCC5B032D3987DE21BE7E191D578E9E5644
+81BC38C95513F04C8F1BB7DD82DA3909DC75CD509C0A5EF8226E0EAC4BAD4D64
+FD2D6BD98699B1B147B03FB3235F4F16F367D9EF10EEEF02093C40B9C6905716
+E43CBE3B6814EC7DC6358B72A2DBDB3A22F65E1B9CDDD4A639ED9FF36E021E07
+F5C45A74E31E755CD1F75CD2432D2E369537D3D738D643624E43CB52A1675A2A
+2501397B11A902B26BFA828E9A744AB40CE3C143C758C6969350BA53BB8CDE8C
+B21FF1336AAB3DA651DA4E822AC8E7B26B484955D115689E5B47F1FC0A88D9E1
+C58559306D908BEFBAAC4411B52396F19D4585B4DA54EA8929B11DC4428F158C
+AA3AB1B6C5736A7F52A3424F1B7995A97253C8F822C11204E340635D13BBEF95
+108334977E7FE842A2159F2B9C85558031F5D1B00F3C41E627B1DB9876EE658C
+50AB296BCF6987C92C60EA329075C391FE8162A7ED4E48FEEF9A7ABD6C26A1A2
+C667A8B8CD2647A9CFA8C792FFE0C2F0DE0C0E93D1A7B33E8E7872F061FD9655
+F39311738856E18EA0D00B495CB2457719FEA94CAB84DB6F5FC372411D7A0AB2
+ADE0DE96EFD4C911DFDA9E71FDCEAFF5D560F3F5452B64A5DBFC767F42C2E275
+BD357515CA488B6396DBB3F64411CA16977271074F78E59A64D710D418B800ED
+C6B89803DB4C5C203539D1F5B72F010F93C7C4AD5B083D12593C3FB192661D2D
+D29EF941C0FFE601698FDCE92045973835637CF0AB9DFC595937BF7D781331E6
+78F335BFC3F213A9C80773876849A5DE2BA1F785DA4970B01E04E68CE7F78DDB
+940917DE35255E56DF93FACBD3F533FD420D0ED3AFC2AC3E45FA9253689BB1D9
+19F38AD55414836234C1D0AF2E1C25912F3ACFE7CCBD43225EED8810DA3CEB40
+E498C288573E42AC5CF17A119164CE2B3B8316210EC5A325D3C195A551AED7EC
+8E818836C4D468C25182A67B415B1E7A4671532E2E5B0A48DC0572515421DF03
+8C3111B7941E16AF76C4DB3B4966CD94B2771D9ED98561F8F63DA8A7729A9A44
+1B1ACAE266EF483DBA4330352BB78C9A633973E74FF825496C2B2460B7433B1B
+871A62E67A4A0C875EAB2584287CF19765247632CD042A8F461F1BB23CDB247C
+335FD5EC01BA73BEA6683515BE8D8B581B08C36F80672D305901FC7EE293A718
+10AB9DC8F570C0E788408EDA4BD73805C778942149309120287B89F798D9E2B3
+5A27C13E8525BFA0932328B2DDCBB108152A94203F0DF156FD7DE126F223B9F7
+71787CC4910E27135F97E2B11B3AA69E2B6D2B5124BEFA9DEE221AE8D7DD7BC3
+52F345D77C923FCEA0CD12087871E25268727E7DAD97B14F98D369CB482E2087
+6085299F47729D78B4528F7595CF6FE9D00FB307D1C77921ED2E6BB9A2A89B25
+C0106697F84A40F3C69A77AD00B7BFC242095FCC24AE45E00A8D5BC61CFB0153
+27141353885C248820C49E9FA54BFD9F9AE8E9D60E06A3E1955B9E3970B83B53
+A8AE3201615EA63E30417C943F5A83D81FC8827E4B6213C3B344E5D336C31BA0
+F17562408B68E55CF6FA1A764101BAE523C472ECF817D5BB88CC063E9EA87B17
+05F8452F5EC322023BE3FFB2E4CAA480DD197489E5C01F53CB69981E00E5A8C7
+F7DFD97D8373808FBB4F98A9081F4BAF812F4E2ED6C2570DF157AD19D1784999
+10258144701B92605229AF97A54E15518170417775913FE55AE0E85B4F80A001
+4721E49FD1A564DDECB23829604F294E84C61D88558615EF1A68C240D886C2A3
+90A61444B7C0994A062874CF6C06282107EE224D32E120073B5A828FED32A0C3
+FC07BD8A70F8C0EB84DDBF7A4CAEB2551A09B9083E86F578C06D114C3BAA3AE2
+B585B6BF554B2BF64B8E2FCBB727E61597736886CD9943AC0866AC714834A884
+A4957BED0BDCD5F023C5CA15453F8431F7ED284E0C90863E3C0BC7E4C535305A
+DD7183F445D18A816B2E3F0E0C8A34D5FCFD2B18F0CC2EC83451D1D23384AE00
+DECB0C1520958D503EB5FA250D20C30854B6AA35582485F048BF06AA5F6965E9
+63D2ADF0F587B232DCCB7369D94EBFC519F5562DF8014A8421FE88C1BE962D2C
+02842016F9D3556FF339DA87CBA6F4A23318447C4F5CFB55552241E0D701E0A4
+90321FA5F1975FDACCDDF298CCFB76912BD7225AD2A064E1E61800F2C1CBC8F8
+9464C38F7E68A338859B54C917DE5CC4FA18B4F9BD2B5DB074D0AB289F48927C
+4D5CD97F9359C701C79DBFBDF6D4708311CFF6365E3D93CE0750B17F9150B6BE
+B454F18A3C4DEAE8D31E97643024602025FA25E374A2DCE0E76777E5DA8A64C6
+70DBC1162D156E60DF2A1ABA1192574B8FF0972BA80B3B732FDE78FE0AF06A0B
+3E3A704AC798375574D4B0D36B329A4BBE2F4A57DB9349CAF380494C0E6FD6BD
+EEA4C61899D8520E88AC2D124B798C550F2ABBACEA3BE57CEAA9144CB9652B6F
+EC4E36F3B7C2A8E94287FAF6FA3B03DF1C84E15E26B6614B29DBF107C977EEDB
+6F57C612ADBA4FDD7928F4C10DF79C4DAF719B67E961EB4C1A87B5C27CDA9682
+875B17E0A772D42BE6DCF11C447252B419C2EDCEE0815287DDC8CA6B6750D122
+6D5A551C7FA86C310BABA8B0C048944B78099AF16165D61D3D7A6EFF411500A2
+E3491108AF707FBF9CE3D668E41BF7C97504F5407DF2F31C3D5C976E5CB237CD
+664C4986AFFD1AE09C6717B9FD725A778D7E4D4F09C67B880209E00B442A3734
+E22D2543574126AFB1AF1AE80D2C6483E53FA9272FFB4FF099C4B6C637FBF78C
+2A5A36D3CB222F44F9CA9450471CFB17EEBEA64FDB46F35D3B48B91286135EA9
+5B1906F18001263D83956A8CD566B5A4FD4AEF61E92877FA7CE884083339D8E7
+B13099D241E662D916EEC85CD11598D05FFE815376B28EFA41A5B382B6AC3420
+2A6F805357E35B4B1291E29D5C9AC84FCBCD4489C9E33CE354125D924F64AA44
+8C50679A3AB7EEB0476E6DA95B0DB0A29C002F2A85CDA30489CF1FD53842E7FE
+D4A024FEF55B06A6036AA45C5E37C17A4C498A9CA5F409B03B98880271C5393E
+2AFC361E2A3840F78ABA1574F47E6CA9A878AC634061D1BD0E971E9CF2415CEE
+DA51246D949EC798E2346D46130450A74AB0AEED24D534081F297FEEAAFFF7A5
+3009B7D530214CA1FBCF0499E0C5D4FCDD763A8020312AEBFA27DC0FC248F881
+C67E58E44EAFEEE0CA12CADF526FC5B7738EE0E828B08418BDA620151D15457E
+C7B364C6D30EC4A8FE66021A927DEBBC2C65E57056B005D8D7D85D8D5E34E616
+B2C1D23E04E9AFA303DEA1CDD0A541C7C798C8DA1206CA034E238687B4F5AD3F
+D2CCB1ECC6C69EBD5E77361A35D3E8E19E2D0BE39967278F4770D12AA218DC53
+679E4E9E6C40147AD34C48F156B61341ADB0776657C17E9C65769F501D24FC84
+211A2270F82F63D1528159CC82D5B258CAAE9F3D5B05077E581AD28562D06423
+1CA125502DA74E81878B6B75D0F33A7D61531F2EE2D04CEBD6C4E7D2B69449D0
+B5D3F38E2044618556EE622B5BFD352907D3F961DB8D05B5E7D191639699ED01
+F8184FB49BC0678FF6D5A199877FD3CAF6E4B4B1DC7B5BE243A19FDB1B8C1CF3
+D96DB50B3EB40D76FD0C6405B7DC5B64C2DFF8F8552871B4724008F0D935626E
+9F168B5D0A789BF29A46A33B5BA22B317766B100C21EBB2E771415614D036958
+841BD00A85CA9FCEC57DE410FDAFEA71DD6F35FEDD6FD4C1F0C596F8FB501885
+10A1ADAB1A04AB4C2BBDEAC9DBE5FF9A99BBEA6E1DD628E22BBC8F511DFC25EA
+94C178C929ECD10076C89559CE5937B5B97327412ED1CA9211C019AE5AF7A5E6
+8D0E973F62ED545EC5400A358B8E1CC75861F77E3C444C037C87788BFFD92534
+DA0E0876FA196C0D612D9C31A042026757C430C559A1F4CBBA32DD21B9410FF1
+412626227653770A58644381BB75D82AEA161CA59CBE1A1522FE71A0A1E3EB8E
+C92493EDD13B3BFC4C8CA37785310C76E31EAAF25AC3645DAA1889BA8D497134
+29FAEED6FA819AB75BF92355FE503141938B9D9598DE9750BC545A8E44102897
+C4AC2FB63C93972E53588B299B61B584B1E8D97EB57EAD2DBE607449E683FA4C
+499873BA7809F4B20C8491E1250E626A02DAF6EBCDFC5EA497B320EB42C452B7
+B01B28FD82C84DE5DCFF74AE05A7800EBD5D045958B23F4D5A78C17F7C7DB66F
+914379982CD52CD940C94E53F5283E7D5B7D5E36644657390037BE2758D4FEE0
+59A258B4B12C3F58791E626A5B91BBDAC63D81D02D7A077A61E0E1354F0A7525
+7E32CACCA3EA70C776924CC60A09BEA9A64EDABC1F59C8BEAFBC878677AEF15B
+0CB68D588A96D8A16AF46795ED408BA514B9046411A34EEFDD4DAF58B3C5D861
+38D5169E6984DD68C7EC5BD656898F101674EF8935C10BE7BEE24A29D2E33B1C
+58AB1ADBCD7CC421CC0EDA4A499B575A2AC7E8789770F17A138774F354A6534E
+0041BAAC7529BBE4A3F7952BCF4E5AA41B9F4875A6C9273986EF5E4BEE8E7223
+B69AF09FF47614E5BFF2A20C33F85AAC3757023C02002491C88CC7E57DC15E4A
+F234577D89E96BE19729594FA3769192031CAF26986168CCA55069567229DC90
+7DB302C8B5DFF54E1B883DBB1CC9F5BE25F3AFCCCAB0CE7DBA07A4BFAC9A42D1
+17CB7AFC5DBF8B64C244048500916718F1AA29C4F70C3DA2AF8132BAC978F3B1
+57B0C9609D6154B6B29B23B326086B9BA19F34690B76BF4A5350D5C464E55ED0
+A2B3D135132736AB06D1FBA716EFD67DE10CC169CB7262E8BFD0B74A441F74BC
+EA002D2EF2892FAAB07D9B7C029909361FE3464A3A9EA730C7919F730674C320
+A162B4A37A85E5C093D11BFB3BA3C489EC7607C9778C05EA753781D676DED75D
+802D4408313C9194D97B4BEB8939C29A7F25D4204D590C43FC57B88D218CC8FA
+887609140475C83D84214E34B83E65D57D70169EF86BE2517ABCB65889AAEF38
+1E7E3C9FFB255FF53605841D2014635C984367750D8D28D88D5A3247F5761225
+11C3C0224D8D9E8969C0A22601A57C18BA2D075F69D354C65F896BEEECB90EB0
+A9676043C02F1F0F5555884F71BEA5DF08E84ADCE651EC874D9C6FABEFBD26FD
+6D92B7BF2644A859C267217185665F143C2B7BB983CFDA3A5642D33A2FB235DA
+BCB3700070AE0F169100E539C238299417CC3BF096979E48FE902420AA988C95
+D8B496FFC01D25FC8BC97CD471E43CBB828CD85F2E9CBD5EFA8F45520F358A7C
+D841826312AFB98EF4D00750BA52CF0162E4B488AC30E505A0FFBAC9999A557A
+EB434B55535BC652DD78D78D3C5EF788FB8BD0A7BCBA60C51FDCE574CEAE2B5B
+69BF792E765BC5CA46CA40DB9CF1313AA81A7470971A76CB9D076DC9785E2A39
+232E9AF8B2255B1DFAC67F6CF1934C425D85F50F3CF73EF17621BCD9BDF7748B
+DA2D174EEBAB313EA65D3CB43DDE773B1232DC4C7C2595712BB62D6B8EAEF9D9
+C711AD792E50005DF0718AFF4F3A1A611D473926C79502BF7BEFCA405B1F3CD8
+E3A900AB22FBC0007B0CFB1ED6E06D6BA4297E003129CEBE0AA212BE8C4A5563
+733C75EA3FF09AB5889542158190511B7ADF466B174207B8F6F0145EB114AB55
+39F422E5EA4F60E6C69F8EE550095B57D086918B21511C3A8C3260E8A89890DC
+30C51BAF770DFD44D9B2E16DAEE8A2AA1306975591E098FD4B6D73CBE79BB8F5
+5E2194C3A1A92FE0AFB51673BB078799F07B7BEE5DF73AF655F3F1427A64FFD8
+F9A3CACB4FDC14B3E8DD327794F944DE33AD067E11A80A1E2B88039C01C42BB1
+6D4162D442EA830AA62EAE7D83FBAB29FE6A7742B3FD1D5229811ADBB647AB04
+2BC5C01CB2E72944082A0A75AD13552BCD9E244503FDBDB53001F53A45F7296D
+DD15D2D78597F4F141F4735999BF8E24C80E4E74598C74925517CBB569E279E4
+B6E600A5D9573BEF2D0A0EEFDC861F15CF6F42243C23441398CD57EB41E8F7D9
+E9E389FC3DAA464D31ECAEF89264FB4C0EBDF043B20F2B82BC18537AA2709030
+E478AB2427EB5CAA208D6327DE1DC64F0069726767BB8DC6FDE268C495581813
+6EA8D7477A2DA7869DED5EC93C3F4DFB0B7CCB96DD83B1444C3AA888FF6E44A6
+7FAA892E626A34EC44D5B56F9DBE3DF36E4972A582D5657C1CEF084DC368C827
+0C04509775BE9125262CA557911A37C20EB5CCB6BBD2761319282A69AEE9AF3E
+12AC1164C10D2FB7CF16A33C2613A77515AE605D3071FBD5AFB5B0959E3BF642
+A844F8D6759ED8634F775C3BB5B56EE0CD9DDBED2D84845AED1816986A78CB8B
+EE63AE48F2EA606DC42CB04160952D6240F73C886A88B5DE0FAA91A1D441A89A
+25EDA3F27A8E5A21A392C76D9D4F41679617E98D4AE394EB1071CA0EE5ED3E5F
+B4EC7E726BCF69725CF5C67AF7C9C09405063E9843D9BBDD96C4D031C6C59B08
+9D381EA53669E2ACBDCF7AD987A82B8A5E8E5378D0F0A7165BE3EA926120734D
+679A5DE2021D185118A7817AC6BFDA4A52B342FBFF9B52748F0C20695375AFF6
+E210BC3BE6FC91E591A7419E27FA75D3D8E2A74C5667E4956CCAF8871FE28B02
+DD668464E379E7FA4655A826DC4F3E8133DFD39AD0A0AC9689D15F9AF0FC4181
+D128EC3353647FAE021225D33A1B6EBA00D209F4AE0425CFF818A98593F8826D
+49189F3A8C6A7A772FD068FDBEA2E30750F0C8141D07AB4213D71C64A464E1ED
+5E19DFD72DED66F0B9BA26DC217D190DDE4C0512A729FA391B1538689138D805
+E828019853D8FFD93DBB33C8B5A29368607246DEC8A1A267F02E115C86B2C5B2
+B64342CE7BE2D7283D02E25FEE780BBAD6E383CF9E8DD9D042039058550FFB80
+AF7704C67501A95FC997FA11787EAED8AC6CB2614062A7DDFA6105F20DDFA000
+4A35A81B947818DC33A595562528C22CAB25AB135FD86A58571DE03E8A6B3CE8
+7D6807B430EC5B98494F1CEB5BB94801DA67C77DB4FD680938A23D6A56392DF9
+C920EDBD39F3EAA975BD31A522C01031D823CB997AAFC92DD92B2C881C69E238
+20B58C7434C5DEB7AA1214F4DB18AF28351A354BF7738DB9AADF6AE2CD6D5D11
+928ECA3E975BE10E3ED6CC70C89FD1E256DA5FBEB3BF72D2E5F99E64ECEAF77B
+A7BCF7DF578BC6314531D8BC497DF6964A0C5DD319555E20B0DA59916177E0B4
+C3B0D49F9947FDE1C2634D0B99A3959330C10BA5BC02954912556409C787E37E
+B83ACD16A991F47739E406B5E1
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMSY9
+%!PS-AdobeFont-1.0: CMSY9 003.002
+%%Title: CMSY9
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMSY9.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMSY9 known{/CMSY9 findfont dup/UniqueID known{dup
+/UniqueID get 5096650 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMSY9 def
+/FontBBox {-29 -958 1146 777 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMSY9.) readonly def
+/FullName (CMSY9) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle -14.04 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 104 /angbracketleft put
+dup 105 /angbracketright put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CD06DFE1BE899059C588357426D7A0
+7B684C079A47D271426064AD18CB9750D8A986D1D67C1B2AEEF8CE785CC19C81
+DE96489F740045C5E342F02DA1C9F9F3C167651E646F1A67CF379789E311EF91
+511D0F605B045B279357D6FC8537C233E7AEE6A4FDBE73E75A39EB206D20A6F6
+1021961B748D419EBEEB028B592124E174CA595C108E12725B9875544955CFFD
+028B698EF742BC8C19F979E35B8E99CADDDDC89CC6C59733F2A24BC3AF36AD86
+1319147A4A219ECB92D0D9F6228B51A97C29547000FCC8A580F0834F28818EBF
+F29D3B2C7C9AFD969BA6D3B7429E222AF78F6DE00CE2C8008A5966422936DC5A
+DE549B458EB41026E123FE75E703E046F665B7DC78298A145548DEF8D579E008
+39279A5208EAF898A357DF3FD9CE4450811F20B454D86B2947BEBB11EABFC62B
+187B12458E022CDBAA6EDF4A89D79300F635D8CD973E35FA8D9B1240B3D30D72
+4F30444BDF0B51ABA15A181A3196A6CDF9CD1D38D64C83E745A767446641991E
+23EAE067609DC2E84B44D923CC98407812813D5AEF0EA21E560B31BD77D735BD
+E35EAA564A570DD3294C703E16BB9F251D54407269C8B23DEAD063018D6EB748
+4204A415AAC8384025FA922E7074FA7B8A6C31FD3761E7B2737D4D9C9992B7B6
+DBD0CFDBD87D42E1A451FC5C7EFAAEC65D10D278470DDF42DFABC836CF15D042
+6900E0DCDD36E7153BA186B8358E74F91A1D43D62EB0B821C0E97FE63F1586D0
+98F01E8F6B6F2A435343A25CDD80D3AEB42DC8E5AE02F8837B84EE5EB508B02B
+6980D2349984FE1A0D3ED12355D556BA483CA078B7921FB336EDAFC22AE05C1C
+5614F5025B890009272DA8C838B81913C872A54F7E932237FB1BC2CE5D64CD04
+2D320C8E2E610E9EE36EAC7C28C833F8A14048E751B61D0CEB342CBAAB34D104
+311B421B8CE4D903D2E2518BA8B734E2637E2CA55426C4A87EEBCE637F8D71F1
+54626C52083262A5A9A3B49142948BC1AC0B7698811AE81FC3D3B1C14E6C274E
+CFD6C480514F3649D7725A0A14C82C9D537B1C5A9ADC816340B8B4E484AF55AA
+905EA936A83FE2BE788D084469008F407447E0077417096333F163CE94CD3098
+4B9712EE23120829AE2695EA63975492DB2615214B11C87ED0ADB776ED4BA0B1
+40D09D1A617D4F57EE1A9B05C8D5F42AECB9C6AE67757DE6307B1A9C467123DA
+773239976AB0EA052B23F263031ACABEC9EEC7A43ACD0DC2D7AD66664FB0D937
+6A0F463A173E8B90B2596DD323D2350435D9D31B638112D70492F44769FC0C6B
+40A291FE78AA598CAFC19E5AD195BE7264F0EC29305D36C7AB8F2A733797D75D
+94C8F7AAFC49C13C108F514745A394F460294C6F3F44162BBFA878F773A5115F
+062E934253B786DA2B9A6E8E843E06B97075BE99F21B330D6684998C5C340B72
+09D69B655097354CB682D42120ABF5109E5522ABEC94D05E7211DACE8737A1A9
+0BD3EC16F48798E67C7C85560D79366504BBFE5F7F5EC1B05B9F68F98149A02E
+E53F321C213456D802C01871E9024F965258F71215F40EA71057C15E349F06A3
+A016BF1B7E44DC4766FC92EE500EBF7C47D36B1EA34981EE6FE38FF4903466A8
+C9020B91CFC731642003AAEB145EC0F13D6281B0838BB4236C220F6F467F7DCB
+C79BB9CD5B6A180DD2ED7F94DA6B5CB833E62E898BE832DF601BFBC8148F9430
+C8AC459F23EA2536E301C9DFD3FFBAF4D01E7853B60A69B5D012DCC0054C0BA2
+1293D3B4EEDF7C5C78118138544A60FB1A500F72BA39E63EF5D97D68369850E6
+9B6336DA577128DE68FEB71877360D97204B5F3C06E808BF95AA6D6013524BCC
+85CBA9FD2CFEF383645E7E960E7AD471A6A3B8B8C3A0A0B8464836499309D82F
+52004FCDB68997BAD9E4B5B881634FE1213283B6B19308BB67F2364F7ECD5534
+467EF07CBE71989FFCBC6224417C0710EB3EF2676B9DE846E7FFB1AA6608EC9A
+76C31724A19ABB2AD08CC102F5DE8E4E513F90A53F06D440A66B000CCAF6AD12
+6F4B161B56FA5FAED65A24FA183B84F4B45407AA69624068EE0E3E47BBE973CA
+C72137823F1D676131C8CD5070092CD73FC2A93E0480310E21CFB14C031206AB
+411694AFE7B639ACF35C28705A115E98BC69C66F6C58E9E79902453798D76267
+29B780AFB6B895B34CBEA51530E8300569EE4D500527BA294282FED81F730A46
+6ED19AA5AD45852739882216EE937FC45D75116BBDBA6FF4B4423B398E383CCD
+A7D705B8BA85076133E823300C3EFC9EB9399575F5F6BBF868265304B299AD77
+B6B4EEA04C83E163E8CE2BFACA65F9DAAE3AD2B0F8DA1F986E6A12DDB2AFACD2
+217E37B093F46FF3E20E587A9490401C2833F5844763FE2C528E151214E8CA95
+018E1D8D47C9EB5FB4F0EA2A6D064680DEFD2C5489298F83B58EA7FA8CB019E0
+671028C59C3E007DD86CD247889ECFA6AD6DA2433B02180DCE6ECF9E495D0976
+D063A61B007233DED5E3F351D790F26D4011582735A69F37E7CCBB0AF254B925
+B378522B748BD9BF152E2187DEA12BB168C42AD8D67D18567393B35DB2AD8403
+5A7093EB59FC276525B8796FE81944F7F03349BB077110E182A61754ADECECD8
+A5255DBADB523F3DC251A7D97F17DC76281CC632FAEB382A972D60A15FDDA57E
+2F42AA338D889B47F6A3C1FADAFA8D11D63EF8D0C8C0FCE61FBD8AD34EB8DB3B
+722BD86CE5B1268F704ACE82A39466DC2D96C9849B9422567FA5E728B17FAF61
+59A77E9B3289DB807DF54D076139E3DFE176C3131FA4540C1542AE5AD6200FCD
+B92D5DAA77DD4D3022049B6EA2A037FE96E0CEBB1608C663F1373246FA74D70A
+BAE7BD37F3AC23E003204FA8270B4514DE1FDC5401B69CBC98A67A5CAB5505F2
+87C242B6ECC86E88EEF44B9C79DA5F88CFADAE8B4CF437A7CBD5E0C01A9BC479
+E92EA48C808820C567E74D62ED7597FCEC53DE9A0B3EBB9A3FB50AEACAB82BF9
+2AA56D029357AAE016582592972ED01C0ADE565E87607F17BCF4983E3321F606
+ED664B9516D404B277C2C1B0F873D469D64A9744D9C1897125FD471E71BE060B
+A3A617DC8D812E184664BD83EC74EEB5197611380F2D859E1A61A14404493D04
+B5537C04541E557CB5039905F37E72B762EBD2321633E12C38C409338AD5AAD3
+1A507BB2B8F5235F0614D0CEC2BE44CAD504C9B2CD3E45437A493A33B9BF8A1C
+3FE66B1E673449A54E8E3C3470688E94EE4404C888583F7C96B43A592D586D25
+8AC1F206EE5FBF3AFF7EDF9BA91EEC6BABD573D455E0AD6802E7E23A662D4F12
+FDDA00EA054CD331DF86C099C4BE8AB4EAF5D8EC1BFEFCF50302BE61E6FF26D8
+1E88C544570E8D6F7D875466C70AA91D6CCD4DF4BBA34FC67191D1692D3FB76A
+66F114152956A5E38345E7495BEB1A389B7D0A59624ABA784F77C1BF7728E556
+F9D97D71858D61624C22C6914A3A995BD75922A2C37EF2CA91F923A4561CD3D5
+2DCEACD9C3A65A9FAFFFA4822E79D6D89D6366DA6362DB16FF061840582DA35D
+E4EE8308040C2DA5F298944EED470D6E4E1FF58DFDDA96C20C85E2DF2652E12B
+2EFB8F890D301E8CE777678FA786E552A62A60DFC369AF4BDC069F5457FC86F5
+1FB1A38A2222EEE86FE1AC9A8227663AE33217C1F381115CCD04D2F381A27E97
+36D356DC64615AD63E1952B37AD4F967317D76A6DEF039CE8446AA634086BFB7
+7B0B34F595B61ACEB346F51ED10ADDB7B852B5B2BCFE416D0435A7CAA4C9D9A6
+152D9AD938F39E9756AC752F1604D884992BAD768C720C45479F5AD8E53A4832
+1B44D6109DE4460A662DA6081465E2BE02ACBEB52259E046767DA24E1416FF44
+D5AA1D303CC4249510D703CC6CD0FD7DDB078A91089FD86ACE1721F875F019B9
+82D7C5B2530567F2306F47DE90EADDCD12AA1C693B1982827DC36A74C86474B7
+0A8A2E084CA403AF654E2F8488806B943E38ABF544ECD45FECDC441DD970B180
+FF3FFF1A50D5E22216B240A527F95DA1E43770A3867F225DD2A8AF01A965E06E
+A063997C4CDC0B16B52F9B9C8B0DBA94F88F26A7A01E596DCF8F33DA3DA5B02D
+2ACF771F25A1372F521A80B93DB0337886FCAC0A2E8FAE0D7E1E0C31EB43AE3D
+B4C2020F322A9857A9EADFA7782CA70DE7421B9A83DE1873EED8D096701370B7
+7EC33B9C104E9CC16DF8C80ED24D1F91677E355DF037621ABBB75E09ACDBEB82
+30F1AFB82FAEC4D9E2DA93303F72C1078679EDDA35ABF2AB38DFF091AEB273CC
+5A7B29C0164977160CA75F62BC20474C7C1F127AE7E4DE865FBCEF852698AB80
+B61340CAB6F86017FEF570104E46B6FB3320E78D387CC58DF1C4FAD8570C0126
+B6F54AB5BCD47904A9255366AC9C88576456D3CF605822269CC65979EC3CC740
+AE3D09257BA3AC7A364A7F5EECA3E658AA20B53423553C416D98FD8100D80A30
+A1B19F029B7473070D7C60CDE51BBEEFD2B45B1C82F4FE32A5BB6BB5BC32BBB8
+F600ABE893B83B806A5435AE2B40E5CEA9068C6ABBCE73C9B3533520439F28F5
+E171DB1DD90B2EC04A1F36767B2B97D4EC0FBF217D4E80ADA5383BADCD7E066F
+5F4B23738A14F19AC7D765119AAC9AB6CD0A8AD4EAF8955CB9F5BDB0156CACFF
+236D24E8A12AEBA549FAA9D7053D10AB7094B5D9B86FC7375E245EA8D7FC64B9
+859A1A37C006E0449AA8DB8B89730348C71C7E014A2EF8D871AAA856407C33C9
+392720173DA60850938D0537564455C3957631AC8F8C0B3B29BF6163828796E6
+0944C3000B990715188203B32BC4E3FCDF173A4A9C78753AB7D76BB9A4C2DA4E
+3EC638753D6FF6356EBB07D0A9E8D3F50EA5451FB6C836B9E5EBB8F1331C8CA0
+B0CD271AF316502CBE87F652B5ACCD43176AAA32C6530C69E77E3C85DA496F3C
+06980ACA739DECB5D986622AD81F204579218660EA791774C2D11878DE23F858
+BBC4ABC7EBA01B7FEBB32BC914FEA8E5720731FD43F8A5CC53954D13455827EE
+9C7BADAE8322E77EE7413D6C86E6D378FF8044F50F529E765A1CAC29E8B1D91E
+CD40F70F2D4890E0FD04502933212D5AB176DB143831958605C1667B8841E770
+CB4D513DF0C3182C23CA653A7A714B2A8DE29D6B203F5A9481E0CF3FF073FC6F
+476B0B205136DA43650A940035A970584DD7D06B7CDA8E960186158B75FE3917
+9B1D0FFE45EE1606C875DF635B80F5A9E5B67A6ED748F52A53A710A45AC20BCF
+FC96755E685A3B0712D5E09D860986C61C631A8D2A505C57D57C1D4AE78C552C
+DC5C9EE15B82A4C3020331B78FDEFDE53974C391F375E8118EB7B2D23DFA3F15
+389043EB6F33842C82B896073760197B13D3DAC172D77779DF517AE31BAC43BF
+5BD6F75B59AAA59C7EB81B776FADB720282DC06BBC9C33AF5AC0BC59F6A0044E
+3898A4B5868EF32BC4F980DD863E8EDF6DE3E753A7B3E39F8E8BCB3D3BF14EDE
+3395E73BD07440FCE88FB28A96878E823C1E5519650F2054EC2CF733EB8AEB0D
+510E5659A3179C3FA8E31EED621BE0EA648D76C370C3CBD8043BE206F28699D7
+5871DA483AA5D3580CD55902C85DB9EF5CF5D3191738FE64DB42410F5AB8ACFC
+CE07E524BECA5633B082F4793002A4A7215AD1BA31159A30D72AC60EDD0B2BAF
+73C9934C85C5372B47BCD3ECEE463CADC05CE8352EC1399ABE2465AA53E5965E
+79400336B1F5D1401EE2DA5807F9701D1086DE505F6AD4E64DD4F3E5E90CD64D
+FDD25E6FA03B679597CFB8C5C1F03641CEB7B9B40787E70BC6B063621382E3D5
+1287365426E44A2EA208C26155CDF782F404CA7B3C6D379103EF4A51CA3F1343
+22B04A0B55CE5A7633175838B9E50480E9B80446CD3B541362E7A10BB3C58A42
+88C0FF580B4A0296073F5B6505E4FCCA5D4BA2F7E8D59BB04EC9ED4E664BC2BB
+8754777594DB26DA0985663D321CCD13FB261BE8A771470DDDA783493E452A87
+D0AD01AFF8EDCB7BB159F1408FBCC52F126C46234CE6BEF241B49472102598D6
+91FF2DCBA2CD0E6658A61DB3591EA02E4DF202954B655C5A3C34B14CB60CF9C9
+2A6683AB282DFD79B33FF3A6AA524582F174F11A5568159083496B242ACD2770
+0ACE8473D363AC11250E5DCDCD3CB2281B71FCEB8AAC1367D0714796AF3BF01E
+80BD4B05A0A45E6CFA6C672850B9DF113F5EB15923ED885A0E4488D4914B62A2
+FAFB6A63F8AF0CF0DA498E1BA68C4150B6E59CBA80BD17026FA09920006D2075
+BC6F1010D0A10648A20D8ABF8137BFCD6A5DB3606F6B3CA51E8A4645D32E5966
+6DFF7537F65DA4268A86BCA5791C21F5FA9F4C2F1F6C1AFC4D4BADFA63609C4F
+5F5158608E6FFD9C5BF00646C3AAB983DDA5E37A9C2EA81796B161A06201FB6F
+8EACE87008EE7A008BFBA69AAC04D73A8C0447FADA0249D8861ED405537E23E7
+BE68C4349FD64A14E3A53D6C6484E704BE4AD5FA0269F56D3B752A070D9872FD
+A5CEE543B413F13CC4CFABCE885BA4533EA0969FDADC14DE6846B330552CFD60
+A75BC8C9DDA76102E48DB6B81975A1F3FBE182CEF410841CC6164AFA0CE51FD6
+8E8E6F0971277052E21126909B5EE51508306B886E945C11DFFE1C91BD0D79E4
+554CC7D6A774C9B98610A1E49C3326D62F157CA9D89B56699F32DBB9D49C716D
+CBDEC052133F8E18E8F3D7A59008398AF3E4E1192CFFE4D0B7D2ECC8DE2ABC1D
+4DF7F2EA5EC0DD756CB2FF9F95FF10E506463D3037BABD221C08506FA603DE1C
+DC45A5998921C4023E501DBA494C1F41C0955A761AC3D5B13A88EC4F0BF40756
+BAE8645EA76027B8AF74726521DC129B9AED4BAE67A511EA56EE9D0D8D30C7F6
+FA8BB890375A263A0BC4E9CBBBB8F8F8613A43B10E964F8CBD6BAA2B0BAA70C4
+4CFAF6EBF4882B610AE13689823D37B046FD26DA85BD96B896CBDAB6662573D0
+2CB87D45A86A016146513441BF7A748F1E9C2AC7172460EA628BFB22F9797905
+F6DF6749F13C7F234A2CE4829D41E0F53EF3C5F52165297AAC4B5AF4747A9F53
+60370B4C0110DBB42C25308F489A856B6664371FC2126BAF4710790021255653
+CACDE1B9ED6AF5C696C3D8BEA4698DD9045B3004A5C4C03EA994A5445C9D4EB9
+865266850047E28F2D82A08617E9283FE637CFAE4F7F261CC2D616A8C746EF23
+7360553A6B434201944C04B1522533C61F615A20BA3678AF8D4BAD1FB548D82C
+72D41699FB96EF40ABBABDEE633F05B4445BFC4E6E661DCBC8EC473BD2BBAF7F
+75F7FC86CC7B1F3A2343EDEDF6B5F7E98A0BC4443E21611F4D807FE7F597A37A
+A4DAF8A8E6D04FEFB320E0E25C61E156A72A3E4A69EDA04B0E3B72B69FC19E63
+AA33A682663A8F37F4FFC1533CCA2A80DAA675DD723A7E13D9DAE3BB0F5F3E07
+99BAB9B9BCFB29B73FC76EFA02F4F632690651DAAEC2B3688B636F0FCB156047
+F8EF7239716BE5D3DB2FD1DAEEC11DC2D65CFBEDC1C950CA737A04FCCCA509C4
+7E47664E160322366F70CCC641B9B49192AB839E0AC609AB2FDD3783095293C3
+11C56740FB50D23AE9FEAF66DB13F35367B562F15161AA270EE44713881B2387
+7889FD10198AD4D750390811714DAE7A8DC6F5770224E93408F8CCD4F8712A9B
+3C583C983D98CCA7FF9DDDEF8AFA292781B1D7089336CA631413EA0728353E8B
+3650EDED7ABB6E5DB5B85014A3A9C4C76EBB664A5B3E0F3CB2ECFBB6294F5C4F
+69EA3AC8C071B122B129A28E04FE989DA9670EB6246806A516517DDBC52DC001
+4C027D51EF1F98506F21E63D57FEF267B913F1ED4770D892239222F3A9035C35
+FFA38D1AF3ED9A8C02235D7422695D30A2F801389DADF34CDC489EEB38089B6B
+026D884EE1C24FE5785C383B988FFFEB5459A1644CA44D353503AE117E87F956
+393DEF6C47D4E1C5B1A33835C9B8E1B98809DFEE43C4D6DBEF1C2B1ADE4B8F13
+3B5D224C25927433D5738B0FE019CB88B1F373E4AC2BDB5BD86887FCFC50FA1F
+3E01CC550BE5FA0703E1B89486C67E8A16C560DBC051028078BEF85B349D3058
+55D633040BF5853FE9E50A671CA0A088959B2AACA1B614DBDBD906FBCB6A6B13
+7ED6C5BF448F92E9EB110ECAEADA36CADF4B6D79703CA2EA9BBCC810A6E3532F
+63C155FB86CBF6A6049D730B4729C613BD759AF3742399C6B118C1D2B38FBC4A
+2324BCABE5841102D7040970F36DCEE10B8D8708CC440A7C71AB86921F94B67E
+7E100DEED6F4DE49CABF3B3C9E4678EA45E69E5CC2BDBB2D29AFD22F1127C146
+E8728C97F121DEDE3F7C6E368F76B4CD91124AA35192E16FD57698646E72D031
+9876C6733B33A84E0C4EB52BC1000463EEEF0635E8D7924984F5E994EDC9818D
+156F673EA49DAEE7A1E5CBDC4665D3DA38E7F2925558ED1AF7ADD097308BA4F7
+78D09384458319B19B7A9C0A0423681702EF99FFC41D2F73181E7C9EDDEA3970
+EDFF05591BAD5B4A267307FBB6890E1DBB3ED7D2436094D1327FDD1B8EBE6504
+255327C4A4AD2681461B50CE36D7E6C9A93C99C07063F9E880194CB257C6A3F1
+264527D028F22AE80843231A051F0F1230BB0C743B7E220F8250EF543381E24B
+CB94A4F700E33B6AFA826A83E4BCBDA6ADF3299E22D4043B82D2E1767A1E9223
+B850213D2F79FE60AF64970F4F8E667F1B21A210A49FE974E2145B81EA5282FD
+93478D9DE9FAE7BCF57021970B04C5CF799F253E73D31EAA85936601B45F178F
+F154662CE6EC160D3A089F1DBCEC490878D77A0C5D553F12C29DB63351691AC3
+2DDE29375891CAD6F174919ACE0A3624E38913FE8C
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMR8
+%!PS-AdobeFont-1.0: CMR8 003.002
+%%Title: CMR8
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMR8.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMR8 known{/CMR8 findfont dup/UniqueID known{dup
+/UniqueID get 5000791 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMR8 def
+/FontBBox {-36 -250 1070 750 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMR8.) readonly def
+/FullName (CMR8) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle 0 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 12 /fi put
+dup 40 /parenleft put
+dup 41 /parenright put
+dup 45 /hyphen put
+dup 48 /zero put
+dup 49 /one put
+dup 50 /two put
+dup 51 /three put
+dup 52 /four put
+dup 53 /five put
+dup 55 /seven put
+dup 56 /eight put
+dup 57 /nine put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 110 /n put
+dup 114 /r put
+dup 118 /v put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA
+0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93
+51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71
+7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551
+E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078
+0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273
+C01924195A181D03F5054A93B71E5065F8D92FE23794D2DB9928A7C95D3A6E9B
+8E92F84CA0AA44461D2F4FA0F8B81C6F5B7BE98C9712BE166610465CF689DFAF
+27C875C029C0116DE61C21DA0092D029E7DBEDFDDEE3D67E6936623AB53FA2AF
+18BEDDD7AC19A19CADB6ED6CA7A26E6044BE414FFF59C0B98D5819A6B881F9AB
+7AD0D03BDD5CD309C67811D5CF0B93F6FDC9AE64F74ED4E81F2E18D880BD842A
+DAFD0BDF06300201C6946087FC0B999447BC370200BFB8CA420B668B32EBC242
+6DB1546A7164CF55B332FE9D239B65F532B69EF9F4F93828A44C8F5C526126F8
+B7A369114CA68D4F98638121F4E17F351723D9F1A902FCF087F94AFD23876517
+2D15B482AF2D68C3F31FFA864E031596E597882578AC7FB0DAE2A713B065B374
+3E2E72519ED6D50CBCA40A7275A7109A4F3ED8A4566AD8832890D3D1F4899850
+9B757442B7EA355175CD5D6D8B4152ED2D7EEB4CE30F174FF672140354046A45
+7098EC45B9DF3DF5CF7B417E201DA88308CEF4CED8E8903AF24FB8DD0187352D
+25738519ECBC70304F8F620CC45D2586619205DA3955696FAFFE2082402B3502
+CB682F410DE5FFE80A4DA3D3BCF02E35BD577D0DE55E7B8A33B7A2FD5136B5DD
+A0BCB61F8E7F4363C21F890CF287304DDB8FCE7FE207C0D160B81E7EA662BED2
+DFF8C444E19C91E72254257CD87240A70F1A964FA54ED9ECF27E27A57DACC3DE
+EABB92C085030870C6CF5C40B6E47F5C0AEB30E84A73ECDABB2D754EF6EA28BB
+16EBD6636BC288E62F4A38BFB55F5F4DD20FDD77D767F6CB52F9513E8EB75413
+07F1877B2C01278675177499E4E8EB09F2657821613F5C7643FC064293EC6E9E
+B519FFAEEA36B19C9D1302CF91FCBF87FCB57C5F995CB6712BB3D8681EB6F05B
+B2A4195A3C73CB4ABCCFB958EAC533BD89560D2790CDE1444C0F2E4EF27A529C
+F01052964E56F6D76A190E5FF45934BB711A3406284AF130D4DC0D8112BB3752
+762CA0200CA262359D4F54C0CCFA9A50DE18C7DB14419E2990ADDC4A54B94978
+D9174CA39434022FA77FB30179EF805E2189C35919F5EBE215EE2A00B4407826
+CE56329C5586D8B414770BA5D45513C3AF1931D632FCE69B4CA504944E03362C
+74A1177C6398A61A12DAA0F156543E2A8E9969C4308B7ACC21A5ECAC8F172541
+1B1316A88C0C163E574FFD3CD22FF08488662FCF2F9344BC25D02146F36CA6F9
+E2D0130C654B7485EEA9A110A33AA0C769121F81821E9A2BD062FAC158359D44
+3F9D9947200EF1EDDD5860F10438B162A69683957300C75AF7546C70C97AB2EE
+37EAAF0089E2623F787F252569B06C665FDB45EC9681C0774ACFBA76B98C4E89
+7EB12AA5F8798FFC110B49C25E3A483ABE83B0BCC6DF0578403ADC369E013762
+C9D08FC94D949BAE636ACA9F36F4E3F02296775A062077B011A705B6F1784D36
+A926622CB3847533D7ACB24A4EBABB14593B5D8E1DAE2BFEF8A51835C8D4E76D
+7543C126A4271C59A5881A5AF89331694F84489CA66725995DC3070F306EA447
+CF30F63CD476A46D528EC1FFBFB8EACFA2BEEDCF54C92CE2BD26DEA5827186BD
+3A4D1709415CEE7D51D671357B4A5D11E835F63521B9824EE5282E58F05A8ACC
+FD249461181A38C2F47BAC4E79BE368D64F886AA493C61CBCB2ED401C8AFBA61
+59CA6F6216D941A92AC52ACB3D7ECC28D6A58EF4CC70BA6DE23E80937AB38E89
+6F05FDD15B954C0826636267EDAF9F2BB466BF79D2E10EED9B04297E6BC93069
+79581ADD1A9D9FAE9306F46AC95B98C60A2E53D60CF1AA4069BE301E17E25070
+F98DD67BD8642B1D07571A32766072E48BF27E1576FFEED300D7313A358A823B
+49C8F135961B7E259095C9BB67F996CE0B90E95344F203922F47E11753F70D38
+2ECB615403490310CEE6C03AFA97DA2F47ED47125D110FA69725BA0018F6A40B
+29A307FDB3E52322A77A0102E6F57654CF1E96A134D13860D83AFA0A41112D3F
+2247A09ACF7D06713BE443FA27C7E7220E875965D53030FE7D2D62EFD2F1DB87
+5FB091FEAF599BA8C5167525899E578AB341BFE2BC4E53A047093168AE189237
+EA55F055514EFA939DAE9E859CB5FBCF37D99484F44FE5AA5FA386B28BB642F5
+5DBAF059A50FE96C7C6D834531D64F1F2E99AB2E96EE74D149178B1C0618495E
+293973D9A03E1790654B67C0882376ABEC17D74785B3737D81644F28B3BC6FFF
+F92FE29126995A07E0BC5EF3A4B93789A103C428943E045B8D1A5063AE71E806
+568D48072E53DEA85253B01DF0BB7367A6BE4DD7BE514AD74E3F77C825ABA405
+64DAFA25EAFF8F63344B5F6B523629776CEB090B546469F6A6008DE43072DD3C
+DEF51F62731037D1FBD0C038A1E9B669849EB3BEBA281624F13D20B61917A109
+A0A7871A73F7BAA18077360B38A4625C5DB9AB9E43BDEEB856FD0E2D3AA2E075
+267B978B9EB47F2369302E87DBD5D5B422830BEC32411FE75D584C58650EFB1D
+136FEB92B94BF8939FD63AFB7349C7511E5E46AA7324F8B1FFCA9C2A9E9720C0
+A720918E8E860F137567D386AC29870FD990BD69465B3A3D2A0ECF2753578AD7
+80DC87EBB319EB5AFE0B6F6FF8616EA30C51425FE3ECBC5F8D0B0BEFDEF32FA7
+D168B4E85C804B7326A0942CFDE732B1171C643452B7099B31649CA2C38B62FB
+46EBDF7180004C549B53F88021D029452C2B37D8C565BCDB0B11541039A13C0A
+E45D4B68C7907B8BF08C6F41F564B62BB554235D50330E78DD02795516D969C9
+66119D718798120442CB7EB9877FF84EC69DAE25F8559DCE3BD8042959F695F8
+2F99845B1B5680DDCF181D806CC4903E077D1FF5E60918EB34C0B1E028422B71
+CA63EFBF3F4F3CD813CE831EB54265A555BDD35AD7D723F9CFBDAB29C54F8AFF
+2D35C6A3299E0A2DB470C7B141B1E3E10DABB7873AE302926BA8743278FAA8C0
+DC6174501D6A289CF980A3F55F2DD5C3A514E7E7F13133C35D2697D64C25130C
+DB78FC997968D6B3BC929E8A31B6D212C5128E4412632BC52B3A1049F7F2F61B
+C74AE9A6AD19B9E2E240617E2882F7D29ED3A4279439107AF9AEBEE47CE85DE5
+CE9595A96A118ACF1EB1F5929930321AF7732E351E18C6AD378508E37B4C327B
+0E06AAE21278AFA9255AFE5C022034DA2968D260879B4B38E7EE2E11A593DC3F
+CE71ABA050C004473324CAB6F3C50E85DEDA3E9A27388D8FD3A8F6E42A79670E
+F7549CFAD4CCB337A6E0BAA4846ABCA059F1E1933CF11DC0FFBFF550CC4A1B47
+CF7BCE0875FA747AA854534960F757884505A5AEE0330179A9547A4AE3E68479
+7A457DE83326DC30B67F27CFD4AB697601CEE352F72F0966B3CEE3EA24683BEF
+6D23AD51B8432C3F0DD0D0F80791E1091F38988B7A54E466A9AC7810DE8B7893
+6B0AA6356597891D56190A7660BC7F657BC559E0525D41EC228078F2FBF89C6C
+72D666DAD838CBF0861FBF0A1D4ECC069AA49DFBAE5C56B781A1D5D79DAAC256
+13E3F9B928A2394FC71691E4355642764459714412D6F8EF803FC5F7353822DE
+6CCBB8FBE5AA1F2C7F4D384039D85E7728527DF9FE0239E2CF8BCB7411C000B7
+1FE660AE6A2A19229E5E8776CC83EFF3C27403935756463EB4721C51FE0B1197
+86C2F17842A0FB639F28083DFD4F1E86D7D3BEFA922514ABF489C5CCE93D6F72
+D2EAAE14F6CBA2BE4BBE7D7EA8EA19DB3A87350D4A52064137C3D15A5B05B03B
+70B1DA7328D10713B83974C390C3270AF5A9A47C0BFBFABB9F31063B0CCFBB10
+0F236C74446688198EFF039110F6FF42FA9F82D463AD3958B5FD205BDF85DE20
+FE3F0C7AEEF350AEE6DBC1DE2E2DA4F4599956F59D6F121F7086DC120416E180
+52DBBC4E56C09746938698860F30007091E1CC0351B43990E47208ED495310F5
+7BA9C6AB3CA10A3F1B318FD47C1CE3B9FF1304321F9623E32D315AA9CE64B35B
+F841E6C62B5B2488A311C94937879E5E0E170FA77AF0AC75C5E6E9F3E8F825AA
+09C1702682E14FDFA72D27901C5BDE009B1E52E8C4511C6F6336251BD45261F7
+401CA3DAE7C4B0CAEB91B9954BF4A97C48ECE7FAD401351D59DDAE9DA94E2335
+74A2B880E4749D3D7026CB5299F16C204B6E00A20A6619C34922C7D3FB50F127
+3157CFC08DCC5164C8023CD1B6C3556C73CB8E4ADA845339CA9BABA1457ECEE6
+ECB9849DF1F0FEBC89E5F97C92978A500196520839CEBA6C0FD2E3D27BB4B4F0
+93CB2BB565F4627C6DB62DD0E084E627D69B5DEF42EF094381B62C0D67EFD197
+301B132420F51A41561E6106870147E0D597078435BE3819ACF0DE28AD779847
+F3D2CF667DA06955D53E0204CEA2935E9E984E76963D3079EC092031E2A10E61
+1227E5EE6770DD4D745A52655369EBA06A19BD7D95BBA271E488241199D1008E
+36EA99F8DFD2A9F87B06B070158B466AA4C6EA3BA77DB0F853F0BF9A304EA291
+34069714368E0B94DFCBA3BE5EDB6C8204DFA7EAF5C3406F60A7056407D1BF6C
+CB85C1F432F97D821F5518BBA79AF8453A568FB2C2D025A70CEC75F46C545011
+ACE3A99B2582793BA1DC655230AE2EFD24DE20A01D4A441AFFAB7771F223FA6B
+9169849E727E494247F67D6E1EA9DCA06A082FE2094BD548AD7F08B565145634
+E7ED832FEC1378306DDC796303392ADB0CBA130B63B38ED57B7828B47732853A
+893E8836FE19CCF27002AE92C2B2CACFDF8A42F1B8066E033B965D2E9157FDF8
+E1264B40813C1A4CE424274AA3528A4F09B3B53DD4D23789A68B3D17BC1398AE
+0ADA2C2168427A49846DE0216908C2FFFEF4F13C1ECA12AD341E238EE46E6DC2
+B71B54C52659632911F901660261E493AE2483D64E119D9924489779B62BC9FB
+A052E822FD8D83178E09ADC825DF0DA07FCE7AD68EEB29FAA275A13691B4A5A5
+B0BC0499CD6307610CD6209583C1152C559A2760823F8DC0B9B990BFFE7B7E9F
+3969B968AFEAADB9FC0F1410EBBAA0DB979CF153F0B8C978405F8E6F2B6406D7
+AAFBF4A655A15DD6D1E9A7EAE10EF89264659B09283F50B734236885FC09FBE5
+98D780012FA77FCB19F15BDC522CC7312546C0730EF5225DEA8C22A3BC6554EF
+4FE73B9AEB5C2F7DBD474221760E5F539A064AC450591BCF3499E3968F2CBD6B
+F15BA2B37080A4129B66D4C2188524F025414F14DB3F96049A8B0E5EB2BBE7A1
+AD64A988FE875FE4FE5186BB4F5DDA16983CB052D474B7D72F3E8965663EB50E
+015C72407C3437142D3D7DBC055FA627139488DBC5A0F98D805C2143D99F491A
+167E07AF60EC9F17C36289368D740B632CB919A0E74C412B76CE7A5906D5200F
+9E79CEB9C65ADA3A0F23E8947E834AE7A329A9F0AA7A6BF545B1D7B4666C6522
+CFF268634EA06DB3A82D91A4C0A9B227E79961212881A54A6762C335DE7E0831
+130C45D94394D21C049B9D189ED955438C2151514F17BFC67E431DD9A8349202
+2F616AEC1C7B19F63D5000EB4771370924BD4B9053FE78B5E4A244B9A149D66D
+A8BF3B398396D2233E92E4A5FDC70FAADEADAFD255193D688842DBA865CF6154
+C9348D590F3FEB135D4B7BD4D76A52CB140888247CAFAB25ED51F4D187041CA0
+ABD956F83A5661CEC171B52AF92F9ADE27973B560C802E1E0FF51C4003D1289A
+CDD09F8EDA8AFDFF666D35418CEADF3B0BE298F0D1E5C8E024D6A2017A7E71F3
+3A9FEC9930F1118101E040339F9D41379170928DDF5B5875212B271DC843F612
+E0C21C67263186E3D6929160464D4D5C8928E14D0845762C36FFBDE548188E20
+3B6BAFE5EECA0385142F01216FB8A90C43A472C1D4447FE5C7C78CC088FC72E7
+3FAFA062C338BDE8A430FDF1951B107D8D73FF9376FACDE5900BA362C66F8C1D
+947F9545C5C13A53E4479B1C1A50472C05E8F8C266C6D4F4EB08E97B3B1BA972
+26973B844545089C5732322BCC9A5A8FC972FA0D7DB8BD85D2F515ADE65DA479
+0224F7EA2276CFED0B75B2C23AE7377F86F1F6F205D6FE19377D87E782143697
+984E731F83CA888199CEB425643C259D4FB8B58DD69A96085198306494BB497E
+FE7C9954EF35B679BBE3847A9C73507874F71FC97665E2A58BA41407A1745247
+44A79B588D969D11CE4B863CDA655DAA53CEA5C3C263B345E782006CE9831D49
+603D2D95DE9E370D617F5928BA416C362BB2B4DEF16A5D44BD24B34257765F3B
+6223B3F9B54DAED69A90C7050AB97B06693D253C6894CBD7B497DA449F1D9B7C
+D91B421891EC0724F59C82B9CB288DC42F2D2D7A7F22EE3D910E15953D7766AE
+276DABED3820390BAF2700C4653E1C77FE63DB71A66D93ED293E25B8412A1EFF
+809554BF04ED0DE83F7F190883ED793803CAD2C34A66524D3A580ACDF3C13B22
+08F18905E7A4A16DA9ED2A112462FB9FFE481EC2069E484E8BBFC19D594153B7
+3DED4C11762223B7586483B06BC164D824D1A6FCAE80A35DE0DB8B33396771DF
+76DC5C05578EF1BE00A70BAF3D951A01C87328DB2B0DAD6E1B4C21F37D1BC0C5
+A929BDE5EADF20DA60C4DE2E3C151005814F24824D33B95F700E09A0207EB602
+3EF60DEB1622B91DB99A855A8F1DA96358F05CFCEDBDDDFC8446AE3391BEEC41
+966E594E28D052DD5ADA49DFF65E79540EBE5329DFD86C23CC800F95221B9C18
+CBBF941D2FA47EF1EF59A89DB5DD188E75EE94AD2A79E2221107E5992C00D531
+2E00B544895A9204656867E3DE9D4CDB64B920B5CCA9A73E6514B36CABAE01BF
+94C15603B86780190595560F792E5EF01650074EA4A9BBC6ED284B9AC2020641
+DCBCEE0ED27FE58171DFE104EEE4202759E594159DF45113C00236127A46FB35
+9EC705F21C0E456C1F0F924594C09AC64D4377C5FEEF764BA4A09ABA8D09DEB1
+FC13B0CD202B2F04CF5D73DEAB65C36C2FA7C0DC236BEEF6D23BFFC9C493DC8E
+1831F19EEF81EEDD976E43BAC6B5CED13F901DE59835FC75490EA528A72CEB77
+24C38B258EC38B9E6B97F85CA8C10D8809BBE55A6FAA12456FCAC786942E123C
+06D1E55F7ED04400088BEC968BC5081DC7A1B1B65166E7821679F76694F235FC
+6854C8776AF855B83445D9FF919B1D80E98DE0741D06D6C5EEDB3E3EA6392530
+F1BA817737D8162F7B3A36AC2A03190CDEC654383E31934C3E0A012B639532C6
+26FEBE9B412F1C92D1943B7C18CEF510729D501349644C97F087F2F840074AE6
+D8CD0FB2E620FFC908BFCD938B675A0A4A687F7FBE8F3DD06A62D7B6DE7DF3E2
+49D367D60B10061EA86CD512F5A1BE8950D83C62695E130128E0037B62552D17
+064319BBB9B1FAB9D79705E5D68AAE9B36EA14BF1A59A863BDB8DAD9AB5D7B8A
+E30E2B499F952D65877C8E38EDD7DB29F9579D09E629AC188DB6A6403AB4BA3A
+D358B3770D727A2B77D84B6C9EC17E29D88E3421F9B7D2D822EB78BB8BB50692
+8C46DD6F9BBEF2E848A2B5669B200019802AD19661537A84D3514AEC5AA47445
+2C791E01DCEDF18D9506367241255FFADEEA6183F51A9F42448A7DE413C08359
+52DAD2A60FD606AFE14702BD3B0EC448720FE63438D020DEDFCDE3582FC31DF1
+17B25FC152789D2F17FD60B8209D292D2152DCF8D28B5ADC04F6659BBB746CDF
+145163361823CA343763AA951C640B5D4A99B7787105A1609EDD6A596EFC3F6F
+2AEE2476FB2855F4E5AD91E1779E88751EAAFDDBC082E579A0E8C8B7AE5CC5A2
+E0CC83A9ADBEA1F7EA19CCCB813219196F9653441D5D99D6ECA2ECB2B1D2E211
+B7812E89AAD716A148C5E9680DC50EE792CD6FDD52CF1E3480229AE086F5581E
+8F42C1DDCEDAC02652AD32B78F7531B73CA9EA39DF033F8FA90DBA3D31126330
+0AB0844D233E4751A88881FD5D5E7CBA740B6A4A544179C5B0C83453E1C0F6D5
+2568ADC4161A59C422FF30204C334F1D3E8E7A1D220FA70EA9CBF0B38D6DAA11
+63CDF1CA131F5338E07126051E2E0D4B643A36A44F1986461CDF084B59B57868
+59662242E4FB89185EE0B4DFF28E8B1DF45EA09FACD50E35DA75FA891762F85E
+8BE3A69D94C97D5FA7F1C90D70B5187331B37D797C28A3A5C25871D190E4758A
+89DC70366AD98D5D74F5DBA665F885113CD2E239B65D0E985B783590AEA21D14
+51567BF58497ECE9A3564909A644B2C84AA91D2504539D2F42E0EA32252D1F31
+3345668AA407C5671DDA8C83EFFA0E1BF70A3E67336D832623965E9D223A8BD1
+CE1DF03648ADCB088425C49699BE53783482DA365EFC083512A78B6B0F373987
+2C5348ECB4D1A1960284B7FF4CBC01B07533677BB5AA0BF32C55DB940434CCD4
+F2B24B9773964EDA3C20A8237D399DEB865AF23CFDF06D991E1E96D3EFC1E057
+E2A0D97CCFC53A0C5596AAED8DCB731C9C5C81D980C780E76EA96D1E4905DB6E
+26475138BDBC004B452B68A32411B6FB34C048C52C0B65B89933A49371BD37A9
+06D1C1418F1B8CA575EDA2DE68B57A4E79AC10D7E43DDDAB913B310E2B599A58
+A7F275D00B81BF8DE6E50E797A4898A98B749549892331659BE31CF3C9496272
+4BB2345ABC77014514817B58A97DABF697FE70D5F015B39B2EE1BE8C35886B1C
+D9B5F1F77B282AE5AED5B613AD9552070DFDAC86256688EC321EC2285C060AA0
+03676DE1181E1217321583B42DE5E0F954F5494F9BEA15DC51DE50D432166080
+7AC8C2F535E5625D8A9B5826536C67AE552242FD284A66E5B083DE9B6A778DB6
+877368FFD8EA70A4FFBFDEC00D655846FFC1FD8E5FD499BB73C93BC0C6E794CD
+29334FD3DEEA6D853BACAC8AD3753B8498F4C8AAB207AF5D624D8780AC3F30F9
+A54771EAA474C6BFA593154E5CD9B78EE41E7BAFF988D195B3AE56FB8D852059
+40CCC78B1A79C50868EA8AF396D52570DE77BDBAFEB799FF74A63B510A2E8749
+B2CB7B1B71B4EDB9B5B3A68DFB4D2F7E0AD77CBB6DA95CC9E0AA4EE20241F941
+2DD2CACEE2B37C19A4B54193DCBEF65DF7708F698736C15EBEBF093D2F8EAAB6
+BE26151101B71C41F1F677B732915998E1DE360712E0C3E63FF3AB58D7F8D078
+FB54D50A7BC3C041B29EE521879E4F5FBD18A12F5D0C7F427BC9BD281881EAE4
+A6F6DB18047051C6AA870BB9E8E6ECD8690D090E22072FC2A5067826A6D8B96B
+C1A32DA9B2134CE9AFF49EC3AF6850C6F3930B2133BD330F846636B428D6AACB
+6F0D9EEA42E13DD5562A8D95FBF80B99CB4EC433F1C33132A7DC4592081FD456
+93D61804C90540D905F2189DA06CB1BB0ADC366924BAEA8382363A4901915DE8
+62C750E831DAB0EB4444861BF5243C17502D00811593E1CACC2FE6DE16AC2CAD
+5E00ADD0608472FBAB9BCB232377222D8A0508B0A541C69154B4B9CA3F2AD62D
+4F892A43D191266E3A2ABD7A9492B14DF90F2941B5491E7E7151BD96E0F78627
+DFF3A84D743E9D92F25542A0469B42BF1C8EA00CDF68C8A024CBED39547C6A39
+7DB8608DCC79EA30B7D36D652A5B06B5C93C463A4D7E48F5117FBD607CC626B4
+CB6C015E88D9B5C9F4254D09C3018BFAC614F30A7DE44C9E5B30A11A134D3744
+0F7EF48B75BA0E779E7803B632A0AC8933F66673A376CE1A28F553C43DA6152A
+0EA402E6305B03AB910C2CC37FD064B73985F5DB45011E6EDC35E5331AB68A37
+5715DF50928951B539D5E374ADD338590A2CF39DE99F5CD263CCCD356ACDAB34
+E3383A7F538A57D0869D4497CFD90953A0025887674EECC4146A8069064B139B
+8989B1EF82E5429ED9401634F0DE690FBE0FBDB1594A386BA88766D3F7A7D17E
+AC45D4170E0C56C4C35339BEE77CBB26A3CF7B37C05068B506DDB665CDBDD9CE
+E85BA3896DCB2CC908B7C003B086C333AABDD14C519B48699D197DA89D5477C4
+48F83AA9BDCF086F1952D74F99D4A60B0E2FA5E06355B46DFAD11C407D5C4162
+7F4BF0E7CE49FC03B2C7346478DDA96BBBA1A38DB52E9378F701BF708F7D4FDD
+278957F5445199583CF73DF14F35EC2544650AC01C0C33F5E5DCAACF68FBB31D
+4DD6B5E9682051DFC31500FB17E266E100C7F5CE7F8EA93DAA1A8D8EF1A28858
+31E4C66FA2D4F3E482B1F62546DD571E36EE5BD536660D6A4AD5CEB4EE0EE701
+698C93E04B57E61664E8BB7E69AE822478DE28125012178A49E1A759B225F641
+549B1F14ED44A23C954E81671137C23186D702D625A371A5F80317D4A218414C
+536B3A4202C62C818CE71391F3AC8BD93BB80317BDE1752F51A3BFF271C5C21A
+F12D5C816B1C245AC2D26BE75644C0B82C2C07E306834CC487A5CCB8C94E0471
+BC012B5CAEE8BA91F11FD2CA7D86580C2D590C651A72A26B83CDC0058E0EF7ED
+5681EA2FD864724306B1F3DEE1A601EB87E05E93F3650FB210AE703A705DBF53
+4916ABB67B46FB4116531C7F40ADCCEC1A6C8E9FEB1BC1F7732F83BE2A888601
+D0E6911C79183F9124AC9CF4F31CD3485AEC755A40C4DC80B74A79DA3434A1C8
+1B2E9ED10B4DA5802F25CD1E5BB0CD6685897049C8CCE17CD8970AAB0E3D6D2F
+500C2997F487877DA0A9735DEF7F67C044456A6A4E4371AB920D6EDFEE78CD51
+77F6248B1FDFADB47533C3694CB6DE02380967300210FA0B06EBD55D54E5CBD2
+970D4643F5A60DC071A828546857A0C4FB83DD4C948617B0F0EDA1AC0CFBA888
+6A78B63352F21615A6343A7C3FDAAF6848EEACD2B6D6E1FC644C744F1C2E1369
+ABDE8DAF5E3528152866502C4FB7032C34DBDE182EBBF93DF99517E76CCEB19E
+43ACBAC49E86C16CD431B2E68C2BB926C9F755D2CB0BFC9938666FBF80BF8829
+DF784993709E797B9ABD970E36214BCC5FFF7E7A7EB0E921C183C3835AD001DD
+D2EF2AE8D0B5D001A34E381EFF55E63E1AD43EF232CF94D2E107BFC50034F7F9
+936E377CA06B36C5667C25722B7A80CA89B7553A1701EE6D3B9575849BE414B3
+C6F6AE2F5DB222EEFC38569BA78710BB26FC8516603A292F8179757F095FE65F
+05597EF07E0B7A5909B07BD533C4EEDFD4AD869AD9D84E8A42477B6F4E707D7B
+79CF00FA9EFF0C5A489B5CAE986D8E1FCE08345198DA4DB78C5FCDD0893D6DF6
+E9331C3094CED900015CEBD4CD059442D286D77B710E173CB8221A80244171F1
+B2974B01F6E9B1DCD9EE250BAF26506BB2F118CB98A3A99D85D3E09918F43099
+61513F46D19DDEE823CC7B12D664D2C9016445144AC2DD7ECC80EF843202A611
+3C67E91239A22AC72EA04C13D2A4BCAB6DC4BBD6C49CA7D894204C9E0BF414F2
+4B650ACAF14D69C96429B9BC62298B87BFA9BDA2DAEE4BF42A6A73A11B962008
+45CDD672ABDD8BA7A6598486D63BFD46C04BA5B007445BD2B71D5A5AD1E6F392
+08F58DE71EB89143D3F316EEF75BBDCADFDE6FDBEC4CBB64F2279F66D621CFC6
+1F8D88A0980700CC2F3B1A5701D7AE546D3D4A360286F455B62790DF6D9D2546
+8C1EE14572E5C013CF85B946F3FE1A1F0F4A403BF9111D58353B12BABE98C2D5
+63FF720807F95D97C421180D24DD4D4F2AEC6D99016AF3E33779311B17172B01
+FA7C0F3A7B8EC4BF38B0A0E7399CFD11C65CD907FD48B55808D9C4FDAC57CF45
+1E58F77209456EA680D4E74F695B4BDDD29A1615DA9CE03A5F5F7A3CA6317825
+73CBAC89C61E60BBBF1B090546594A57498B3F584F21066327922289B150B8C7
+318936988DB4E35812DFCB8F2C0A02E9763166CE566F852D0757977E7A7F8B84
+A030E13847635ADF2B4D1C6368A0472B3A516153E2EE4209223E988B400CB227
+0447B5944C9C502217559C8651A8D7AA7CF1695EF3FBE0931126DCD23F232A51
+A69B9A9ED5F1D978C6D4CF9A006E297A90D87E2EC77CA791518DFDFF3D665FFB
+DA1834511766EF8E5E672FD4E27EBDE82142A1A12B73303F12F1564030FD93AC
+D96EB70DC48DCCC1804FCD8BDBFD180A4633B858ADE127C552C971AEAEADB4BD
+B22A02CE396BD5E07FCFA134DB88986A34E32EC1484860ADDA97866DD32F1F20
+51C5F17FA3C78DD79EEA2340AC38770FB9273EC3E6CF9C03DCCC03A5DFDD4481
+5E89BFC46910E7C2C556151E59AE021D93D8A5ECEC62E1E0B1079C1C895D7089
+A18F7DCA3BBA4482AA9C5F09EEFB4D5D7AA92847E197CE278AEC8E2FD2BBFEA2
+DA4764AFE97C07617969CDC578AB5F6BE1176C2FD926B193E72531624ED5C476
+E7C223D314A0041886420714CE9ED7BA13D73909EA77AD7E86D248A7DB86882E
+17937277DEE01371DFD0EF3D994F220360D509F35C41FC80D67F16B316CBB572
+9862FBF0DA654069CF638F2865293A0A96CC9AD701EF788A7D7791C1D75AAA7A
+BDC95F2D4C797D741899B4D0DA785F58D22141BA06D3C1404D9CC76D380BD879
+893AA129940AEA69AF82D0A581378629884F7BC3B2C15489B51C2B4415CFFE3F
+3B858DDFEF06D7B21EF57CC2945D930E5451A5E95B386EA84D352250C1E08FF1
+524418AEDEC6D1A4C3DEBC200D2987F8929F2F868186863D7000078C7A4FA294
+AF1F8260D52E204CF4771457261B4BD8BEE78C7DBCE058CCF5F03BC3F5CEDA66
+3115FBC00E91E5C321504EFAAB3CC9A801318A9DA2A85CB4FA60AE1CD7DB0A83
+EB96A79F92C80B768BE7C34941D956325A3BC0F0E215B52D0E00F13ACB9C2689
+4843948C16B7BEB12FB8A9726AF4480DF108EF4BCD26839BB1579154F5D2A1BE
+99C7EBA628DBAA7404A78C22D580BD801CCB8FC9E69A5659E9D2B20D93A3EDD8
+B758D384D343CDCE2EBB2CEB23BC04375A9ED4E1DAF8E8D1C602A6B73EAA3E56
+69D1BB0208A83E16FD429CC21B1E1E0E719C63A059EF45693C7F296D2D1E155D
+F1B4CCC347461B6E0EBE60D8BB00D6B7686B771F403A10127831D6F37F7B1A85
+D1B91E9F966E1ACE78992FA31B2AA0B913E2F04D98CD97BD4022EA78B5AF95D9
+AEC3AE766E28BA89D850762F4B3C0FF4E4A5A1986F30866878635BC0445C931B
+138DAE189587FCB3B935EFEC081A959740D284674AE01F82F072279D2F41382D
+B441112FB8D3FA8FBDF2E2C0DF150E0FA44EEF94181720CE4CE12F1F483A0CB5
+D0A7BB1DDDED38FEA893DCDDDEE01FD1733758FF4F2E49E27342C1CF51B0C6F1
+8FE3F4DEF13BEBA1A1693554DF91A27993C8EBA88966696361F7A58EE1CACA35
+27D786067F21334B63E3BBCB3C098305731BACBDAC07385C015CC4966077
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMR7
+%!PS-AdobeFont-1.0: CMR7 003.002
+%%Title: CMR7
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMR7.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMR7 known{/CMR7 findfont dup/UniqueID known{dup
+/UniqueID get 5000790 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMR7 def
+/FontBBox {-27 -250 1122 750 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMR7.) readonly def
+/FullName (CMR7) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle 0 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 48 /zero put
+dup 49 /one put
+dup 65 /A put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA
+0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93
+51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71
+7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551
+E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078
+0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273
+C01924195A181D03F5054A93B71E5065F8D92FE23794D2DB981ABA2ACC9A23A5
+3E152596AF52983541F86D859FC064A0E3D5FC6647C3CAB83AD4F31DDA35019C
+CDB9E3DD3FEBD4C2B36BA3CF6E6C7DA85E25D8A31A9BAD39BDF31FD0D1790707
+9DE6A078E8A409D8295F642DF492AC4F86AC84383B0F4C6BAA7C22AD5A898A71
+D6CB34D2CD12266C486B75E75A69C14819DD9BB8159088E04D4717E576B8482D
+BDA52110AC8B8A80E4E9D58F470EEBD3CF44A1E1EE8DA318FFF3611B02534FC9
+F4018C7C57E80570D2F634D98BE5D5EC6D95051157F0EA94A3D12BE0B4B79939
+F82F8D73136D3337C44E314B0B16CB030D9A12E01FB667105F334C3EE965E5A3
+D410D2F1531547A4497C355AEEB295CD3C5334BEE5232992960B757594B89F3E
+52095042DBE6B4DA3C3AD50CA95EA9EBADA10630B500CF1FCCA7D60306743681
+7E428D33B7F7C40B425CD58E4CD8AB474BCE6A307BC6C6EBC15A8A96E0E2977E
+A33389154536F5C5D8CF036D07F24094E779E5ACBE5502C92892F10F4C6DB627
+C7EC4C7BF20B39418A8A85D7FD9B0EAAFD871DDD41F93BDE5FE619AFB8711824
+DE890E62C1969A6FE28DD3578AF43D58A728FAFF0B9FAA640962C8F35A26F76C
+67F3548D6DB54A25CEB368B47F97EA2B0C4D7C0E7894A4F0C823C6C1922CF9DC
+10E05600556F1C7C9AFB33A2DB6F8730F70D6BF94B1FB0887451F2FFEEF3584F
+DFADCFA9A2D4846B8F0E51620E1327D994CDF973B837D10C90FF76DE22B47CD5
+EE3183898D156861AB4DFAD34A1E3FA260B8164E6680BF58413A553E88F6100B
+C4F4E8E972C81A5F88A7DBCDC308B4C3581BCDE13877B976B1F84330839FE5CF
+C78551620EB803DF94A5C921F8EE24F7EF8FC4C3E1653514212631F54F90E3DC
+E9EAF96E998F340C4F729ECF7AB430FDB7C0BE3DF2C0D23015820E28B743CAD7
+7F0AE95413C3EEABBC69E852F53EE1DC260D7F1E712BECEF2F18437DB23D8E74
+2902AAFBC733AC5BAA452DD6F3671859AD836C8564E99CDC4183D8495AFD99D6
+1F0D65B6588CE7546717911E25BDCA6C2649E3A7466A3E2DA7C7994A30AB4449
+672EFD00632EFA8629C1AFB7D53D801028F77C864869FE636213A69173003EA6
+BE1ABA95EB07B13D1594BEFCC95ECB0A9CFA9892EE0677D6B6C250855762B7A7
+8E4E022640F93169DFA0303A0D5E73BF3E0F4D4AAD10FD7E4EB20532BA30371F
+E9F480F9513432946F9828AFB5D4AEAFA5829B2CB544E5EB634C4537EF7DF08A
+A1CFD94A52DCF0E7CE4C5EFFB01E6D50558B75DB4C8D5512B06080F27BE62E01
+2EEA6A0357441401458C842D3DD4C35B8F561D816B336216CE0C14BF77648AF5
+E33912CF95872A1E1AB9A18980A0B29A881D13397C15E1CBA5D3E0B27943EBE2
+F3003D15EB446BCFC1C231832475D5B7AA19E4CFDE119D6CD62D053C6D29C333
+5F729791D17B3F7108074EEF4D1BD101CB33E01004532CB0D716D2E54D169C6E
+80163E70C0E9081F31A1ECBAE079D2A518B790B0CB2CD03DFD034A0F4788E800
+B0CD2DC1FAFDD487C2F381EBAB2A2F3F3AF82021B211DC9CD2FBA6A1BB3D4AEA
+4C7F3D9A5C21DFF284CCB827D205A69638E98D5DD8E36AFC1A4481B5CB2A2E8F
+D6C838DA6F81990F5ED928DC7457501B5C979FF4CD20A830896A460C5DB13D56
+A3B2B5D9B292374A9BF392894DD99FCD6A1E655AB395E839F074D1596488700C
+4E2891C8AEEF66568E82A8B826F9A28FF84D4D9BDA21F638EAF96880B4EBE0D8
+081982F34831A03BEE81FC177700C2360D2A48915EC40D5FE85B400E175D5AF1
+067FA0097904FB647757BB44B4042D30D1557BD0F7922D731142FD682139CEB7
+58CA4C8C240A0B86B1888CACC507E24E04020BF1882BD9B4CAECFA97DB24D7F5
+AD64C69454027F198BA35881B94EE9159A2D73E450C3BDAED66B886D6DEBC84B
+653E165176228F88993F12A170775A8D7038BDF2FE8DC1F7B98BDC02D1E6686E
+9B834F6C0AD90780B17DFE25F0A4E470CBA84E73F2D22BEE09A040F14CFA2C14
+0FDA5A5149B5FAFFE49F55EEFC43831BC43A8326FEE9C7F469C0FC3B000884FA
+41DA7318EB57262CB96FC4EC7F16CA07FE1C3BE8C2DBC8A8135953D6DDF20BDF
+75A2B6D26074FCE752BD32FB9F5CA797775E8DB9BB9786B469A3CD65A0D9DDDA
+C2A166E454A94860EEF5B5C12172DDFC576A03F6E6F8A735FF21A3E9CCB4CAA1
+3064893487697986A42CB5888B2B0A79FA3C74E8187BDDF7BEAB884B70B8D4AA
+AC6615745AEB906E08BF831CFDE222F58D02B428D55E9D5A3CDE74E42D8A2CB7
+E1A3A9439B678AD438793ABBEB72B21C58981DAF3EDCE4BB93D95F4A1E943BBC
+B3A012DE92FED4F232A3A7D60CE60B605151F9C7C18A5C653E5D6D15E5B49A63
+73E7A339504D0ACC74B8B116EA88C3EBA2CC631AAB29F761E5F062966AD2FD28
+7FFE52FA8A115DBE23E471094FFB3CBAFBDF11B7E9058313F2D069B2CE98A962
+64645738F02A31E2F2AC11628724034ADBCEE012721EBF0A567893411F950410
+B20754A7510D041FFA6144AC9CC46D846B82581F20BBD001D34D9764010824BE
+61C30D05E5C5D100A24F1917F01799CF5BC4E50FCECFEA732CB50196825F0E08
+8A1EC868C6D4357857EE2957E081A0E4372E31A8ABEF23C3F2EA0FEE57DE4D08
+61C570175C41AA0C7A3A579ADF593F18B4AE3782D2552E4E0759C32E059EE741
+2D8191E381731769F6648B3581CAF11DAE46471896666F18F02918B0860BDA3C
+BD5DE777672447C23C62ACFC2611ED5239D6A266FDA6031EBC5A530C1A2FF7A6
+B4380B9A4C877267854AD1F1677CB5433F28894ADF93D39EAB94541A8D232E08
+22D082D0951A60F62B87DC028714EC74133A4D65F7D0D1296C0E189C4A42AA98
+28E8AE7ECBB9FC8DFABCC6EEB1E9FB06227F90808EF31331CCC5D4C9A6182181
+047902DC9FD0444FB94B60FC74F3B677758088CE6A159D940C5CF682335E756A
+8BACF06AD7225D49B0002392C889B0FE2C71311D2596F4903D12FA20BA2FFE25
+A0804B4BC282929BE31E0F46B34532CB5795A65218CFAE21F390792DA67775C7
+B91A2BF4C16DE4F6551DAE3A5827F616BE9040EE6B1008DA2F99A01EF66D697A
+6CD1A44E0A15D1F39EA8025E886A68A1E9C334327C7703EE721E497CA924AC90
+7723106D913C5ED4BA4FC743CEA8D0F5172526107DA65775C0B1B77179D336C2
+9B09B608D80B1A1E87CA1A84A833A00D980D919BFF56F6390E9D5B45E9935CF5
+E69D003564462F750F7DCE02DC23CC215A0696B74D8BD3156A392A94F557655E
+00BFAA035647568ED66157FACC585E411F7F428569C147DC43F6E4FDE693D0F3
+9917BEFEDF61FB980B85515FF6424824E2D995B05CA1E5D3E8BD8D3281DB7CE4
+E54923E84058FFC0A8A2C491327D0F87CE4C352B724167CEE224DABA3B95757E
+4A419594BE4F92E78BA6D35D4C93D31ECC3134B24A45DC32445725BB044F09A3
+AA8C31EFC0A2944ACE2F2CE054CF24DB350FB3C71115518C24BDC0F7E54250AF
+9D3378D38480E1CB9029F31570C619A28F065CA4FED5665EDB96712ABEB33B9B
+4232C00C1B0215F08D53F7E430887035AC25BEAF06942FD1B6C442253C887AB7
+D694C1A6115C8990B4CAF1E81DD1FDDD6B03C00055BE956BE7FD8A4E1049AE69
+EDA8593CBA8C4A41E046C689FBBF9F1B64E5856A7FB1C61EC815A56DE2A8ED33
+41F370B8203D4E5B19C63AE9E6E0D26F4F3814B5AF48AD30EC9B8402C941FDD9
+722FCAFC638FBB835F83DC77F93D367266FA7DFFFCB567EF82B1695AB4D94D09
+B18AC041811027229DF431F5CB2BBF6ACCE9D500C8F075A74590641C1A607C56
+D2B8624797BCD9C91C3177818691FBB4744EDB6056464A0B95B8D63F7C22309B
+82D6126E2057BCC9FE5566D96B7A9B201A09B0D3252A5494C8CA2C8BA8A13C29
+37EF2A882D61DA708C279F663D88A8E2999A0F3B6F98C49901A7631BF7708B67
+54D0B4C52BF4BE0DA0439E6763A7C9D639AD4092E77B13D3510DAE1475C978AC
+796F9B2AAD3BFF35C5A3E19B5E2BF704B3BBDF68CE48BA4FA2496D60E58888EA
+28AE12D00E9F0816FAC190590A865BB58569A91BF0345D01230ABA361442006D
+BA2C90EC2036BBAB79EBAFC3F217DBD5854C519235F9627A1C3C71D21ED38AEF
+0BB40F3B86BB9F09A3F309473D8757AB7E638DC1C59A7F9BCD49DE4107A2E54F
+422767FB94048987847205584309397F554744690ACFFDF5902FE5DB355930B8
+71863217830DD7A563B0B3A4025ACE75B0E777B4414B62A13B50C54E0E6D47E9
+D43BF769B9411B74E1069BF71BA873B4B8973EC9BA492A5DEA58D267872BB246
+10AA67B143D0E2223FFB4991E583E629413CC894C3FA4869B72D19CE1A0CEC8C
+0FF5E5A3EC1FCB7D3C4289813F0D249A11B55104BD60B2A89BEF44CC77CCDA9A
+065B8B83B4F4253AA1D535290DCFAA4773452D110D2B3370F9E2FE5432B54A9E
+644EB3BA9BFF62347F376839024CD5EF3C5DFD30F412DD5474B7933E6A1AB63B
+4B12F2417C72D0543C26A263AEA53E5BAEBD67E23553A72E949DEC556BEB5D09
+C4D7A89B14FE4EC68D0E3E9D65A64B285E53590F418EDA8175113CA375A29930
+DDCF4C71ABB26CEB800C2C2B253AC1F53651C88A56ABE5A74F3B54CB4FFDDB92
+60AD7272BA25EC2F6FB759AA6E1E7964FB55AD09F4EB25DE45FD01833947BD05
+6266AA8ABB7DD792941C7A070FCF3A4636FBF8921C70298D42FE92F079DBA2AD
+6149D9CF9EF7264DE6DFCD4429949B15EA90B596340713BD61926DDB2BB23BE8
+F9DE38A31620A817420A245946E551463960A8C5C7295E3B3D6A59BCDF5E472A
+40B7A2CDDAA43CD8AAFC411D037142579D11054A903E102DF0D0C7B5BB854DBA
+F3F086AF991F7F5D5C730F8F9AF213F25786F3EC0E54530FF912F4876FDE16B6
+A07D0DC4FC46EC6363BCB68B83ACC448B801EC43FDD2F8BE0E93D809FF81E38E
+176AE17C67C85FEA58EC95435434C49A950AA955D8B20989C550AB1F1C31B7FF
+99422E1F48FB7D6F327C6DBC4695A03903DB275B94CB39386E46579271870A25
+21823E75C377E9D5B46655E8CD8F986372CF8BA846423E26582315A9D19E0BF5
+305C32B2A0EAC3ECB275B1D8BE11A37ADF524944219D94EA2C5DBDA768828B6D
+775DA8CDB09E0570E4ADDF462EFD8D3FA3F86B1DEECDFFB699AF6507257C1879
+16FC615868C2D51F03CD57BA38D42995D9164B257441210084DC409B6EE4C119
+0B2E17B0A8D5326DD0010E4A325D5F77BF935693BC90A00A28C7B5F74817DA39
+F47A41E32F4F92AA04D30D810F7B1484EB53AD8CFC8CE8928B570314E0F713F8
+AF127227190F9C16BB73D2A217FF801C391A29095DA5E4974D137A0CAA7DE702
+E20DD4755B1D78739756A5E7EC3542B96AD6844199FFA2F5F2E9C64E2DA4FB2A
+ED79869F745C59D235438251BC2E6D26112AAED20E06021D1AB896EE1F1DD2EB
+437FBD4A25E42245C5A647493FCC9922E6DD7AF57D5D482921D1CBD6F0F02949
+C27777144751C1E72F4EE2BC343D4AE7A8A8758123B54FB1A026144C643651EF
+0907A376945E19A8FC7F98A034832A5820A481B0823F980F59623E0511593FEA
+BDE6EFBCC0383242CBD4954027B075B21F10472059A480D6E5ED01C3B07461CE
+9810251A5C5643EC7403130C2246E8616CEA25EAC7A0076731FEA8CC43BCE3BE
+933FCE61067F5FD402E67E2B9DAD954AA77C5BC86BC5E4BCE2ED676D8D8EC7D0
+ABC5C86D82180B9D5D7451C71B5149B6B67883578DE9909317928C0A92E3205E
+F23015400A1763A6FBF67FDE3318AD2696685A1832FC31CF38589EBC7CA1C818
+60D2B2211E04EFCCEA88D9A9082E82951EEB123924A267CB03C48889032F2892
+4227E217FA28F87E01CBF27BF1EA60641A4238258CB7AA355908FE36D90F5CAD
+FE992D03A33E47CA9AEBEFDA57793F39DC6A9E85D5B289F6B862B35DBCF82E43
+5CD6A862F6FFAC36478C384C3BDB0148CB1FEDF55969C776E77917635B5A65EB
+F2AD351D21CD3822D43289FE8EB0FED58182997097C7E9F4373553AE1CA92083
+EDE3BBE6C3BC7009D15AB5FEC6A59E9FD1BCC7B2099CA15FEF083B9CBF7B890E
+CDDDE6BA0AFF306C76500C945DC91BD533FF9A585CEEDEF79238C54E6168001E
+26FEB29E523EE501BFA4F60B782B1499B07084C35A2434B4D29D3D8E2C8F945F
+A9922443B68D07DF7EAA1F4CDEFFC438B597D8943E231B5216808A85F30EDC81
+9DF5DD22F54A45335B4C2203887475F39D247F0E7347BACFEAF220ED82F9263A
+6488E73C1910023E505FDEB143006C1A351D441AC57F9D52D2C6D63D78C75605
+999885676BBBAD56074298E0BFDACBA1830BA58E87F436CC670EE8EB1870154D
+72DDBBF3794F8CAAA3F1E11DE29752DD99EAC695838A19BB67A1FA3829B6E0BC
+5301610A0351AAA749F456AE31ADD87D6ABADCDD1FB3CE81C3713F48780DF407
+530CB284B2AC709F52EE7AD647DEF9FA4D2A867CCEF728F3D40CF34C28D21527
+10160B3DAFB5FE16AFC9D36C6EC4021FC189005862082BEA60AC72B63AD27D72
+FAF3C2D89DA2648FC4C65104A069212D87144E8533CD86A6D73DC7CD9DBA25CE
+7DA53B000266F3871B24663C77723703315C5E4A89DFCDBAB384AE7EB2F455AE
+AB191FED406F7F6EC9E5B8276EF5C4CBA041AC7E8BCEC7CAE840154BDCA3232F
+15711ABD1E867A434E9787CA0A6D1F197597DA27ED2402CB2D84ED082E8D3A39
+81E6EB270DCA4E7A90E2BEBD3CBB3A2BE3CAB926192D7292CC16845B6399A543
+BCFD224BB52F21352732DB5154FA3442733066CDC3E186D8AA97CD801DFBE43A
+116C86889BE198DA88CA978B8C40ACB67E8F7BA499DE68A6FF0DC72C3D00BA1A
+B378B39610F15CA026F95ED8155CE3FFFFA2E2FEB352DBE14CEE1669F2387B70
+55B91185FBBED764266215D518716EDA3DFC9E5DB6B148A553E75AE5E38E1CFC
+6EF47B314D54CF24BC13856F4F7C976BB91D143DE32FF49BFFC87E17885A1893
+BA1B8E441B08EFC04F7D103C1FFBB665194B3D0920473740C55FB1C50EBCF717
+A2359B687FCEAD65616EE89A68F8D91AFACAA0B238EE4AF0279AF5BE5294C3DE
+A7E1F5E6248C0210E7D40683F04B12A933C746ECB517CF94BBCC6E4CF49AC715
+D8005AFECBDFB7A6B417DB8A28F8E9EAF39CEC1CA64DF37A5E66A76C26F721F8
+A63B003A040A62F87DCF61B298F960D510BEFA453F118E59E7DE8CA3DD002EF0
+127EAF733D5C61B5132348D280F84D159809CC71A3C6F7373BBFD8D6EF715D34
+0016DEFF14AA5F960BF1BB9AC304A1823722843547BB4CA5EA4C41C6C2701C8F
+7BDC810443F9DF34BA469A3260009B799871BAF8523C8763544DCD0B382D44C5
+F75046AFF85F0B5A3188C2EE786CEEE5496A5AF4BCB0B429CAFC403FB983EFE3
+61FD9F52ADFC38E07A0FD7BACBA530D2E4DAB2592AA9564843E7E2305047F060
+C5FE4243FA8FDF1B5D4F61ACA7850A604FBC6D6970959752695C90F78961B4E2
+C8CFA41082B1A37405AABCEE5BA3DC2B9EA76F486117B84728EC6D8AE6379CCB
+402C2AA89078EC992C00D53151E9D82C65643F549A572A20F05107A41BE5AC57
+8EDE92AE20B05E2D0C98151CC92D5389A675DFE39DF546A33A84A4C534337ADE
+B17C34E09145B37CE1EB1D10D42CC8D6E6B127A3809F7202381FDB88D42084CD
+0AEAEB8A8288CB56870EA2BE9D0B9DC8291021CA561E2BA388DA3494E433E0EE
+5E69DA51D0AC505C9F71562D3E9750F23CF14D2C8ECF0692FBBCB4A92B48B4B0
+AA2163A2EA883B9272CE7F3630C6CD3865D78C49FB54B677E4E09581B1991D83
+972DECD70AA818D27095A01A1645ADBCD7A5C6BA0828C09A2136D215BD19ED26
+9654807E60D2CACFD440352DF3805E35F8E16D7BE240671D2714A9A870526855
+AE1913A0A914E19B73C1970203ADFC23A8968413067A158380172ABEF962CC52
+5D735B435A0404CCEB570936F54ADF38BA30FA263B3FF106392435C95131F1E2
+1DC1E374FE78B21FAA46D29F5AAC759BD400C843E221718C4EE130D50B8D87A6
+26E1B97D88E1536B3BC263484034C155E5D6F9D1BEB05C198B29D3043EA2FC61
+84BF86DA4F9066618F15A6C0751FCD68BCC17B918ABED0830B0C98F8ACF58610
+0D83491E05675346195B8276AF6FDFBC78D0131E3FB8443829E2D9886E0F12EA
+DE094AA2EC7E8A9A7084B7876192BEE3940BDEB199E6C10DC536B22B32F3BB5B
+1C2BA05E38BAC59991DB98ECB101A40DC768D5535E585FDE1BE847828B0447AE
+C0E610F07775F492D53CBF9B4EED354B844D252E48AD3A48E22274196903F418
+FE5CB587CBF33C0C7A94C97800BC038FF9D303EB4EFFBBB3D9D7A8497AFFCA78
+25590E71928565A72C86CD863B7F1304913A38B77A912C5226E868190E120980
+88129DD2ED8E0D57B09FC0D75AD6696746A3F59BAB0A8D7273CAA84D88BEE20A
+113C2751677D24BEB7F342952EF38480B01FACDF23F5708C01AE2087520DFFC7
+622CC32CF8A4E17CF052CAC90C3E5747091012780EC9AF4EBF243FE28CA5C82B
+B9063700DA3B396B1981C1DAB3C8798A6F88C0D71B8F4AB36D5C4AB2F2B4B333
+0EF21A802562B464EBDE5199AC7F3071117206F9939EC14224035AA41DF92482
+5AEFF299796BC14771306DA6FD140974D2E0A851B35775F0E91C47
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMR10
+%!PS-AdobeFont-1.0: CMR10 003.002
+%%Title: CMR10
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMR10.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMR10 known{/CMR10 findfont dup/UniqueID known{dup
+/UniqueID get 5000793 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMR10 def
+/FontBBox {-40 -250 1009 750 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMR10.) readonly def
+/FullName (CMR10) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle 0 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 11 /ff put
+dup 12 /fi put
+dup 34 /quotedblright put
+dup 39 /quoteright put
+dup 40 /parenleft put
+dup 41 /parenright put
+dup 43 /plus put
+dup 44 /comma put
+dup 45 /hyphen put
+dup 46 /period put
+dup 48 /zero put
+dup 49 /one put
+dup 50 /two put
+dup 51 /three put
+dup 52 /four put
+dup 53 /five put
+dup 54 /six put
+dup 55 /seven put
+dup 56 /eight put
+dup 57 /nine put
+dup 58 /colon put
+dup 59 /semicolon put
+dup 61 /equal put
+dup 63 /question put
+dup 66 /B put
+dup 68 /D put
+dup 69 /E put
+dup 70 /F put
+dup 72 /H put
+dup 73 /I put
+dup 74 /J put
+dup 76 /L put
+dup 77 /M put
+dup 78 /N put
+dup 79 /O put
+dup 82 /R put
+dup 83 /S put
+dup 84 /T put
+dup 85 /U put
+dup 87 /W put
+dup 88 /X put
+dup 91 /bracketleft put
+dup 92 /quotedblleft put
+dup 93 /bracketright put
+dup 96 /quoteleft put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 102 /f put
+dup 103 /g put
+dup 104 /h put
+dup 105 /i put
+dup 106 /j put
+dup 107 /k put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 111 /o put
+dup 112 /p put
+dup 113 /q put
+dup 114 /r put
+dup 115 /s put
+dup 116 /t put
+dup 117 /u put
+dup 118 /v put
+dup 119 /w put
+dup 120 /x put
+dup 121 /y put
+dup 122 /z put
+dup 124 /emdash put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA
+0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93
+51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71
+7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551
+E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078
+0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273
+C01924195A181D03F5054A93B71E5065F8D92FE23794D2DB9B8591E5F01442D8
+569672CF86B91C3F79C5DDC97C190EE0082814A5B5A2A5E77C790F087E729079
+24A5AC880DDED58334DD5E8DC6A0B2BD4F04B17334A74BF8FF5D88B7B678A04A
+2255C050CB39A389106B0C672A1912AFA86A49EFD02E61E6509E50EE35E67944
+8FC63D91C3D2794B49A0C2993832BC4CDC8F7BD7575AD61BCDF42E2E421AA93E
+3FF9E4FAD980256D8B377043A07FC75D6169338028692CCA8CD1FE92FD60AD26
+D57B7519B80A8F8DCE9CEE5CDF720AF268D3C14099498A843D76E3B6C0328F24
+D36EFE7F5C4E5B5C612786200C8DE3A41EE5F1FFAF4097653CFCDC8F4FD32E0B
+03EDB3E413283B9EFB0AC33B055617005BC9B0057FD68C52D1B0E67F0C571685
+767F2AA85ADE4E0104A1C777733D5E318A22A9944336E5B98D965E50D31F357A
+8B6EA5A0EA98E1B027CE68C2EDB149EDDD04ED74A1B3D206D471A0C11C11449B
+DE190BBFEBC08C9E1B7513B43DA3134D6B11A2516E6E86B67F68C970A320D05E
+94FEC57FB347606DF89989C33482BD09D011C55AA920319E7B26A205D3D0F004
+22466F09C0482A164CFB27EF6ED2B040ECCC3DCAF345B5A73676F193D43123B7
+72FD6CFC5E37930E61EBD5A6307E4DE70194E6384EC0D79DB6AD86D3B319A31C
+8B0589D0FE28241D8ACE280D0530EE99C80723E560BB72AE9D53F4713181F491
+344B06D3027BA4E9E94D4305BE1D817197C54C8FF56CD6964165F6448ECC8A8A
+64B48B4F0FD69299A137589E2491A283509B21A3A5772F75B7602A9F60AE559B
+07A58436D04222C73EAEA72DE9A5A441F88D27C11F4F91255EFE280E91A4ACAC
+1E98A4E5E6C57B9AE86FD218C3CD8F24A4104156A80F13821384E529783C52C8
+78B94AB3A0096090867ED32E8A30980E737922037F75F062BD83BF4F5929BC51
+CC22AEE2DBBAAA001CFFBFF41D258424FAD888FFF1BEAB796A44E3126159E120
+7E4025C676CF94888A1971AEF8B6764B3AF4A92D36FAF6FC56FD049710EE3782
+BC2CD84FE2473F133BE03C1346B875463F126DCAB15C7A9BCC9A727D23611462
+4E8D2BFD2466600285D79518712B8681ABCD69608E6AA9578F7BD771EC36E01A
+5A17BC17E375020ECA59B43790ABEB9DF5F4FBBEF807E5699EFEAC563E1ACC5D
+EFA336E75DE6D8248E9381BB110884FDC89C2F9A41EBBC9A8A1F98E6A41F68BE
+EE30E25CA148C1EFF42DFF8C214A6537AB11F260B8C329A4947B5FC8DC9C5622
+4DF7BF4FBFB00380D47BABB03BC30627AA74103E553F55278F538EDD8C1E64CE
+0F1398CA0AB5A86630139B4A7E8FC02804CAFF3830114640AE50D2FDA3B561B5
+C63AD7EE3347804CBB40FB1E77A6C89735DD870351C3A1811591AB493251B904
+314F65791963C0412377C1D02362C5E9655F1C3D4803CD379A8EF24C48218C2E
+DF1165840462BF37DDE1B8D5FF09FA2C3B261E2F1A65ECFBE5D4EAD43B52C029
+EEB3948CB8A252CBAF545C8FA1C31E920E23A12DD7222CEF2D2A513BD758EA13
+DA33BF5FBF1D734653EB83DA2D374A5B9A0CE316F24EE375D6DF6BDA49954C2E
+DB25A88821193636119D469BA66E5DAA9C92520FD4F84426A4E54273FA469084
+7517817A6EE3E21176D333825E88046F50B3CF6938AF9BA79A2F51398239EB91
+1A2D07F7FCD948427FF62F40FF95E39FE1A1AA8451411563FD5388472251C155
+69BDE9283B41900B21EB1190D06E6B13B7794FED020D2C1BDD205AE77B084BCE
+EF628249398B496DE85B406FC2E1939EF00DFC84C07E26CF72EC401BAAE756E5
+7F6673216E7560D1C2A723CB405EE5CA474A07F61B81F8836482F73DC9516D67
+CE0CB770EAD755B6B356198B4B97EBB29C63456953270CCC8D5650C1D006E69D
+38DE2DFEAB27DAD50A817F0D645D30AF5B75A7B53CBD3D2B8D87BD0A7E525AF3
+22F7ADDFCE31716914C2318260C2E2B4664893921B68C5A93334A361D94A759C
+0D7B146D6FD94F0442D672BDA0F6432E18F3C5DFA37ADA378D95B75F413C9ED1
+BB5C606A3EC7DFB3F796F59B0478C13FD1900381EFE0BB5242D5B5D34D03AF1D
+4BDC93EAF8020E26CA23C8B0E7DDEBBC6762A557067A4CE05A524188A8F02E2F
+3625DA38DFCF381727887F5646A3995A8A38A5FB1E5D5EBB395FDD0B7C8E71AD
+B48EEDB62AB2CE99D121435EFBBFCEEA69AE9ED8238B60CC7288DE33C766CDFE
+15B767B4AE2E6CE0965E77272AC9F86023DA620548CFAC85BC751C44218A29C9
+849F1C2DCBDFAD895B54E51A569952ED50F82DC8A19F367E7E44643854EFD6B3
+FCAEB04E55E4661C82D31E2932611748480EF61FB2FBFB0CFB940BEA81AFCD84
+4C6A6332D7A600170E38A8EAFCD4F93DC153C43175434C86BC747348FAC61B76
+1FEC9027C1A193E55C80F1F20B5317AA0A05AAA36AE235F6E49F06E570FEE798
+84857D7552EA92EF3EFAD52DE39C2F8F43C59E3A957B7B926FC95FC4B60186DF
+7F3523EE2AB74E294C8C4BCD8B4975E84849E0FBDA6C0B0F24A636DFA578B122
+CF97BC5089E21E9F5298D1C9F30CB8BAFF6A3A11BB4D9A0A5CF2B18D055C44CA
+4FD4D8FE1AF3630907DE7E585AA811F9CD11FB2C8FC791851D651009FA5DF20B
+3C33FD2FF848A9E3F5652BD294965A332DD3F246C91B0ADA34017FF2451D1394
+F9C3C95AAC6EC8062BE98E8914D51DA6A164AD13938693D446044859D03A949D
+F9AC5DF4A000CDA98BB516D762CB9F6D44B5268FD0C26E88BC4A760C0F75A140
+DEBDECA4F511128B7D2805872160C55236F0A0FA7637FF0D4E94AC079CD3C8A7
+D03A5A56F26B0438B577C46011A10532FEBCAD14FBD6032E224F45691A726886
+56F305231EB2FCDF59C8BBFCB5DBD2D093A0E84D62AC93A2312CA69295E937C4
+8DBA1802B85F54B5E7E6D6216A918F911FF705D3B5CF055F1D873B96283A0B53
+59344D910CD396D883F6F7836BA65FAB4393A773A8F6BC298069E5BA38210EED
+49C9D920F718E3FCE692527DC7CCE6963BF744F2C91BC5952564196D60574E86
+87A0FAB21F2DB2BD5A51D7FBD8FC19946D24E5A228462C4772F978E650ADCE3B
+8D66B9C21279C531CA1C3A8ECE3420BB65837287A7222CC3673A2A5F8BBFDB60
+C719CD073EF9A23675198462C7C87B24CC92D6AEE5C25AC63855CC3281494342
+D28F3D2FDE0C183486769A4FD5B0143193D31FCB2C2A14E487BBD96D0BADBB64
+D1B56021C363A795BF10E2DB448261C363A54A4AC1182B470C457AA82DF3F5D1
+F4B329806141EBD53CAE309319B94133D7EBDC2D0453A905ADD207364371E178
+0A95C2686E3B34C4A978BFC0EE968C39ABA00889BC5149162C2B54483D44FD3B
+5CFF41F611C7E03B94945F414560E874D7CF27FFD0630890D7D7EA66CBD15448
+229059E1C436BB33D69552B5367AB5D53591C4678D0C704DD3EA23F5D9E8A7AC
+17D003C19E333E726FFFA2961F33C70F429085F7BFE3E2510F59B78F58B19CB4
+01B48E184BAD9020FECCE3AF52048A056981DAEA02AE78197E65855DDB170616
+F54278395D9EA50DC83761AE759F9CDEF9E1948E7002414FC05286ED793E6662
+3347F2A9AF8917493D7305B92CF93E8E9185F70015F5594084298A6C2F9FD3C0
+689F262AC9FEDC9B89577ECDE92F08D3142209FBCE7B5C0A840CC767BCA56C20
+4E4E545E2BE4D21C53855CEE4CD0AB35D1A604C0FFFF77DBAE4289752276559F
+A05FEE65F45ECAF44E95E23FAB6052195C7948AF0B1126482D4E02D72BF8AB03
+DE0F1A632F7672AD9DDE70EDC82AA993678A82BEAD0BC2649C4707FD8509810D
+364B5C6FE0E10772E95288C622C2F06C634F4DF8C7FD1432BC9310D5F24FEE3F
+7AB324863D6DABAA1576E70643CA79EF4D7DF4105093D66CEE0F3B87D2164A7F
+26EA05F5C4645B22D3E1BFD2219657712C168FD90DE801FB0F32759E80DEC1E1
+43CEEB19FED12D757205043FC98FEC62D6A8D8B97BC083B4A0E985AF7850D6FD
+8716B9957C1C35A0675BC53DF672C425C79F43FDABAEE7D63F092CF271C9A9D7
+C41F40C4189510987887942E60A412B3EEC84C9A6E1AC7D54D528F5604B72C08
+94B7882621A5BF1F325B92FF96B80878CC550D1AE4D8196E41CB1251856609A5
+C4D3BD05A922D0D45E039D9450DEF8490A3E924E41434194910BF60BA1B08BE1
+B41824345627745541A4F1703E956328F6227D11C74946B38CFB096139979E56
+4E723B889B44C6D78673868C89912F8B4F0B4B485F1587A637B630F92E6072D5
+7F3B44EA6FD96BBD4FC28A6C1D90805E3BE3E42A7BC9C880762966C55BC04E01
+204D083AE976FAE6F37C94F27E68F8C0F28D52B17F6C0FD7C9150701FD78F8CE
+B8E8DC9260E3974005EB5CA728171F482D765016C94D4ADFE4A42EF42212BC56
+7E4EEEE8B0D2A7856CD4E44F55C0BAB762F92CB8D64C17022D4BF3A47C12F5E6
+279FC23101FEE93753653CE8CEDC3B75C9CCB29BF1D4554C6120DE8EE750FCBB
+E38B5D915206974962E320362E59B3F21B3AB1875703191043D03284D4467346
+CFF2F98CEB4845B73ED8E003E0DC94251B73E13A9B51A3F1430BCF6A21EB9B7A
+65E17FA411F53BE6432F1506232B8159E008FA257F884A4A01AC53BE91754D78
+BF14A5B0FBFB9C31BF4908355F8A762052968DF526D118708CCB0B7CB5BEE285
+6DAB6CD2E3934178E60BECB11AAB5478623CF6C50C92F8BB5D1A583609028FA7
+B8A53B791BDC9EF76A124F3F7641857E4BEA0837CB36176EC9A522EA7F41B8D3
+63C37D1145367BD300F17B54522A834BBB74DE12BF9EB26ACE6F24A046D58F89
+4D4B7DF74875F1A0C1C9D97BE0849593D7B398EB4B00BEBC8C8D1497B6EF831A
+A35380FFB7F1AFA4D888AA52C9482E8B1755CC209905F98F40D95B44D4DCBCB6
+67423D1BC2F3560FF0A8B4F0CAC352A4EE2C1D946E45AAEC8A6AD40303F3382C
+DF0756BFA3B1ED64C169E56ED1C760F2FF0E24DC5C9F41306EF8D2628153D30A
+5DCB0791126BEFD4947D7EF08301FE015F2B0008DFFCBF9F2D4D859FD43EC7D9
+C5BE237E9BF6665B7B1BEBB362F0C0C3A8D86010B9C97FA741C97C2E0513386C
+9C26C235B14DD2A58BFDAC7B5F63DB4DA6D5D37D0098175A9071590E1DF66A3D
+B8173A047C29D7D35557F06132CC920B5460B8AFC11D23D09A4E45D089F5EB51
+963FA1A6256E359D485107FD143B2BF21FDE9DA5744BC2615E86C31C89470CF0
+D06C6397D9FCCB316EA9989430240759D2C4945D941F159FC02327F34B042BAB
+B5C3A47C78E8C1A6FBCD396B1A51CC4B020B8AD401841EDABACECDB482D6EC5B
+72D2BFEB4556720FADD49D07307C8B22ACB7E310CA4151A85C71EEF70E8D15DE
+B3B00F26E0E166C14647A65ADA228A3D1C89025BE059306565DB1B1EFC37D358
+8C1EB024254AFD049BA977BD4C2C605050E17940A89D0D4C5D963E792320F5DB
+3706682E03D25D9E02487247819551465092CC22B6B56E93F3AB528038FEC3F0
+668F866707A19B0463BE706EC729D2EE1653AAC7E29BD25BFB3241D4792F5152
+ED415B4E7FA92C2EE5A22E27E8B75542C492E56D811C192E95542A6FE0BFE5A5
+69273C2ABED4300D491B92D2AECDD278404CB84B1BB1BD7AFEC858215837D118
+C0E928BE7E07CFEEB51A6D21375B772B8248C994564014015232A0DA4BEA1754
+3274F407FED0837A236371F1A32056240F2015B1E7F4B2CA72C6B58610A66F13
+407CFFBA5E0A2893C1F572D50F51286E9133B5A84239C9493B0574E77D281D01
+11D00683354A000C9700EAFBC1FD104EA19DFCB87470190E7E2CE26E3A6FD0FF
+2620B87B82AC8686B6206B530F17E9348BC7D04B948348802CE53A312443DB87
+4DBBA5313A6A2A8DAB8A1CC9A594FF8C299281C0A261C8CB2226B732FBEEDE40
+2C6ACC74A1A61379E2E1CD5548CD908268A32FA83D8504C442EA0E183ADBF7FF
+9FD09C037AB03516ECCA93FF048235BD11A25DB07F164512A079C5392AC7F889
+CE96AE5C8D9580BCAFCC087C35E76EED1A671E87C12E3045E15A687134736DF8
+DA984772AFD189D68571A2ED7256F1E204230E41D3D9DD876F938951714A3973
+0CA9310489F8E807C1C7A4E51AEA5BC030610A5D7263FF7E0F9FDE3E5E37A362
+5B919000BD94D978583B942EB79CF2BEAC33FEBC9A67272EB10865BA8FB75FD7
+9D280AB59F91B96C16C982DE848D76D8FA8620DFD7C80B7DEAE7264350D6FB3A
+EF04794DA3305844A7CF718F6D1A4A3AFF6826173A076A1372ABFC54ED3AC6C2
+09C9287FC830556CA694E21CA5342ECA7B10C90AFC4783D841D7B1E34FA3DB7A
+2B706F3E21B0FBAB23E7257962FC3BC309CEA2C7239A9D6B44CC96825115ABD2
+AF9A2566D2F3382C01569FBDB94C8D664A5DA0F7DC3DD140CA77C743D7BC1420
+324ECF9E4780280EB119885E96A6C619CE3C0C8E1E264E2DEB137E5DC8149786
+486D65667ECF47B1A1E20E9E6E4FC8323E0BC8E61BDD3BCDFC6575C69C03E31A
+EFFC290472CBBD049DE3F840AEE37A2486034240F80E75D8A79E0762377DF660
+52B12EAA16D678990B11A9BFBC03C1D4FCDA9FD4FFBB3E88352438102F10B7C5
+9F04C013B6575B5E948FAB58EA691984A0E54E6B9F3F505FFFEF74D06FA1CDF3
+4B8A95904C8A2763AA8AF5B71D00F5DE09DC1CDF87A08B6D181453063E14C12D
+B7BB3775A6E2A901636273D9EEB833EA8CF20FD83AE899E28DADE10EEEC20BD7
+BD93085A4B1AC80AC1AE8280C14767F1A487BD066007A0D050317BD081131A14
+6EA0898ED59E46DA7B6254BDCCBC660686E2EDA0E77A705A653733BB5C5497D0
+B130359F866CF293FB6EF0C2AC5BAA2DB0DED045E2DED3A2612D078333260359
+16CF0CCB272D34767EA069E0F0B0D42327A18529D72E890EDA6195C2688438ED
+E9ACDBEED41E81CA8EB5E43C2B09CE266EFCA03F2D7FF57F12B06F9E54FCC6A6
+546676F6FFC5B8B7D3F0982B6FF0D21D949309F0C0B175CC1D0976F8C55C6AED
+6E821C39041E22D91AB30922F2B2EC2746BC7DAB484991542FBC82D87B487507
+559AB466F73EE23C2D3194DC5CE4C9AE66D3164613AC5CBB3DB501B64DA7C91B
+C7ED2EE9027FC0906820B35D4F2CF66C4F9CE4A884B7C07155BCA884ECA5EB3A
+ABB83F84DB1F5639599DC7D3F51241AB5D95C3BCB7AB1EC90B4BC989F74FB354
+04B2D7366A34D335A47B8C00C05CB423482BF6C7970A95545424A08AFF9A035B
+7F83F52B65A9799CE76E303B85664B624C65E9CA58184C7BE2BB9D9C86A4DE5A
+8165EE3DA2E652B5022EE7893896BABD88931DE1D538F615787645DF5ACBBA0B
+A8E5B899A37321AA7D4B283AC9234978C2DD81813A1EE5DB6EC170DAC1B6EF02
+94892635B498765C07A38D2E9DB0B7581B11056C28278F89B0E60998379C07EB
+C0EAEDC32AA69B8B836F92A61AFD35688315B2C3F860632FC13E4BDFB63214BC
+41CC6859EAB3AC3034449213CAB99FA1D216563419CD6D6CE4E1B56F33E6C654
+7AA9DCB5B05FC068DF02AC32408C8010AD004F6CCA9887830927F8CBCD49CDB5
+18CAC1EAFF815FF2F6F527F936948201565003022C6C7390B4E3C2B219FB4F76
+9F12BD25CA7B3B61D1A2F8DFEE795D04D5428B42FB66E0C254AF7B7A10CEF7FD
+E5ADA5E217BE24851180E9A1700FBA66C7D2B0D7BFDE4F4EED1D24B821A40947
+5620363657F6D048E651A689822CF815E72FC8AE9D835BE31D1DD8B54C9A717F
+4DC319B4B59AE073936EA40B070524C7E71D5A7B64436DA107749746B516E29F
+E3BBCB8F8C473E706670E11E5B221716F315FF097CD1841D0069FA69EA1898FF
+9F9EC2518C77806A19730C97F54BEAD604548D553D4A6EDB247853225E24E7E9
+89D71F6BC94DB986467E755CCC99069B313F5745B02B4BB608A39F0A0A732B87
+7EA2DED68219754BF1FBCA350327572D769C962EF9242132D93A5C8E9725D8D3
+AAAEC15ED0F43F9A1290E91C463895BD12E8A831DAD661EF23CB9AD2C26CFB26
+71B72D15270CD8CB1D59CA2D9DE884C96BB923B1EC8208BD7DCEAB0FC2293629
+2AA1F72C6B470701C381E335C2364CFCEBACDD20CA36182CA7E70AFF5B14B02B
+75CBD0738E35DAD8E60CB3DA4DDED557FF9ED386DA52D10615E700751C842FBC
+85D89C0E713F556814E051C6CEFE7E83C2F379B88A801DDA565BE73013DD56D9
+44D97798564787AE6D5A6A9FB777EEB850C7481B4A353EB9279731512C9B95D3
+2ACA3A0D44585E55AFD968135F6492A9381FA2D126CF50373AB7D47B509AE6F5
+C4B100BE8334ABE2268DAFB7983BF339540A8D8280F3576CDCD4F21408AA7D95
+D50A7C1599E62D4FCAB001D5F9DA84FA530B88F2F8746157E7A60FE8610C87C2
+9592E30AC21163023C7898F2DA2A54906F2221C56AD7A9DF6C2C6A95EBD915BE
+E2AE4770EC9BAF986358B661FF1620D17527EF0EC2614EFC317D9A778DB1DD2B
+545FF4B9938D2EE9029BD66526CBA334ECDDF677ECD1AC125C7750AB21E30695
+7C52294854F30847A269652851601B1FC9768FFB51F71E20BC676767B2D94549
+A80ED3563868A3DE6E265309F863B934C287ED175678E0F25358166DAFF2D796
+F2E0F86528870DB2BE07044913F0BAAE0F953D5B8A1120F4024D2A720C278345
+70C10B78932757C3682BF74A67FB418B338E79C6B136D0ECB93786E1FD810166
+4C2DFD660D65C6BBE76370700AFCC9BC635A5FAB41D757E1BC4DFD8F20C1887A
+7B273A60D565A1FEAC20B3C4C48029F584506640142839B3DBDA5DEB0F755D09
+43B00B3A2FCD87F3A42856BAB4BE44C2FF31014776B3EEF3693145CB14BD2C56
+58C938C2C2489B7067DB31C6F5575564C791F77E215AE12B4AF3CB8D98621983
+A4CA131B6EB15B4271DD9E7B96DF61AE7EAB1C06612200007DE374B7E7CA79C6
+A9DBE8CB7D79D8B639E5A57A779636760C9A55D27FB8FC94F99D4B3778E50274
+88D49AF7FD67872618D9D139C5501915A412A013385761EAA33500D6497B38B5
+81077B9C5A19177BBF30C439E46FAB8D7A009B4DB2FA0DAAACBFEF0A04B27897
+DE463F4C241B9F161DCA2427929E4EA5529ECEB3758E9DFD2D15945CD05B9EF2
+8A272C4C23D8608E72E44379F895D1AD1DCD36CB4D62885608F8D108455510C6
+AB9398D0189A358F18CAC251ADDF3FE3E42C71FE0DB768E1FB8EF40078DBAB97
+125E03ACF2426421F0093C6045DAB1420587CC73A0D514B7D3ACE3A39E29AFA2
+43A214842D1606259688DA0C6F26C51D0AD9C7ED63B8F7759EB99B8A98A04263
+5A55CF2155C5F41C3B07F3C460F00B5229B48D5EA93302FD5FE881F9994498C7
+E9D5E1600A5BD3C596AEF8B61021BC372B7C47A04C7004E4D3B74E0CA329F6D2
+295CFF06365DF060A4893ABFC2682172E2A6D124DBAF4E194DBD94ADD389BFC6
+49DF6EC04984F549F4FF7DCDA5DD9F9B3695368BF85CE0F607A4F4D772BA52D1
+7FC66E06ACCBEBC07AFE7DC3807891D039AECEAC3F500A09579E660C7318D732
+3F9B6752AD3F194F0C8ACCC73F7D8B3CD0113C25175B14083CDDB3ABFE914A9A
+EED19BD229B255F7783ED0E15235B3B2C4B38FC9EBCA27F674FFCDA9F5A15540
+9FA23355E3276C61F812E6638F90CF4F43A855888A638140C0F45C6B35F7A256
+EFE0E6ADF8C7F0FE81B63E3EEB4A0DD6688DCC1B6B66FD190AD3F6147CFB5C9A
+4A7184FB2F524760C29BA3C89C2AA19CC28F17C34BA4C8AD3C47EFE73881B40E
+293796A9A5143464DF9B406DA49C68D134B3DD2B06D394E6C79B375C6994340F
+76EB9B0BB959ECE8C805B15CC28A61DEDA9859E0173DE412A2681BE0218448DF
+EDF16CF2DA1B7481AAC5DDF82AC3089F2C51AFB51ABAE624EF50E7F23B3A436E
+45F5EE5880A5A96C3AE145E3B8A7E61BCC2DA35104BB526053ACC5C0FF6206B2
+953C9350E57657B370295985EF99E3302B40CEB35592BBEB7BC05AE1507D2778
+94E405957E67C432D34DABD05059ACEEC8AEDB587E6A46E7CBA12017897EACAF
+AA3DDECEEFA90DBC98EECE835F2F6E5FBF31E2D2931F8CF6627BC3064CE6959C
+766387E4A2F56EEF9FB83BA93C278215C47FAB2B41C082A1C20DC98478567A18
+C2DFE4478A73544BBC44CAC862797FC5C2B18DE5F42B0018F834AEDEF448A10F
+F12E1781DAE8248A7455393D0D97ABBE2E2E9FCB67D7526CFBD3C7467A15E6BD
+BEF0EFC91D679657FB5CEC58F75A0BBD8CEA4AD8DA1FC52F0BC9FFD1E42DFDDC
+FA6178FB486D2D2A220C388EBC504889C67669FBA4230BEEEA3E262B509B4CE7
+CB5A55AF22AF3C69EFDDEE428C46AFBF0AA67F5ED49775FBEEFB96FF6D01778C
+C5985647EB401680CF16AC19B5BC04DF4D12AC512D1DD5A68A0C3496BCA7687A
+16FB1F681EB443F4EB52D4C75A6CA7AB79DFF9245BE238DDAC4B809B80408BB9
+B61C2DDD1F2CAE35374EC47A70CB07838843899C72172DDDB3DA4865E338647E
+078F1EF7C777E48060E5CE655612567DA35A999399968B2BEC3A2B111D6B34D2
+C6B10BD404BDBC4B8FB8AAA3591FA9981CA6AAB29CCA2414C2B1A5F8186EF42A
+E32E572F6642EA1E449C26554EA066DCD8F1133B9EDA096C2843F871B6C390BE
+93C0CB8ADF6E3BDDBCAE30B6296B96C78BD218AB6DFD16AA490F16C1E18A8641
+C7F54804ED676411B1B59CC34939C0BE1F33A0DB7564F097B4A2ED921E31D52D
+639073FFF921E16BD26A00ADCB8C1E42A8910C7734E5ECEC6E72A40B22AB73B6
+5CC25F03931C2CFA408F85B4D29AB9C567AE579D727DAD1E967D50AC31CBA670
+0277DE0ED8432147C93CF8F1596A86867D4639287B9957F65713AB604224E142
+F3A043B9421EEFE7E6DA53823342F34F3350A3780BC16E827FE47C41AAC23F2D
+D9BF5AC0E79C0B211C49E28ECE61D2B94E0C5EF66E5F42D98E68D617E788B5CA
+C2AEAF593E9B59BCE097374D182906892912A95F4B6F698497C8889F77AA93C7
+7D64A0E6B52AF6683CF900534C8CAFB1077E4268598D1D0657BD087F75314904
+09D02BE3018D0C19A4165AC73F32D01DEDBCAA4053F737146AA15FB862F01E69
+17E4EB64ED996274CFB2E5004AA42F8D865B2C35B2875A44EF7DAF6E35501BB9
+AD0A6699F823D28BC89DFA79F106BB7E60303CDBE5BC714C92EC61C534209942
+BCFB67217D04F6A23965F6DC10C0EE79A7012A045FF72BF9FAAEFC95CF03E794
+D875023D6F9A18B3DC87B157B8F3CCFAF2F1EB9A22C914AE451D1748F08D486D
+E001FF37A35C1813F56BB1A0E289C7A9694E495F0E14BE41FAB4331BFDA9466C
+2612E15C9A68B32DBAED4B5C07434A54C5CA0440A10C2051826470772BD2F655
+410122D1A37119EAD017076FD65E4B00FD203DAF0C11C0552660DA97D3209091
+D8139E740F5AD8FBAC1FDFB0A68E7670C87FEB4412FC80CDBA62F8B74F50BCBA
+6E236B1704C8D6D2EBD3E1D3B565C3923F9D7B9BBADC7D610DB32C86FF6F9DBF
+0F357951D907D1505553F11ACB57DFC241F8D19D65B9FBA531A8C0372D42FAB8
+C427C2CAD01CFDAAD7B363AAEF5CA4DAFF86201F0F01001D38DB57F959FD977B
+DF2844565A6DC515C88CCA391DCC7B08A445684F4A277165A13A1D0CB694E7C8
+C7CB3110415B0408AABAE20A1B96489B78A821417CE269C40120B99667816FAF
+2DAF22C825D485A52F6AF342C057523F44EABD3EF7B704F7641BC26DF8EA9F95
+F99CE2D3DFF09825B9E1E1F316EF8F367ECF03F6F5BC7948E4FD982349D6FE77
+0FD2E54A5B4B6A3BC26AC08DA9888699BE9823778291A59372D14545FCCE25C2
+923372C0A870FCD92547EDA25B5E2BBC2F802F0033CB68EFCACFFD2C035D9C06
+B2177120996E76C827664C5AE756C5FBE2DB836CB4A4CEB8A220485DC4D2B13B
+7A8C38C2A06CEA17CE26737D36FF31765E5003A98CAEBE7C450BBA19A48A47CF
+3212920CAAF3A770152AF6F7C07916C7B7569E6BA4AE0AB2EB0ED5F63317937B
+9B17F18B32D0C89C77B79F371440077ADF646EA9D2299BFA0DBB57C313C49E7E
+3427B1460681115D615AA45056CF69D59D1090E822EB97AAF4E70942F58DE62D
+AE2EAF5159FB19BAE7C86D4649B9442628098D9565A56B696080FA9F6CD4A9C4
+0AB2A4B0E918D19A709B47F75CEC33A0C021E45BE7B53A1DE5101D757346E2C5
+DE26C569001E24261089F5E10980957FD338384130B535D0579D727DAD1E967D
+5F815151F9820F0D260B7DEBA7DF72F17F6C4C051E2458227728783073726990
+5CD09517F295E1898623DE34BFB42F0FCCBA55B1F6CBBAC98BDD1EE923FF42C1
+00B4DB7E3E09CEDBCE4EA84E09999380DF3F8385F90897F3FFA02D3F4C699647
+E9F07C3A279C43814EDB2482F7EBEA50E943D9C01EF1C9EFC24137351407FBF9
+68CD67B7D4330C8C8147CE26A24E0C4976ADB5A5CDC35ACEC705FDEBB03C004F
+BE28B38F1E68BEBF387FC143B4C9892DF4A062BEA11998D025B544A987BAA117
+D60F48685EEE1AF58852B50FD32B243CB4B55833D01438DCE417472A0B5E268C
+7D1B25F8131379A057266489CCAE6F1190BBC0B763C1FEA38E96377C1E4B2817
+754EC8722B1EA719D085F6AFAB86C65B6A8D711C64AB80BF7B342AACEFFE5556
+1063927D13E50DDEDF8CBB58AAB27C30814DA78FF368F112736EC85AE93AE8D4
+C245CF768BAB03DC70130158933F88571D558050D5A88CC53F346D5AB105D5CA
+D2E44E849CAFE86506A9C3B59D1F0962E6FC4D8197803D15F7C2717D78854024
+5DF65D66AFDF95F76F5872C8AFBFE191EB944319F4933B2FAAB2060A1915AFE5
+1BCAC814488E736517865BECAAE5A48793207229A24FAA992C1D6200033392BB
+DB3D0B723C67D825C49ADD3BB95D63F6DC7072B13822F92578128F4AD2C7BAD0
+FC2E01686E24B05B42FCBCB7B2C1048DBE7BF16D11F1C34AA293C19D89799F7A
+C8BB5E75C231F0E1622C9BA10958335ABE90053C9BD61070EC98250D08BCA727
+66F10190E08A2A223755C72742DBAD656C5BB4F116812EEA91BB3D6E443D2CD4
+1875D1A219CA187E5FF1D329A8BC083A45113E80E8D9DF7873E6659F47AC95F9
+91220FFE65073F62299CF20B6063555BE3E334901C00A30394308284A3E244F2
+C42ED3FAE633B429E8F3023F48C5025DE93673C137A935A1B0EF37AE7129C720
+BF4FF1E4452D978AF89056ADA748CB87773840E118EC1DCFD6CA5E9B77999CCF
+571915A94E41658421AFFFFB4EC9F94B770FFED4AEF7C46F2061254456019220
+2FF635D58D5D1C28C6B52EEEFDD43CB555CBF65BFE589C091F0606E2FCF87D6D
+0EEC6452CE4D506EC6CBD6547412B8D8C4F012B4F092D1E63DBD452980C7AB48
+4DC3A3C8C0D12252FCCBD4EC21F59F44180F6EB8DA2332BA9A5DED80CE64990D
+6A97DBB3B72C720CF8E1F30B09B83386CFBB2EF6D8406E19B31EB035C42C067B
+096A73E127D5BC58D1A82D057CCC187531FAE16B073626E584546B7850ADCE5B
+BDFD0DA309D7581EE6EB2DBD340FDCBD86E40E7804EE590A5DACD4E91FE2D0DD
+FC09D7862767B57464C5EF92636705A9C7B3FC252E08BCF3057F888F54CE0DEB
+26C91E4E57A1A5273B7CB1A49988E9FAA1EECD9346D3B288DE374D9FB6AEBC14
+B084A2545E15EE0E468FD87DE5ABF4BA02BC6C4C25B66B9479CB897631CA8493
+BB9AFA640614F0A86292BA30D828327C211A616BD0638BC2274A7CCFC1EA6C38
+81667517BD76162E9276D6881DA8999E911F7294CA962A22ADC887BF087209A3
+A5A959B82CC52AFBFC34824C9984DA488D5E9E64A628D5D0056115A25CE175E9
+9A923F5516665E9C17D5F005F153C8CE47AE8ECEABAD1629D430B9F4D28F1E64
+E11D1489635AB07303DD83B3F1B6756342D6BA59435FD61116B8F9E24B8BAA4E
+E996B6619E3CB09E8064717F604ACA4FE2E0A3A750ABA221B26208E12D921C66
+41AB7576A1AE107FE53EC270D17D41BC43895F2B01178C7725595895F46CC592
+E56F45CB4C899D9ABEED131C985E6F4AEE81BBB1913853E55FA3DFE34BA86679
+0F9972FFB060ABC6A7D9063472315A746794062F9180B2623318EB48586FC2DA
+B409124E2BD6B1156C222648913A22F039CACA201AB57345833638272237BDFB
+C04824EA76B096244714F373BECBBE5E86A04B3D31C8B44880F25A8276DF50B0
+C1ACFC2B1A615F95F314C5AF1A57251D2A955ED793855A16F1381D94E0E97061
+B238223F0DBDFE93047E4035BF7D4DA8274500733B87CF49DEABFDF003B07A68
+A8600B4F00F9DD10C8D37E7BDCC2C0BC28405ED3B6EDC6A6C9AEC1888C582ED8
+5B3CC0680C332C551DD2DF2089238C6159DD16D9EE21571AEBD3763653DDB4A0
+4D22F63C8533D2E05DDD8AC5364B1CC415315741C9887F579D42D6608AE6084D
+9835094CAA3C155E92AD1EAB7758B4CDEC1A8DC6DB3F3E54B5DE3D7C5F23EF43
+A751B40CC3F8A6DBADF13131953FCED0C3886995CA4575D3B471C556D2657667
+04678ADA7247CE99FB0F66E2A60C309431D9F6B0BD01DBDC71FDD1DE1F4F8A25
+3ACC932CEC1E38ACDE8AAF593D632FF2ED520270890AEF3D3CE4E0BC52C5AAE3
+0746F59F84BE98E507C46EF4D10F18898D24CD382B7E75264C5098160CC6447A
+4CD11D118CDB8D1F3010EFC7278FC26ED12465F6D9BFD74BAC09BD290C162C53
+95B416A6918E8971482F526B707C0753ECE6A8C55322AC28E3A3B6E1238732DF
+256327FD2888811D0837595A91424EF29E7231C39BE8FBE0EA9FAF4A8FBFE8DC
+ABEDE883D6524EC75A84AC186EAF98ADC5B10DA69322622163CD749E353B6C84
+8158F6E3A9F9EFF3B0CF9648F4DEF93E81EDBCECCC339FFB62E31836C6962DCF
+80037E4BEDA967967FE5CC5EA60D9FD37AD26EA95E8FA0434A047258AD98F3B4
+18A61188C03BAC8D8AD51EDA50E80FE7865E994B9975EF0083D0C9615D7BCFF5
+331B2997773DDB4A330E470EBA08F2F4836E8D580D8A2F865454A84FEF051853
+377B17E1283DDE5ECDE97178603FA9EBD9C1FE39EEAD02AE8ABE63944B4B6CB2
+340E88B57A7CEFE62A44EB2835176DEA064FFF8270BF0D9A7ED8D4C1E06BF234
+D0D649F4F3A8082C5D91442EA1030C972B9A79477E0927333270284318982C24
+F0A71220FDBF2AB9515902F3812C9C0079707BB4530F1FAC4A2E1838B04A8E20
+0D8419B14F3A4A87F8471741633F3B87C6D45939256AB4B891EDFCD2CA183C50
+B604879445C29119BDFCA860D013438E7F26167CC9A2F3141405210546045642
+856EDC288E441AD5B4268731259BE5D1FE1332BBD38D1B59885E0D18921F11B9
+03274CA50671012290AB8FA479CF97D7EA59E01D86848014CD32A032C7254D68
+551D85BF0753762B588768915B17B4C91F7FD91BE5C026E2C3897DDFEB08D225
+79A9FC289A43EA57773443F534C7D18D61B4D7AB093225A7C9611FD15A99CD2D
+0A21CDD65C8708638245EBE2DB4887ADA7053D9D2CD33E0C118018DDC24CEEF5
+8B5875B74EE824AFFBAEFE1370B4ACFE296F3B9C4C5EDF8004A99D31AED321FC
+39388733CAB053A1D78A8A725B3A694355A674B58DA25ED0536A4900FF89639B
+91E402B3C3598BE0CB8FA915401280EBFFA6A8104EB919F8C9700AE8EEA275F2
+E8BEB3A37A688317F9A385794EFADE63785689CF7E478D6BC16C6DA386E9F2A2
+429307CFAA43E2D61619C0CC037D3E3726F1498EB85B23610F59D57CDA6C34E2
+6F07E268993ED3352BF506337CE21FD303BE1361F7198F83986EB56A641FCEFB
+4B76031FADAE7674D79FCA655A1503347BAFE8AD00FFA31DC69C79C833C586A4
+AD9D7645DD1E3AA3087628B158E42DF0A0C4C915C80F25D5D665AF05813A3E4B
+A043583521DFADEA37106760AD0C70FC72ACE8D492052FEF54BE8E74520C4F1B
+1C04032F255FE37DE4CE4894605A091E0D9419D01194C44BFDB6D34E4FAF2EEF
+F0AB21AF916CB2A6B863F93DC3E4B366B4EA45EB2B9E47B549CBC1B13FEDFF2F
+C691CEDC39740E919F49A2FACBC5A35049750ABC0EB4C0AD801524A63533F107
+0173D7AF2FFFDFCC1A7FE6EADB8D86B1082B42208E6E973800CD706A6C784419
+8FD0BBB8FEA43440B9BEAEAC0218EC27CCEEB7144D40FA05B77E34871A6BCAB4
+82FE7FE70150B339B55CCB387E8A6CF7E95B2A5A21A68D0EAE75EFADF0FB56EA
+F751038129F248AF0BB72343BC9048457DDC5177D0BAF900EAA03D36D6FB9A4F
+56D08FB880A8C9A21192CE1F1A5BAF6CBC894C5E0EAF0B695A69070FBC6CD4DF
+D341E267BA704AD90BC5FF3CB9D30C14B79AE4D4E4DFB67EF8067360BC8214CA
+BB4B0C9B49F79B80E935DE652A2AB2C84497E72226A7B7425BF66A5C926E6A68
+8A04D29C9A36C026FA06B370050CEDF59CD9B3EDEBF3FD22D3C90002074D7BC7
+60835DA02CA369CDD4AE6D2195D179D9310D16055924E050D06D537F33ED580F
+28D76752721C74D858164D8FC0033CEEF644EDF90A0AAEB3C499C930F1BF4907
+37EAF1A017092EFC40D79C9C720734292256649C9F904F42513437D203E22A50
+BB0D8236E59FB71CD5DB6FFB13F91127227A6174E243568AD20F059504826773
+D84C8AD4BBAB15EC0349AF3BE29021CF990CC65AABD53E74EEC34119A1B0DB38
+C5209792461AA86DC4D65535C7EAE3BC25BF39F3EF743FB0E75576B1F603A1DF
+4594215573DC3DAB17C022F4A4CD704E8EAFC757AF914192475873C1547244F5
+4DA91A078306ED495A5DEA22D2698EC1D2B9387A5EA7AD2993C09351066BC5C9
+A5111B294B94E1A8F3B9C258177908F23739958D30A164069024D2AE85BE0DF7
+C21A77A182B5CC741F9AF94C0C9953DC29B3D81869E3E5E69A316098DAD5B1DB
+F7E3F32DD6E22CFCE32055D00556D6EEFB36539AA57C5D08390806116CC86790
+DFB96F01A296444ACE64A841B0237194B10FE3EC3E84573D373B81323A7E861E
+1CC46AB4BD74424A3CD1FCEF4C5843D039BBFADC6136865A606B6262EA85AF9F
+A3CC025FC1B6600AE53D05B3BD73F6BE22FDF77ECD6E5CE190F5F21C4B84FCBA
+6A40BD458A7232D85F96A682E5443FFB5E3E6B76AE055E797D619AEB458B0205
+97121D4B90F4152C9C25890B4BC7DF0CB67F65552BDA022CD58BC8397266FFDE
+C1ED46D44B9F93A9DC9E12D205D1F89C5B497B457B7A036DC1DD8C75FBA69A29
+C8F2FCFBE3D74874A75E7EAE47EFA775822B585E548123D43FA67FD2D1911DD0
+6CC6978CA4F591AFF111064021A64CEA4AB766D232B0C5A68FAAB6743FAF8E58
+6C693D961A27CE0A5B9741E1F61269472272E6511BD0987BA64B65C6DC86640C
+1859EA6438ED59888220A32C610DDEFF3EF5DE0F439265F9D42243C4DA942F2C
+5EDC5C9F9C11527D8B3E21F481ACCE202FE511AE531D71A6EC7BC39A7C529D0E
+63DA2CD368D9AE3FF675A299C7B4D1FA34F9E167165A114733B85228251557EB
+EE20F03069DB8684036FEF56F99123DB8230EF416EB68D3BF8F718AD8B94C2E5
+37D91B850228DDD02D1884ED2010021EE9D4B863DCC5D61CDB88EADB67B1040B
+FD55CC8C3A5B342F1414604AA1AC9AE8113B263520A01618E298A1A5D8C46C37
+DAE4481AAE4F381DC6B1507CCBB8B2CDFD97E267AD009F305538A6648CBA0A70
+057E28C8870ABF1B72CD197FDE167B689AC7BD7D3797082BC93371B4C23DC404
+47A277E6FF7C3EFB2AEB98E44CB0031F034F50670AC101669B359F7A10441FA0
+800F872716F44C621645582ECA81CED557AE92B0DF16A308087B8B8D8954EE05
+BA7ED4B1156079CCDB6FF66B612A95116625DE37FDEC0B90B3928D9C3DF11309
+04479ACA31ED9EE17A750FD6A8016786A77545367E852DD0F46561F664ED1EA3
+F0E669411F157591E50F9D1B1DEF073D3A260F22DB546DC16D6DFE6F4B456773
+F4D13C3862A6B2EE20595DC64251CB6D3BB8BC6278AF3D0D259D05CCBBD0F688
+82B3C0992529F8DEF8D0F6BD82CB447626C887467696CD1E9BA2BF47E7508709
+2460FFB83A86D84F0A751C3F9901F361264684AE0AC0F9FEA6BB562A1C0FD7CE
+D8D760E195230C053110E99E0672257A5639AFDEF9C4E34068475EF1CE6BF97E
+C995EF438E3D5BE3CFFD21DA216DAF570A8CD8DEAC1B30893F43BCAC8BFE6550
+DB6D169944B1542AF9A0B2EB036015ACFCB7D62669E199C2B255C0AE1E0CF222
+4CF329DFD5F2D53868E95E8A78986821E72EF7D17D26C8239C1890F28DD23E33
+FC4C92F5E1E89CEEA780A9DDA9062AE5F80CBA446A7F288994D41078237E593D
+B7B840F762371695CDA9DF5BFA90F60655A4B88CF96A37498861868884D8E02F
+3595C7921940795D0F15DE5A8409F3BA99098C7412DFAFA2F26E5D323E7AFB4F
+4541366C1B920CDC52FB0A2CBB0AC45F9927BCD6E4ADED9A5489199CAEF855FD
+4A8BC0E548E892D76D8B75BF1A108156F74366795971AEFEE7670B7A39CA1552
+E89EF90BF737D4C975FEF101211F4F761AC8F70A0144EA87FDDC1E8BF49683D1
+7D0D51AA6E86154357C77F1B78DE041F1BF9599DC3195FFC78A8780CEBB0158F
+6001CFE13E042EDF6972F5D06DB20652AA6CE9E3E5A21FA947144DD58A3442FC
+0F0042F5E47606BD840D7371986D677BB87437D9C97A424A3974D6D97AB303A4
+0DECF43EA78DE33DFEEB9145503F885B765AD4955638186CA4F55AF3E9B071D4
+B836C3C77BCCF4489D851537B4CD4E5D196D3D05A234AC7BC9A532EA0F25419A
+08AF8435058F55EF559E488F4844AF7997525636676337AF6D8D9331DF5F087A
+B4883C86310E3E65B053A2EAB96D39CEFF4C9532A795EA8BB6E2418B36026AFE
+DE1C4E52EC3640F6D5F23AF1D14AE9D273298F1B1C3D7979264FF712A4E20834
+96AB90E0ED75972B380931985FE9C1641F769B7A1954A5FEF49139F1AE318A27
+EFC90DD05D7FE975DD3A073572D6CAF0D4917FA7FE2AF0930D16E3F7364F214F
+17CDF089CB4BFA150301D56462FFD8C4C9414A1F683D0370E3E6B0907A9FFF19
+500A005BAF537B6A91DE9CAB8E51AE7BFD3C6B73BACFC947AA7B8A808E22FA93
+743CCB9D4F642F23B9DDAFA35E3614E9C9BEFD09F46DD2712F71AFDEEEA2E82B
+804191018E5A65F5E165CFDD0E14C2B051D376D442CA6E43C9CC4118E61925B3
+769D863B82BCF85BF3EFE70270DE3FDF909A9DB5ADF166EE9BB2D29749392C66
+BA7C9AD2E24E51A2C0258D4C441A53B1EE19698ADDFFB9833D3C9D10AAFF6121
+ECBC6A16182F0317884E5CA98021045DC09C95C909CCDB0E0306C8820A1BCA34
+9528DDDD57A02F859D083DEC4C8C6E28D00EA549504D01F412B16AAEFE8DADB5
+03D3B24DD87427492B094B7AACCACD9E55C8E16031A64261AE9A0D7CB7993129
+A29E4A528B2D15B044803683CD5C24C3939441555B6975C2A8B3E2267176F58F
+5EB1C339A8D1754C15A5FDF504080B09B8D5D6018BF1F4B3D8FE9D8870D12AEA
+3CFD66391670B7B5F611B100E07CE804A9E7D9A5C2FB1A60EC0560A6DA86E96F
+46022D9E5B93F43CB14F0CD0941DFDDF4DDEA62A0010A79542412280120A17E7
+02E0050E364CC32D330CCC121589249EC305A68039F667A5DA58D60B0E625A18
+7FA7B90061907F55BAE3574A9D772AA053D9D1705990A5DC1E5113997C96188D
+2F7B63F8612F2A45E17AC21E9427FA0C4255219EB64F733E3E3D1DD8D18A9F58
+A952C4E8E4FDDAF1DA768D6743737C35F8FB7898CA25712F62239D4A650EF9A6
+4AA4B69FBBE017B67E29D6232A43943E987B92B09F9EBCDBE100B0960591BD47
+5238A62A20C11A3BF8A1F3857328C3E7BA4B0F40C941D59CFA44DE816E854BAD
+F70B669294E6AF347D70CAAF7BDE1859E09677DBA4EA9A6DB36E14C4BC3CAA56
+32516A18359F40A84990C9E278DEE775DDE33D6C6E104E7A76806C7594C54B5F
+718F451D7FCDDA4FBEF2FF119CD1EB2D55E5476B69CF6EBF77D05AF9D6FC80D8
+1C5B675331F0019ED8EEF2E3C027B56F1C6012D6B4B1A1DA6E2350CFC58D1795
+9E2B1499F73DD578D489C72EE95EDB90E01B06A8EA0BA3CCBE33D28E58B973F3
+D71AFBDD41AF1F7A056C15C262E992EDB879115075A57C599238F52B78BABE43
+0303F224DBF60B36354510FACBE7E5156E6AA3CECFFC5CCF48CA29B1108C6C5C
+5A7CFEE51E47A249C75A38E620C87E92E3DC5838776CFE165CDA7BFCB476C1F4
+58305C255A14F3A84578295A355A43E13AEA820A43F42F26151CD1710873D437
+508304F71C1FA2FDDE2D5533D3792FE4DE5C438501913690654B4F7670D032EB
+AD1F53A474BC082BD504D5112BC2271037F50605F58F499D1534A3EFD0FB932A
+9A0624481EA99CE04C57BA83BBE8D2AEAD228B5EDD0790C6088CB853D92C06B3
+38995BC172FFEF7A37671DFFEE978B871CBC663ED60DE0B1A2AC93198185FA51
+0C10BF0F9598F59271791CB3EFBBF5C08E70184542C525EBFA2B22DE3E524A57
+3FC68C72442769E3E4731553077A92B3D033E401095ECB26A10E2615D9155253
+92BA319CC9A711C7933BAB39371B30A8FB443653C37D598566883ADE04C277D1
+D1EC22F89046923DA61C4B5E03DFD6EF04EA845A628937C0C25E765E12AEAA2E
+C4F028403F799161597FE4FA051A5ECAC74563856B3A3E835964D82F59D64F21
+D18102A6499D8C264FD4545CDBD1427C46AB54C18963228A17C5A59A4CB4C771
+559D529DE20DCD85D07A1AB3D63D35F84C7D06B450FB7987D28259089DC25508
+D76AB9058149F84A664C3FAF32D3C004AF0C84A283FD63A8BDD18A2275690D75
+46385766936AE0BCEE9F8C6AF8AE73AB15D12B0A605C40F2E566AF3B632DC7DA
+3A9D18BF26BA6B64D93F31CBDB7E352FB767C759881B4EB03199075366901AE9
+0C61C7BB0B72ED422B49713D1AF8F2FFFF9C49C84B39B412A199D30C290DD2BC
+8967A7A7A700EFDD6329E6C5584ADCC7543353AD55D1B8FC1EDE2219AECAC5A2
+6C5031697281BDF13D53708338DE9775B41FAF2AF2ACD22BDA6493DFAF8F8B73
+AF180FFDD56E75069FBEAFB7AC6200F14897359E98D539FD8B088876358EB94D
+2C29153200E5C47EEFA6BE1E6F71BBADFA869B6336E886EE01BFEF1CFE57E6AC
+92DB4A4D91D96765F16D3A311EDF8F0F44E9337555997A0010B518B0CC90DB0C
+0FAD6A672963FB31F1DCFA08A59549F35E179F5D565ED992232BCA51C3BB0F88
+51AC1AD4216915BC24B9ADAF9908227AE1AEBD3B81C848220000C94ED1617EFD
+12A926067EA52FA5DA67EE9C2743DB307304C8AD0052D5B11747385F4C1BA93E
+78DB9B866EB3035865F16C806C1A44BFE06EEA76016B3ACF627A22C321C6AA81
+06E3B94FD07505EAE331566320A9E368C04BC4204B66CBF82F787C787D722518
+6D2A5A64503129E79A132528A337EDC55D4CABC17CB1460A56FF4F02C70DB561
+A4D076155155214A25F155C4EB9A797850B7190C140DCC53F507F085450F0887
+310774EEA9CF0BD4651D69FB954DF151101B69B542D41B838F81399EAFC8AF5C
+D569B1A404DA2F98A572733EE654CA7BBDD2D446E3D40964F0D30742C7883AAF
+1476A0E9C7465222EA57FBD2943AFE78EE700EFC8BDA7190BDDB608558B7DD9A
+23B1E4DF43C30982C55A524734596CAEBC3B250BBF5AC0208B23908447EF0FB7
+EFF98FB1AB570C0CF07DB4AED85AD8EDA4ECB1989B30DF86E8720B08512353F6
+4D242CF9E6EC3EC6E34693E50B537F67A4E77D55F767A7540D60BEB17D88A3DB
+DAC1179E7B5224364E1FDA539BB21E7E163FB12DC3F8BD4D9F6187977ED1E12B
+33F3F882336F7BEC0E1E11045A12474749678D461718C4CC7185ED32A1B618C6
+C3AFC454F7D47BE6460571CCAD7ED584B77300D9C9083D11E9D40A2414485E4D
+BAE521E20A27D2F7EBEDFE0BF9969EAE775801EB87A72FC4612E9C2AD4C28FD8
+D1E9110E45D39C95F521E872672C6399C9AE8A3066205FF915FAB0B0BA16431B
+DEEA4E521292475C6AAE3FD9EF2FB8F16DC9C49880B2C717E04DD2907BDD7B0B
+04F8D33BD28C75356E13B1EF69F35E265DCEE5C98116B35E0084DBF39726C50D
+A72B9ACD42F9445D7D29E1C77CD50BB334D4569477FAAD2381C3F91EB2E9778F
+1D5269ED9638F4096B2E81CD57AA26BF414EBC285CA934B61A2E640E1E5178EA
+AA884464A3214F547C4DA207783A0EC0A731E9154D2465214BAF466DC6B5BD09
+A06615F0116E4827A6D61A2937B123F095C401FE5F85D56AE581C38DAD0541F0
+C737D6CFD32CCFA3439352B5BA031244990AE5FBEDDA56B9D8177E8A808DC3E4
+BAA54CEAD5DD8E4D3B5BC51F2D006C4201F09E9C4FF12499B07A53AE6F1E15B8
+019419744822A61DC40AA7E226E3A3F0F85BDBC7B0780342216A85995B1465E9
+C0B2CA74153169202557823519C6DEE75EF454B245F100590239C6570810AE9A
+CC519E2492D1F812CCD05C470D45F1CC4589FF5FA056A3A6A30B38AB7589B18A
+4CCBAF971D9D435F95543E6F5CCBC57809367E0BDB1097B67A4BCB91D378E110
+D1726653BC8D911E85428D9D0FDED249033968A382BA8406D7FE1CD7326AE12B
+896F41B4660A75B6EA950E7D5A469F4A749BC0C19CC250D40F83942D899AE43E
+8AF0EDD860E413FE7FA4B292DFF210C382C307C3EC17B8055F54054D63EA1E87
+EA4F5A7D4FCCE61924C77CEBA4EC2628598382BD26B23C4B565B31FD04E12BFA
+3A0B18E888937B6B97A5F7D1222DDA8868454B81CAB34505D8A7D7F3F5470BD1
+BB561AF3F05EA21AA56DC1E79EF12309349B8E525C1529969846670A9E4C4E43
+5632C46413FDC2F9945837B42EF3A2E775C968DE303BEDEDBB48C4E30233E2DF
+A7E2CF06B0D2F2768D164B1B9529CB4A9FC0722AD961D12AEC0C68563B5213BA
+067775E651894BFBC428A2CE4A1235E6C37AAC9595603AA8D700D34471FC0058
+892E10A0EC34E4F78CBFE934041E8E5BA70C3D24792D912D726DB197D1C0454C
+CC6ECC7C0C8BEFE4B298F398780D76790424ECB8B009CD4E7B8A60AC372559BB
+A79DC34D08B87F6E2473F5B44E03F6265E426E60F15BA068B354AAE4C2D88ED1
+2268A67B193B82C2D7C1F510F6529D208FC561E7F1DB8552CD18E811F2B381AA
+6761DD096D68C094046DF846688227EEF12BA037D756CECBA796F065447BAA26
+A959D465B74109BA18E508CAB49D295173B5D955548ECA177CB80DCB703474F0
+281D0555CBD696611751272E6742E294D4B0045FF108193DBEAF90C16D564E91
+AA0AA9EAE96CD37A672D2FEAADD043EE72F1E674A874525ED7F0C45059476C7F
+69C39F459C3D8D864AB4BE8A5119B439351FBA13EC5D7F02B01CB922571B8E5E
+DB07E936748E9D65D20C7806A8074B75D9EF83F8C2BF48818373C3B3214B39C7
+68FA9C93C5F3B73489CB5A31CA693453638DB01A7896DE78C5A305C157537F82
+7E04BC73BD758AB4914844FC04009631B43372B56E8C15E550DF331AB070EFF0
+629FE2D7A79A36A152AD8FF0D2600EB9C98EBBB72B496AD659E1A373D5BD3854
+EC046E43E2C96BC80C5B421E2B10C644CED50169D6A8A07C0CAAA57932CC4E61
+3410D466BDFAEABFF0FF17941BF7819BB6D00C06E353F7A17094462AAA8D5320
+2D7E49A392C1896C373FCD801D3E9B376A8D918AD36B8C7148476C7BF260DDF0
+E375D4B59EFC7D1871960900F68F873B37925BE02371F6889B051B7031B050FD
+0096B0E418FEA14D0BE256287BBA25ADF44E706DE035D33834CB17B8FCED456C
+7E845E76F8404DE2292BDD35C115D5CB56BB9EBD0A84B11CF537F2A8BA7FC974
+20DC53FAFBD227E0221B7FBB529030AAA9911B80C7E91CB25DEAB06A72D76BC3
+7540AC7E91E32A2A3CD92B5E8775148364FC0B9B134103ED2A4F22E83806B655
+176F255AC04DF8C2D4A254FD26CD38B7F50790C3B45CEDA5A7D17F5427057169
+3C3CD88527AE000647D67230E246A650FC8A6A9F55CA85AAB1AB3E8BB5F9CB60
+A2B2B7D3DEB2719023C6C64A0D77BF899B6A952E6FA97C2599DC4F90709E0975
+18A9C1185BF00CA2DD872330A7FE09BA82E2BF2E7CF82722A0C43D6705F07494
+1D0A2496F48B83647ECCF95703513B781AD65B4199A3F4CDA28B39FCE9F4BD6C
+2E13812BE03D9F3E8F809460D73C25EA81DF6CD676AFC9B1AB66C25BACE37D09
+FC6E78EEEAD585F53DEC03F54C675830DCB17B65A516449B0E9C8E1C8DAE3D55
+BA2557E9698D4C1C4F72AD082A8F26528F990CFF4119875791E5FB3569A7FF3C
+5D04AB6665FDAC036157FE49104B1D4557B9A3BE087C3FFA72ADC15D75E4900F
+102A8CB40284E332B5F89DF3FFAA26AD98BA67CCEC68AAC18FF68F77F3836B60
+6CC19287478BED9FD32836EEA8358353D09C1716AA25B9512BCA51F1CA84250C
+D1B028438226AC5045ABA3C9A1A92AE40AACF659B913971504697770AD1423DB
+F2768BFDE03A0147DA585CF3477702B21DFB57FD9BB39E39B55F9E11F9FA1553
+50AFD3ECB1DE71E39473670D16754711CE3946DEB9D673214687A0DC5E409340
+83E0D0A07C10C6EAEC45B18D2F281917960FD385E9C9D1D73B4C80FB6028E6A8
+785DF08047236D86AEB76093F4F5C830D8F3249A346F2A7F1CF380715F431F55
+30037A9981B7B744D97BC0011D8DEBA049FD140530EA8920C04B03D5A186BA9C
+49DFC4A2A61BFD6C1396CAA0740408D13986BD3FE2F1BD3076319672DD9C7A9D
+F1C287AAB3F198D03799FF72F5DABBC0C294AEC4092C1B220F542115D722369D
+C1A58EE387AC12DEC80512EC3E0AF70270D0E2806ABCF9170613D352116A2889
+73A116B0DBFE39B54ADF106BC33438C8BB8FE5A2499C58DDFBE35F2F700F2A35
+884BB49D25591CA4D3F2B2ABF24352755A14C4E5F213EEDC40B112ABAFBD8295
+37C2BD49A7EF58777C4C28CA13007768AB00751731F98E1B8955ED4D2421564A
+E5D0DB68744ADDBB342B4F8FF0B594E476F52B2BF41170C80952730BEC40B51F
+65A2DEEA7A4A4D459F2C4718D344BB50E6C875CEAF26D5CC6D07DF77590107EF
+78DDB78A6C6A55A49553DC3F56D3B0C1BEC40DDF02D74D79A3188CAD6B2B7322
+DE4F5F28203627DB3B77394F05DBA511E62AF03B84BB819B441F1E5DC62F5E72
+2EACFDD4F6A6E300E7D7A75FE0AE861B7C54D9824305E80B49463945B1B0F001
+A06BC3D82B467198028B02AC42139F8829BA9972B1C7AA6B02368F37B0E8B418
+CCF7AFB508E3B585FE408E9C1F0428C6A3D4CE846491EE5FEB4FA9813DF4866E
+311D5B69922DAB995A2ECA6F000CF9266CA87C27E63CD61EC39804DE1C0F569E
+D04E7E4996953F36B0E995BA662327B9FF8FB6CCAA7C1990815929F2AF0637EC
+1D91D932FEA8A730E2F9FE49C5DE524D03D03911CA09AC38ED6E2EAAA2E99670
+0989F6A1B61F4E56992349480D7E27041A73D4C90C204723A8764E84444A4894
+C908BC6B69003B81421AFD07E991E2BA8F1B198405B8F3565D1687A40A9A7261
+9C812885B4C8E4411059BBE9A0C0FB2A67B3659A2B00CD8BCADE424C090E3CE5
+4056B7762A2161890703174AB88ECA83429C3814E967B8A5F1BE5CC8BB95CFF3
+7EB52EE4D294785945796C8DFF48A85DB0FFAD3E348D2F868A84B3EFC50AD76F
+091C808F14C210700636981D68B49C328C5F7C3D6AE4E7F6F9602DD4F5D737BC
+1ABD48E915A1B46F949C417251B1B32871A659480A0E78072171EAD52886F3B1
+9D6D6FFD83CB255475B698AA1DDD51348AA52FE3F7395657BA2F0445C046BAEA
+DDF883D4F6B533408F3D73324752B520A8564B9CAB43555F6A2B9715194556DE
+F6D53F9D165CB6298146519D26A4B05694507BE29DBDC8139659C80D8B8757F4
+C50320B5D07DD3D060B394871D38F5E2A67909122B08F0E48194627B8486C64A
+A7A31D4B65F13DA134347E9E38C0C8AA0BF0CB613A192552CB0E963E1377852C
+932F62749619C737E71C5B243CD3E60ACB8F4F89A37A113C5DB4A2B80B01E42B
+7B5ADC7111FC1BD334421A79B9AF7F1672CC4A341F6715C21B56B8AE1B540BD6
+24E93A8C4AADE37C635A0541D27B4FE8325A90141467A71207F6CA1E1EE5C7AB
+3C4107EE7E72A847B84BB6399326E807A7ED6009037E658B2C7CB9065D354CB1
+EA800A31C497E9F0E04AFB4AE80B97C0E20FF9D5828DF37B16B5423867F5E5F9
+9AB5E2B9CB419FAFDF118CA69E2BDC5161F3E242FC9A212F0E1D3EF8C00FBD03
+A718534C1751AE465DBC9C52CFEC73B49703EB6584E33CD6F6133FF1AAC8DBE6
+E37065B637C7690CFED68DA923180E4E1E1B7EF0C780B37E18D1148DE9498E91
+65051B7019E0AEE66A61B454CFF9D8A31592530C4D35C0118B4037EACACE4EB5
+E74513ECEF747A9C37DC36742920692ABFBEC85CB40D92864ABC17E825460DCE
+15581B05BADC7ED84A06E9A85931E7383289D2F4C27CE63BEE24DBECFD760E0C
+B475268963D497D6203AAD86821BC70BAFB1E5D4D1443CA164735A60F8B61190
+C4EE112A3F42A9EF8FBC10FCE90617275E3EB5D6E3F045F5F2C4B00757F8AE06
+FAE75483A6E34D48B51C6FEF6AE91B2EB0ADD0875EE526CFD5E239686AC97298
+8F583EEACE380541C8CE731D7E57B9D7B2E3B843B62522E425D69B2D0856262F
+30CA9BAC14727810A4911973FAF47CB8E82E5F311D9B3B2835620C1E04161D7C
+97F9DB42021C0098BD1B6D408E4233758C8379980F766CA73627F819F4575DF7
+2BA28939CCB167494B0756B0BA7151422E0251FDAC40E8B97D39FA1FCE4977EC
+0CC9D3D768CCAA7F74311BDDC5AF1F67756B41EC9A2B42A61C6210D3E032AF3F
+ED5F06E3E9AABC8D0549993477667253A7AD0D8887E64FE301512B2DEBEE360F
+36D35E249DD79744B38A9BE74976471767D977758047C94BC472B84D556BAA89
+C14EB7861F4C66C047F62BB5E7C7DACA79083B83297F997A26B787070D4E64D1
+A6206E66D78042F49F687BAD1174364936C2832B48252D4B7109C4D89F74FB61
+33581595F4628167ADDF33643CC512EBEB561943265467094DBE4E42463BB068
+0596DDF52110083DE5D314869C9999CDDF0A1C4CB64D52701697CDA9B2B2ACE6
+9FEB83472527BF73DA442497B141527CC4A8E7E16A5E98DD9D2BDE0BEE73F0D5
+C40BBF6D856819A8D8E940F7239EEB012C211169CF3E22496DA4A3F4517E98CD
+D1F643F5E691DB9C65790C225FA2EA55B8295498F19FD44E8AF057F7DA3F7DB4
+70D2B9FB295A57ABC9ADBEC0D448A5EFF0EA278F4B6D4FE579916E2402977CAB
+ACF70FC79F65939B07A261DF3542B4F4958DBA6E8596C7BEA437353B309C2C80
+B30F64E74B82E2A0DC7061BE6AB3EDD9859C05972260976176FF0DAE3DFB08CB
+634860289B4B1FA3A15B34FD89E32F29A0C68EFEA0EF0BB908D0858C71A0C89B
+CCEF8A03CABE7D68526846C8F5DEA18BC3044E8A88D0435E0F64BA4B8172C86A
+632ABAC884E331E5BAC8A78A081683086076DA8C7DC1FD3D12D91A839750EE4E
+3B793EAFA48C27531C8E56823FA8CC62D568035C30A37B16A1131E9AA1D82FBC
+A6AC9B56353F15FEF4756A8E8056ACE512CD7B4E9FE6B4CAFE23E8BEF99C182F
+503FB5B912473E6C1F1C8C74E1454474EBB9346DADED3294C61D997FD8D5378B
+01DBDE07481C7D9FDBE4994B2013122273F2F25BD36AA58D4D63DF00810D792B
+5C90E240F76ABCB06B018C929E15B4F54EF11A00930D2EF39551E0FFDDA45375
+2FF8E1AE6700BC669518B02610B7F7B859638FDAC8F4814286ED75B776FA639E
+B6AADC3ED88B58200AB680F1B25C4FD7E079C3AB654066C666DFE0F52087FFD4
+82993F0EA8BB87F37D25305F67EED67F18E93C2BB76942FA8C6D4E7365385530
+849BD2E11AEF151F68A9EEB5E944C8B4EE357B448D7432D62D32609B7356F03D
+613FA7BC221DA83F26121BAB44F8DD0A79006E4D4D361A20E831CB3ADCC3271D
+FBE71974AB048E748A8073030F81352E876AA6A1AF623DF6A543C7539DC3953A
+B5957E258564826D4468DC0799DEA65C4ECEA2CD876D4DB7608CDDA893AFEA9D
+ED0DDAB30E5A27168CBF9441EFBAE959EE99E13F7D7DECE56A82BE04F9FDF591
+0E96F3C09EF7F1A2008B7DAA48BEE9CA111C29EF778E361AE82231AE2A51221C
+7B1D5CCBB7C5EEDF806209675F99F065FC0CAD2E194B02B9DC531A95B683C550
+F7908B461F5C8F2A458FA87FBA13A3D735AC75D8D7787DCE6337A1AB30ED5F09
+DEF32E147E505795F9C339DA9A8C77BE60EAA79623CB627B219E92FC9BD04F84
+671F5C9A02E5E15F491CECC15A4F33F4982E464FA1F237DBE7E9E01F378F7114
+CC5E09383319BB794875E43423052FDD30FFEE467D614B9C9F249C73C7F6B2E2
+26E4D82F09F035F3D42CDBBA74401CBBF4331F51135ECFD2CBB49647D09F58CC
+F00A78D223D6650D4C2A460CDBDF78E7C664F984EA37B12485CDC165BBAB3BF7
+2818A4A6B70E668E65FC028E3EDFDCF36D10E5733297D2160242D9FDF865BF8A
+D681E75AD45B2A916684D4584BD5862AC7FE470ACAE0DF18970C906A62F931FE
+56DE8FE533D8595D38D903C71CC818C6E1B4191D5FAB2B106616CF67B20160EC
+8BD4399672F2B27D8BC65C18CA69FDA610CA10D0F750E4EB4F634E4174E68C7D
+19CEEB238DFCCEEA67294785C2D64F03DB37060C501A6A40EB07C1E98AE63163
+50C61E12FF1112FAD1DFEB3CBBCE42813BF0F1FFB369441C4FA4928A6484C92F
+78068EC74A29506F0D3827E864D2C6C883715C599CA674F025B9765DF102036A
+221820AF2A68C5934E382E7C31F99F6BD97924814E2C36E71DEA049D54D3DFCB
+3AF2C0BE356653795EAA7E115710C23175E29EDAEF2D44C59919D0E80F7EE044
+C6EC960B3306E72EA8FAF860AD61A0A63656051E25C2529B6B0590058EB96FB6
+D02500428DFD5FF181C215E5D921F5438433D3A85B41A468D6B2CDAA6F36D5CD
+16C1FD67D482EF5F4CE0121AEE2BCC7934FEC104F05EFEC44D1DD3DA08377CCF
+B59F10BB0530FED3393B3F218D8FBF0645A7585A955A8B88F084FCCE03B0D431
+44AE84458EEE695FD5D41383340DDA01A92DC36090AB92A467F70B881FFA6D2A
+34D59BAF4BBD77322926418514522326E4C308EEEFD7CD1910FE800E01A1B8EE
+9BB2CD087A7900457F237930144DECA8032A3A7E77684FBA48C7D8C8079F1A59
+4C2D30C2E34E73E6ABF21683007EF0884DE8154B4797EC313B8B0F7FE5E9D0D8
+8FF490888A9CCCAAC8957AF4DE9F4C23E19E6144C4B03B359EE91FA75CF773FC
+A857D61BF38FB137CC947EDBD8EE9CE217BCB2A266AC3EC95F6A03CF779821FD
+3C21DEABEB020F39BCAD3E36CBC15D96889D1D326139F85FB6C243011CFC73F9
+C305D55ADB0CD458273476DB22AA2B2C8E7CE950B361463A88CA88CBA6586E29
+39D34E9F19EF2FB66AFE46B918836B85522580827B7B52B6547806D6996DBF07
+3F00F1FF9EAE4FB3CA81FAD1A35532
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+%%BeginFont: CMTT10
+%!PS-AdobeFont-1.0: CMTT10 003.002
+%%Title: CMTT10
+%Version: 003.002
+%%CreationDate: Mon Jul 13 16:17:00 2009
+%%Creator: David M. Jones
+%Copyright: Copyright (c) 1997, 2009 American Mathematical Society
+%Copyright: (<http://www.ams.org>), with Reserved Font Name CMTT10.
+% This Font Software is licensed under the SIL Open Font License, Version 1.1.
+% This license is in the accompanying file OFL.txt, and is also
+% available with a FAQ at: http://scripts.sil.org/OFL.
+%%EndComments
+FontDirectory/CMTT10 known{/CMTT10 findfont dup/UniqueID known{dup
+/UniqueID get 5000832 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /CMTT10 def
+/FontBBox {-4 -233 537 696 }readonly def
+/PaintType 0 def
+/FontInfo 9 dict dup begin
+/version (003.002) readonly def
+/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMTT10.) readonly def
+/FullName (CMTT10) readonly def
+/FamilyName (Computer Modern) readonly def
+/Weight (Medium) readonly def
+/ItalicAngle 0 def
+/isFixedPitch true def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 35 /numbersign put
+dup 46 /period put
+dup 49 /one put
+dup 50 /two put
+dup 51 /three put
+dup 64 /at put
+dup 92 /backslash put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 102 /f put
+dup 103 /g put
+dup 104 /h put
+dup 105 /i put
+dup 107 /k put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 111 /o put
+dup 112 /p put
+dup 114 /r put
+dup 115 /s put
+dup 116 /t put
+dup 117 /u put
+dup 118 /v put
+dup 119 /w put
+dup 120 /x put
+dup 121 /y put
+dup 123 /braceleft put
+dup 125 /braceright put
+readonly def
+currentdict end
+currentfile eexec
+D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA
+0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93
+51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71
+7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551
+E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078
+0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273
+C01924195A181D03F5054A93B71E5065F8D92FE23794DDF2E5ECEBA191DB82B3
+7A69521B0C4D40495B5D9CE7A3AF33D17EE69979B82B715BAD8A5904C5DE0260
+6C15950CCF6E188A0CDF841EB68E5A2F88253E382140F87C87E55C9EA93B8C89
+14A36CDF630D6BE7CD36DBDCE22B21778E8648B97B7EC6742EB5114BDF0454B0
+0EA7B1FE236C84C0E5308C871F67B973892890557AA12E00B2C20C71F516C397
+3F3BBD14A1D0149CA064391056E45E9470FC7F6F556ABC82653B3C8049AB5CF4
+BA83C8F2158C236B2FFD4208846013BAF4165E8BB8D334C8FF2E8D74AF5DAB2F
+D44788869B08399421AAA900ECC6A2D594641C121660D4B5F512938994C18DD0
+FCD9B008F68F0351D21ED735B2740CB1E0C1CCD25EB548C35B844601D98828DB
+556F71D07E081A593FF12DAF83676492A0FFE16E95717A07082B43A966C1EE8F
+8A59E1255E1705C43A23CF29A5E4A6547C93F1680A870EE7BAD8CF74D838CD5E
+F806911D8FE4262ED8E7F5BC58B92C9C6D74F8AD45FBB021EC7E97393018B9DB
+B1B84E7B243ADB05ADD3F1DB3692ADC5D47FEC7DF93080669E63281F1576B673
+125EDF08016664BE73364F65389F7C3B66623AD1754ECBEF9E5CE6948D933787
+A5674279ACB2EBECD3B4E6361419AB32028A27670C9F3E18B746A10B00AF6D77
+4EC00E3BE521C02A99AE5BAA98F793EB1228952BE67934B91472E01AF7B816BC
+56D7F19F631A1927846D800C107B1E9CBFF9D2DD513B4A8CE2E0DFD77B1ED178
+E43FA7052765E9FAF89989D490D8FEF6C536EC0D4AE27A74F474B98DA9E6B92F
+15E063DB260571979A5DE2423920CE1F59F56EB11E00E3BB9D466A8263E1E385
+2014BEFDA8D1EA3EDA04BE32AEE6CD15C5C010A1DF7F705A2C0C18E87C8DCCE9
+05D9163181CBA56C0FAC8C06A2990554C8E759D076B01BBEADE3B5FB8B551390
+6C8E4A2A1C6E7D9C708614626F3770C0AB7DD2027469C77975C27576065862AD
+04E5E50CEBE907E3E991FA0C627302C0E207B4D5992BEBAB5853AD1C0D271728
+C76F40A79392ACCA7358F948AC65DC823CFDA59E1FF69CEBB6B7EC3CF21669E4
+70D999508F9C49E2D9F8818CA53C977D93E15FBBBAF75B1E84F0BA62BCC4BAFA
+4EEC82D804C8A8C0210F3E5E258BB1F6921AF02BA9861BAD5C3D5FC8CEFABA8A
+A607E547B802096F7AEB09FBA99C83C9A494B94408DD607CA6561A6E6660C473
+62CF8D35F31D052F6C6C8138A8E1430CBA7EA6973D6D510C1A06B3FBD79D9364
+240C1A00272DA44B89A9FE8D5BF36DC1B5EBB4A78ADBE9C5EDB485F093D9517D
+69E1AC9A8E6C9D7C324E3797CFEAD9A18E82E03F69B2CED7D5DDCD1A218BF2E2
+ED2293AE999FE2A4B5213A10083EE0407BCF8007670B8C737EAB30311C868D84
+121149ACB4A27F3ED6C0C181C98AAAF51B105F264B5672D7F745131ABAB5BEA4
+0C9B43C0DD9116D6DC61F90BE72018F290D26D5E9D341055CAF09C9F45333CDB
+D45B7954271767F638EEC499F7B53C2CC5774EA7A7F024C4CABFB93D9CB1856A
+0C671A4ECA7C62EA5242648A84E7F3AFB9547A0AFC29593CFCE6D8B873A78157
+D337CABD291431C0A2CE1F37E0CD7340567AC206FF98E4B5A6410F70F750451C
+550EFB54AA259A1B236CA9CB730D2CEF125EC65D959441F7CC9768F777B44844
+CC9842A307C72B740680ACBBF6AA35FA7A94825069BF7696ED81A371A9E5475A
+9D997F2DFAD339AADF797F7E03E654234455AC3D17702A420EE0A597BA31BDE4
+FEB8DBA7C61D311CC90441A620164DC22DC2D373973EF84CC553453AB1B3337F
+7B39983B8DFFB3A9425F119B45C1CD37A76F905777B3154CA6200792F1759D06
+E017890F4041A385F2238E3C48B6C8EE6F5258463FDBFF7AC762F6C4363926D6
+50F004D473B7B7F73CA686B559C2885F1AA761653C727A77D73431E9D110E76A
+2E55C68CD50F43997C9B2FC4710F8C8540909829E215678E63BB8363C4B8AF05
+9986102BB36580D9CA95CD216B7C321822CB41B2E0422CD077F3B55E0246FDB2
+44D5976F67296B5B0BE4B06F6E43535C21164E6C5089C3E9BA2D6B30888C57DE
+49DC8D9D46C0D5EDC47ACF2C03B72DE3B69512508539019B759280BABEA12BC9
+385308A0395C4CD33182A10A5A229743379C2075D82D8BFCE4A66E1AA087A091
+8F5372684FA5037D1B92D50CD9CB4F50AD4F8EE7D51F1C9E63C721CB5B9BD011
+6F0A8DD4FDCD2B008F223A1036D90F0F3B252487DE7898F9AFBB3A9D9CD49E0C
+EF4ADAD5155A98D2125ED5A3D3907F67301649519419F33CD942E8DDEAC1BDA0
+E90C431B198F646766A8FA9F8D1561B57E126EF604838C0C1966655CF31FB7EB
+C8CCC434FC1C96046D38203E1791EC824A3D7AED85C029288D4608CA7668A2BE
+484C99639F121845B22EEFCE0A3B808261921AA042AE19E641769E91277BEC29
+4594082CCB3058F90FAC4A700A8A827ACA00FCF574ABC8EB7DBCECD97F2B22C0
+0AA19E8739B81AF8C6F621D69B8E6F29BAE233FBA655A0AF5BDFD7F5C6B9167C
+6BC7AB693D45EF2AD999F5DA3CEFA39BA48A17EE6D9F2C4DAB91AE3F0044DC3F
+5D5506CE4675AA928B0092D6F173644F91295216D8BBB14CDDE0AD524A4D545C
+1B5E284A3BF0396664081CFB4F186A84A0D24D61E82F4767C1E55A0642720CF3
+909FA1AB8EAB78030B59BEA067DEDBD2F1D0340E790AB2777DB18248521934A8
+BB38A58B7F633DEA4291B0D5D13E9A882C974697CC6D3B49E030C94EA29B5506
+CC29C44D01B4751B453A46A9F6BF3BF135AE87A4CE232AF57B66578310DE41E0
+2A6AC422117F1963C4D7CC306BD25A6E724E51921779F22F029733122E23E2F0
+CB340008813ABB104380C80A492B3FC6D0BB07CB8D8409E9576891EF6E5C9D08
+EB8320DFA31BAFFBD336D0C2BBC3D3B2D30368B9860768FC080D30569C7F7811
+0EBEDA2962476113625EEB555490B8CE4C5F99D74ED10F738C61854CFF8B41C6
+9402E56BE8856144A1A05D0B05F4CB7EF728B2F4F5A439F18C3B68CEFA41E59A
+D8308ADC92EC1289DC84CF48D2CDEFF509A145BF945E1E00D552D329EBD2A7C4
+21D58082CC8FA790E981F4AC8EAB99950678FD3A7DA3DF13778681B208DD71A0
+7C3CBD0664B37C9EDC6B601D79A2C51FB54DAEE849F93209793849104E722D3F
+52DFAF7047EEEDDFE744787A5801E4AC2C3D58EC5DDC15FCEE03990C53B0C57A
+FC54F125A04C8E4A0ADAA725808C587E7DAFB9F784FA2875689979D316DC22BD
+AA36B306A1ABCF907B63C6476737B746099973CAEA8C1E2C5C41F27E0F7DE8D7
+F0D942E34E92F43FE902653D4D2EBB6F3B9F7928B1550A82AF234D45D028F429
+067652BD3D391BF423AE72B9CB1E8D91E898161BE3A7849D456A861A2046711E
+E934DC59442AE7D81661CE8EF727D8D7DDC0270E937E40F896AEAE6171661431
+C1025C53172F9D366834BA0054FBFD84503FBAE328B6FDEA180F8EA35B1DA937
+5CC3B8F00C206908C2FFFFA6A7AC6915D15EA44BDCF29E2BFCFD4A849535F19B
+0D307C696BE8205C7D84B9C77F02EF27D911056EDBB4080E4D3ED72788666CAD
+CD91B0ECE27A177DB23320A7FA9C31408B4D02D2A4B1CC6DDE1A6CAC3D8EC1EC
+2226EC98E51046D1EC26FA20EE62D24747D83CF4941DCE5CCEEC0DBE387149CD
+E05B19FFCAFC0D117F9A3E60DCD4C815228D98EF95EB559AD0ACC0D50FFDF714
+56C3C812EA5ADBB013BBD956A7C4CC0ED7D3E25D5C9AF5E626F18297F75D4957
+F5B0B33379114B903FE98BCF35C3FF76FEE1D9AEB711F2962276531F7380EE3F
+E368720E0292A170A15C5539B1FC7BB954EE2624B504CB8C805B8D31AC38307F
+0513606F09211AE64DAC447693B2A0AD15E9A64C34F5A911ECD0ABCA90E9791D
+67C6BD202B0858EF96E7722305B8AC02B01AB1706CC6AE875A8DDD15EE349046
+EAA65005E7866B506EDFB7A5A2AFD5C9E9DCC821A79EE9C1EA2C7BBA32A40BC7
+CEC26DB1AC473C8C3960ACEC581B37D6569E8C8C42950BAB7930B65E1570E3F8
+9A7FA719F1DCFDA45A3BF2AAB32C9A93BA3552608A61C623DE59BCB346E87EF5
+9CF025A87803161221C5C1C6F6B3403712C76E9D755C7BD68D7F2DC03C14CDF0
+C1BBED1D648B905B4B17037B7263C1EA7A7F06FAAC4E09E08483A8D714C19861
+327CD9C32DDF850302DD6DDE24912D00C22ECDF3CDFB18FA831A41A7488EC203
+F564CFE30D506F0829A96D35A7E09C3DCD107D589B627A15B55C5D6649126BEC
+60B88C55ECCBB4E680265D9EAB4CE22965D3B1AF759B01ACB0D0E6C92B6B4EFD
+A81E6A648708979487FC591CF09631310D46891423F4EC159A73E30D8DD147A4
+B0EACF6D45D18CD16CEB8176F03ABCB41F2234747B9733C8FAF34AE5D43D3BA5
+0CE0FACFC9B087F84FB6C68678BC6E76022B1526D6E5B3A48EC1A110BD75F45F
+1C4DC6D39F254976453F57DF873B7D635C80C42026DE020E5BAFE0DA0D54D1E1
+DC634D2621BA184347E5252F645A6A1DB7657C48124186F0E4C644077457C24D
+55753C651A9A7B6349867641464B515B821349C795A645420508673B93750D0C
+7A3B33EB1F09782033742AE8F3A23FC02284E6C03818FADD1731361542E3FA3E
+75B8D52B668C3E18A4AE967D0FC3157083D952AFB8144D549E69EAAC51C279C5
+E5D88A0D9D53013DFFB4352A1598FF84DCDE6FA32FC377306B9B92C0F96EE149
+8CD55E7B2445B86CCA7A547FA732D52D59025129FD8C6333AC0DF4F0CFF6287E
+F2036D5DBBB3B91B92F12FEBE0B61A313A4DB5A9CF0BB3DDB781A56FEBFFACCB
+8CB9D1D3DBDBC4CB6AAE6769E470582403CB920630221B68BCB625CD4605FA8F
+D3D5B7A1A28D15E44B38E92E906C138E72C15B86F64C38E23BF0440052A8C914
+54397F49DBED99D0AF7CEA3B0A05FF37C2D7EAE1412567E6776333237C31E3C0
+49949EC8BFD6E0F6446CE2D4DCD2C1524A288818CC5D159BF8463A847AE4A2B9
+CC8C58F822804B81B13BF4F2DEB6229C4F51F093075581791D02C36A13B855A0
+34900AA7CD4F1A797652656FE3A8425A38F421C4CC0ACA1CDD44FA6B31219276
+1CDE1CD63D6A58CE705CB56CCA1260F9B86E989019071563A9B4C274A87558CA
+6EF1660D574EDA276801F0057740E2C3B80D253D697736484D892CE1AB128B8A
+DECD69712F5E70E895FBAA927E8194D792A04AB6CE205E04E38A433BBB793FB4
+E8BBC4279D58A223C6673D909D6AFECD246E66A52F4CB35E5931D24C828489BD
+4ECAF621A220D8ECF702BEB01C4FC7510197D3F6D15321EC87175ADBA6434ECD
+2B5A306E91375CAD22CD94301763E4A8B981472890422C5488FCD523C9CB17DC
+ED22FBF12D5F7525D0D6BCFE8CE85B0DFB1D6F989C267FFBA0A996D309E4A934
+3DB54A9D29C88B9D55D7300DA3D46419256C5A07A2A529A8DE8BD1727281F5FE
+97033D861E0531B14E811378EC1AF1CC7EE9BA2B07D935843D3053F673979F8C
+FAFD59D555B56CE338F606747238B22BD62C42BB7238FEA335678D474A643570
+A9E7B4970E8C541CE9DBC7BF70ED7BA33639D6744A18379455029E934C95E2EF
+639C4848CE9A0879B51649FAB023A71782444B451F92A34CB8A124270CCF86D4
+D18EEF5C1D2B2A29012613851C49F50702D63BACF95EE2AB4D72B375E0A62615
+E0991E130A67ECBA9E05329B740708F1CB148724C3A6E5E3AEC1F88EBCA398D2
+1CA8827C977D72734310233176D1AE26C55CF2CEACA62223315C28FCF6305C7E
+A22414D4739A059F552F1F9372CCCA5FED4F9AC987942848EB498900269511F3
+F408CBEA0659B954F5F1B18AE4FB270213646F9B28AE4439D2BA2D3E0AAAA780
+5E530E4EFC8A060EB979E12191044509DA0C14397AFF949E12DC970658D5EAF5
+4EA963F5BC1407A32F3837CA6A24B7F3D60EB8E6222B702E25ED903F9D21AE50
+664A095009BDEAF4B78DAF94E5A55D48366CABF07791A1684B2F54EA69070844
+4F031AF8DF416C2D3679F8BA038B0DC9DD0400CA6B34667BCBBC07E62C1668A8
+35A8C57C9048A7227E672E89681B54D662079A189A9E96A3CA96D8DD10189B04
+1DA49BA2729F1CA585B1BD5C467295285D52E47CA904235A1A3E48EFAE9EB6F6
+01374125CE89D53C276858668CF45D2F092DDCAA52418E0BB94C2B8266B4D88A
+5D911507BB1DDA3D8F6E7C14A91CA11AE799EC42E993098E18CADA70BD2A1D82
+2C39326C6E3F9E84CD9758B9AE43D79BF99E6A0CD713E95B3D9B7DB90D127DE0
+DAFEBF850CAAACBD860B5DEF2082F1ADA64B44B193C4A1417BE221FDCA36456C
+BE5934C8CE3ED55AE3A11697C2D682B7D0F72D48976451D205783BE25DBD2507
+39C14FFB4BB828DFD187104F38A7F11D5F0698C11E8C1D4F107CACE573FDC4B1
+C56FDAE47024D6FD16A2FEABB434CA320300FC4B6C1B6CA08F76C60B7C08A665
+99F404DBA8A2A1EB18EF6750E4EC186E31561A3F080BA6562967546715859481
+7BA782940F5C5D06626D6F6A412CA7C13820EC7C1DF23E15E5829F698CF617BE
+D940523E4EE4ADECEC48C24297DBAD528BA1DCE7AC335A1D15D55415B108EFC8
+6D45030D27B3EA63B2B4CD771DBE66AE0218ABB1153D4B7482289D1313CEF184
+5C960B1E3C3C953912CC6F4521D1E15636C1545EEE457EFB87B88C9E43CC2F38
+6BC4BC96969F4FF28ABB06F4454C01CEF1B6DC538F1E832FC1666D977E5A881B
+F72F1B4C7DD4BE167A5535F1163A0706F9A0B26400178DF8A128FB5EBE6A7B81
+E478AD183EC06622B591337B9F1872AAEA356F4FC67EE767B34CB5A4D90702D9
+39FB846947F4096FB3DCF16EC81455164783BA0B5D723060DAFF411B68307E81
+7BEA1D9A47A5AA3D648E618C83C60F060029E6EC4D46B045FA7415BAB2AD0AA5
+ED9C729C24136F6AF61E6409C0B5CA760B16225641E268A68CFB8260BBEAFC77
+6626EBD97195E77CAB425CFB0096D805D9EE699E41680D095AE9FA10122A7882
+2F00F495C9EB2102DF0D3E61833BC0A2E468C5CF7AB430FDB7C0BE3DF2C0D230
+1580BAA25D65F599378D873165482A1FBB224AEA89C6BCCFBDBA42AE1C5DCF41
+06969F585CD3B737D1388D6359F5468D88FCD2279BDB270F6A858FB7D2ABDEFE
+5EE8FB79FA437F8F50237B92C307B73B0DCB808D07A9C3255CB9B3B17039CE5A
+288103D05D132863FB522A02CEE3839EF9AF7F07D99732F0B8B384745369FB3E
+7901166478F4A16076A1504C5E98D17408494E270BBF4470ED12B4332422679F
+759F1D93984D7E506D16950DB6C2682FE1379EFFA6F6C95DD71F6E55BE3EF6AF
+E0CB25388EEB436E6527806FC75484133F6E561DEB979D5C1FFEFDAF2A6D964E
+03BAE0BD593C2992AD84569C81050F7A793C5263E50C2F50B98C4CC703EAE17A
+6AEDAACE312DAFAF5278D125B6EFC5587484F61DAFF46B87B7C9B1EEDECA4859
+314A9A9E2248467DE1E54D90DD671660B9040B3E0DD982260822177EFD757266
+74A16C83A7FB168016A320D3DF3BD7726F1F4EC90EE5DFE810C96B099FD4368D
+906AE4699049EFD37E8EF058D4B97BF71106445AADD4FC6E90615A0066823A36
+673B8DE32322BBE861AE251226B4385AB28702831270DBD25D666FBB0AD7B96E
+A44E891EA1EAF0F87013AFC982E33D67A28E96E0C9CB99B9E4192536830D9901
+931A8CAFA41289633B20BA3BD7AA3414B6DA8D57CCF2FBE39920CC06361F075B
+CC40335DB9A0071CFF77F6B7BB47F3100DBDC9C4A58C2B81EC99E8E966AF3390
+E3FBCC28BA1D79961C8A1584266454DF772FBA99664D74D4A89FC82FFEDFCFE1
+4C9E4A04291E803D142E37E7ACA66AB279378F2F192FFB2B5BBAD18B95F03136
+2CB594A3D6D3F8576B90A6C4DAD6D6C8EE07AF682F925F01D0B26CBA347C03BE
+F3B0585CF4539FDC66915E22117078CC94D621F31DCB3E021998A5D6EE94CA4B
+E214D07517283D56973D8E4367392BF6C1150DEBF459D141AE0941C1C8C5CFBE
+E735D796E365A1B0F60BB4CF2801EAFE4889EE5F338D3C4885368281B3C95CCE
+251C28A90D318A8A0384439B38D63B94757252062EA44E88509FDD2E75FAAB71
+7329622828B2785C1A8B26351BC7448C1719C88FE99BCB73F7DEA427FBFCDF4F
+00EE079B0C712F7D2C8DF98D4830A9D8C8B70A8C5D54BC1DF3171135278BED55
+DA1CF0E696B12935EB59B606AA3C0CC50C7A259AF32F4C81D9B39470D9993CBC
+8644403D2833B34AF40511654F96BCE0064860F39849DC62E4A0693F75308FF5
+FF450EC05F142D5E300D3850C66D432BA581D5D8DFA97D901589C53181CB5057
+7FA8B2C95DF751A861DD1A614B2F32ABD284607F40B3462FB05C79DCBB586B43
+B853D7F77AF5ED7AF2A913FB2CE66241C5102CAEC3992BEEF19A4F760E98EAF5
+063E373A084CD6829DC18D063618B4AE443B35B63BFA956368397A69D41DD715
+6C5ED849CFCB2825CCB577C1669626E2C87DE60D69559B3CB98FAA07F1893EE9
+DAAAE01D549A252D77E79AD37BF64540DAF7FDF2FDF4017F94D9D89F1B6F249B
+CAAC5BF817A1979163F3A316640E382B501A6BE18C334DED469CA5643FD07D8F
+6E37275108F7168F45BFB5024D4FFBDB140741D2C8AA4AF19F22592587A05FF0
+A324A0DD415F312D653513ADE6EDE9E560BA16573295F6B3A0427A15A585A40D
+5265A4CB711011332AAE28B05BE6E4B11B1B3C178225B2108D94089E6544907F
+DDC2496C2624F6F7E45CD885C5E032FFEA7C337BE414E421FF8AD3D0959B08F6
+6B8931D93180F66A13E86ABB8C7F755D67838B8E8B5A35E6BF9BF3098535D75A
+3A8880D5E2B1D9C87CDF16AE86047B3D6CB83D9A7A3702A2428BBA8209D50F64
+7728F58AFB5CE3F8E8387EE3F2ABFBA17B3F0E6D549E7C6D13BFC785759F32C5
+B1C8A525B1CED15790CF637B59BAD929E3E3E52223066404D53CEC7C42236ED0
+E509521FAD3CCADF68D695660BC6A6F743E66DDE0A4A395F7F17F5D533E82963
+B831C3F3A7BDC6A6F5F62F5F7F9A3C75C12C7E401DCAB10411FB36B96894B6B7
+765205D82B57A53D0148BCB96CE67468ED168A7EE08120D79E30FEDB84C86D4D
+1A103694E049DB8929F2E389124FBA0DBA9E4CC099AE441600E63F70978D0C2E
+0B21352A2113D96B50649491592406CF1EE84B5AD03265040AB41503D2FBE78C
+1B0726B6027551614D756C17F939CBC1FD3EE28B99BC31FF9BB31C292002F1BF
+67BA8B632D158A299E13335EF69FEDFBD28BBF5773AD17D0ED5623F1E578AEA4
+FF9F8E856950CC7A10CA01238A7371B619AE8C08F51628F39E7173F60745F218
+8401AE34EBF1BD24B442988AE5DCE4EC0DA8F922D3DBFB6E2C47B27FBF000735
+2C6EFBACD68367409253A4DDBB04501562CC2543F368881E5062A25F890C7711
+1A6C3C5AD462F825F1D340D8AED4AF056CC26E592C0337EA2F1DCFDD91F00F82
+11642DE4E37B381ADD4976C0C850E31B6EF51DD65E1DECC56BAF0D22F7A4EB91
+276AB6567430CD58BB1F3F685149BC5AD0083EBD3AD39976C921024B55FC6DDD
+3478009D95A97CB0F2A1FF263C72291E18515F5CC3BB29A6221395B2F35826AA
+AA4737FDC0FC2D92581F94F9BCE5D19845D63A6ED2CB38988BA640D58DE8CE81
+01F19825E14967E7A55169B3CAC1DABDD00842BC207CDC793D00147328BBED17
+149ECEC72C43393CC83C631D0D28F471170004020424DD239C2AC9F94F2FABE7
+64897C9DC88630F7BF75C57F4AAF4D3ECFA5F9FB8D26B63043DA049712C6FE4E
+B0FF5CAE2FC836E039D8B86D8EE8C8572A5A86DC4B174C826D4766165D19889D
+4DB469E5C2EF55D8CDE91101660FCE91FE3DCFC3E1A07E4DE822D40D801D30B1
+357C3432A6CCE1D12F8744ED2863C2466291818516B1E6D7A194951D56CDCDD0
+C9B584109998C520F77AA5036DFF5A96D446083741766ADBEEAF795E282850F1
+8C898E8F37C083280929534199C14B7B552BDCECB7055E177EE41030FD3A1CCF
+760E35553432256BFE41FBDA131BA12C40C5F7D9DCA52F5EE23CD23B496822E9
+B21788714891F9DB6545C649F44580845F0A4FA80E73FB8DA6D0FC305210A825
+5DF2373418EE13A579F1220C70899B2E62D89D13286C05F5D528A3CB3F59C131
+1A1AF5C8284CF9950AF7366D8A74D8331365679DE5E7CDFD746B9A4A6BBDD784
+11D194A831BD236F58E72C5616F83D8F5C1B8D4599BA7A9E0ECB0CB937C9F2E6
+72137F55E1B5E0B69A5316CDA1E30D1E71543DB184C2E548F1DF919F519EC7B7
+BEDA27431534700371469A49A9C05D6FABB7A8C644DE5DF971F9A24136315988
+08E0F91DBA758A23E515E9F684CF2C0A7AD89DB843535B0E997279491F908C00
+F74B44248A555F141201EC7FB955035FC8F3399F07B6CD6533FDB8CC5D17CBF0
+E1965CAF317CEEDE31EBA1C6E0DC5C4E9D5A481B25B04AB440CFF283A8553117
+26073A68E158806140838FFF0514FD20B90E7E8F11F5616A8373AADD91993E70
+7C32B6E22C2CAFC254B52413A107BF5B596BAF902B8D616FBA9B877B857DA390
+49F5887F6C75EA22E2C1A23A50CB0EC9013F7EA391C8922ED288DA4ED0C81666
+7516E7E3F7F3B3373C705FDF1C081D047168874FEA3887BCDFA1A09BA01C45E3
+02E6AAC33B6CDC29A962B53429412C3D66F1E02B41F17FE2382DF77C1684B0D3
+E51503D325E952136D61A9EEF500AB67EE667FF07F36234721A11BA9B4017D9A
+660E622E62C3475A1C98D66300E1FDB8482A076F1723C4518B79BBCB1DC80EE2
+D09164A1DCF844D57357F1D6589EF03BB4B1BFF0C177615608C2A0C807FEA4D4
+DC6A82081B8032DE5AF3E1EEFFD04AAC59E875D13C10DD240A21B4F175A5CDDB
+CC03DCF36B6022D43B58232347B555C67BABD3EE2A40F3897F1D8835371FDBD6
+E426E6B04531458D723247F0BF5A617AE7B4C8EF396B04CF1A4720F1EA94B0F2
+C2454DC34DAB3FCC3302E6BA45B2FCA41AB79B36F142A6A7953943B44606B0C7
+EBFD09516EFE933F952196793B75CE75E57BC7624179282A410C80D676617862
+F9C56B4DACFD70645D35FFC78868514279C15E8AAFE06FBE2A5ED6C2DCBC742C
+4B7209B9EAF2EA3B2E72B9F3B14ACC3B319B1D62DF16326E75953EDC48EFCD91
+1C30A634A48F72896B7B47BA02C30369B8F9EE380BCBDD4F20A1C8FCACE8AE52
+3B68836DF8A9543D153B5E77F40AC0360A6E2B7F1FA0D0F1B319E79663F450F5
+7035DA505D9A3DD59A9E8CD6C12E185D852C92A08DD15D260DBA3E67C09DC15F
+26CD796ADF01F3119AED62E359A48AB069BE0EA117C5B0FEF0DC96C25E2C18CA
+5B8FB7B662817E90756AF11DEEA5883D9FAE82653A5E65D52D45E3233960F713
+75426BD675398F37F07DBF89FC0F3AE320D947C87A2B10BB524C5470D10BFFF9
+4A4E2DA7806785CDE96281ABD608EE815051EA20F8E57ED173F89C206A2B09AF
+45882A9DDBAFB0017E80A7700C391E4FD27977185A8B4322EC38AA33C2D93ECB
+5620B390317A8F1B09CDAD182600A6698CF245A4D45B5B76A4D08E7E5E869CC2
+E4CA0981664C32ECF2F1822911E071C63BBC66158FD7D7812296539BA7C31675
+C4B716C873FD80F29BEA2716AC280A53F9DE61EC5F3845928632F4DF438E68DB
+17787FE2CC03E85EF2B1BABFBAF651A40A88E360EA60CC04A7A8D1B91B12F872
+1A3A61902E0CAB263F76A76F79616A2A596B25C59F645A071D806F3C39F1535C
+CB185DB05E7C563A6DC4624FD1A83AF7FC0D7133726B07D1F278270C5A9D9BBE
+E69772974A459A2FCA1CCCE2ED308B81492E93A7780FB2B3C22D0E5D68FB74CA
+94014661F0339E9E1A40B1D04B845A4D2714CFB1875951BA0A8E6A07A25663CE
+13FB5E8CF4F999B020D19D1E5FE24369E3AA6359C3B3CCAAC604F1736CBB20B9
+9AF2E6F4713FC58FAF9E38C4C6B474F2204D3A77C55D2E45CF46E997D17B5C60
+08B4B17316610E9BC17E50C796BC3523A9D83E38D854B81EFD29349816620A75
+6CA29721D678846BC6C65502483750B28EB30D34B2FDA6BC6BAF3B2B28F516B3
+975711BCACBED6266EDCE6B20C412AC54E39B1423FC67A3D59F64348D98CEAA6
+9A34F681AB20F6C06DB63F3F387D156F9D1546488B7E05AB638F07B6605F250C
+07FE80094577650D6A3F82969F5BBB6BAF26D528024CE229ABB64B9CBFF6AE79
+F0F968DB81D9CC59778086538A046C1B940420835F784E0145354CE8DEFBB97A
+F75725D14EF908D955AC950C499E633035383ED226E3A3224FEE7AD9165C69D0
+09868B1309C04C1ED26B6A7D33055D00BAC28F1E5CAC7262445D7D874E36956A
+24FBD3B8DBAC9A060E87E0D036FC9665322AEFD997AD21C556AB21C203669838
+CBB12A3D0802535BAC9DBFF126237FCBA2D4B60883088FD383BB87E9958C52EA
+A3D600918105C4CDF1845667CF685341B805F1A7E1CDB16A09691383F1855A10
+E2678B1C4C7307234A6285B56CDE41DCE65FCAF3BBDE54CEA5A52CE57E11DFBF
+69D2E8DF226E83E8EC0EF0E60363DAE304F2498F905D1DABA516CF74A5A8E2A1
+584E01A6EDBD034C8EDE1A82EC3E280FEB59E2E6369FEBFD2BC4CD8D05667459
+0C3697F3E3BAD563678E81ADF67288DD32CAFB65AA99783F8F6A63E2E07197A2
+7209F6A11F381A7545A1BA05B7BB392C111309D0A63B2873EF684ACDE33C5FCC
+944AFEAA6E8E69A5E44A9A7B2117684F58A97A9131BF06BA09C217DC261E2244
+26829868822AA9359994B391B27788995028666A29D5FD68532C677E59117567
+627A4DF9145AF22F806494FFC27269CAB8B08C51D7629298F50A091F41748857
+B385FBB3CED7191A19DC5E4D4FB2BA9D37FDA9C768523EC1247EBD9B98B2625B
+FB80CABCD03F5A3C930F41E86F2D4EEB994CA2C18DD995B5459CDE2A6ABCF256
+1726283B41C4EB205BBCFD67CD2562E2A871944035155E7DFEC876F4B7F6FF76
+71762B5DDCFBA9E11C510B9FC9908D6663D901D68C17E081C34167BEF07BB2A6
+1B6A40FCFFE464D62E5C6F628ECFEE53A22A30C543E2BD840196F8D7DBDCA800
+5BCF5F7528F3D39E0D60348B70EFE43FAEBE2E0D47DE0E4E7844270A99CC889C
+1E4A9267FCBDA85EF72549C844DA97004D20FB179DBB8EDA1B3FDD92A1AE86D2
+3CAB75084B7D4EE6A27D3DC3BCE432FC2993CE2932A2E89899A4A077269FFAB8
+7318902EE9A9C9505955B813FA1F6171A1D35AB2CF77138A6D9A1A41423D03F3
+7F7600892835B1FA16A74AFB67F025842B0F91F6E4AB53B0BD8566263367A561
+415721A652D2C3412A1EFEAC8AED986697F8244AD17B07C957F928BCCC1BD72B
+4DB1E66A93B44CA2A30C2E46FC57CF4D55766F66EF5AC705CADE7BD8578D3BB5
+EF47101AD8ABA57CCADAC9C53B99815E08882E77E02730130363EA2EF59A7253
+E8312A325FDC1EB6BD747E32081AF6880A271A5B1AFA8E1C4D071E640A5BA92C
+95614EF4EA5E9185633E267ADB2E4586892C9C567CDADBB769BCF198C25285E2
+2E20A533129F47501D65638D29FAF9ADAA602844E15DDBD03582F0A6CF157C0C
+FE50F537E67620069A36B7B91710F188F23E52FD74F0957603B9245A31526000
+9233FDE0B38C481E1A53B8DBBF2FE2A8CBEEC83B78149E526FC0CD89F0DAAC20
+608444AE6E75B19DE1C9B5CB3988CD8F362B7BDA46D806C97DF1028D8B5B25E4
+A61E68F3DF8AF978D2ED0A25B1061CC574E4D29E005C9F35A0DA574A2C3EE7D7
+CF8D40CB651BD13043E4506A5B8B9C56FDEAED8FBA4046C3E642F83C9CF03A3C
+8FF90BB5296B4AE8C6E0088367E0125B37DF11D02F6D2A639E1FD66B020CFE42
+518757C384D99C90EF1B0D81D9B53BD3DE3BF0BA0B903FA03EA9604BAA44D2BE
+A1951EEE0ECF5EA0AF51A623EEFEAD415C924443F9886C45C8994723EC77E907
+DF43FA7E2F190F4B70436AFFB925EDE9109D9864283D3CAF5125A7ABDC37BA30
+A96395683A19F42B9C12EE3C21EA6410022600836AE036D88C256CABDC6EF2DA
+D937BE4F77DA3ED55B40B6933EC6E9221476DFFFA64A0188DDA74A21D2532C00
+4F779ECCB83DC5C87B5208A118AD263F5A510470B5C385D274B35443F5C06ED2
+CB93084BCF486F753F84F4C01FDF84B17C0BF80310F89160EA4D1DC1A52944E0
+555DFF4BA876F5889EB9AADB23DD2024756539AEA0325E223140975B78F6EE80
+B581C290A3420F9A1B8BB21523552A9E62F08FE0BCBF7BDE0C56297C56DBB1BE
+8A35FFD3110CBF8F7747A4CFA6030D3D196285DFF0CDD072EE70029F2325CEB3
+8088F15BE649C2CEDF8D67F72DA6A9A1D690ED77929881CB26D4C3846B17CA6B
+DD4C05FEE4C423F823703540AAC656822889FD2E38290D4528EA6AD80E25F641
+D5D776055109EF86115303DFAEB310E68C561AF086E5DC702F120142CE4A7D42
+DE893A73886C7BF83766B8A1E09C2D166AEBF0AA4275DA7DAB2E7DE262A23AB4
+89284B834A2000C1C807707D5630AD29549A52FF52077E5446D07CA8A24394E9
+2CBFF4EFB16B30AEEF0B944525140DEA2D469507AC1F15BA263FDB122C036F86
+00B4E36B14638DD89336C2FC82CF7350E5A5E1BBE3C548241FA4F06F5F86F5E0
+8A906E192FB9997A16CF2ADDF70746FA566266FDE5D1C1B91E2CD581F9794D5F
+94D1CBFA8CC180A4E19DFA42141548F528DA3B0014F1D9624D5E70B149BE6CE1
+EDEA0DBB26BE07DF735113650984BEC3FA70A36E6F2E4E3C4FF5DA234EB54F4C
+A78A041A144C9B2443699CE8BB85E474869B5225BC8D0F4506A4268D145329DB
+91FBEE574312F0C7BE9923A47A7B55A6448710F206F3A228B1ADF7C8348A3803
+84286BDE38BB139030D26F190CCC768581AA72EC3A0092814536BAA00D094FD5
+12DD9E356F1CC5C3C29101945236DAF39C27F0B4A11C90BEE90AF69777019AC1
+A2F4B442D6E3EB923F7F4CFCFA234FE41EC91F03B5A92CC5258690944DB38016
+5F356EB3DF908675CC724366DE229766E3D78E1778C8C7C0D12720744F510D8A
+49BF32EAB3BACA019189E4ED61437D8C76BD97B10AA0B900DCA5B54A7149FE39
+25399EA05A83F57C8E54C362B0CBFEC272980D5681641839DFFF911FC1509110
+3E00C252B495DF08D0300BE1C4D84025ABE4F968A7D6E953930884C22638AC35
+B7B94C071496017C150A252B22387DF4D23F042CC517D77AE42F8ABAA9B5C7B9
+D6BFB7701AA8CE5B44A3FA8F58737C55E8C217A4BAE45E683A985215318A7A3A
+CDC54AB53E829A539D44582A1CA8A4BD21AFDF42DDA691F48B1CB0AEE9BE1338
+FC641F20C9910985DAA523FE050774364C5B4376D74EC0EA9A1270ABC4D76ECD
+990C5EC8DC9056D180EAFBA13E99C6D77144E4E06DF2B3E10B9EB1E0B503176A
+2447CB9FFB483F6364850720211C653774AEC3660F1B2BAA482AC819E18A6D16
+851E534AAB2F1444486DFD9DFC5ACEFC0E9345D64C654CA707CE1618DC6BE3FD
+98C5EF080215B0CB8A514C81258C1BE2EE1010AEC7B204CD1D0DD11FCD427849
+DE3B036C8A719D47EB18EC5C9707E0256CD19F39CFE05822FBFBF63428F4254D
+3DE1C18ECA322A3D44D5D30100040ED28F3F820A2B3A15D3B5F6833888114BD9
+88DCFB58D2369A15C488F5808AD5E13C992278AE204AC187E6D1627365E9F141
+CC3CD4193AF378E033F6C91E37DE65E19AF7BBC215D7074EFB6349E3F406B5F0
+90521CBF66E343141487D102D18F5C06330C47CC701AE4FCE6EC297F6B5826FA
+C76F9CE853800AC96E07D9EDF0FCBF28291A1B543015F3E32D6D2D673FC46FE4
+3EA144B6E9915FBDE8C91E846779FFB93EF69E54758F6F368E58EF4A1EE9576E
+25EB201C3802ACA4B737FAF0B92EEAF523C7C234C94AA37EF8778992B577B146
+483F0A0D3B6B6D7691DD1DA6EB8E21514E6B9F40D95B923DDFC475187E5123A3
+73C85829FC33C96D86FD8B0276CC4C56292B781AD317E5C3C9FEFDD32CD93A36
+32DEC7BA3C1EBE2E1C0898F81ADC92F6F4B72E9A1184815E8B79F8673150E70C
+0BCBD7D0DA1F1021D1D4C0CBC1CCA263E84E4BD09590AEDB2563DAE8847F7FB6
+57DB2E3459085625329F3F636B6A5047D139E125D21E2D17B7037E27D7ABF80B
+4B9690415BB4D69729C3F13667C3D8937E74E0887A66891FE0B0CFCAF8BC0A0C
+4106A7D334F1A616A3C1899E6EC8824C806571A51434DD466DBFDBE4F019F314
+9853CA6DCA237C2A05DE93119ED1DD34F829B60FDB9F56F8B41741B0C44D636D
+0CA3A0744751548355CE366331E340DC42F2E66AAA8E40FBE2E026563F2DEC29
+9709BC66DE7F5B134159DD0375405E3CE88FA97EB0D813C349AD2EE573E99736
+345CFEF2F253DEA8B5756A8FCB78BB74B19369FC053C5A8DC60C33736ACB54AD
+DC52B3B94EFA4DFD838E2858372D8A310D09D1C496C8BC7399D3040310D9F099
+57940A33C69ADDD451AA37676871ECCB0BD2A6A69FCC9890D00F524C71CE1557
+D7FF74B057EE34A986DADB16BE5FB59B9B930FEAE5E5F5459E419528B283E03E
+A08106480820871D59721687C404297B83B5414E2BD14C780B462FC084E2F51C
+484F283CAC27B239354C0FC2FAECF5C12009D3C4BF291048FCCDD592DD81711C
+C219EE04E50AD0275F4533F790599B688E1947D433619FDBA01EA446CFDEEAB0
+3A5AA71650A84AF48917598E4ECF5C7081436C604A7DE64DEB36C56B707DE3DE
+D95187D6459B49670CDBB2635908DBDE705D9DD7FE3322AB1BF1BA1960E11578
+718979205CB6108A6A46A5A55286FCAD7F86556D7A49C6954FDAA232CAD227DF
+D921E5A7942DEE8D1D89AFBDAD4B81E11A494AC6BB72BC6215D8FD83A27A66CB
+0CE60EFAD0EF6FD4DB38252674DB0AAC08A66CB97FD3037695B811E901D4006B
+E67DA576D0211E2B3BC143897A231913D1BD0CE51B44C827CC57CC8F43CAC301
+7D97913F5CBBED9F9D005E0D8A1F26CABEC36370BAA55D4975108F5C64FCAD4B
+FDB1BCE523D485CE8953AFD38EA64F8D7A1DE5CEEEE43AA49DC31996A948F18B
+63372E8DA264DC7493620124F2F30380ECDBB4ADF18D5787A018ABB788CDE354
+2CFFE2A4C80CF62AEDAADB693E45ADC0FB299EB8CBEEDC306E63F68DE7B2EF94
+0D1FADDF6D16B088E87105C84BEA4E42E1448F09EDBF01BEA566A1F2BE1B31F5
+0348FC7DB471BDADC389B4948FC0CA4F6546AF743F1EDF2A4EAEB530FEE2E016
+0629B457D86163B2D9D54717D6F1141CA43102F830FD6D852C3D3FB64318F31D
+F929D3C64EDDE62FEB3836A54E9D4FA80975B087E8C2B17511C00E78E3870FE7
+C836FB9B585439780CE08451BDE3FE9D6C95C702F57041FE9422AA44843CEA21
+012923B3CFE053735520B025E2B7D38FD1F653FC
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+{restore}if
+%%EndFont
+TeXDict begin 40258431 52099146 1000 600 600 (support.dvi)
+@start /Fa 255[52{}1 58.1154 /CMSY7 rf /Fb 145[50 2[43
+40[63 66[{}3 83.022 /CMMI10 rf /Fc 148[35 107[{}1 58.1154
+/CMMI7 rf /Fd 168[51 17[51 2[51 66[{}3 99.6264 /CMTT12
+rf /Fe 138[62 1[44 46 1[62 1[62 93 31 59 1[31 62 56 34
+51 1[50 62 54 13[62 25[56 56 5[56 3[31 37 45[{}22 99.6264
+/CMBX12 rf /Ff 134[40 39 1[38 45 28 1[35 1[42 42 47 68
+21 3[42 38 25 38 42 38 38 42 11[62 2[61 5[52 29[25 30
+45[{}24 83.022 /CMTI10 rf /Fg 134[44 4[32 4[42 2[23 44
+2[46 2[37 17[46 83[{}8 83.022 /CMSL10 rf /Fh 129[39 39
+1[39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39
+1[39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 6[39 39
+39 1[39 10[39 1[39 39 39 39 39 39 39 39 39 39 39 39 1[39
+1[39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 1[39
+39 34[{}70 74.7198 /CMTT9 rf /Fi 208[35 35 46[{}2 66.4176
+/CMMI8 rf /Fj 150[32 32 86[65 1[42 14[65{}5 83.022 /CMSY10
+rf /Fk 134[37 1[51 1[41 25 31 32 35 39 39 43 63 20 2[24
+1[35 24 35 39 35 35 39 23[30 14[24 11[24 33[43 12[{}24
+74.7198 /CMTI9 rf /Fl 150[30 30 104[{}2 74.7198 /CMSY9
+rf /Fm 137[37 3[28 3[39 8[31 39 31 39 35 39[35 35 35
+1[35 35 35 35 35 35 2[24 3[27 27 27[39 12[{}21 66.4176
+/CMR8 rf /Fn 190[49 15[33 33 48[{}3 58.1154 /CMR7 rf
+/Fo 131[83 1[37 44 44 60 44 46 32 33 33 44 46 42 46 69
+23 44 25 23 46 42 25 37 46 37 46 42 23 2[23 42 23 2[62
+85 1[62 60 46 61 2[65 62 76 52 1[43 30 62 1[54 57 63
+1[59 2[39 1[65 1[23 23 42 42 42 42 42 42 42 42 42 42
+1[23 28 23 65 1[32 32 23 4[42 21[46 48 11[{}72 83.022
+/CMR10 rf /Fp 130[44 1[44 1[44 44 44 44 44 44 44 44 1[44
+44 44 44 44 44 1[44 44 44 44 44 44 44 44 44 4[44 27[44
+12[44 44 44 2[44 10[44 35[{}32 83.022 /CMTT10 rf end
+%%EndProlog
+%%BeginSetup
+%%Feature: *Resolution 600dpi
+TeXDict begin
+%%BeginPaperSize: Letter
+letter
+%%EndPaperSize
+ end
+%%EndSetup
+%%Page: 18 1
+TeXDict begin 18 0 bop 739 232 a Fo(18)165 b Fp(support.nw)1530
+b Fo(Decem)n(b)r(er)28 b(2,)f(2015)739 523 y Fe(2.8)112
+b(Sub-page)40 b(references)739 676 y Fo(This)34 b(is)g(the)h(w)n
+(onderful)f(co)r(de)g(that)h(Da)n(v)n(e)e(Lo)n(v)n(e)g(pro)n(vided)g
+(to)h(mak)n(e)g(page)f(references)739 776 y(lik)n(e)27
+b(7a,)g(7b,)g(and)h(so)f(on.)863 876 y(This)42 b(co)r(de)g(pro)n(vides)
+f(a)h(mec)n(hanism)f(for)h(de\014ning)g(`page)f(sub-references')g
+(using)739 975 y Fp(\\sublabel{foo})34 b Fo(referenced)k(with)j
+Fp(\\subpageref{foo)o(})p Fo(.)67 b(Sub-references)38
+b(will)i(b)r(e)739 1075 y(n)n(um)n(b)r(ered)31 b(lik)n(e)g(these)g
+(real)g(examples:)44 b(18a,)31 b(18b,)g(18c)g(etc.)g(unless)g(there)g
+(is)h(only)f(one)739 1174 y(on)c(the)h(page,)f(in)h(whic)n(h)f(case)g
+(the)h(letter)g(will)g(b)r(e)g(dropp)r(ed)f(lik)n(e)g(this:)37
+b(4b.)863 1274 y(T)-7 b(o)33 b(b)r(e)g(able)f(to)h(use)f
+Fp(\\subpageref)d Fo(w)n(e)j(m)n(ust)h(de\014ne)g(the)g(lab)r(el)g
+(with)g Fp(\\sublabel)p Fo(,)739 1374 y(used)h(lik)n(e)g(lab)r(el.)58
+b(\(Using)35 b Fp(\\ref)d Fo(with)j(a)g(lab)r(el)f(de\014ned)h(b)n(y)f
+Fp(\\sublabel)d Fo(will)k(pro)r(duce)739 1473 y(the)27
+b(sub-reference)f(n)n(um)n(b)r(er,)h(b)n(y)f(the)h(w)n(a)n(y)-7
+b(,)26 b(and)h Fp(\\pageref)d Fo(w)n(orks)h(as)h(exp)r(ected.\))37
+b(Note)739 1573 y(that)27 b Fp(\\subpageref)c Fo(is)k(robust)f(and)h
+Fp(\\ref)f Fo(and)h Fp(\\pageref)c Fo(are)k(rede\014ned)f(to)h(b)r(e)h
+(robust)739 1673 y(also,)f(as)h(they)g(will)h(b)r(e)f(in)h(future)g(L)
+1858 1656 y Fn(A)1895 1673 y Fo(T)1941 1690 y(E)1986
+1673 y(X)g(releases.)37 b(Inciden)n(tally)-7 b(,)29 b(these)f(expand)g
+(to)g(the)739 1772 y(relev)-5 b(an)n(t)25 b(text)i(plus)f
+Fp(\\null)p Fo(|y)n(ou)d(migh)n(t)j(w)n(an)n(t)g(to)g(strip)g(this)g
+(o\013,)h(e.g.)f(for)f(sorting)g(lists.)863 1872 y(There)h(are)f(v)-5
+b(arious)25 b(w)n(a)n(ys)g(w)n(e)h(could)g(attac)n(k)f(this)h(task)g
+(\(whic)n(h)g(is)g(made)g(non-trivial)739 1971 y(b)n(y)i(the)g(w)n
+(ell-kno)n(wn)e(async)n(hron)n(y)g(of)i(\(La\)T)2163
+1989 y(E)2209 1971 y(X's)g(output)h(routine\),)f(but)g(they)g(all)g(m)n
+(ust)739 2071 y(dep)r(end)e(on)g(hac)n(ks)f(in)h(the)g
+Fp(.aux)f Fo(\014le)h(or)f(a)g(similar)g(one.)36 b(Joac)n(him)25
+b(Sc)n(hro)r(d's)g Fp(fnpag.sty)739 2171 y Fo(do)r(es)39
+b(the)g(same)g(sort)f(of)h(thing)h(di\013eren)n(tly)f(to)g(this)g(L)
+2539 2154 y Fn(A)2576 2171 y Fo(T)2622 2189 y(E)2668
+2171 y(X-sp)r(eci\014c)h(approac)n(h.)69 b(See)739 2270
+y Fp(latex.tex)18 b Fo(for)j(enligh)n(tenmen)n(t)h(on)g(the)g
+(cross-referencing)d(mec)n(hanism)i(and)h(the)g(L)3412
+2253 y Fn(A)3449 2270 y Fo(T)3495 2288 y(E)3541 2270
+y(X)739 2370 y(in)n(ternals)38 b(used)h(b)r(elo)n(w.)71
+b([DL:)40 b(The)f(in)n(ternals)f(c)n(hange)g(in)h(L)2743
+2353 y Fn(A)2780 2370 y Fo(T)2826 2388 y(E)2872 2370
+y(X2e)g(compared)f(with)739 2470 y(L)761 2453 y Fn(A)798
+2470 y Fo(T)844 2487 y(E)890 2470 y(X)28 b(2.09.)35 b(The)28
+b(co)r(de)f(here)g(still)h(w)n(orks,)e(though.])863 2569
+y(The)35 b(new-st)n(yle)e(L)1434 2552 y Fn(A)1471 2569
+y Fo(T)1517 2587 y(E)1563 2569 y(X)h(page-reference)e(macros)g(all)i(w)
+n(ork)f(the)h(same)g(w)n(a)n(y:)48 b(if)35 b(the)739
+2669 y(thing)29 b(is)g(unde\014ned,)h(barf.)40 b(Otherwise,)28
+b(do)h(the)g(sp)r(eci\014ed)g(thing.)41 b(W)-7 b(e)30
+b(need)f(to)f(handle)739 2768 y(the)19 b(fact)g(that)g(the)g(expansion)
+f(of)h(the)g(lab)r(el)g(ma)n(y)f(b)r(e)h(t)n(w)n(o)f(items)h(or)f
+(\014v)n(e)g(items,)j(dep)r(ending)739 2868 y(on)41 b(whether)g(h)n(yp)
+r(ertext)g(is)h(used.)78 b(Since)41 b(w)n(e're)g(only)g(ev)n(er)f(in)n
+(terested)h(in)h(the)f(\014rst)739 2968 y(t)n(w)n(o)e(items,)k(w)n(e)d
+(use)g(a)f(hac)n(k|the)h(\\do)f(the)h(sp)r(eci\014ed)g(thing")g(m)n
+(ust)g(b)r(e)h(de\014ned)f(as)739 3067 y Fp(\\def\\dome#1#2#3\\)o(\\{)o
+(...)o(})21 b Fo(where)28 b Fp(...)e Fo(uses)h(only)g(the)h(\014rst)g
+(t)n(w)n(o)e(parameters.)449 3184 y Fm(18d)181 b Fl(h)p
+Fk(noweb.sty)29 b Fm(2b)p Fl(i)p Fo(+)p Fj(\021)1906
+b Fi(/)12 b Fm(17c)48 b(18e)13 b Fi(.)822 3275 y Fh
+(\\newcommand\\nw@genericref[2]{)q(\045)45 b(what)40
+b(to)g(do,)g(name)g(of)g(ref)900 3366 y(\\expandafter\\nw@g@nericref\\)
+q(csnam)q(e)45 b(r@#2\\endcsname#1{#2}})822 3458 y
+(\\newcommand\\nw@g@nericref[3]{)q(\045)g(control)c(sequence,)g(what)f
+(to)g(do,)g(name)900 3549 y(\\ifx#1\\relax)979 3640 y(\\ref{#3}\045)h
+(trigger)g(the)f(standard)h(`undefined)g(ref')g(mechanisms)900
+3731 y(\\else)979 3823 y(\\expandafter#2#1.\\\\\045)900
+3914 y(\\fi})739 4039 y Fo(Muc)n(h)25 b(of)h(what)f(w)n(e)h(w)n(an)n(t)
+f(can)g(b)r(e)h(done)f(b)n(y)g(pulling)h(out)f(the)h(\014rst,)g
+(second,)f(or)g(\014rst)g(and)739 4138 y(second)i(elemen)n(ts)g(of)h(a)
+f(ref.)457 4255 y Fm(18e)181 b Fl(h)p Fk(noweb.sty)29
+b Fm(2b)p Fl(i)p Fo(+)p Fj(\021)1894 b Fi(/)12 b Fm(18d)48
+b(19a)13 b Fi(.)822 4346 y Fh(\\def\\nw@selectone#1#2#3\\\\{#1})822
+4437 y(\\def\\nw@selecttwo#1#2#3\\\\{#2})822 4529 y
+(\\def\\nw@selectonetwo#1#2#3\\\\{)q({#1}{)q(#2}})p eop
+end
+%%Page: 19 2
+TeXDict begin 19 1 bop 291 232 a Fo(Decem)n(b)r(er)27
+b(2,)g(2015)1533 b Fp(support.nw)162 b Fo(19)415 523
+y(The)33 b Fp(\\subpageref)28 b Fo(macro)j(\014rst)h(do)r(es)g(a)h
+(normal)e Fp(\\pageref)p Fo(.)49 b(If)32 b(the)h(reference)f(is)291
+623 y(actually)21 b(de\014ned,)j(it)f(then)g(go)r(es)f(on)g(to)g(c)n
+(hec)n(k)g(whether)g(the)h(con)n(trol)e(sequence)h Fp(2on)p
+Fj(h)p Ff(p)l(age)291 722 y(r)l(efer)l(enc)l(e)l(d)9
+b Fj(i)34 b Fo(is)f(de\014ned)h(and)f(sets)g(the)h Fp(\\ref)e
+Fo(v)-5 b(alue)34 b(to)f(get)g Fp(a)g Fo(etc.)h(if)g(so.)54
+b(The)34 b(magic,)291 822 y(of)g(course,)h(is)f(in)g(de\014ning)h(the)f
+Fp(2on)f Fo(bit)i(appropriately)-7 b(.)55 b Fp(\\subpageref)30
+b Fo(also)j(tries)h(to)291 922 y(include)28 b(the)g(righ)n(t)e(h)n(yp)r
+(erstu\013)i(for)f(xhdvi.)5 1038 y Fm(19a)181 b Fl(h)p
+Fk(noweb.sty)28 b Fm(2b)p Fl(i)q Fo(+)o Fj(\021)1899
+b Fi(/)12 b Fm(18e)48 b(19b)13 b Fi(.)374 1129 y Fh
+(\\newcommand{\\subpageref}[1]{\045)452 1220 y
+(\\nwhyperreference{#1}{\\nw@gen)q(eric)q(ref\\@)q(subp)q(ager)q(ef{#1)
+q(}}})374 1312 y(\\def\\@subpageref#1#2#3\\\\{\045)452
+1403 y(\\@ifundefined{2on#2}{#2}{\\nwt)q(hepa)q(genum)q({#1})q({#2})q
+(}})415 1528 y Fp(\\subpagepair)23 b Fo(pro)r(duces)k(a)g
+Fp({subpage}{page})21 b Fo(pair.)1 1644 y Fm(19b)181
+b Fl(h)p Fk(noweb.sty)28 b Fm(2b)p Fl(i)q Fo(+)o Fj(\021)1903
+b Fi(/)12 b Fm(19a)48 b(19c)13 b Fi(.)374 1735 y Fh
+(\\newcommand{\\subpagepair}[1]{\045)85 b(\045)39 b(produces)i
+({subpage}{page})452 1826 y(\\@ifundefined{r@#1}\045)531
+1918 y({{0}{0}}\045)531 2009 y({\\nw@genericref\\@subpagepair{#1)q(}}})
+374 2100 y(\\def\\@subpagepair#1#2#3\\\\{\045)452 2192
+y(\\@ifundefined{2on#2}{{0}{#2}})q({{#1)q(}{#2})q(}})415
+2316 y Fp(\\sublabel)20 b Fo(is)j(lik)n(e)g(the)h Fp(\\label)d
+Fo(command,)j(except)f(that)h(it)g(writes)f Fp(\\newsublabel)291
+2416 y Fo(on)n(to)h(the)i Fp(.aux)d Fo(\014le)j(rather)e(than)h
+Fp(\\newlabel)p Fo(.)33 b(F)-7 b(or)25 b(h)n(yp)r(erreferencing,)f(all)
+h(lab)r(els)g(m)n(ust)291 2516 y(b)r(e)j(h)n(yp)r(ertext)f(anc)n(hors,)
+f(for)h(whic)n(h)g(w)n(e)h(use)f Fp(\\nwblindhyperanch)o(or)o
+Fo(.)9 2632 y Fm(19c)181 b Fl(h)p Fk(noweb.sty)28 b Fm(2b)p
+Fl(i)q Fo(+)o Fj(\021)1891 b Fi(/)12 b Fm(19b)48 b(19d)13
+b Fi(.)374 2723 y Fh(\\newcommand{\\sublabel}[1]{\045)452
+2814 y(\\leavevmode)42 b(\045)d(needed)i(to)f(make)g(\\@bsphack)h(work)
+452 2906 y(\\@bsphack)452 2997 y(\\nwblindhyperanchor{#1}\045)452
+3088 y(\\if@filesw)h({\\let\\thepage\\relax)491 3180
+y(\\def\\protect{\\noexpand\\noexp)q(and\\)q(noexp)q(and})q(\045)491
+3271 y(\\edef\\@tempa{\\write\\@auxout{)q(\\str)q(ing)609
+3362 y(\\newsublabel{#1}{{}{\\thepage})q(}}}\045)491
+3454 y(\\expandafter}\\@tempa)491 3545 y(\\if@nobreak)g
+(\\ifvmode\\nobreak\\fi\\fi\\fi\\@es)q(phac)q(k})415
+3670 y Fp(\\nosublabel)23 b Fo(creates)k(a)g(lab)r(el)g(with)i(a)e
+(sub-page)f(part)h(of)h(0.)1 3786 y Fm(19d)181 b Fl(h)p
+Fk(noweb.sty)28 b Fm(2b)p Fl(i)q Fo(+)o Fj(\021)1903
+b Fi(/)12 b Fm(19c)48 b(20a)13 b Fi(.)374 3877 y Fh
+(\\newcommand{\\nosublabel}[1]{\045)452 3968 y(\\@bsphack\\if@filesw)44
+b({\\let\\thepage\\relax)491 4060 y(\\def\\protect{\\noexpand\\noexp)q
+(and\\)q(noexp)q(and})q(\045)491 4151 y
+(\\edef\\@tempa{\\write\\@auxout{)q(\\str)q(ing)609 4242
+y(\\newlabel{#1}{{0}{\\thepage}}})q(}\045)491 4334 y
+(\\expandafter}\\@tempa)491 4425 y(\\if@nobreak)e
+(\\ifvmode\\nobreak\\fi\\fi\\fi\\@es)q(phac)q(k})p eop
+end
+%%Page: 20 3
+TeXDict begin 20 2 bop 739 232 a Fo(20)165 b Fp(support.nw)1530
+b Fo(Decem)n(b)r(er)28 b(2,)f(2015)863 523 y Fp(\\newsublabel)d
+Fo(is)j(the)i(macro)d(that)j(do)r(es)e(the)i(imp)r(ortan)n(t)e(w)n
+(ork.)37 b(It)28 b(is)g(called)g(with)739 623 y(the)f(same)f(sort)f(of)
+i(argumen)n(ts)e(as)h Fp(\\newlabel)p Fo(:)33 b(the)27
+b(\014rst)f(argumen)n(t)f(is)i(the)g(lab)r(el)f(name)739
+722 y(and)42 b(the)g(second)g(is)g Fp({)p Fj(h)p Ff(r)l(ef)h(value)g
+Fm(\(nev)n(er)37 b(de\014ned\))p Fj(i)p Fp(}{)p Fj(h)p
+Ff(p)l(age)46 b(numb)l(er)c Fm(\(nev)n(er)37 b(de\014ned\))p
+Fj(i)p Fp(})p Fo(.)739 822 y(\(Note)25 b(that)g(the)h(only)e
+(de\014nition)h(here)g(whic)n(h)f(needs)h(to)g(b)r(e)g(global)f(is)h
+(the)g(one)f(whic)n(h)h(is,)739 922 y(and)i(that)h Fp(\\global)c
+Fo(is)j(rede\014ned)g(b)n(y)g Fp(\\enddocument)p Fo(,)c(whic)n(h)k
+(will)h(bite)g(y)n(ou)e(if)i(y)n(ou)e(use)739 1021 y(it.)14
+b(.)g(.)g(\))453 1137 y Fm(20a)181 b Fl(h)p Fk(noweb.sty)29
+b Fm(2b)p Fl(i)p Fo(+)p Fj(\021)1890 b Fi(/)13 b Fm(19d)47
+b(21b)13 b Fi(.)822 1229 y Fl(h)p Fk(de\014nition)28
+b(of)f Fh(\\newsublabel)j Fm(20b)p Fl(i)863 1353 y Fo(Before)19
+b(w)n(e)h(create)f(a)g Fp(\\newsublabel)c Fo(for)20 b(the)g(\014rst)g
+(time,)i(w)n(e)d(set)h(the)h(prop)r(er)d(trailers.)449
+1469 y Fm(20b)181 b Fl(h)p Fk(de\014nition)28 b(of)f
+Fh(\\newsublabel)j Fm(20b)p Fl(i)q Fj(\021)1341 b Fm(\(20a\))49
+b(20c)13 b Fi(.)822 1561 y Fh(\\newcommand\\newsublabel{\045)900
+1652 y(\\nw@settrailers)900 1743 y(\\global\\let\\newsublabel\\@ne)q
+(wsubl)q(abel)900 1835 y(\\@newsublabel})739 1959 y Fo(First)27
+b(w)n(e)h(extract)e(the)i(page)f(n)n(um)n(b)r(er)h(in)n(to)f
+Fp(\\this@page)p Fo(.)457 2076 y Fm(20c)181 b Fl(h)p
+Fk(de\014nition)28 b(of)f Fh(\\newsublabel)j Fm(20b)p
+Fl(i)q Fo(+)o Fj(\021)1066 b Fm(\(20a\))48 b Fi(/)13
+b Fm(20b)47 b(20d)13 b Fi(.)822 2167 y Fh
+(\\newcommand{\\@newsublabel}[2])q({\045)900 2258 y
+(\\edef\\this@page{\\@cdr#2\\@ni)q(l}\045)863 2383 y
+Fo(Then)29 b(w)n(e)f(see)f(whether)i(it's)f(c)n(hanged)f(from)h(the)h
+(v)-5 b(alue)28 b(of)g Fp(\\last@page)c Fo(whic)n(h)k(w)n(as)739
+2482 y(stashed)k(a)n(w)n(a)n(y)f(b)n(y)h(the)h(last)g
+Fp(\\newsublabel)28 b Fo(\(or)k(is)g Fp(\\relax)f Fo(if)i(this)g(is)g
+(the)g(\014rst)f(one\).)739 2582 y(If)f(the)g(page)f(has)g(c)n(hanged,)
+g(w)n(e)g(reset)g(the)h(coun)n(ter)f Fp(\\sub@page)d
+Fo(telling)j(us)h(ho)n(w)f(man)n(y)739 2682 y(sub-lab)r(els)d(there)g
+(ha)n(v)n(e)g(b)r(een)h(on)f(the)h(page.)449 2798 y Fm(20d)181
+b Fl(h)p Fk(de\014nition)28 b(of)f Fh(\\newsublabel)j
+Fm(20b)p Fl(i)q Fo(+)o Fj(\021)1081 b Fm(\(20a\))49 b
+Fi(/)12 b Fm(20c)48 b(20e)13 b Fi(.)900 2889 y Fh
+(\\ifx\\this@page\\last@page\\el)q(se)979 2980 y(\\sub@page=\\z@)900
+3072 y(\\fi)900 3163 y(\\edef\\last@page{\\this@page})900
+3254 y(\\advance\\sub@page)43 b(by)d(\\@ne)863 3379 y
+Fo(If)28 b(w)n(e'v)n(e)e(had)h(at)g(least)f(t)n(w)n(o)h(on)f(the)i
+(page,)e(w)n(e)h(de\014ne)g(the)g Fp(2on)p Fj(h)p Ff(p)l(age)j(no.)p
+Fj(i)e Fo(macro)d(to)739 3479 y(indicate)j(the)g(fact.)457
+3595 y Fm(20e)181 b Fl(h)p Fk(de\014nition)28 b(of)f
+Fh(\\newsublabel)j Fm(20b)p Fl(i)q Fo(+)o Fj(\021)1070
+b Fm(\(20a\))48 b Fi(/)12 b Fm(20d)48 b(21a)13 b Fi(.)900
+3686 y Fh(\\ifnum\\sub@page=\\tw@)979 3778 y
+(\\global\\@namedef{2on\\this@page)q(}{}\045)900 3869
+y(\\fi)p eop end
+%%Page: 21 4
+TeXDict begin 21 3 bop 291 232 a Fo(Decem)n(b)r(er)27
+b(2,)g(2015)1533 b Fp(support.nw)162 b Fo(21)415 523
+y(Then)36 b(w)n(e)f(write)g(a)g(normal)f Fp(\\newlabel)e
+Fo(with)k(the)f(sub-reference)f(as)h(the)h(normal)291
+623 y(reference)d(v)-5 b(alue)34 b(in)h(the)g(second)f(argumen)n(t.)56
+b(Unfortunately)-7 b(,)36 b(if)f(w)n(e)f(w)n(an)n(t)g(h)n(yp)r(ertext)
+291 722 y(supp)r(ort,)27 b(the)h(second)f(argumen)n(t)g(of)g
+Fp(\\newlabel)d Fo(gets)j(complicated.)37 b(It)28 b(is)f(either)415
+888 y Fj(\017)41 b Fp({)p Fj(h)p Ff(r)l(ef)f(value)h
+Fm(\(nev)n(er)34 b(de\014ned\))p Fj(i)p Fp(}{)p Fj(h)p
+Ff(p)l(age)43 b(numb)l(er)c Fm(\(nev)n(er)34 b(de\014ned\))p
+Fj(i)p Fp(})p Fo(,)44 b(when)39 b(normal)498 988 y(L)520
+971 y Fn(A)557 988 y Fo(T)603 1006 y(E)649 988 y(X)28
+b(is)f(running,)h(or)415 1154 y Fj(\017)41 b Fp({)p Fj(h)p
+Ff(r)l(ef)d(value)g Fm(\(nev)n(er)31 b(de\014ned\))p
+Fj(i)p Fp(}{)p Fj(h)p Ff(p)l(age)41 b(numb)l(er)36 b
+Fm(\(nev)n(er)c(de\014ned\))p Fj(i)p Fp(}{)p Fj(h)p Ff(text)38
+b Fm(\(nev)n(er)32 b(de-)498 1254 y(\014ned\))p Fj(i)p
+Fp(}}{)p Fj(h)p Ff(hyp)l(er)f(c)l(ate)l(gory)g Fm(\(nev)n(er)24
+b(de\014ned\))p Fj(i)p Fp(}{)p Fj(h)p Ff(URL)30 b Fm(\(nev)n(er)25
+b(de\014ned\))p Fj(i)p Fp(})p Fo(,)k(when)f(the)498 1353
+y Fp(hyperref)c Fo(pac)n(k)-5 b(age)26 b(is)h(running.)36
+b(\(W)-7 b(e)28 b(actually)f(detect)g(this)h(b)n(y)f(lo)r(oking)f(for)h
+(the)498 1453 y Fp(nameref)e Fo(pac)n(k)-5 b(age,)26
+b(b)r(ecause)h(that's)h(the)g(one)f(that)h(c)n(hanges)e(the)i(use)g(of)
+f(lab)r(els.\))291 1619 y(W)-7 b(e)26 b(unify)g(these)g(t)n(w)n(o)f
+(things)h(b)n(y)f(pro)r(ducing)g Fp({)p Fj(h)p Ff(r)l(ef)k(value)f
+Fm(\(nev)n(er)23 b(de\014ned\))p Fj(i)p Fp(}{)p Fj(h)p
+Ff(p)l(age)31 b(num-)291 1719 y(b)l(er)e Fm(\(nev)n(er)c(de\014ned\))p
+Fj(i)p Fp(}\\nw@labeltrailers)415 1818 y Fo(W)-7 b(e)29
+b(ma)n(y)g(ha)n(v)n(e)f(p)r(ending)h(lab)r(els)g(in)g(supp)r(ort)g(of)g
+Fp(\\nextchunklabel)o Fo(,)24 b(as)k(de\014ned)i(in)291
+1918 y(c)n(h)n(unk)c(22a.)35 b(Because)26 b(w)n(e)g(w)n(an)n(t)g(to)g
+(de\014ne)h(all)g(of)f(the)h(\\p)r(ending)g(sublab)r(els")f(in)h
+(exactly)291 2017 y(the)d(same)f(w)n(a)n(y)-7 b(,)23
+b(w)n(e)h(do)f(something)h(a)f(bit)i(o)r(dd|w)n(e)e(mak)n(e)g(the)h
+(curren)n(t)f(lab)r(el)h(a)g(p)r(ending)291 2117 y(lab)r(el)j(as)g(w)n
+(ell.)5 2233 y Fm(21a)181 b Fl(h)p Fk(de\014nition)27
+b(of)h Fh(\\newsublabel)i Fm(20b)p Fl(i)p Fo(+)p Fj(\021)1277
+b Fm(\(20a\))49 b Fi(/)12 b Fm(20e)452 2325 y Fh
+(\\pendingsublabel{#1}\045)452 2416 y
+(\\edef\\@tempa##1{\\noexpand\\new)q(labe)q(l{##1)q(}\045)531
+2507 y({{\\number\\sub@page}{\\this@page})q(\\nw@l)q(abel)q(trai)q
+(lers})q(}\045)452 2599 y(\\pending@sublabels)452 2690
+y(\\def\\pending@sublabels{}})415 2814 y Fo(W)-7 b(e)45
+b(can't)g(use)g Fp(\\@ifpackageloade)o(d)39 b Fo(to)45
+b(see)f(if)52 b Fp(nameref)42 b Fo(is)j(loaded,)j(b)r(ecause)291
+2914 y(that)33 b(is)g(restricted)g(to)g(the)g(pream)n(ble,)h(and)f
+Fp(\\newsublabel)28 b Fo(go)r(es)33 b(in)n(to)g(the)g
+Fp(.aux)f Fo(\014le,)291 3014 y(whic)n(h)27 b(is)h(executed)f(after)h
+(the)g(whole)f(do)r(cumen)n(t)h(is)g(pro)r(cessed.)36
+b(W)-7 b(e)28 b(therefore)e(test)i(for)291 3113 y Fp(\\@secondoffive)p
+Fo(.)j(This)c(is)h(lame,)f(but)h(what)g(else)f(can)g(w)n(e)h(do?)1
+3230 y Fm(21b)181 b Fl(h)p Fk(noweb.sty)28 b Fm(2b)p
+Fl(i)q Fo(+)o Fj(\021)1899 b Fi(/)12 b Fm(20a)48 b(22a)13
+b Fi(.)374 3321 y Fh(\\newcommand\\nw@settrailers{\045)45
+b(--)40 b(won't)g(work)g(on)g(first)g(run)452 3412 y
+(\\@ifpackageloaded{nameref}\045)570 3504 y
+({\\gdef\\nw@labeltrailers{{}{}{})q(}}\045)570 3595 y
+({\\gdef\\nw@labeltrailers{}}})374 3686 y
+(\\renewcommand\\nw@settrailers{\045)452 3778 y
+(\\@ifundefined{@secondoffive}\045)570 3869 y
+({\\gdef\\nw@labeltrailers{}}\045)570 3960 y
+({\\gdef\\nw@labeltrailers{{}{}{})q(}}})p eop end
+%%Page: 22 5
+TeXDict begin 22 4 bop 739 232 a Fo(22)165 b Fp(support.nw)1530
+b Fo(Decem)n(b)r(er)28 b(2,)f(2015)863 523 y(No)n(w)f(w)n(e)g(k)n(eep)g
+(trac)n(k)f(of)h(those)g(p)r(ending)h(guys.)36 b(The)26
+b(goal)f(here)h(is)g(to)g(sa)n(v)n(e)f(them)i(up)739
+623 y(un)n(til)j(they're)f(all)g(equiv)-5 b(alen)n(t)29
+b(to)g(the)h(lab)r(el)f(on)g(the)h(next)f(c)n(h)n(unk.)42
+b(W)-7 b(e)29 b(ha)n(v)n(e)f(to)i(con)n(trol)739 722
+y(expansion)c(so)h(c)n(h)n(unks)g(lik)n(e)h(21a)e(\(21a\))h(can)g(b)r
+(e)h(lab)r(elled)f(t)n(wice.)453 839 y Fm(22a)181 b Fl(h)p
+Fk(noweb.sty)29 b Fm(2b)p Fl(i)p Fo(+)p Fj(\021)1898
+b Fi(/)12 b Fm(21b)48 b(22c)13 b Fi(.)822 930 y Fh
+(\\newcommand{\\nextchunklabel}[)q(1]{\045)900 1021 y
+(\\nwblindhyperanchor{#1}\045)124 b(\045)39 b(looks)h(slightly)h(bogus)
+g(---)f(nr)900 1112 y(\\@bsphack\\if@filesw)k({\\let\\thepage\\relax)
+1057 1204 y(\\edef\\@tempa{\\write\\@auxout{)q(\\str)q(ing\\p)q(endi)q
+(ngsu)q(blabe)q(l{#1)q(}}}\045)1057 1295 y(\\expandafter}\\@tempa)940
+1386 y(\\if@nobreak)d(\\ifvmode\\nobreak\\fi\\fi\\fi\\@e)q(spha)q(ck})
+822 1478 y(\\newcommand\\pendingsublabel[1)q(]{\045)900
+1569 y(\\def\\@tempa{\\noexpand\\@temp)q(a}\045)900 1660
+y(\\edef\\pending@sublabels{\\no)q(expan)q(d\\@t)q(empa{)q(#1}\\)q
+(pend)q(ing@s)q(ubla)q(bels})q(})822 1752 y(\\def\\pending@sublabels{})
+449 1910 y Fm(22b)181 b Fl(h)p Fk(man)27 b(p)l(age:)h(noweb)h(style)f
+(c)l(ontr)l(ol)h(se)l(quenc)l(es)h Fm(22b)p Fl(i)q Fj(\021)1099
+b Fm(32b)13 b Fi(.)822 2001 y Fh(.PP)40 b(\\")g(.TP)f(will)i(not)e
+(work)i(with)f(the)g(backslashes)h(on)f(the)g(next)g(line.)g(Period.)
+822 2092 y(\\fB\\\\nextchunklabel{l}\\fP)822 2183 y(.RS)822
+2275 y(Associates)h(label)g(\\fBl\\fP)822 2366 y(with)f(the)g(sub-page)
+h(reference)g(of)f(the)g(next)g(code)g(chunk.)822 2457
+y(Can)g(be)g(used)g(in)f(for)h(concise)h(chunk)f(cross-reference)j
+(with,)d(e.g.,)822 2549 y(\\fBchunk~\\\\subpageref{l}\\fP.)822
+2640 y(.RE)863 2781 y Fo(W)-7 b(e)28 b(need)g(to)g(de\014ne)f(these.)
+457 2897 y Fm(22c)181 b Fl(h)p Fk(noweb.sty)29 b Fm(2b)p
+Fl(i)p Fo(+)p Fj(\021)1898 b Fi(/)12 b Fm(22a)48 b(23a)13
+b Fi(.)822 2989 y Fh(\\def\\last@page{\\relax})822 3080
+y(\\newcount\\sub@page)863 3205 y Fo(W)-7 b(e)24 b(no)e(longer)g(use)h
+(Rainer's)f(new)h(expandable)f(de\014nitions)h(of)g Fp(\\ref)f
+Fo(and)g Fp(\\pageref)739 3304 y Fo(to)g(minimise)h(the)g(risk)f(of)g
+(nast)n(y)g(surprises;)g(enough)g(time)h(has)f(elapsed)g(that)h(this)f
+(should)739 3404 y(no)27 b(longer)g(b)r(e)h(necessary)-7
+b(.)449 3520 y Fm(22d)181 b Fl(h)p Fk(old)27 b(noweb.sty)i
+Fm(22d)p Fl(i)q Fj(\021)822 3611 y Fh(\045)39 b(RmS)h(92/08/14:)i(made)
+e(\\ref)g(and)g(\\pageref)h(robust)822 3703 y
+(\\def\\ref#1{\\@ifundefined{r@#1)q(}{{\\b)q(f)k(??})p
+Fl(h)p Fk(warn)29 b(of)e(unde\014ne)l(d)i(r)l(efer)l(enc)l(e)g(to)g
+Fh(#1)e Fm(22e)p Fl(i)q Fh(}\045)979 3794 y
+({\\expandafter\\expandafter\\expa)q(ndaf)q(ter)1018
+3885 y(\\@car\\csname)42 b(r@#1\\endcsname\\@nil\\null}})822
+3977 y(\\def\\pageref#1{\\@ifundefined{)q(r@#1})q({{\\b)q(f)j(??})p
+Fl(h)p Fk(warn)29 b(of)e(unde\014ne)l(d)i(r)l(efer)l(enc)l(e)g(to)f
+Fh(#1)g Fm(22e)p Fl(i)q Fh(}\045)1018 4068 y
+({\\expandafter\\expandafter\\exp)q(anda)q(fter)1057
+4159 y(\\@cdr\\csname)42 b(r@#1\\endcsname\\@nil\\null}})822
+4251 y(\\def\\@refpair#1{\\@ifundefined)q({r@#1)q(}{{0)q(}{0})p
+Fl(h)p Fk(wa)q(rn)33 b(of)28 b(unde\014ne)l(d)h(r)l(efer)l(enc)l(e)g
+(to)f Fh(#1)g Fm(22e)p Fl(i)q Fh(}\045)979 4342 y({\\@nameuse{r@#1}}})
+457 4500 y Fm(22e)181 b Fl(h)p Fk(warn)28 b(of)f(unde\014ne)l(d)i(r)l
+(efer)l(enc)l(e)h(to)e Fh(#1)g Fm(22e)p Fl(i)p Fj(\021)1192
+b Fm(\(17d)25 b(22d\))822 4591 y Fh(\\@warning{Reference)43
+b(`#1')e(on)e(page)h(\\thepage)h(\\space)g(undefined})p
+eop end
+%%Page: 23 6
+TeXDict begin 23 5 bop 291 232 a Fo(Decem)n(b)r(er)27
+b(2,)g(2015)1533 b Fp(support.nw)162 b Fo(23)415 523
+y(Here)35 b(a)g(a)g(couple)h(of)f(ho)r(oks)g(for)g(formatting)g
+(sub-page)f(n)n(um)n(b)r(ers,)j(whic)n(h)e(can)h(b)r(e)291
+623 y(alphab)r(etic,)27 b(n)n(umeric,)g(or)g(omitted.)-2267
+b Fg(St)n(yle)27 b(ho)r(ok)5 739 y Fm(23a)181 b Fl(h)p
+Fk(noweb.sty)28 b Fm(2b)p Fl(i)q Fo(+)o Fj(\021)1903
+b Fi(/)12 b Fm(22c)48 b(24a)13 b Fi(.)374 830 y Fh
+(\\def\\@alphasubpagenum#1#2{#2\\if)q(num#)q(1=0)45 b
+(\\else\\@alph{#1}\\fi})374 922 y(\\def\\@nosubpagenum#1#2{#2})374
+1013 y(\\def\\@numsubpagenum#1#2{#2\\ifnu)q(m#1=)q(0)g
+(\\else.\\@arabic{#1}\\fi})374 1104 y
+(\\def\\nwopt@nosubpage{\\let\\nwthe)q(page)q(num=\\)q(@nos)q(ubpa)q
+(genum)q(\\nwo)q(pt@no)q(marg)q(inta)q(g})374 1196 y
+(\\def\\nwopt@numsubpage{\\let\\nwth)q(epag)q(enum=)q(\\@nu)q(msub)q
+(pagen)q(um})374 1287 y(\\def\\nwopt@alphasubpage{\\let\\nw)q(thep)q
+(agenu)q(m=\\@)q(alph)q(asubp)q(agen)q(um})374 1378 y
+(\\nwopt@alphasubpage)415 1503 y Fo(In)28 b(rare)e(cases,)g(there)i(ma)
+n(y)f(b)r(e)g(more)g(than)h(26)e(c)n(h)n(unks)h(on)h(a)f(page.)36
+b(In)27 b(suc)n(h)h(a)f(case,)291 1602 y(w)n(e)21 b(need)i(a)e
+(sub-page)g(n)n(um)n(b)r(ering)h(sc)n(heme)f(that)i(can)e(go)h(b)r(ey)n
+(ond)f(\\a)h(to)g(z.")34 b(The)22 b(sc)n(heme)291 1702
+y(I)31 b(ha)n(v)n(e)g(c)n(hosen)g(is)g(\\a)g(to)h(z,)g(then)h(aa)e(to)g
+(zz,)i(then)f(aaa)e(to)i(zzz,)h(etc.")48 b(The)32 b(con)n(v)n(ersion)
+291 1802 y(requires)c(a)h(bit)g(of)h(though)n(t)f(b)r(ecause)g(it)g(is)
+h Ff(not)37 b Fo(an)29 b(ordinary)e(con)n(v)n(ersion)g(of)j(in)n(teger)
+e(to)291 1901 y(string)h(as)g(w)n(e)h(usually)f(think)i(of)f(suc)n(h)f
+(things.)44 b(The)30 b(problem)g(is)g(that)g(the)g(meaning)g(of)291
+2001 y(the)22 b(letters)g(dep)r(ends)h(on)e(the)i(p)r(osition;)h(the)e
+(letter)g(a)g(acts)g(lik)n(e)g(a)f(zero)g(in)i(some)e(p)r(ositions)291
+2100 y(or)26 b(a)h(one)h(in)g(others.)415 2200 y(The)22
+b(solution)g(I)g(ha)n(v)n(e)f(implemen)n(ted)i(uses)e(a)h(v)-5
+b(ariable)21 b Fp(bound)f Fo(whic)n(h)i(is)g(alw)n(a)n(ys)e(equal)291
+2300 y(to)30 b(26)479 2270 y Fc(k)549 2300 y Fo(for)g(some)g
+Fb(k)s Fo(.)46 b(If)30 b(w)n(e)h(write)f(the)h(recurrence)d
+Fb(B)2044 2312 y Fc(k)2113 2300 y Fo(=)g Fb(B)2269 2312
+y Fc(k)q Fa(\000)p Fn(1)2415 2300 y Fo(+)20 b(26)2584
+2270 y Fc(k)2624 2300 y Fo(,)31 b(with)g Fb(B)2933 2312
+y Fn(0)2998 2300 y Fo(=)c(0,)291 2399 y(w)n(e)k(then)i(use)f(a)f
+(string)g(of)h Fb(k)j Fo(letters)d(to)g(represen)n(t)f(n)n(um)n(b)r
+(ers)g(b)r(et)n(w)n(een)h Fb(B)2704 2411 y Fc(k)q Fa(\000)p
+Fn(1)2862 2399 y Fo(and)g Fb(B)3091 2411 y Fc(k)3132
+2399 y Fo(.)291 2499 y(Within)f(that)f(string,)g(a's)g(are)f(0's,)h
+(and)g(so)f(on)h(up)h(to)f(z's)g(whic)n(h)g(are)f(25's,)g(and)h(w)n(e)g
+(use)291 2599 y(standard)c(in)n(teger-con)n(v)n(ersion)e(metho)r(ds)k
+(to)f(enco)r(de)h Fb(n)18 b Fj(\000)g Fb(B)2241 2611
+y Fc(k)q Fa(\000)p Fn(1)2367 2599 y Fo(.)415 2698 y(The)28
+b(follo)n(wing)e(Icon)i(implemen)n(tation)g(ma)n(y)f(b)r(e)h(more)e(p)r
+(erspicuous)h(than)h(the)g(T)3046 2716 y(E)3093 2698
+y(X)291 2798 y(co)r(de)23 b(actually)h(used.)36 b(Here)23
+b(the)i(v)-5 b(ariable)23 b Fp(bound)f Fo(is)i(26)2058
+2768 y Fc(k)2098 2798 y Fo(,)h(with)f Fb(k)i Fo(=)d(1)g(initially)-7
+b(,)25 b(and)f Fp(n)g Fo(is)291 2897 y Fb(n)15 b Fj(\000)f
+Fb(B)498 2909 y Fc(k)q Fa(\000)p Fn(1)624 2897 y Fo(.)37
+b(The)26 b(\014rst)g(lo)r(op)f(\014nds)h(the)h(righ)n(t)e
+Fb(k)s Fo(,)h(and)g(the)h(second)e(do)r(es)h(the)g(usual)g(string)291
+2997 y(con)n(v)n(ersion.)1 3113 y Fm(23b)181 b Fl(h)p
+Fk(Ic)l(on)27 b(c)l(o)l(de)i(for)e(subp)l(age)j(numb)l(ering)e
+Fm(23b)p Fl(i)q Fj(\021)374 3205 y Fh(procedure)41 b(alphastring\(n\))
+452 3296 y(bound)f(:=)g(26)452 3479 y(while)g(n)g(>=)g(bound)g(do)g({)
+531 3570 y(#)f(invariant:)i(bound)g(=)e(26^\(k+1\))i(&)f(n)f(is)h
+(initial)h(n)e(-)h(B_k)531 3661 y(n)f(-:=)h(bound)531
+3753 y(bound)g(*:=)g(26)452 3844 y(})452 4027 y(while)g(bound)h(>)e(1)h
+(do)f({)531 4118 y(bound)h(/:=)g(26)531 4209 y(d)f(:=)h(integer\(n)h(/)
+e(bound\))531 4301 y(n)g(-:=)h(d)f(*)h(bound)531 4392
+y(writes\(&lcase[d+1]\))452 4483 y(})374 4575 y(end)p
+eop end
+%%Page: 24 7
+TeXDict begin 24 6 bop 739 232 a Fo(24)165 b Fp(support.nw)1530
+b Fo(Decem)n(b)r(er)28 b(2,)f(2015)863 523 y(Here's)22
+b(T)1156 541 y(E)1203 523 y(X)h(co)r(de)f(to)g(ac)n(hiev)n(e)f(the)i
+(same)f(end.)36 b(The)22 b(en)n(tire)g(macro)g(b)r(o)r(dy)g(is)h
+(enclosed)739 623 y(in)39 b(braces,)h(so)e(that)h(it)g(can)f(b)r(e)h
+(used)f(with)h Fp(\\loop)e Fo(without)i(pic)n(king)f(up)h(the)g(wrong)
+739 722 y Fp(\\repeat)p Fo(.)453 839 y Fm(24a)181 b Fl(h)p
+Fk(noweb.sty)29 b Fm(2b)p Fl(i)p Fo(+)p Fj(\021)1894
+b Fi(/)12 b Fm(23a)48 b(24b)13 b Fi(.)822 930 y Fh
+(\\newcount\\@nwalph@n)822 1021 y(\\let\\@nwalph@d\\@tempcnta)822
+1112 y(\\let\\@nwalph@bound\\@tempcntb)822 1204 y
+(\\def\\@nwlongalph#1{{\045)900 1295 y(\\@nwalph@n=#1\\advance\\@nwal)q
+(ph@n)46 b(by-1)900 1386 y(\\@nwalph@bound=26)900 1478
+y(\\loop\\ifnum\\@nwalph@n<\\@nwa)q(lph@b)q(ound)q(\\else)1018
+1569 y(\\advance\\@nwalph@n)d(by)d(-\\@nwalph@bound)1018
+1660 y(\\multiply\\@nwalph@bound)45 b(by)39 b(26)900
+1752 y(\\repeat)900 1843 y(\\loop\\ifnum\\@nwalph@bound>1)979
+1934 y(\\divide\\@nwalph@bound)44 b(by)c(26)979 2026
+y(\\@nwalph@d=\\@nwalph@n\\divide\\@)q(nwal)q(ph@d)46
+b(by)39 b(\\@nwalph@bound)979 2117 y(\045)g(d)h(:=)f(d)h(*)f(bound)i(;)
+e(n)h(-:=)g(d;)f(d)h(:=)f(d)h(/)f(bound)i(---)f(saves)g(a)f(temporary)
+979 2208 y(\\multiply\\@nwalph@d)k(by)d(\\@nwalph@bound)979
+2300 y(\\advance\\@nwalph@n)j(by)d(-\\@nwalph@d)979 2391
+y(\\divide\\@nwalph@d)j(by)d(\\@nwalph@bound)979 2482
+y(\\advance\\@nwalph@d)j(by)d(1)f(\\@alph{\\@nwalph@d}\045)900
+2574 y(\\repeat)822 2665 y(}})739 2922 y Fe(2.9)112 b
+Fd(WEB)p Fe(-lik)m(e)39 b(c)m(h)m(unk)f(n)m(um)m(b)s(ering)739
+3076 y Fo(Here's)29 b(a)h(righ)n(teous)e(hac)n(k:)41
+b(w)n(e)29 b(get)h(the)g(e\013ect)h(of)e(WEB-lik)n(e)g(c)n(h)n(unk)h(n)
+n(um)n(b)r(ers)f(just)i(b)n(y)739 3175 y(rede\014ning)20
+b Fp(\\sublabel)d Fo(to)j(use)g(a)g(coun)n(ter)g(instead)g(of)h(the)g
+(curren)n(t)e(page)h(n)n(um)n(b)r(er.)34 b(Since)739
+3275 y(the)28 b(n)n(um)n(b)r(ers)f(are)g(all)g(distinct,)h(no)g
+(sub-page)e(n)n(um)n(b)r(er)h(is)h(ev)n(er)e(used.)449
+3391 y Fm(24b)181 b Fl(h)p Fk(noweb.sty)29 b Fm(2b)p
+Fl(i)p Fo(+)p Fj(\021)1898 b Fi(/)12 b Fm(24a)48 b(25a)13
+b Fi(.)822 3482 y Fh(\\newcount\\nw@chunkcount)822 3574
+y(\\nw@chunkcount=\\@ne)822 3665 y(\\newcommand{\\weblabel}[1]{\045)900
+3756 y(\\@bsphack)900 3848 y(\\nwblindhyperanchor{#1}\045)900
+3939 y(\\if@filesw)42 b({\\let\\thepage\\relax)940 4030
+y(\\def\\protect{\\noexpand\\noexpand)q(\\noe)q(xpand)q(}\045)940
+4122 y(\\edef\\@tempa{\\write\\@auxout{\\st)q(ring)1057
+4213 y(\\newsublabel{#1}{{}{\\number\\)q(nw@c)q(hunkc)q(ount)q(}}}})q
+(\045)940 4304 y(\\expandafter}\\@tempa)940 4396 y
+(\\global\\advance\\nw@chunkcount)j(by)40 b(\\@ne)940
+4487 y(\\if@nobreak)h(\\ifvmode\\nobreak\\fi\\fi\\fi\\@e)q(spha)q(ck})
+822 4578 y(\\def\\nwopt@webnumbering{\045)900 4670 y
+(\\let\\sublabel=\\weblabel)900 4761 y(\\def\\nwpageword{chunk}\\def\\)
+q(nwpag)q(eswo)q(rd{ch)q(unks)q(}\045)900 4852 y
+(\\def\\nwpageprep{in}})p eop end
+%%Trailer
+
+userdict /end-hook known{end-hook}if
+%%EOF
diff --git a/web/noweb/src/xdoc/Makefile b/web/noweb/src/xdoc/Makefile
new file mode 100644
index 0000000000..402b3cfbcf
--- /dev/null
+++ b/web/noweb/src/xdoc/Makefile
@@ -0,0 +1,110 @@
+WWW=$(HOME)/www/noweb
+SHELL=/bin/sh
+.SUFFIXES: .1 .7 .txt .ps
+.1.txt: ; nroff -man $*.1 > $*.txt
+.1.ps: ; psroff -t -man $*.1 > $*.ps
+.7.txt: ; nroff -man $*.7 > $*.txt
+.7.ps: ; psroff -t -man $*.7 > $*.ps
+
+MANPAGES=notangle.1 cpif.1 noweb.1 nodefs.1 noroots.1 noindex.1 \
+ nowebstyle.7 nowebfilters.7 nuweb2noweb.1 sl2h.1 htmltoc.1 \
+ noroff.1
+TXTPAGES=notangle.txt cpif.txt noweb.txt nodefs.txt noroots.txt noindex.txt \
+ nowebstyle.txt nowebfilters.txt nuweb2noweb.txt sl2h.txt htmltoc.txt \
+ noroff.txt
+SRCS=$(MANPAGES) $(TXTPAGES)
+
+NAME="name of version checked in"
+CIMSG="message for version checked in"
+RCSFILES=*.nw *.tex Makefile
+DOVERSION=./doversion
+
+all: $(SRCS)
+source: $(SRCS)
+touch: $(SRCS)
+ touch $(SRCS)
+boot:
+ touch $(SRCS)
+
+www: $(WWW)/onepage.ps $(WWW)/guide.ps $(WWW)/guide.html
+
+checkin:
+ ci -l $(CINAME) $(CIMSG) $(RCSFILES)
+
+$(WWW)/onepage.ps: onepage.ps
+ cp onepage.ps $(WWW)
+
+$(WWW)/guide.ps: guide.ps
+ cp guide.ps $(WWW)
+
+$(WWW)/guide.html: guide.html
+ cp guide.html $(WWW)
+
+notangle.1: manpage.nw ../shell/noweave.nw docdate.nw
+ notangle -t8 -Rnotangle.1 manpage.nw ../shell/noweave.nw docdate.nw | $(DOVERSION) > notangle.1
+
+nowebstyle.7: manpage.nw ../tex/support.nw docdate.nw
+ notangle -t8 -Rnowebstyle.7 manpage.nw ../tex/support.nw docdate.nw | $(DOVERSION) > nowebstyle.7
+
+nowebfilters.7: nowebfilters.nw docdate.nw
+ notangle -t8 nowebfilters.nw docdate.nw | $(DOVERSION) > nowebfilters.7
+
+noweb.1: manpage.nw docdate.nw
+ notangle -t8 -Rnoweb.1 manpage.nw docdate.nw | $(DOVERSION) > noweb.1
+
+nodefs.1: nodefs.nw docdate.nw
+ notangle -t8 nodefs.nw docdate.nw | $(DOVERSION) > nodefs.1
+
+noroots.1: noroots.nw docdate.nw
+ notangle -t8 noroots.nw docdate.nw | $(DOVERSION) > noroots.1
+
+noindex.1: noindex.nw docdate.nw
+ notangle -t8 noindex.nw docdate.nw | $(DOVERSION) > noindex.1
+
+sl2h.1: sl2h.nw docdate.nw
+ notangle -t8 sl2h.nw docdate.nw | $(DOVERSION) > sl2h.1
+
+htmltoc.1: htmltoc.nw docdate.nw
+ notangle -t8 htmltoc.nw docdate.nw | $(DOVERSION) > htmltoc.1
+
+cpif.1: manpage.nw docdate.nw
+ notangle -t8 -Rcpif.1 manpage.nw docdate.nw | $(DOVERSION) > cpif.1
+
+nuweb2noweb.1: manpage.nw docdate.nw
+ notangle -t8 -Rnuweb2noweb.1 manpage.nw docdate.nw | $(DOVERSION) > nuweb2noweb.1
+
+noroff.1: noroff.nw docdate.nw
+ notangle -t8 noroff.nw docdate.nw | $(DOVERSION) > noroff.1
+
+wc.tex: ../../examples/wc.nw
+ (cd ../../examples; noweave -n -index wc.nw) > wc.tex
+
+techrep.dvi: techrep.tex wc.tex
+ latex '\scrollmode \input '"techrep"
+ while grep -s 'Rerun to get cross-references right' techrep.log; do latex '\scrollmode \input '"techrep"; done
+
+onepage.dvi: onepage.tex
+ latex '\scrollmode \input '"onepage"
+ while grep -s 'Rerun to get cross-references right' onepage.log; do latex '\scrollmode \input '"onepage"; done
+
+onepage.ps: onepage.dvi
+ dvips -P cmz -o onepage.ps onepage
+
+guide.dvi: guide.tex
+ latex '\scrollmode \input '"guide"
+ while grep -s 'Rerun to get cross-references right' guide.log; do latex '\scrollmode \input '"guide"; done
+
+guide.ps: guide.dvi
+ dvips -P cmz -o guide.ps guide
+
+guide.uu: guide.ps
+ gzip < guide.ps > guide.ps.gz
+ uuencode guide.ps.gz < guide.ps.gz > guide.uu
+
+guide.html: guide.dvi
+ sl2h guide.tex | htmltoc > guide.html
+
+clean: ; /bin/rm -f *.dvi *.log *.blg *~ wc.tex *.ps *.gz *.uu *.html
+clobber: clean
+ rm -f *.1 *.7 *.txt
+
diff --git a/web/noweb/src/xdoc/chicago.bst b/web/noweb/src/xdoc/chicago.bst
new file mode 100644
index 0000000000..925f9a2e0e
--- /dev/null
+++ b/web/noweb/src/xdoc/chicago.bst
@@ -0,0 +1,1653 @@
+%%% ====================================================================
+%%% @BibTeX-style-file{
+%%% author = "Glenn Paulley",
+%%% version = "4",
+%%% date = "28 August 1992",
+%%% time = "10:23:39 199",
+%%% filename = "chicago.bst",
+%%% address = "Data Structuring Group
+%%% Department of Computer Science
+%%% University of Waterloo
+%%% Waterloo, Ontario, Canada
+%%% N2L 3G1",
+%%% telephone = "(519) 885-1211",
+%%% FAX = "(519) 885-1208",
+%%% checksum = "26323 1654 5143 37417",
+%%% email = "gnpaulle@bluebox.uwaterloo.ca",
+%%% codetable = "ISO/ASCII",
+%%% keywords = "",
+%%% supported = "yes",
+%%% abstract = "A BibTeX bibliography style that follows the
+%%% `B' reference style of the 13th Edition of
+%%% the Chicago Manual of Style. A detailed
+%%% feature list is given below.",
+%%% docstring = "The checksum field above contains a CRC-16
+%%% checksum as the first value, followed by the
+%%% equivalent of the standard UNIX wc (word
+%%% count) utility output of lines, words, and
+%%% characters. This is produced by Robert
+%%% Solovay's checksum utility.",
+%%% }
+%%% ====================================================================
+%
+% "Chicago" BibTeX style, chicago.bst
+% ===================================
+%
+% BibTeX `chicago' style file for BibTeX version 0.99c, LaTeX version 2.09
+% Place it in a file called chicago.bst in the BibTeX search path.
+% You need to include chicago.sty as a \documentstyle option.
+% (Placing it in the same directory as the LaTeX document should also work.)
+% This "chicago" style is based on newapa.bst (American Psych. Assoc.)
+% found at ymir.claremont.edu.
+%
+% Citation format: (author-last-name year)
+% (author-last-name and author-last-name year)
+% (author-last-name, author-last-name, and author-last-name year)
+% (author-last-name et al. year)
+% (author-last-name)
+% author-last-name (year)
+% (author-last-name and author-last-name)
+% (author-last-name et al.)
+% (year) or (year,year)
+% year or year,year
+%
+% Reference list ordering: alphabetical by author or whatever passes
+% for author in the absence of one.
+%
+% This BibTeX style has support for abbreviated author lists and for
+% year-only citations. This is done by having the citations
+% actually look like
+%
+% \citeauthoryear{full-author-info}{abbrev-author-info}{year}
+%
+% The LaTeX style has to have the following (or similar)
+%
+% \let\@internalcite\cite
+% \def\fullcite{\def\citeauthoryear##1##2##3{##1, ##3}\@internalcite}
+% \def\fullciteA{\def\citeauthoryear##1##2##3{##1}\@internalcite}
+% \def\shortcite{\def\citeauthoryear##1##2##3{##2, ##3}\@internalcite}
+% \def\shortciteA{\def\citeauthoryear##1##2##3{##2}\@internalcite}
+% \def\citeyear{\def\citeauthoryear##1##2##3{##3}\@internalcite}
+%
+% These TeX macro definitions are found in chicago.sty. Additional
+% commands to manipulate different components of a citation can be defined
+% so that, for example, you can list author's names without parentheses
+% if using a citation as a noun or object in a sentence.
+%
+% This file was originally copied from newapa.bst at ymir.claremont.edu.
+%
+% Features of chicago.bst:
+% =======================
+%
+% - full names used in citations, but abbreviated citations are available
+% (see above)
+% - if an entry has a "month", then the month and year are also printed
+% as part of that bibitem.
+% - all conjunctions use "and" instead of "\&"
+% - major modification from Chicago Manual of Style (13th ed.) is that
+% only the first author in a reference appears last name first-
+% additional authors appear as J. Q. Public.
+% - pages are listed as "pp. xx-xx" in all entry types except
+% article entries.
+% - book, inbook, and manual use "location: publisher" (or organization)
+% for address and publisher. All other types list publishers separately.
+% - "pp." are used to identify page numbers for all entry types except
+% articles.
+% - organization is used as a citation label if neither author nor editor
+% is present (for manuals).
+% - "et al." is used for long author and editor lists, or when "others"
+% is used.
+%
+% Modifications and bug fixes from newapa.bst:
+% ===========================================
+%
+% - added month, year to bib entries if month is present
+% - fixed bug with In proceedings, added necessary comma after title
+% - all conjunctions changed to "and" from "\&"
+% - fixed bug with author labels in my.full.label: "et al." now is
+% generated when "others" is an author name
+% - major modification from Chicago Manual of Style (13th ed.) is that
+% only the first author in a reference appears last name first-
+% additional authors appear as J. Q. Public.
+% - pages are listed as "pp. xx-xx" in all entry types except
+% article entries. Unnecessary (IMHO) "()" around page numbers
+% were removed, and page numbers now don't end with a period.
+% - created chicago.sty for use with this bibstyle (required).
+% - fixed bugs in FUNCTION {format.vol.num.pages} for missing volume,
+% number, and /or pages. Renamed to format.jour.vol.
+% - fixed bug in formatting booktitles: additional period an error if
+% book has a volume.
+% - fixed bug: editors usually given redundant period before next clause
+% (format.editors.dot) removed.
+% - added label support for organizations, if both author and editor
+% are missing (from alpha.bst). If organization is too long, then
+% the key field is used for abbreviated citations.
+% - In proceedings or books of several volumes, no comma was written
+% between the "Volume x" and the page numbers (this was intentional
+% in newapa.bst). Fixed.
+% - Some journals may not have volumes/numbers, only month/year (eg.
+% IEEE Computer). Fixed bug in article style that assumed volume/number
+% was always present.
+%
+% Original documentation for newapa.sty:
+% =====================================
+%
+% This version was made by modifying the master file made by
+% Oren Patashnik (PATASHNIK@SCORE.STANFORD.EDU), and the 'named' BibTeX
+% style of Peter F. Patel-Schneider.
+%
+% Copyright (C) 1985, all rights reserved.
+% Copying of this file is authorized only if either
+% (1) you make absolutely no changes to your copy, including name, or
+% (2) if you do make changes, you name it something other than 'newapa.bst'.
+% There are undoubtably bugs in this style. If you make bug fixes,
+% improvements, etc. please let me know. My e-mail address is:
+% spencer@cgrg.ohio.state.edu or 71160.3141@compuserve.com
+%
+% This style was made from 'plain.bst', 'named.bst', and 'apalike.bst',
+% with lots of tweaking to make it look like APA style, along with tips
+% from Young Ryu and Brian Reiser's modifications of 'apalike.bst'.
+
+ENTRY
+ { address
+ author
+ booktitle
+ chapter
+ edition
+ editor
+ howpublished
+ institution
+ journal
+ key
+ month
+ note
+ number
+ organization
+ pages
+ publisher
+ school
+ series
+ title
+ type
+ volume
+ year
+ }
+ {}
+ { label.year extra.label sort.year sort.label }
+
+INTEGERS { output.state before.all mid.sentence after.sentence after.block }
+
+FUNCTION {init.state.consts}
+{ #0 'before.all :=
+ #1 'mid.sentence :=
+ #2 'after.sentence :=
+ #3 'after.block :=
+}
+
+STRINGS { s t u }
+
+FUNCTION {output.nonnull}
+{ 's :=
+ output.state mid.sentence =
+ { ", " * write$ }
+ { output.state after.block =
+ { add.period$ write$
+ newline$
+ "\newblock " write$
+ }
+ { output.state before.all =
+ 'write$
+ { add.period$ " " * write$ }
+ if$
+ }
+ if$
+ mid.sentence 'output.state :=
+ }
+ if$
+ s
+}
+
+% Use a colon to separate output. Used only for address/publisher
+% combination in book/inbook types, address/institution for manuals,
+% and organization:publisher for proceedings (inproceedings).
+%
+FUNCTION {output.nonnull.colon}
+{ 's :=
+ output.state mid.sentence =
+ { ": " * write$ }
+ { output.state after.block =
+ { add.period$ write$
+ newline$
+ "\newblock " write$
+ }
+ { output.state before.all =
+ 'write$
+ { add.period$ " " * write$ }
+ if$
+ }
+ if$
+ mid.sentence 'output.state :=
+ }
+ if$
+ s
+}
+
+FUNCTION {output}
+{ duplicate$ empty$
+ 'pop$
+ 'output.nonnull
+ if$
+}
+
+FUNCTION {output.colon}
+{ duplicate$ empty$
+ 'pop$
+ 'output.nonnull.colon
+ if$
+}
+
+FUNCTION {output.check}
+{ 't :=
+ duplicate$ empty$
+ { pop$ "empty " t * " in " * cite$ * warning$ }
+ 'output.nonnull
+ if$
+}
+
+FUNCTION {output.check.colon}
+{ 't :=
+ duplicate$ empty$
+ { pop$ "empty " t * " in " * cite$ * warning$ }
+ 'output.nonnull.colon
+ if$
+}
+
+FUNCTION {output.year.check}
+{ year empty$
+ { "empty year in " cite$ * warning$ }
+ { write$
+ " (" year * extra.label *
+ month empty$
+ { ")" * }
+ { ", " * month * ")" * }
+ if$
+ mid.sentence 'output.state :=
+ }
+ if$
+}
+
+
+FUNCTION {fin.entry}
+{ add.period$
+ write$
+ newline$
+}
+
+FUNCTION {new.block}
+{ output.state before.all =
+ 'skip$
+ { after.block 'output.state := }
+ if$
+}
+
+FUNCTION {new.sentence}
+{ output.state after.block =
+ 'skip$
+ { output.state before.all =
+ 'skip$
+ { after.sentence 'output.state := }
+ if$
+ }
+ if$
+}
+
+FUNCTION {not}
+{ { #0 }
+ { #1 }
+ if$
+}
+
+FUNCTION {and}
+{ 'skip$
+ { pop$ #0 }
+ if$
+}
+
+FUNCTION {or}
+{ { pop$ #1 }
+ 'skip$
+ if$
+}
+
+FUNCTION {new.block.checka}
+{ empty$
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.block.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.sentence.checka}
+{ empty$
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {new.sentence.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {field.or.null}
+{ duplicate$ empty$
+ { pop$ "" }
+ 'skip$
+ if$
+}
+
+%
+% Emphasize the top string on the stack.
+%
+FUNCTION {emphasize}
+{ duplicate$ empty$
+ { pop$ "" }
+ { "{\em " swap$ * "}" * }
+ if$
+}
+
+%
+% Emphasize the top string on the stack, but add a trailing space.
+%
+FUNCTION {emphasize.space}
+{ duplicate$ empty$
+ { pop$ "" }
+ { "{\em " swap$ * "\/}" * }
+ if$
+}
+
+INTEGERS { nameptr namesleft numnames }
+%
+% Format bibliographical entries with the first author last name first,
+% and subsequent authors with initials followed by last name.
+% All names are formatted in this routine.
+%
+FUNCTION {format.names}
+{ 's :=
+ #1 'nameptr := % nameptr = 1;
+ s num.names$ 'numnames := % numnames = num.name$(s);
+ numnames 'namesleft :=
+ { namesleft #0 > }
+
+ { nameptr #1 =
+ {s nameptr "{vv~}{ll}{, jj}{, f.}" format.name$ 't := }
+ {s nameptr "{f.~}{vv~}{ll}{, jj}" format.name$ 't := }
+ if$
+ nameptr #1 >
+ { namesleft #1 >
+ { ", " * t * }
+ { numnames #2 >
+ { "," * }
+ 'skip$
+ if$
+ t "others" =
+ { " et~al." * }
+ { " and " * t * } % from Chicago Manual of Style
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr := % nameptr += 1;
+ namesleft #1 - 'namesleft := % namesleft =- 1;
+ }
+ while$
+}
+
+FUNCTION {my.full.label}
+{ 's :=
+ #1 'nameptr := % nameptr = 1;
+ s num.names$ 'numnames := % numnames = num.name$(s);
+ numnames 'namesleft :=
+ { namesleft #0 > }
+
+ { s nameptr "{vv~}{ll}" format.name$ 't := % get the next name
+ nameptr #1 >
+ { namesleft #1 >
+ { ", " * t * }
+ { numnames #2 >
+ { "," * }
+ 'skip$
+ if$
+ t "others" =
+ { " et~al." * }
+ { " and " * t * } % from Chicago Manual of Style
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr := % nameptr += 1;
+ namesleft #1 - 'namesleft := % namesleft =- 1;
+ }
+ while$
+
+}
+
+FUNCTION {format.names.fml}
+%
+% Format names in "familiar" format, with first initial followed by
+% last name. Like format.names, ALL names are formatted.
+%
+{ 's :=
+ #1 'nameptr := % nameptr = 1;
+ s num.names$ 'numnames := % numnames = num.name$(s);
+ numnames 'namesleft :=
+ { namesleft #0 > }
+
+ { s nameptr "{f.~}{vv~}{ll}{, jj}" format.name$ 't :=
+
+ nameptr #1 >
+ { namesleft #1 >
+ { ", " * t * }
+ { numnames #2 >
+ { "," * }
+ 'skip$
+ if$
+ t "others" =
+ { " et~al." * }
+ { " and " * t * }
+% { " \& " * t * }
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr := % nameptr += 1;
+ namesleft #1 - 'namesleft := % namesleft =- 1;
+ }
+ while$
+}
+
+FUNCTION {format.authors}
+{ author empty$
+ { "" }
+ { author format.names }
+ if$
+}
+
+FUNCTION {format.key}
+{ empty$
+ { key field.or.null }
+ { "" }
+ if$
+}
+
+%
+% Format editor names for use in the "in" types: inbook, incollection,
+% inproceedings: first initial, then last names. When editors are the
+% LABEL for an entry, then format.editor is used which lists editors
+% by last name first.
+%
+FUNCTION {format.editors.fml}
+{ editor empty$
+ { "" }
+ { editor format.names.fml
+ editor num.names$ #1 >
+ { " (Eds.)" * }
+ { " (Ed.)" * }
+ if$
+ }
+ if$
+}
+
+%
+% Format editor names for use in labels, last names first.
+%
+FUNCTION {format.editors}
+{ editor empty$
+ { "" }
+ { editor format.names
+ editor num.names$ #1 >
+ { " (Eds.)" * }
+ { " (Ed.)" * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.title}
+{ title empty$
+ { "" }
+ { title "t" change.case$ }
+ if$
+}
+
+% Note that the APA style requres case changes
+% in article titles. The following does not
+% change cases. If you perfer it, uncomment the
+% following and comment out the above.
+
+%FUNCTION {format.title}
+%{ title empty$
+% { "" }
+% { title }
+% if$
+%}
+
+FUNCTION {n.dashify}
+{ 't :=
+ ""
+ { t empty$ not }
+ { t #1 #1 substring$ "-" =
+ { t #1 #2 substring$ "--" = not
+ { "--" *
+ t #2 global.max$ substring$ 't :=
+ }
+ { { t #1 #1 substring$ "-" = }
+ { "-" *
+ t #2 global.max$ substring$ 't :=
+ }
+ while$
+ }
+ if$
+ }
+ { t #1 #1 substring$ *
+ t #2 global.max$ substring$ 't :=
+ }
+ if$
+ }
+ while$
+}
+
+FUNCTION {format.btitle}
+{ edition empty$
+ { title emphasize }
+ { title empty$
+ { title emphasize }
+ { volume empty$ % gnp - check for volume, then don't need period
+ { "{\em " title * "\/} (" * edition * " ed.)" * "." * }
+ { "{\em " title * "\/} (" * edition * " ed.)" * }
+ if$
+ }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.emphasize.booktitle}
+{ edition empty$
+ { booktitle emphasize }
+ { booktitle empty$
+ { booktitle emphasize }
+ { volume empty$ % gnp - extra period an error if book has a volume
+ { "{\em " booktitle * "\/} (" * edition * " ed.)" * "." *}
+ { "{\em " booktitle * "\/} (" * edition * " ed.)" * }
+ if$
+ }
+ if$
+ }
+ if$
+ }
+
+
+FUNCTION {tie.or.space.connect}
+{ duplicate$ text.length$ #3 <
+ { "~" }
+ { " " }
+ if$
+ swap$ * *
+}
+
+FUNCTION {either.or.check}
+{ empty$
+ 'pop$
+ { "can't use both " swap$ * " fields in " * cite$ * warning$ }
+ if$
+}
+
+FUNCTION {format.bvolume}
+{ volume empty$
+ { "" }
+ { "Volume" volume tie.or.space.connect % gnp - changed to mixed case
+ series empty$
+ 'skip$
+ { " of " * series emphasize * }
+ if$
+ "volume and number" number either.or.check
+ }
+ if$
+}
+
+FUNCTION {format.number.series}
+{ volume empty$
+ { number empty$
+ { series field.or.null }
+ { output.state mid.sentence =
+ { "Number" } % gnp - changed to mixed case always
+ { "Number" }
+ if$
+ number tie.or.space.connect
+ series empty$
+ { "there's a number but no series in " cite$ * warning$ }
+ { " in " * series * }
+ if$
+ }
+ if$
+ }
+ { "" }
+ if$
+}
+
+INTEGERS { multiresult }
+
+FUNCTION {multi.page.check}
+{ 't :=
+ #0 'multiresult :=
+ { multiresult not
+ t empty$ not
+ and
+ }
+ { t #1 #1 substring$
+ duplicate$ "-" =
+ swap$ duplicate$ "," =
+ swap$ "+" =
+ or or
+ { #1 'multiresult := }
+ { t #2 global.max$ substring$ 't := }
+ if$
+ }
+ while$
+ multiresult
+}
+
+FUNCTION {format.pages}
+{ pages empty$
+ { "" }
+ { pages multi.page.check
+ { "pp.\ " pages n.dashify tie.or.space.connect } % gnp - removed ()
+ { "pp.\ " pages tie.or.space.connect }
+ if$
+ }
+ if$
+}
+
+% By Young (and Spencer)
+% GNP - fixed bugs with missing volume, number, and/or pages
+%
+% Format journal, volume, number, pages for article types.
+%
+FUNCTION {format.jour.vol}
+{ journal empty$
+ { "no journal in " cite$ * warning$
+ "" }
+ { journal emphasize.space }
+ if$
+ number empty$
+ { volume empty$
+ { "no number and no volume in " cite$ * warning$
+ "" * }
+ { "~{\em " * Volume * "}" * }
+ if$
+ }
+ { volume empty$
+ {"no volume for " cite$ * warning$
+ "~(" * number * ")" * }
+ { "~" *
+ volume emphasize.space
+ "(" * number * ")" * * }
+ if$
+ }
+ if$
+ pages empty$
+ {"page numbers missing in " cite$ * warning$
+ "" * } % gnp - place a null string on the stack for output
+ { duplicate$ empty$
+ { pop$ format.pages }
+ { ", " * pages n.dashify * } % gnp - removed pp. for articles
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.chapter.pages}
+{ chapter empty$
+ 'format.pages
+ { type empty$
+ { "Chapter" } % gnp - changed to mixed case
+ { type "t" change.case$ }
+ if$
+ chapter tie.or.space.connect
+ pages empty$
+ {"page numbers missing in " cite$ * warning$} % gnp - added check
+ { ", " * format.pages * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.in.ed.booktitle}
+{ booktitle empty$
+ { "" }
+ { editor empty$
+ { "In " format.emphasize.booktitle * }
+ { "In " format.editors.fml * ", " * format.emphasize.booktitle * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.thesis.type}
+{ type empty$
+ 'skip$
+ { pop$
+ type "t" change.case$
+ }
+ if$
+}
+
+FUNCTION {format.tr.number}
+{ type empty$
+ { "Technical Report" }
+ 'type
+ if$
+ number empty$
+ { "t" change.case$ }
+ { number tie.or.space.connect }
+ if$
+}
+
+FUNCTION {format.article.crossref}
+{ "See"
+ "\citeN{" * crossref * "}" *
+}
+
+FUNCTION {format.crossref.editor}
+{ editor #1 "{vv~}{ll}" format.name$
+ editor num.names$ duplicate$
+ #2 >
+ { pop$ " et~al." * }
+ { #2 <
+ 'skip$
+ { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+ { " et~al." * }
+ { " and " * editor #2 "{vv~}{ll}" format.name$ * }
+ if$
+ }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.book.crossref}
+{ volume empty$
+ { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
+ "In "
+ }
+ { "Volume" volume tie.or.space.connect % gnp - changed to mixed case
+ " of " *
+ }
+ if$
+ editor empty$
+ editor field.or.null author field.or.null =
+ or
+ { key empty$
+ { series empty$
+ { "need editor, key, or series for " cite$ * " to crossref " *
+ crossref * warning$
+ "" *
+ }
+ { "{\em " * series * "\/}" * }
+ if$
+ }
+ { key * }
+ if$
+ }
+ { format.crossref.editor * }
+ if$
+ " \citeN{" * crossref * "}" *
+}
+
+FUNCTION {format.incoll.inproc.crossref}
+{ "See"
+ " \citeN{" * crossref * "}" *
+}
+
+% format.lab.names:
+%
+% determines "short" names for the abbreviated author information.
+% "Long" labels are created in calc.label, using the routine my.full.label
+% to format author and editor fields.
+%
+% There are 4 cases for labels. (n=3 in the example)
+% a) one author Foo
+% b) one to n Foo, Bar and Baz
+% c) use of "and others" Foo, Bar et al.
+% d) more than n Foo et al.
+%
+FUNCTION {format.lab.names}
+{ 's :=
+ s num.names$ 'numnames :=
+ numnames #2 > % change number to number of others allowed before
+ % forcing "et al".
+ { s #1 "{vv~}{ll}" format.name$ " et~al." * }
+ {
+ numnames #1 - 'namesleft :=
+ #2 'nameptr :=
+ s #1 "{vv~}{ll}" format.name$
+ { namesleft #0 > }
+ { nameptr numnames =
+ { s nameptr "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+ { " et~al." * }
+ { " and " * s nameptr "{vv~}{ll}" format.name$ * }
+ if$
+ }
+ { ", " * s nameptr "{vv~}{ll}" format.name$ * }
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+ }
+ if$
+}
+
+FUNCTION {author.key.label}
+{ author empty$
+ { key empty$
+ { "no key, author in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { author format.lab.names }
+ if$
+}
+
+FUNCTION {editor.key.label}
+{ editor empty$
+ { key empty$
+ { "no key, editor in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { editor format.lab.names }
+ if$
+}
+
+FUNCTION {author.key.organization.label}
+%
+% added - gnp. Provide label formatting by organization if author is null.
+%
+{ author empty$
+ { organization empty$
+ { key empty$
+ { "no key, author or organization in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { organization }
+ if$
+ }
+ { author format.lab.names }
+ if$
+}
+
+FUNCTION {editor.key.organization.label}
+%
+% added - gnp. Provide label formatting by organization if editor is null.
+%
+{ editor empty$
+ { organization empty$
+ { key empty$
+ { "no key, editor or organization in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { organization }
+ if$
+ }
+ { editor format.lab.names }
+ if$
+}
+
+FUNCTION {author.editor.key.label}
+{ author empty$
+ { editor empty$
+ { key empty$
+ { "no key, author, or editor in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { editor format.lab.names }
+ if$
+ }
+ { author format.lab.names }
+ if$
+}
+
+FUNCTION {calc.label}
+%
+% Changed - GNP. See also author.organization.sort, editor.organization.sort
+% Form label for BibTeX entry. The classification of which fields are used
+% for which type of entry (book, inbook, etc.) are taken from alpha.bst.
+% The change here from newapa is to also include organization as a
+% citation label if author or editor is missing.
+%
+{ type$ "book" =
+ type$ "inbook" =
+ or
+ 'author.editor.key.label
+ { type$ "proceedings" =
+ 'editor.key.organization.label
+ { type$ "manual" =
+ 'author.key.organization.label
+ 'author.key.label
+ if$
+ }
+ if$
+ }
+ if$
+
+ author empty$ % generate the full label citation information.
+ { editor empty$
+ { organization empty$
+ { "no author, editor, or organization in " cite$ * warning$
+ "??" }
+ { organization }
+ if$
+ }
+ { editor my.full.label }
+ if$
+ }
+ { author my.full.label }
+ if$
+
+% leave label on the stack, to be popped when required.
+
+ "}{" * swap$ * "}{" *
+% year field.or.null purify$ #-1 #4 substring$ *
+%
+% save the year for sort processing afterwards (adding a, b, c, etc.)
+%
+ year field.or.null purify$ #-1 #4 substring$
+ 'label.year :=
+}
+
+FUNCTION {output.bibitem}
+{ newline$
+
+ "\bibitem[\protect\citeauthoryear{" write$
+ calc.label write$
+ sort.year write$
+ "}]{" write$
+
+ cite$ write$
+ "}" write$
+ newline$
+ ""
+ before.all 'output.state :=
+}
+
+FUNCTION {article}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ crossref missing$
+ { format.jour.vol output
+ }
+ { format.article.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {book}
+{ output.bibitem
+ author empty$
+ { format.editors
+ "author and editor" output.check }
+ { format.authors
+ output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ output.year.check % added
+ new.block
+ format.btitle
+ "title" output.check
+ crossref missing$
+ { format.bvolume output
+ new.block
+ format.number.series output
+ new.sentence
+ address output
+ publisher "publisher" output.check.colon
+ }
+ { new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {booklet}
+{ output.bibitem
+ format.authors output
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ howpublished output
+ address output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {inbook}
+{ output.bibitem
+ author empty$
+ { format.editors
+ "author and editor" output.check
+ }
+ { format.authors output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ output.year.check % added
+ new.block
+ format.btitle
+ "title" output.check
+ crossref missing$
+ { format.bvolume output
+ format.chapter.pages
+ "chapter and pages" output.check
+ new.block
+ format.number.series output
+ new.sentence
+ address output
+ publisher
+ "publisher" output.check.colon
+ }
+ { format.chapter.pages "chapter and pages" output.check
+ new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {incollection}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ crossref missing$
+ { format.in.ed.booktitle
+ "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ format.chapter.pages output % gnp - was special.output.nonnull
+% left out comma before page numbers
+ new.sentence
+ address output
+ publisher "publisher" output.check.colon
+ }
+ { format.incoll.inproc.crossref
+ output.nonnull
+ format.chapter.pages output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {inproceedings}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ crossref missing$
+ { format.in.ed.booktitle
+ "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ address output
+ format.pages output
+ new.sentence
+ organization output
+ publisher output.colon
+ }
+ { format.incoll.inproc.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {conference} { inproceedings }
+
+FUNCTION {manual}
+{ output.bibitem
+ author empty$
+ { editor empty$
+ { organization "organization" output.check
+ organization format.key output } % if all else fails, use key
+ { format.editors "author and editor" output.check }
+ if$
+ }
+ { format.authors output.nonnull }
+ if$
+ output.year.check % added
+ new.block
+ format.btitle
+ "title" output.check
+ organization address new.block.checkb
+% Reversed the order of "address" and "organization", added the ":".
+ address output
+ organization "organization" output.check.colon
+% address output
+% ":" output
+% organization output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {mastersthesis}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ "Master's thesis" format.thesis.type output.nonnull
+ school "school" output.check
+ address output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {misc}
+{ output.bibitem
+ format.authors output
+ author format.key output % added
+ output.year.check % added
+ title howpublished new.block.checkb
+ format.title output
+ new.block
+ howpublished output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {phdthesis}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.btitle
+ "title" output.check
+ new.block
+ "Ph.\ D. thesis" format.thesis.type output.nonnull
+ school "school" output.check
+ address output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {proceedings}
+{ output.bibitem
+ editor empty$
+ { organization output
+ organization format.key output } % gnp - changed from author format.key
+ { format.editors output.nonnull }
+ if$
+% author format.key output % gnp - removed (should be either
+% editor or organization
+ output.year.check % added (newapa)
+ new.block
+ format.btitle
+ "title" output.check
+ format.bvolume output
+ format.number.series output
+ address output
+ new.sentence
+ organization output
+ publisher output.colon
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {techreport}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ format.tr.number output.nonnull
+ institution
+ "institution" output.check
+ address output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {unpublished}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ note "note" output.check
+ fin.entry
+}
+
+FUNCTION {default.type} { misc }
+
+MACRO {jan} {"January"}
+
+MACRO {feb} {"February"}
+
+MACRO {mar} {"March"}
+
+MACRO {apr} {"April"}
+
+MACRO {may} {"May"}
+
+MACRO {jun} {"June"}
+
+MACRO {jul} {"July"}
+
+MACRO {aug} {"August"}
+
+MACRO {sep} {"September"}
+
+MACRO {oct} {"October"}
+
+MACRO {nov} {"November"}
+
+MACRO {dec} {"December"}
+
+MACRO {acmcs} {"ACM Computing Surveys"}
+
+MACRO {acta} {"Acta Informatica"}
+
+MACRO {ai} {"Artificial Intelligence"}
+
+MACRO {cacm} {"Communications of the ACM"}
+
+MACRO {ibmjrd} {"IBM Journal of Research and Development"}
+
+MACRO {ibmsj} {"IBM Systems Journal"}
+
+MACRO {ieeese} {"IEEE Transactions on Software Engineering"}
+
+MACRO {ieeetc} {"IEEE Transactions on Computers"}
+
+MACRO {ieeetcad}
+ {"IEEE Transactions on Computer-Aided Design of Integrated Circuits"}
+
+MACRO {ipl} {"Information Processing Letters"}
+
+MACRO {jacm} {"Journal of the ACM"}
+
+MACRO {jcss} {"Journal of Computer and System Sciences"}
+
+MACRO {scp} {"Science of Computer Programming"}
+
+MACRO {sicomp} {"SIAM Journal on Computing"}
+
+MACRO {tocs} {"ACM Transactions on Computer Systems"}
+
+MACRO {tods} {"ACM Transactions on Database Systems"}
+
+MACRO {tog} {"ACM Transactions on Graphics"}
+
+MACRO {toms} {"ACM Transactions on Mathematical Software"}
+
+MACRO {toois} {"ACM Transactions on Office Information Systems"}
+
+MACRO {toplas} {"ACM Transactions on Programming Languages and Systems"}
+
+MACRO {tcs} {"Theoretical Computer Science"}
+
+READ
+
+FUNCTION {sortify}
+{ purify$
+ "l" change.case$
+}
+
+INTEGERS { len }
+
+FUNCTION {chop.word}
+{ 's :=
+ 'len :=
+ s #1 len substring$ =
+ { s len #1 + global.max$ substring$ }
+ 's
+ if$
+}
+
+
+
+FUNCTION {sort.format.names}
+{ 's :=
+ #1 'nameptr :=
+ ""
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { nameptr #1 >
+ { " " * }
+ 'skip$
+ if$
+ s nameptr "{vv{ } }{ll{ }}{ f{ }}{ jj{ }}" format.name$ 't :=
+ nameptr numnames = t "others" = and
+ { " et~al" * }
+ { t sortify * }
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+}
+
+FUNCTION {sort.format.title}
+{ 't :=
+ "A " #2
+ "An " #3
+ "The " #4 t chop.word
+ chop.word
+ chop.word
+ sortify
+ #1 global.max$ substring$
+}
+
+FUNCTION {author.sort}
+{ author empty$
+ { key empty$
+ { "to sort, need author or key in " cite$ * warning$
+ "" }
+ { key sortify }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {editor.sort}
+{ editor empty$
+ { key empty$
+ { "to sort, need editor or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+}
+
+FUNCTION {author.editor.sort}
+{ author empty$
+ { "missing author in " cite$ * warning$
+ editor empty$
+ { key empty$
+ { "to sort, need author, editor, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {author.organization.sort}
+%
+% added - GNP. Stack author or organization for sorting (from alpha.bst).
+% Unlike alpha.bst, we need entire names, not abbreviations
+%
+{ author empty$
+ { organization empty$
+ { key empty$
+ { "to sort, need author, organization, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { organization sortify }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {editor.organization.sort}
+%
+% added - GNP. Stack editor or organization for sorting (from alpha.bst).
+% Unlike alpha.bst, we need entire names, not abbreviations
+%
+{ editor empty$
+ { organization empty$
+ { key empty$
+ { "to sort, need editor, organization, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { organization sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+}
+
+FUNCTION {presort}
+%
+% Presort creates the bibentry's label via a call to calc.label, and then
+% sorts the entries based on entry type. Chicago.bst adds support for
+% including organizations as the sort key; the following is stolen from
+% alpha.bst.
+%
+{ calc.label sortify % recalculate bibitem label
+ year field.or.null purify$ #-1 #4 substring$ * % add year
+ " "
+ *
+ type$ "book" =
+ type$ "inbook" =
+ or
+ 'author.editor.sort
+ { type$ "proceedings" =
+ 'editor.organization.sort
+ { type$ "manual" =
+ 'author.organization.sort
+ 'author.sort
+ if$
+ }
+ if$
+ }
+ if$
+ #1 entry.max$ substring$ % added for newapa
+ 'sort.label := % added for newapa
+ sort.label % added for newapa
+ *
+ " "
+ *
+ title field.or.null
+ sort.format.title
+ *
+ #1 entry.max$ substring$
+ 'sort.key$ :=
+}
+
+ITERATE {presort}
+
+SORT % by label, year, author/editor, title
+
+STRINGS { last.label next.extra }
+
+INTEGERS { last.extra.num }
+
+FUNCTION {initialize.extra.label.stuff}
+{ #0 int.to.chr$ 'last.label :=
+ "" 'next.extra :=
+ #0 'last.extra.num :=
+}
+
+FUNCTION {forward.pass}
+%
+% Pass through all entries, comparing current entry to last one.
+% Need to concatenate year to the stack (done by calc.label) to determine
+% if two entries are the same (see presort)
+%
+{ last.label
+ calc.label year field.or.null purify$ #-1 #4 substring$ * % add year
+ #1 entry.max$ substring$ = % are they equal?
+ { last.extra.num #1 + 'last.extra.num :=
+ last.extra.num int.to.chr$ 'extra.label :=
+ }
+ { "a" chr.to.int$ 'last.extra.num :=
+ "" 'extra.label :=
+ calc.label year field.or.null purify$ #-1 #4 substring$ * % add year
+ #1 entry.max$ substring$ 'last.label := % assign to last.label
+ }
+ if$
+}
+
+FUNCTION {reverse.pass}
+{ next.extra "b" =
+ { "a" 'extra.label := }
+ 'skip$
+ if$
+ label.year extra.label * 'sort.year :=
+ extra.label 'next.extra :=
+}
+
+EXECUTE {initialize.extra.label.stuff}
+
+ITERATE {forward.pass}
+
+REVERSE {reverse.pass}
+
+FUNCTION {bib.sort.order}
+{ sort.label
+ " "
+ *
+ year field.or.null sortify
+ *
+ " "
+ *
+ title field.or.null
+ sort.format.title
+ *
+ #1 entry.max$ substring$
+ 'sort.key$ :=
+}
+
+ITERATE {bib.sort.order}
+
+SORT % by sort.label, year, title --- giving final bib. order.
+
+FUNCTION {begin.bib}
+
+{ preamble$ empty$
+ 'skip$
+ { preamble$ write$ newline$ }
+ if$
+ "\begin{thebibliography}{}" write$ newline$
+}
+
+
+EXECUTE {begin.bib}
+
+EXECUTE {init.state.consts}
+
+ITERATE {call.type$}
+
+FUNCTION {end.bib}
+{ newline$
+ "\end{thebibliography}" write$ newline$
+}
+
+EXECUTE {end.bib}
+
diff --git a/web/noweb/src/xdoc/chicago.sty b/web/noweb/src/xdoc/chicago.sty
new file mode 100644
index 0000000000..db39103502
--- /dev/null
+++ b/web/noweb/src/xdoc/chicago.sty
@@ -0,0 +1,264 @@
+% -*- LaTeX -*-
+%%% ====================================================================
+%%% @LaTeX-style-file{
+%%% author = "Glenn Paulley",
+%%% version = "4",
+%%% date = "31 August 1992",
+%%% time = "09:42:44 199",
+%%% filename = "chicago.sty",
+%%% address = "Data Structuring Group
+%%% Department of Computer Science
+%%% University of Waterloo
+%%% Waterloo, Ontario, Canada
+%%% N2L 3G1",
+%%% telephone = "(519) 885-1211",
+%%% FAX = "(519) 885-1208",
+%%% checksum = "44674 264 1050 10394",
+%%% email = "gnpaulle@bluebox.uwaterloo.ca",
+%%% codetable = "ISO/ASCII",
+%%% keywords = "",
+%%% supported = "yes",
+%%% abstract = "Contains the LaTeX style command definitions
+%%% for the Chicago BibTeX styles chicago.bst and
+%%% chicagoa.bst. For details, see below.",
+%%% docstring = "The checksum field above contains a CRC-16
+%%% checksum as the first value, followed by the
+%%% equivalent of the standard UNIX wc (word
+%%% count) utility output of lines, words, and
+%%% characters. This is produced by Robert
+%%% Solovay's checksum utility.",
+%%% }
+%%% ====================================================================
+%
+% chicago.sty: Style file for use with bibtex style chicago.bst, for
+% bibliographies formatted according to the 13th Edition of the Chicago
+% Manual of Style.
+%
+% 'newapa.bst' was made from 'plain.bst', 'named.bst', and 'apalike.bst',
+% with lots of tweaking to make it look like APA style, along with tips
+% from Young Ryu and Brian Reiser's modifications of 'apalike.bst'.
+% newapa.sty formed the basis of this style, chicago.sty. Author-date
+% references in newapa.bst formed the basis for chicago.bst. Chicagoa.bst
+% supports annotations.
+%
+% Version 4 (August, 1992):
+% - fixed chicago.bst and chicagoa.bst to handle long author lists in
+% sorting
+% - fixed chicago.bst and chicagoa.bst so that missing page numbers in
+% ``article'' entries are handled correctly
+% - modified chicago.sty to format entries with 2nd and subsequent lines
+% indented.
+%
+% Citation format: (author-last-name year)
+% (author-last-name and author-last-name year)
+% (author-last-name et al. year)
+% (author-last-name)
+% author-last-name
+% author-last-name (year)
+% (author-last-name and author-last-name)
+% (author-last-name et al.)
+% (year) or (year,year)
+% year or year,year
+%
+% Reference list ordering: alphabetical by author or whatever passes
+% for author in the absence of one.
+%
+% This BibTeX style has support for abbreviated author lists and for
+% year-only citations. This is done by having the citations
+% actually look like
+%
+% \citeauthoryear{full-author-info}{abbrev-author-info}{year}
+%
+% The LaTeX style has to have the following (or similar)
+%
+% \let\@internalcite\cite
+% \def\fullcite{\def\citeauthoryear##1##2##3{##1, ##3}\@internalcite}
+% \def\fullciteA{\def\citeauthoryear##1##2##3{##1}\@internalcite}
+% \def\shortcite{\def\citeauthoryear##1##2##3{##2, ##3}\@internalcite}
+% \def\shortciteA{\def\citeauthoryear##1##2##3{##2}\@internalcite}
+% \def\citeyear{\def\citeauthoryear##1##2##3{##3}\@internalcite}
+%
+% -------------------------------------------------------------------------
+% This file implements citations for the ``chicago'' bibliography style.
+% Place it in a file called chicago.sty in the TeX search path.
+%(Placing it in the same directory as the LaTeX document should also work.)
+%
+% This file is a modification of the ``newapa'' LaTeX style,
+% originally adapted by Steven Spencer from the ``apalike'' LaTeX style.
+% It was originally modified by Stephen N. Spencer, with further
+% modifications by Young U. Ryu.
+%
+% The ``chicago'' BibTeX bibliography style creates citations with labels:
+% \citeauthoryear{author-info}{abbrev. author-info}{year}
+%
+% These labels are processed by the following LaTeX commands:
+%
+% \cite{key}
+% which produces citations with full author list and year.
+% eg. (Brown 1978; Jarke, Turner, Stohl, et al. 1985)
+% \citeNP{key}
+% which produces citations with full author list and year, but without
+% enclosing parentheses:
+% eg. Brown 1978; Jarke, Turner and Stohl 1985
+% \citeA{key}
+% which produces citations with only the full author list.
+% eg. (Brown; Jarke, Turner and Stohl)
+% \citeANP{key}
+% which produces citations with only the full author list, without
+% parentheses eg. Brown; Jarke, Turner and Stohl
+% \citeN{key}
+% which produces citations with the full author list and year, but
+% can be used as nouns in a sentence; no parentheses appear around
+% the author names, but only around the year.
+% eg. Shneiderman (1978) states that......
+% \citeN should only be used for a single citation.
+% \shortcite{key}
+% which produces citations with abbreviated author list and year.
+% \shortciteNP{key}
+% which produces citations with abbreviated author list and year.
+% \shortciteA{key}
+% which produces only the abbreviated author list.
+% \shortciteANP{key}
+% which produces only the abbreviated author list.
+% \shortciteN{key}
+% which produces the abbreviated author list and year, with only the
+% year in parentheses. Use with only one citation.
+% \citeyear{key}
+% which produces the year information only, within parentheses.
+% \citeyearNP{key}
+% which produces the year information only.
+%
+% Abbreviated author lists use the ``et al.'' construct.
+%
+% `NP' means `no parentheses'.
+%
+% This LaTeX style file must be used with the ``chicago'' or ``chicagoa''
+% (annotated chicago style) BibTeX styles.
+%
+\typeout{Using Chicago Manual of Style bibliography: 31 August 1992}
+%
+% -------------------------------------------------------------------------
+%
+% Citation macros.
+%
+\let\@internalcite\cite
+%
+\def\cite{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{(##1\if@tempswa , ##2\fi)}%
+ \def\citeauthoryear##1##2##3{##1 ##3}\@internalcite}
+\def\citeNP{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2\fi}%
+ \def\citeauthoryear##1##2##3{##1 ##3}\@internalcite}
+\def\citeN{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2)\else{)}\fi}%
+ \def\citeauthoryear##1##2##3{##1 (##3}\@citedata}
+\def\citeA{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{(##1\if@tempswa , ##2\fi)}%
+ \def\citeauthoryear##1##2##3{##1}\@internalcite}
+\def\citeANP{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2\fi}%
+ \def\citeauthoryear##1##2##3{##1}\@internalcite}
+%
+\def\shortcite{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{(##1\if@tempswa , ##2\fi)}%
+ \def\citeauthoryear##1##2##3{##2 ##3}\@internalcite}
+\def\shortciteNP{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2\fi}%
+ \def\citeauthoryear##1##2##3{##2 ##3}\@internalcite}
+\def\shortciteN{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2)\else{)}\fi}%
+ \def\citeauthoryear##1##2##3{##2 (##3}\@citedata}
+\def\shortciteA{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{(##1\if@tempswa , ##2\fi)}%
+ \def\citeauthoryear##1##2##3{##2}\@internalcite}
+\def\shortciteANP{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2\fi}%
+ \def\citeauthoryear##1##2##3{##2}\@internalcite}
+%
+\def\citeyear{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{(##1\if@tempswa , ##2\fi)}%
+ \def\citeauthoryear##1##2##3{##3}\@citedata}
+\def\citeyearNP{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2\fi}%
+ \def\citeauthoryear##1##2##3{##3}\@citedata}
+
+%
+% \@citedata and \@citedatax:
+%
+% Place commas in-between citations in the same \citeyear, \citeyearNP,
+% \citeN, or \shortciteN command.
+% Use something like \citeN{ref1,ref2,ref3} and \citeN{ref4} for a list.
+%
+\def\@citedata{%
+ \@ifnextchar [{\@tempswatrue\@citedatax}%
+ {\@tempswafalse\@citedatax[]}%
+}
+
+\def\@citedatax[#1]#2{%
+\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi%
+ \def\@citea{}\@cite{\@for\@citeb:=#2\do%
+ {\@citea\def\@citea{, }\@ifundefined% by Young
+ {b@\@citeb}{{\bf ?}%
+ \@warning{Citation `\@citeb' on page \thepage \space undefined}}%
+{\csname b@\@citeb\endcsname}}}{#1}}%
+
+% don't box citations, separate with ; and a space
+% also, make the penalty between citations negative: a good place to break.
+%
+\def\@citex[#1]#2{%
+\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi%
+ \def\@citea{}\@cite{\@for\@citeb:=#2\do%
+ {\@citea\def\@citea{; }\@ifundefined% by Young
+ {b@\@citeb}{{\bf ?}%
+ \@warning{Citation `\@citeb' on page \thepage \space undefined}}%
+{\csname b@\@citeb\endcsname}}}{#1}}%
+
+% (from apalike.sty)
+% No labels in the bibliography.
+%
+\def\@biblabel#1{}
+
+% (from apalike.sty)
+% Set length of hanging indentation for bibliography entries.
+%
+\newlength{\bibhang}
+\setlength{\bibhang}{2em}
+
+% Indent second and subsequent lines of bibliographic entries. Stolen
+% from openbib.sty: \newblock is set to {}.
+
+\newdimen\bibindent
+\bibindent=1.5em
+\@ifundefined{refname}%
+ {\@ifundefined{chapter}%
+ {\newcommand{\refname}{References}}%
+ {\newcommand{\refname}{Bibliography}}%
+ }%
+ {}%
+\@ifundefined{chapter}%
+ {\def\thebibliography#1{\section*{\refname\@mkboth
+ {\uppercase{\refname}}{\uppercase{\refname}}}\list
+ {[\arabic{enumi}]}{\settowidth\labelwidth{[#1]}
+ \leftmargin\labelwidth
+ \advance\leftmargin\labelsep
+ \advance\leftmargin\bibindent
+ \itemindent -\bibindent
+ \listparindent \itemindent
+ \parsep \z@
+ \usecounter{enumi}}
+ \def\newblock{}
+ \sloppy
+ \sfcode`\.=1000\relax}}
+ {\def\thebibliography#1{\chapter*{\refname\@mkboth
+ {\uppercase{\refname}}{\uppercase{\refname}}}\list
+ {[\arabic{enumi}]}{\settowidth\labelwidth{[#1]}
+ \leftmargin\labelwidth
+ \advance\leftmargin\labelsep
+ \advance\leftmargin\bibindent
+ \itemindent -\bibindent
+ \listparindent \itemindent
+ \parsep \z@
+ \usecounter{enumi}}
+ \def\newblock{}
+ \sloppy
+ \sfcode`\.=1000\relax}}
diff --git a/web/noweb/src/xdoc/cpif.1 b/web/noweb/src/xdoc/cpif.1
new file mode 100644
index 0000000000..bf714ea7e9
--- /dev/null
+++ b/web/noweb/src/xdoc/cpif.1
@@ -0,0 +1,38 @@
+.TH CPIF 1 "local 10/40/2008"
+.SH NAME
+cpif \- selectively update files
+.SH SYNOPSIS
+.B cpif
+[\fB\-eq\fP|\fB\-ne\fP] file ...
+.SH DESCRIPTION
+.I cpif
+is an auxiliary tool for use with
+.IR notangle (1)
+and
+.IR make (1).
+.I cpif
+compares its standard input to each of the named files,
+overwriting the file if the comparison succeeds or if
+the named file does not exist.
+If neither
+.B \-eq
+or
+.B \-ne
+is specified, the default is
+.BR \-ne .
+Typical usage is in the following default rule, suitable for use in a Makefile.
+.br
+ .nw.h: ; notangle \-Rheader $*.nw | cpif $*.h
+.br
+.SH SEE ALSO
+.IR notangle (1)
+.SH VERSION
+This man page is from
+.I noweb
+version 2.12.
+.SH AUTHOR
+Norman Ramsey, Tufts University.
+Internet address \fBNorman.Ramsey@tufts.edu\fP.
+.br
+Noweb home page at \fBhttp://www.cs.tufts.edu/~nr/noweb\fP.
+
diff --git a/web/noweb/src/xdoc/cpif.txt b/web/noweb/src/xdoc/cpif.txt
new file mode 100644
index 0000000000..91931c01d5
--- /dev/null
+++ b/web/noweb/src/xdoc/cpif.txt
@@ -0,0 +1,33 @@
+CPIF(1) General Commands Manual CPIF(1)
+
+
+
+NNAAMMEE
+ cpif - selectively update files
+
+SSYYNNOOPPSSIISS
+ ccppiiff [--eeqq|--nnee] file ...
+
+DDEESSCCRRIIPPTTIIOONN
+ _c_p_i_f is an auxiliary tool for use with _n_o_t_a_n_g_l_e(1) and _m_a_k_e(1). _c_p_i_f
+ compares its standard input to each of the named files, overwriting the
+ file if the comparison succeeds or if the named file does not exist.
+ If neither --eeqq or --nnee is specified, the default is --nnee. Typical usage
+ is in the following default rule, suitable for use in a Makefile.
+ .nw.h: ; notangle -Rheader $*.nw | cpif $*.h
+
+SSEEEE AALLSSOO
+ _n_o_t_a_n_g_l_e(1)
+
+VVEERRSSIIOONN
+ This man page is from _n_o_w_e_b version 2.12.
+
+AAUUTTHHOORR
+ Norman Ramsey, Tufts University. Internet address NNoorrmmaann..RRaammâ€â€
+ sseeyy@@ttuuffttss..eedduu.
+ Noweb home page at hhttttpp::////wwwwww..ccss..ttuuffttss..eedduu//~~nnrr//nnoowweebb.
+
+
+
+
+ local 10/40/2008 CPIF(1)
diff --git a/web/noweb/src/xdoc/docdate.nw b/web/noweb/src/xdoc/docdate.nw
new file mode 100644
index 0000000000..ee8bf4178c
--- /dev/null
+++ b/web/noweb/src/xdoc/docdate.nw
@@ -0,0 +1,13 @@
+<<noweb documentation date>>=
+10/40/2008
+<<AUTHOR section>>=
+.SH VERSION
+This man page is from
+.I noweb
+version $Name: v2_12 $.
+.SH AUTHOR
+Norman Ramsey, Tufts University.
+Internet address \fBNorman.Ramsey@tufts.edu\fP.
+.br
+Noweb home page at \fBhttp://www.cs.tufts.edu/~nr/noweb\fP.
+
diff --git a/web/noweb/src/xdoc/doversion b/web/noweb/src/xdoc/doversion
new file mode 100755
index 0000000000..bc8ceef2a6
--- /dev/null
+++ b/web/noweb/src/xdoc/doversion
@@ -0,0 +1,2 @@
+#!/bin/sh
+sed '/^version $Name:/s/_/./g;/^version $Name:/s/ $\././;/^version $Name:/s/$Name: v//'
diff --git a/web/noweb/src/xdoc/guide.bbl b/web/noweb/src/xdoc/guide.bbl
new file mode 100644
index 0000000000..7056121fd3
--- /dev/null
+++ b/web/noweb/src/xdoc/guide.bbl
@@ -0,0 +1,26 @@
+\begin{thebibliography}{}
+
+\bibitem[\protect\citeauthoryear{Aho, Kernighan, and Weinberger}{Aho
+ et~al.}{1988}]{aho:awk}
+Aho, A.~V., B.~W. Kernighan, and P.~J. Weinberger (1988).
+\newblock {\em The {AWK} Programming Language}.
+\newblock Reading, MA: Addison-Wesley.
+
+\bibitem[\protect\citeauthoryear{Fraser and Hanson}{Fraser and
+ Hanson}{1995}]{fraser:retargetable:book}
+Fraser, C.~W. and D.~R. Hanson (1995).
+\newblock {\em A Retargetable {C} Compiler: Design and Implementation}.
+\newblock Redwood City, CA: Benjamin/Cummings.
+
+\bibitem[\protect\citeauthoryear{Kernighan and Pike}{Kernighan and
+ Pike}{1984}]{kernighan:unix}
+Kernighan, B.~W. and R.~Pike (1984).
+\newblock {\em The {UNIX} Programming Environment}.
+\newblock Englewood Cliffs, NJ: Prentice-Hall.
+
+\bibitem[\protect\citeauthoryear{Ramsey}{Ramsey}{1994}]{ramsey:simplified}
+Ramsey, N. (1994, September).
+\newblock Literate programming simplified.
+\newblock {\em IEEE Software\/}~{\em 11\/}(5), 97--105.
+
+\end{thebibliography}
diff --git a/web/noweb/src/xdoc/guide.tex b/web/noweb/src/xdoc/guide.tex
new file mode 100644
index 0000000000..cd1a84c2c2
--- /dev/null
+++ b/web/noweb/src/xdoc/guide.tex
@@ -0,0 +1,1162 @@
+\documentclass{article}
+\usepackage{chicago,array,tabularx,afterpage}
+% chicago bibliography style is available from CTAN; others are standard
+
+\setlength{\extrarowheight}{1pt}
+
+\title{The {\tt noweb} Hacker's Guide}
+\author{Norman Ramsey\thanks{Author's current address is Department of
+Computer Science, Tufts University, Medford, MA 02155, USA;
+send email to {\tt nr@cs.tufts.edu}.}\\Department of Computer Science\\
+Princeton University}
+\date{September 1992\\(Revised August 1994, December 1997)}
+
+\setcounter{secnumdepth}{0}
+\setcounter{tocdepth}{3}
+\clubpenalty=10000
+\widowpenalty=10000
+
+\newcommand\kw[1]{\texttt{@#1}}
+\newcommand\kws[2]{\kw{#1}\hbox{\thinspace}\ldots~\kw{#2}}
+\newcommand\ikw[1]{\kw{index~#1}}
+\newcommand\ikws[2]{\ikw{#1}\hbox{\thinspace}\ldots~\ikw{#2}}
+\newcommand\xkw[1]{\kw{xref~#1}}
+\newcommand\xkws[2]{\xkw{#1}\hbox{\thinspace}\ldots~\xkw{#2}}
+
+% l2h argblock kw <tt>@ </tt>
+% l2h argblock kws <tt>@ ...#</tt>@
+% l2h argblock ikw <tt>@index# </tt>
+% l2h argblock ikws <tt>@index# ...#</tt>@index#
+% l2h argblock xkw <tt>@xref# </tt>
+% l2h argblock xkws <tt>@xref# ...#</tt>@xref#
+
+\newcommand\ltxlabel{\relax}
+\let\ltxlabel=\label
+
+% l2h let ltxlabel label
+
+\renewcommand\label{{\rm\it label\/}}
+\newcommand\tag{{\rm\it tag\/}}
+\newcommand\ident{{\rm\it ident\/}}
+
+% l2h substitution label <i>label</i>
+% l2h substitution tag <i>tag</i>
+% l2h substitution ident <i>ident</i>
+
+
+% title in a table
+
+\newcommand\ttitle[1]{\noalign{\medskip}\multicolumn{2}{c}{#1}\\\noalign{\smallskip}}
+
+% l2h argblock ttitle <br><center> </center><br>
+
+% figure hacking
+
+\newcommand\topfigrule{%
+ \vbox to 0pt{
+ \vskip 5pt
+ \centerline{\vrule height 1pt depth 0pt width 3in}
+ \vss}}
+
+\newcommand\botfigrule{%
+ \vbox to 0pt{
+ \vss
+ \centerline{\vrule height 1pt depth 0pt width 3in}
+ \vskip 5pt}}
+
+\begin{document}
+
+\maketitle
+
+\begin{abstract}
+{\tt Noweb} is unique among literate-programming tools in its
+pipelined architecture, which makes it easy for users to change
+its behavior or to add new features, without even recompiling.
+This guide describes the representation used in the
+pipeline and the behavior of the existing pipeline stages.
+Ordinary users will find nothing of interest here; the guide is
+addressed to those who want to change or extend {\tt noweb}.
+\end{abstract}
+
+\clearpage
+
+\tableofcontents
+\listoftables
+
+\newpage
+
+\section{Introduction}
+
+\citeN{ramsey:simplified} describes {\tt {\tt noweb}} from a user's
+point of view, showing its simplicity and examples of its use.
+The {\tt {\tt noweb}} tools are implemented as {\em pipelines}.
+Each pipeline begins with the {\tt noweb}
+source file. Successive stages of the pipeline implement simple
+transformations of the source, until the desired result emerges from
+the end of the pipeline. Figures
+\ref{fig:pipe-notangle}~and~\ref{fig:pipe-noweave} on
+page~\pageref{fig:pipe-notangle} show pipelines for
+{\tt notangle} and {\tt noweave}.
+Pipelines are responsible for {\tt {\tt noweb}}'s
+extensibility, which enables its users to create new literate-programming
+features without having to write their own tools.
+This document explains how to change or extend {\tt noweb} by
+inserting or removing pipeline stages.
+Readers should be familiar with the {\tt {\tt noweb}} man pages, which
+describe the structure of {\tt {\tt noweb}} source files.
+
+{\tt Markup}, which is the first stage in
+every pipeline, converts {\tt noweb} source to a representation easily
+manipulated by common Unix tools like {\tt sed} and {\tt awk}, simplifying
+the construction of later pipeline stages. Middle stages add
+information to the representation. {\tt notangle}'s final stage converts to
+code; {\tt noweave}'s final stages convert to TeX, LaTeX or HTML.
+Middle stages are called {\em filters}, by analogy with Unix filters.
+Final stages are called {\em back ends}, by analogy with
+compilers---they don't transform {\tt {\tt noweb}}'s intermediate
+representation; they emit something else.
+
+\section{The pipeline representation}
+
+In the pipeline, every line begins with an at sign and one of the
+keywords shown in Table~\ref{table:keywords}.
+The structural keywords
+represent the {\tt noweb} source syntax directly.
+They must appear in particular orders that reflect the
+structure of the source.
+The tagging keywords can be inserted
+essentially anywhere (within reason), and with some exceptions, they are not generated
+by {\tt markup}.
+The wrapper keywords
+mark the beginning and end of file,
+and they carry information about what formatters are supposed to do in
+the way of leading and trailing boilerplate.
+They are used by {\tt noweave} but not by {\tt notangle}, and they are
+inserted directly by the {\tt noweave} shell script, not by {\tt markup}.
+
+\begin{table}[t]
+\noindent
+\begin{tabularx}{\textwidth}{|>{\tt}l>{\raggedright\arraybackslash}X|}
+% l2h macro ttitle 1 </td><td></td></tr><tr><td colspan=2 align=center><b>#1</b></td></tr><tr><td>
+\ttitle{Structural keywords}
+\hline
+@begin {\rm\it kind} $n$&Start a chunk\\
+@end {\rm\it kind} $n$&End a chunk\\
+@text {\rm\it string}&{\rm\it string} appeared in a chunk\\
+@nl&A newline appeared in a chunk\\
+@defn {\rm\it name}&The code chunk named {\rm\it name} is being defined\\
+@use {\rm\it name}&A reference to code chunk named {\rm\it name}\\
+@quote&Start of quoted code in a documentation chunk\\
+@endquote&End of quoted code in a documentation chunk\\
+\hline
+\ttitle{Tagging keywords}
+\hline
+@file {\rm\it filename}&Name of the file from which the chunks came\\
+@line $n$&Next text line came from source line $n$ in current file\\
+@language {\rm\it language}&Programming language in which code is written\\
+@index \ldots&Index information.\\
+@xref \ldots&Cross-reference information.\\
+\hline
+\end{tabularx}\\
+\begin{tabularx}{\textwidth}{|>{\tt}l>{\raggedright\arraybackslash}X|}
+\ttitle{Wrapper keywords}
+\hline
+@header {\rm\it formatter options}&
+ First line, identifying formatter and options\\
+@trailer {\rm\it formatter}&Last line, identifying formatter.\\
+\hline
+%\end{tabularx}\\
+%\begin{tabularx}{\textwidth}{|>{\tt}l>{\raggedright\arraybackslash}X|}
+\ttitle{Error keyword}
+\hline
+@fatal {\rm\it stagename} {\rm\it message}&
+ A fatal error has occurred.\\
+\hline
+%\end{tabularx}\\
+%\begin{tabularx}{\textwidth}{|>{\tt}l>{\raggedright\arraybackslash}X|}
+\ttitle{Lying, cheating, stealing keyword}
+\hline
+@literal {\rm\it text}&
+ Copy {\it text} to output.\\
+\hline
+\end{tabularx}
+
+\caption{Keywords used in {\tt noweb}'s pipeline representation}
+\ltxlabel{table:keywords}
+
+\end{table}
+
+\subsection{Structural keywords}
+
+The structural keywords represent the chunks in the {\tt noweb} source.
+Each chunk is bracketed by a \kws{begin}{end} pair,
+and the {\it kind} of chunk is either {\tt docs} or {\tt code}.
+The \kw{begin} and \kw{end} are numbered; within a single file,
+numbers must be monotonically increasing, but they need not be
+consecutive.
+Filters may change chunk numbers at will.
+
+Depending on its kind, a chunk may contain {\em documentation} or {\em
+code}.
+Documentation may contain text and newlines, represented by \kw{text}
+and \kw{nl}.
+It may also contain {\em quoted code} bracketed by
+\kws{quote}{endquote}.
+Every \kw{quote} must be terminated by an \kw{endquote} within the
+same chunk.
+Quoted code corresponds to the \verb+[[+\ldots \verb+]]+ construct in
+the {\tt noweb} source.
+
+Code, whether it appears in quoted code or in a code chunk,
+may contain text and newlines, and also definitions and uses of
+code chunks, marked with \kw{defn} and \kw{use}.
+The first structural keyword in any code chunk must be \kw{defn}.
+\kw{defn} may be preceded or followed by tagging keywords, but the
+next structural keyword
+must be \kw{nl};
+together, the \kw{defn} and \kw{nl}
+represent the initial \verb+<<chunk name>>=+
+that starts the chunk (including the terminating newline).
+
+A few facts follow from what's already stated above, but are probably
+worth noting explicitly:
+\begin{itemize}
+\item
+Quoted code may not appear in code, nor may it appear in
+\kw{defn} or \kw{use}.
+{\tt noweave} back ends are encouraged to give \verb+[[+\ldots
+\verb+]]+ special treatment when it appears in \verb+defn+ or
+\verb+use+, so that the text contained therein is treated as if it
+were quoted code.
+\item
+The text in chunks may be distributed among as many \kw{text}
+keywords as desirable. Any number of empty \kw{text} keywords are
+permitted. In particular, it is not realistic to expect that a single
+line will be represented in a single \kw{text} (see the discussion of
+{\tt finduses} on page~\pageref{finduses}).
+\item
+{\tt markup} will sometimes emit \kw{use} within
+\kws{quote}{endquote}, for example from a source like \verb+[[<<chunk name>>]]+.
+\item
+No two chunks have the same number.
+\item
+Because later filters can change chunk numbers, no filter should
+plant references to chunk numbers anywhere in the pipeline.
+\end{itemize}
+
+\subsection{Tagging keywords}
+
+The structural keywords carry all the code and documentation that
+appears in a {\tt noweb} source file.
+The tagging keywords carry information about that code or
+documentation.
+The \kw{file} keyword carries the name of the source file from which the
+following lines come.
+The \kw{line} keyword give the line number of the next \kw{text} line
+within the current file (as determined by the most recent \kw{file}
+keyword).
+The only guarantee about where these appear is that {\tt markup}
+introduces each new source file with a \kw{file} that appears between
+chunks.
+Most filters ignore \kw{file} and \kw{line}, but {\tt nt}
+respects them, so that {\tt
+notangle} can properly mark line numbers if some {\tt noweb}
+filter starts moving lines around.
+
+\subsubsection{Programming languages}
+
+To support automatic indexing or prettyprinting, it's possible to
+indicate the programming language in which a chunk is written.
+The \kw{language} keyword may appear at most once between
+each \kw{begin~code} and \kw{end code} pair.
+Standard values of \kw{language} and their associated meanings are:
+\begin{quote}
+\begin{tabularx}{\textwidth}{@{}>{\ttfamily}lX@{}}
+\texttt{awk}&awk\\
+\texttt{c}&C\\
+\texttt{c++}&C$++$\\
+\texttt{caml}&CAML\\
+\texttt{html}&HTML\\
+\texttt{icon}&Icon\\
+\texttt{latex}&{\LaTeX} source\\
+\texttt{lisp}&Lisp or Scheme\\
+\texttt{make}&A Makefile\\
+\texttt{m3}&Modula-3\\
+\texttt{ocaml}&Objective CAML\\
+\texttt{perl}&A perl script\\
+\texttt{python}&Python\\
+\texttt{sh}&A shell script\\
+\texttt{sml}&Standard ML\\
+\texttt{tex}&plain {\TeX}\\
+\texttt{tcl}&tcl\\
+\end{tabularx}
+\end{quote}
+If the \kw{language} keyword catches on, it may be useful to create an
+automatic registry on the World-Wide Web.
+
+I have made it impossible to place \kw{language} information directly
+in a \texttt{noweb} source file.
+My intent is that tools will identify the language of the root chunks
+using any of several methods: conventional names of chunks, being told
+on a command line, or identifying the language by looking at the
+content of the chunks.
+(Of these methods, the most practical is to name the root chunks after
+the files to which they will be extracted, and to use the same naming
+conventions as \texttt{make} to figure out what the contents are.)
+A \texttt{noweb} filter will tag non-root chunks with the appropriate
+\kw{language} by propagating information from uses to definitions.
+
+
+
+
+\subsubsection{Indexing and cross-reference concepts}
+
+
+The index and cross-reference commands use \label s, \ident s, and \tag s.
+A \label\ is a unique string generated to refer to some element of a
+literate program.
+They serve as labels or ``anchor points'' for back ends that are
+capable of implementing their own cross-reference.
+So, for example, the {\LaTeX} back end uses labels as arguments to \verb+\label+
+and \verb+\ref+, and the HTML back end uses labels to name and refer
+to anchors.
+Labels never contain white space, which simplifies parsing.
+The standard filters cross-reference at the chunk level, so that each
+label refers to a particular code chunk, and all references to that
+chunk use the same label.
+
+An \ident\ refers to a source-language identifier.
+{\tt Noweb}'s concept of identifier is general; an identifier is
+an arbitrary string.
+It can even contain whitespace.
+Identifiers are used as keys in the index; references to the same
+string are assumed to denote the same identifier.
+
+{\rm\it Tag\/}s are the strings used to identify components for
+cross-reference in the final document.
+For example, Classic {\tt WEB} uses consecutive ``section numbers'' to
+refer to chunks.
+{\tt Noweb}, by default, uses ``sub-page references,'' e.g., ``24b''
+for the second chunk appearing on page~24.
+The HTML back end doesn't use any tags at all; instead, it
+implements cross-referencing using the ``hot link'' mechanism.
+
+The final step of cross-referencing involves generating tags and
+associating a tag with each label.
+All the existing back ends rely on a document formatter to do this
+job, but that strategy might be worth changing.
+Computing tags within a {\tt noweb} filter could be lots easier than
+doing it in a formatter.
+For example, a filter that computed sub-page numbers by grubbing in
+{\tt .aux} files would be pretty easy to write, and it would eliminate
+a lot of squirrely {\LaTeX} code.
+
+
+\subsubsection{Index information}
+
+I've divided the index keywords into several groups.
+There seems to be a plethora of keywords, but most of them are
+straightforward representations of parts of a document produced by
+{\tt noweave}. Readers may want to have a sample of {\tt noweave}'s
+output handy when studying this and the next section.
+
+\begin{table}
+\begin{center}
+\begin{tabularx}{\textwidth}{|>{\tt}l>{\raggedright\arraybackslash}X|}
+\ttitle{Definitions, uses, and {\tt @ \%def}}
+\hline
+@index defn \ident&The current chunk contains a definition of \ident\\
+@index localdefn \ident&The current chunk contains a definition of
+ \ident, which is not to be visible outside this file\\
+@index use \ident&The current chunk contains a use of \ident\\
+@index nl&A newline that is part of markup, not part of the chunk\\
+\hline
+\ttitle{Identifiers defined in a chunk}
+\hline
+@index begindefs&Start list of identifiers defined in this chunk\\
+@index isused \label&
+ The identifier named in the following \ikw{defitem} is used in
+ the chunk labelled by \label\\
+@index defitem \ident&
+ \ident\ is defined in this chunk, and it is used in all the
+ chunks named in the immediately preceding \ikw{isused}.\\
+@index enddefs&End list of identifiers defined in this chunk\\
+\hline
+\ttitle{Identifiers used in a chunk}
+\hline
+@index beginuses&Start list of identifiers used in this chunk\\
+@index isdefined \label&
+ The identifier named in the following \ikw{useitem} is defined in
+ the chunk labelled by \label\\
+@index useitem \ident&
+ \ident\ is used in this chunk, and it is defined in each of the
+ chunks named in the immediately preceding \ikw{isdefined}.\\
+@index enduses&End list of identifiers used in this chunk\\
+\hline
+\end{tabularx}\\
+\begin{tabularx}{\textwidth}{|>{\tt}l>{\raggedright\arraybackslash}X|}
+\ttitle{The index of identifiers}
+\hline
+@index beginindex&Start of the index of identifiers\\
+@index entrybegin \label\ \ident&
+ Beginning of the entry for \ident, whose first definition is
+ found at \label\\
+@index entryuse \label&
+ A use of the identifer named in the last \ikw{entrybegin}
+ occurs at the chunk labelled with \label.\\
+@index entrydefn \label&
+ A definition of the identifer named in the last \ikw{entrybegin}
+ occurs at the chunk labelled with \label.\\
+@index entryend&
+ End of the entry started by the last \ikw{entrybegin}\\
+@index endindex&End of the index of identifiers\\
+\hline
+\end{tabularx}
+\end{center}
+\caption{Indexing keywords}
+\ltxlabel{tab:index}
+\vskip -5pt
+\end{table}
+
+
+
+\paragraph{Definitions, uses, and {\tt @ \%def}}
+
+\ikw{defn}, \ikw{use}, and \ikw{nl} are the only
+\kw{index} keywords that appear in {\tt markup}'s output, and thus
+which can appear in any program.
+They may appear only within the boundaries of a code chunk (\kws{begin
+code}{end code}).
+\ikw{defn} and \ikw{use} simply indicate that the current chunk
+contains a definition or use of the identifier \ident\ which follows
+the keyword.
+The placement of \ikw{defn} need not bear a relationship to the
+text of the definition, but \ikw{use} is normally followed by a
+\kw{text} that contains the source-code text identified as the
+use.%
+\footnote{This property can't hold when one identifier is a prefix of
+another; see the description of {\tt finduses} on page~\pageref{finduses}.}
+
+Instances of \ikw{defn} normally come from one of two sources: either a
+language-dependent recognizer of definitions, or a hand-written
+\verb+@ %def+ line.%
+\footnote{The \texttt{@ \char`\%def} notation has been deprecated
+since version~2.10.}
+In the latter case, the line is terminated by a newline that is
+neither part of a code chunk nor part of a documentation chunk.
+To keep line numbers accurate, that newline can't just be abandoned,
+but neither can it be represented by \kw{nl} in a documentation or
+code chunk.
+The solution is the \ikw{nl} keyword, which serves no purpose other
+than to keep track of these newlines, so that back ends can produce
+accurate line numbers.
+
+Following a suggestion by Oren Ben-Kiki,
+\ikw{localdefn} indicates a definition that is not to be visible
+outside the current file.
+It may be produced by a language-dependent recognizer or other filter.
+Because I have questions about the need for \ikw{localdefn}, there is
+officially no way to cause {\tt markup} to produce it.
+
+\paragraph{Identifiers defined in a chunk}
+
+The keywords from \ikw{begindefs} to \ikw{enddefs} are used to represent
+a more complex data structure giving the list of identifiers defined
+in a code chunk.
+The constellation represents a list of identifiers; one \ikw{defitem}
+appears for each identifier.
+The group also tells in what other chunks each identifier is used;
+those chunks are listed by \ikw{isused} keywords which appear just
+before \ikw{defitem}.
+The labels in these keywords appear in the order of the corresponding
+code chunks, and there are no duplicates.
+
+These keywords can appear anywhere inside a code chunk, but
+filters are encouraged to keep these keywords together.
+The standard
+filters guarantee that only
+\ikw{isused} and \ikw{defitem} appear between \ikw{begindefs} and
+\ikw{enddefs}.
+The standard filters put them at the end of the code chunk, which
+simplifies translation by the {\LaTeX} back end, but that strategy
+might change in the future.
+
+
+It should go without saying, but the keywords in these and all similar
+groups (including some \kw{xref} groups) must be properly structured.
+That is to say:
+\begin{enumerate}
+\item
+Every \ikw{begindefs} must have a matching \ikw{enddefs} within the
+same code chunk.
+\item
+\ikw{isused} and \ikw{defitem} may appear only between matching
+\ikw{begindefs} and \ikw{enddefs}.
+\item
+The damn things can't be nested.
+\end{enumerate}
+
+
+\paragraph{Identifiers used in a chunk}
+
+
+The keywords from \ikw{beginuses} to \ikw{enduses} are the dual of
+\ikw{begindef} to \ikw{enddef};
+the structure lists the identifiers used in the current code chunk,
+with cross-references to the definitions.
+Similar interpretations and restrictions apply.
+Note that an identifier can be defined in more than one chunk,
+although we expect that to be an unusual event.
+{\hfuzz=1.2pt\par}
+
+\paragraph{The index of identifiers}
+
+Keywords \ikw{beginindex} to \ikw{endindex} represent the
+complete index of all the identifiers used in the document.
+Each entry in the index is bracketed by \ikws{entrybegin}{entryend}.
+An entry provides the name of the identifier, plus the labels of all the
+chunks in which the identifier is defined or used.
+The label of the first defining chunk
+is given at the beginning of the entry so that back ends needn't
+search for it.
+{\hfuzz=4.9pt\par}
+
+Filters are encouraged to keep these keywords together.
+The standard filters put them almost at the very end of the {\tt
+noweb} file, just before the optional \kw{trailer}.
+
+
+
+\subsubsection{Cross-reference information}
+
+\newcommand\anchor{{\rmfamily\textit{anchor}}}
+
+% l2h substitution anchor <i>anchor</i>
+
+The most basic function of the cross-referencing keywords is to
+associate labels and pointers (cross-references) with elements of the
+document, which is done with the \xkw{ref} and \xkw{label} keywords.
+The other \kw{xref} keywords all express chunk cross-reference
+information that is emitted directly by one or more back ends.
+
+Chunk cross-reference introduces the idea of
+an {\anchor}, which is a label that refers to an ``interesting point''
+we identify with the
+beginning of a code chunk.
+The anchor is the place we expect to turn when we want to know about a
+code chunk;
+its exact value and interpretation depend on the back end being used.
+The standard {\LaTeX} back end uses the sub-page number of the
+defining chunk as the anchor, but the standard HTML back end uses some
+\kw{text} from the documentation chunk preceding the code chunk.
+
+
+\begin{table}
+\begin{center}
+\begin{tabularx}{\textwidth}{|>{\tt}l>{\raggedright\arraybackslash}X|}
+\ttitle{Basic cross-reference}
+\hline
+@xref label \label&Associates \label\ with tagged item.\\
+@xref ref \label&
+ Cross-reference from tagged item to item associated with \label.\\
+\hline
+\ttitle{Linking previous and next definitions of a code chunk}
+\hline
+@xref prevdef \label&
+ The \kw{defn} from the previous definition of this chunk is
+ associated with \label.\\
+@xref nextdef \label&
+ The \kw{defn} from the next definition of this chunk is
+ associated with \label.\\
+\hline
+\ttitle{Continued definitions of the current chunk}
+\hline
+@xref begindefs&Start ``This definition is continued in \ldots''\\
+@xref defitem \label&Gives the label of a chunk in which the
+definition of the current chunk is continued.\\
+@xref enddefs&Ends the list of chunks where definition is continued.\\
+\hline
+\ttitle{Chunks where this code is used}
+\hline
+@xref beginuses&Start ``This code is used in \ldots''\\
+@xref useitem \label&Gives the label of a chunk in which this
+ chunk is used.\\
+@xref enduses&Ends the list of chunks in which this code is used.\\
+@xref notused {\rm\it name}&
+ Indicates that this chunk isn't used anywhere in this document.\\
+\hline
+\ttitle{The list of chunks}
+\hline
+@xref beginchunks&Start of the list of chunks\\
+@xref chunkbegin \label\ {\it name}&
+ Beginning of the entry for chunk {\it name}, whose {\anchor}
+ is found at \label.\\
+@xref chunkuse \label&
+ The chunk is used in the chunk labelled with \label.\\
+@xref chunkdefn \label&
+ The chunk is defined in the chunk labelled with \label.\\
+@xref chunkend&End of the entry started by the last \xkw{chunkbegin}\\
+@xref endchunks&End of the list of chunks\\
+\hline
+\ttitle{Converting labels to tags}
+\hline
+@xref tag \label\ \tag&Associates \label\ with \tag.\\
+\hline
+\end{tabularx}
+\end{center}
+\vskip -4pt
+\caption{Cross-referencing keywords}
+\ltxlabel{tab:xref}
+\vskip -3pt
+\end{table}
+
+
+
+\paragraph{Basic cross-reference}
+
+\xkw{label} and \xkw{ref} are named by analogy with the {\LaTeX}
+\verb+\label+ and \verb+\ref+ commands.
+\xkw{label} is used to associate a \label\ with a succeeding item.
+Items that can be so labelled include
+\begin{quote}
+\begin{tabularx}{\linewidth}{>{\tt}l>{\raggedright\arraybackslash}X}
+@defn&Labels the code chunk that begins with this \rlap{\kw{defn}.}\\
+ % cheating the line breaker
+@use&Labels this particular use.\\
+@index defn&Labels this definition of an identifier.\\
+@index use&Labels this use of an identifier.\\
+@text&Typically labels part of a documentation chunk.\\
+@end docs&Typically labels an empty documentation chunk.\\
+\end{tabularx}
+\end{quote}
+I haven't made up my mind whether this should be the complete set, but
+these are the ones used by the standard filters.
+Most back ends use the chunk as the basic unit of cross-reference, so
+the labels of \kw{defn} are the ones that are most often used.
+The HTML back end, however, does something a little different---it
+uses labels that refer to documentation preceding a chunk, because the
+typical HTML browser (Mosaic) places the label%
+\footnote{The HTML terminology calls a label an ``anchor.''}
+at the top of the screen, and using the label of the \kw{defn} would
+lose the documentation immediately preceding a chunk.
+The labels used by this back end usually point to \kw{text}, but they
+may point to \kw{end docs} when no text is available.
+
+
+\xkw{ref} is used to associate a reference with a succeeding item.
+Such items include
+\begin{quote}
+\begin{tabularx}{\linewidth}{l>{\raggedright\arraybackslash}X}
+{\tt @defn}, {\tt @use}&Refers to the label used as an {\anchor} for this chunk.\\
+\vtop{\hbox{\strut{\tt @index defn},}\hbox{\strut{\tt @index use}}}&
+ Refers to the label used as an {\anchor} for the first
+ chunk in which this identifier is defined.\\
+\end{tabularx}
+\end{quote}
+
+
+\paragraph{Linking previous and next definitions of a code chunk}
+
+\xkw{prevdef} and \xkw{nextdef} may appear anywhere in a code chunk,
+and they give the labels of the preceding and succeeding definitions
+of that code chunk, if any.
+Standard filters currently put them at the beginning of the code
+chunk, following the initial \kw{defn}, so the information can be used
+on the \kw{defn} line,
+\`a la \citeN{fraser:retargetable:book}.
+
+
+\paragraph{Continued definitions of the current chunk}
+
+The keywords ranging from \xkw{begindefs} to \xkw{enddefs} appear in the first
+definition of each code chunk.
+They provide the information needed by the ``This definition is
+continued in \ldots'' message printed by the standard {\LaTeX} back
+end.
+They can appear anywhere in a code chunk, but standard filters put
+them after all the \kw{text} and \kw{nl}s, so that back ends can just
+print out text.
+
+
+\paragraph{Chunks where this code is used}
+
+The keywords from \xkw{beginuses} to \xkw{enduses} are the dual of
+\xkw{begindefs} to \xkw{enddefs}; they show where the current chunk is
+used.
+As with \xkws{begindefs}{enddefs}, they appear only in the first
+definition of any code chunk, and they come at the end.
+Sometimes, as with root chunks, the code isn't used anywhere, in which
+case \xkw{notused} appears instead of \xkws{beginuses}{enduses}.
+The name of the current chunk appears as an argument to \xkw{notused}
+because some back ends may want to print a special message for unused
+chunks---they might be written to files, for example.
+
+\paragraph{The list of chunks}
+
+The list of chunks, which is defined by the keywords
+\xkws{beginchunks}{endchunks}, is the
+analog of the index of identifiers, but it lists all the code chunks
+in the document, not all the identifiers.
+
+Filters are encouraged to keep these keywords together.
+The standard filters put them at the end of the {\tt
+noweb} file, just before the index of identifiers.
+
+
+\paragraph{Converting labels to tags}
+
+None of the existing back ends actually computes tags; they all use
+formatting engines to do the job.
+The {\LaTeX} back end uses an elaborate macro package to compute
+sub-page numbers, and the HTML back end arranges for ``hot links'' to
+be used instead of textual tags.
+Some people have argued that literate-programming tools shouldn't require
+elaborate macro packages, that they should use the basic facilities
+provided by a formatter. Nuweb, for example, uses standard {\LaTeX}
+commands only, but goes digging through {\tt .aux} files to find
+labels and compute sub-page numbers.
+Doing this kind of computation in a real programming language is much
+easier than doing it with {\TeX} macros, and I expect that one day
+{\tt noweb} will have a tag-computing filter, the results of
+which will be expressed using the \xkw{tag} keyword.
+
+The rules governing \xkw{tag} are that it can appear anywhere.
+None of the standard filters or back ends does anything with it.
+
+
+
+\subsection{Wrapper keywords}
+
+The wrapper keywords, \kw{header} and \kw{trailer}, are anomalous in
+that they're not generated by {\tt markup} or by any of the
+standard filters; instead they're inserted by the {\tt noweave} shell
+script at the very beginning and end of file.
+The standard {\TeX}, {\LaTeX}, and HTML back ends use them to provide
+preamble and postamble markup, i.e., boilerplate that usually has to
+surround a document.
+They're not required (sometimes you don't want that boilerplate), but
+when they appear they must be the very first and last lines in the
+file, and the formatter names must match.
+
+\subsection{Error keyword}
+
+The error keyword \kw{fatal} signifies that a fatal error as
+occurred.
+The pipeline stage originating such an error gives its own name and a
+message, and it also writes a message to standard error.
+Filters seeing \kw{fatal} must copy it to their output and terminate
+themselves with error status.
+Back ends seeing \kw{fatal} must terminate themselves with error
+status. (They should not write anything to standard error since that
+will have been done.)
+
+Using \kw{fatal} enables shell scripts to detect
+that something has gone wrong even if the only exit status they have
+access to is the
+exit status of the last stage in a pipeline.
+
+\subsection{Lying, cheating, stealing keyword}
+
+The \kw{literal} keyword is used to hack output directly into \texttt{noweave}
+back ends, like \texttt{totex} and \texttt{tohtml}.
+These back ends simply copy the text to their output.
+Tangling back ends ignore \kw{literal}.
+The \kw{literal} keyword is used by Master Hackers who are too lazy to
+write new back ends.
+Its use is deprecated.
+It should not exist.
+But it will be retained forever in the name of Backward Compatibility.
+
+
+
+
+\section{Standard filters}
+
+All the standard filters, unless otherwise noted, read the {\tt noweb}
+keyword format on standard input and write it on standard output.
+Some filters may also use auxiliary files.
+
+\subsection{\tt markup}
+
+Strictly speaking, {\tt markup} is a front end, not a filter, but I
+discuss it along with filters because it generates the output that is
+massaged by all the filters.
+{\tt markup}'s output represents a sequence of files.
+Each file is represented by a ``{\tt @file~{\rm\it filename}}'' line,
+followed by a sequence of chunks.
+{\tt markup} numbers chunks consecutively, starting at~0.
+It also recognizes and undoes the escape sequence for double brackets,
+e.g.~converting ``{\tt @<<}'' to ``{\tt <<}''.
+The only tagging keywords found in its output are \ikw{defn} or
+\ikw{nl}; despite what's written about it, \ikw{use} never appears.
+
+\subsection{\tt autodefs.*}
+
+I've written half a dozen language-dependent filters that use simple
+heuristics (``fuzzy parsing'' if you prefer) to try to identify
+interesting definitions of identifiers.
+Many of these doubtless rely on my own idiosyncratic coding styles,
+but all of them provide good value for little effort.
+None of them does anything more complicated than scan individual
+\kw{text} lines in code chunks, spitting out \ikw{defn}
+and \ikw{localdefn} lines after
+the \kw{text} line whenever it thinks it's found something.
+All the filters are written in Icon and use a central core defined in
+\verb+icon/defns.nw+.
+The C filter is the most complicated; it actually tries to understand
+parts of the C grammar for declarations.
+None of these filters has any command-line options.
+
+\subsection{\tt finduses}
+
+\ltxlabel{finduses}
+
+Using code contributed by Preston Briggs, this filter makes two passes
+over its input.
+The first pass reads in all the \ikw{defn} and \ikw{localdefn} lines and builds an
+Aho-Corasick recognizer for the identifiers named therein.
+The second pass copies the input, searching for these identifiers in
+each \kw{text} line that is code.
+When it finds an identifier, {\tt finduses} breaks the \kw{text} line
+into pieces, inserting \ikw{use} immediately before the \kw{text}
+piece that contains the identifier just found.%
+\footnote{The behavior described would duplicate \kw{text} pieces
+whenever one identifier was a prefix of another.
+This event is rare, and probably undesirable, but it can happen if,
+for example, the C$++$ names {\tt MyClass} and {\tt MyClass::Function}
+are both considered identifiers.
+In this case, whatever identifier is found first is emitted first, and
+only the unemitted pieces of longer identifiers are emitted.}
+{\tt finduses} assumes that previous filters will not have broken
+\kw{text} lines in the middle of identifiers.
+
+
+The \verb+-noquote+ command-line option prevents {\tt finduses} from
+searching for uses in quoted code.
+If {\tt finduses} is given arguments, it takes those arguments to be
+file names, and it reads lists of identifiers (one per line) from the
+files so named, rather than from its input.
+This technique enables {\tt finduses} to make a single pass over its
+input; {\tt noweave} uses it to implement the {\tt -indexfrom} option.
+
+{\tt finduses} shouldn't be run before filters which, like the {\tt
+autodefs} filters, expect one line to be represented in a single
+\kw{text}.
+Filters (or back ends) that have to be run late, like
+prettyprinters, should be prepared to deal with lines broken into
+pieces and with \kw{index} and \kw{xref} tags intercalated.
+
+\subsection{\tt noidx}
+
+{\tt noidx} computes all the index and cross-reference information
+represented by the \kw{index} and \kw{xref} keywords.
+
+The {\tt -delay} command-line option delays heading material until
+after the first chunk, and brings trailing material before the last
+chunk.
+In particular, it causes
+the list of chunks and the index of identifiers to be emitted before
+the last chunk.
+
+The {\tt -docanchor $n$} option sets the anchor for a code chunk to be
+either:
+\begin{enumerate}
+\item
+If a documentation chunk precedes the code chunk and is $n$ or more lines long, $n$
+lines from the end of that documentation chunk.
+\item
+If a documentation chunk precedes the code chunk and is fewer than $n$
+lines long, at the beginning of that documentation chunk.
+\item
+If no documentation chunk precedes the code chunk, at the beginning of
+the code chunk, just as if {\tt -docanchor} had not been used.
+\end{enumerate}
+This option is used to create anchors suitable for the HTML back end.
+
+
+\section{Standard back ends}
+
+\subsection{\tt nt}
+
+The {\tt nt} back end implements {\tt notangle}.
+It extracts the program defined by a single code chunk (expanding all
+uses to form their definitions) and writes that program on standard
+output.
+Its command-line options are:
+\begin{quote}
+\begin{tabularx}{\linewidth}{lX}
+\tt -t&Turn off expansion of tabs.\\
+\tt -t$n$&Expand tabs on $n$-column boundaries.\\
+\tt -R{\rmfamily\textit{name}}&Expand the code chunk named \textit{name}.\\
+\tt -L{\rmfamily\textit{format}}&Use \textit{format} as the format string
+ to emit line-number information.
+\end{tabularx}
+\end{quote}
+See the man page for {\tt notangle} for details on the operation of
+{\tt nt}.
+
+
+\subsection{\tt mnt}
+
+{\tt mnt} (for Multiple NoTangle)
+is a back end that can extract several code chunks from a
+single document in a single pass. It is used to make the {\tt noweb}
+shell script more efficient.
+In addition to the {\tt -t} and {\tt -L} options recognized by {\tt
+nt}, it recognizes {\tt -all} as an instruction to extract and write
+to files all of the code chunks that conform to the rules set out in
+the {\tt noweb} man page.
+It also accepts arguments, as well as options; each argument is taken
+to be the name of a code chunk that should be emitted to the file of
+the same name.
+Unlike {\tt nt}, {\tt mnt} has the function of {\tt cpif} built
+in---it writes to a temporary file, then overwrites an existing file
+only if the temporary file is different.
+
+
+
+\subsection{\tt tohtml}
+
+This back end emits HTML.
+It uses the formatter {\tt html} with \kw{header} and \kw{trailer} to
+emit suitable HTML boilerplate.
+For other formatters (like {\tt none}) it emits no header or trailer.
+Its command-line options are:
+\begin{quote}
+\begin{tabularx}{\linewidth}{lX}
+\tt -delay&Accepted, for compatibility with other back ends, but ignored.\\
+\tt -localindex&Produces local identifier cross-reference after each code chunk.\\
+\tt -raw&Wraps text generated for code chunks in a {\LaTeX} {\tt rawhtml}
+environment, making the whole document suitable for processing with
+{\tt latex2html}.\\
+\end{tabularx}
+\end{quote}
+
+
+\subsection{\tt totex}
+
+{\tt totex} implements both the plain {\TeX} and {\LaTeX} back ends,
+using \kw{header tex} and \kw{header latex} to distinguish them.
+When using a {\LaTeX} header, {\tt totex} places the optional text
+following the header inside a \verb+\noweboptions+ command.
+
+On the command line, the {\tt -delay} option makes {\tt totex} delay
+filename markup until after the first documentation chunk; this
+behavior makes the first documentation chunk a ``limbo''
+chunk, which can usefully contain commands like \verb+\documentclass+.
+The {\tt -noindex} option suppresses output relating to the index of
+identifiers; it is used to implement {\tt noweave -x}.
+{\hfuzz=1.2pt\par}
+
+\subsection{\tt unmarkup}
+
+{\tt unmarkup} attempts to be the inverse of markup---a document
+already in the pipeline is converted back to {\tt noweb} source form.
+This back end is useful primarily for trying to convert other literate
+programs to {\tt noweb} form.
+It might also be used to capture and edit the output of an automatic
+definition recognizer.
+
+\section{Standard commands}
+
+
+\begin{figure}[t]
+\noindent
+\begin{tabbing}
+XXl\=XXl\=XXl\=XXl\=XXl\=XXl\=XXl\=XXl\={}\kill
+\>\+{\tt markup}: Convert to pipeline representation\+\\
+{\tt nt:} Extract desired chunk to standard output
+\end{tabbing}
+\caption{Stages in pipeline for {\tt notangle}}
+\ltxlabel{fig:pipe-notangle}
+
+\noindent
+\begin{tabbing}
+XXl\=XXl\=XXl\=XXl\=XXl\=XXl\=XXl\=XXl\={}\kill
+\>\+{\tt markup}: Convert to pipeline representation\+\\
+{\tt autodefs.c}: Find definitions in C code\+\\
+{\tt finduses -noquote}: Find uses of defined identifiers\+\\
+{\tt noidx}: Add index and cross-reference information\+\\
+{\tt totex}: Convert to {\LaTeX}
+\end{tabbing}
+\caption{Stages in pipeline for {\tt noweave -index -autodefs c}}
+\ltxlabel{fig:pipe-noweave}
+\end{figure}
+
+
+The standard commands are all written as Bourne shell scripts~\cite{kernighan:unix}.
+They assemble Unix pipelines using {\tt markup} and the filters and
+back ends described above. They are documented in man pages, and
+there is no sense in repeating that material here.
+I do show two sample pipelines in
+Figures \ref{fig:pipe-notangle}~and~\ref{fig:pipe-noweave}.
+The source code is available in the {\tt shell} directory for those
+who want to explore further.
+
+\begin{figure}[p]
+\begin{verbatim}
+awk 'BEGIN { line = 0; capture = 0
+ format = sprintf("'"$format"'",'"$width"')
+ }
+function comment(s) {
+ '"$subst"'
+ return sprintf(format,s)
+}
+
+function grab(s) {
+ if (capture==0) print
+ else holding[line] = holding[line] s
+}
+
+/^@end doc/ { capture = 0; holding[++line] = "" ; next }
+/^@begin doc/ { capture = 1; next }
+
+/^@text / { grab(substr($0,7)); next}
+/^@quote$/ { grab("[[") ; next}
+/^@endquote$/ { grab("]]") ; next}
+
+/^@nl$/ { if (capture !=0 ) {
+ holding[++line] = ""
+ } else if (defn_pending != 0) {
+ print "@nl"
+ for (i=0; i<=line && holding[i] ~ /^ *$/; i++) i=i
+ for (; i<=line; i++)
+ printf "@text %s\n@nl\n", comment(holding[i])
+ line = 0; holding[0] = ""
+ defn_pending = 0
+ } else print
+ next
+ }
+
+/^@defn / { holding[line] = holding[line] "<"substr($0,7)">="
+ print ; defn_pending = 1 ; next }
+{ print }'
+\end{verbatim}
+\caption{{\tt awk} command used to transform documentation to comments}
+
+\smallskip
+\noindent
+\verb+$subst+, \verb+$format+, and \verb+$width+ are shell variables used
+to adapt the script for different languages.
+executing \verb+$subst+ eliminates comment-end markers (if any) from
+the documentation, and the initial \verb+sprintf+ that creates the
+{\tt awk}
+variable \verb+format+ gives the format used to print a line of
+documentation as a comment.
+
+\ltxlabel{fig:nountangle}
+\end{figure}
+
+\afterpage{\clearpage} % force figures out
+
+
+\section{Examples}
+
+I don't give examples of the pipeline
+representation; it's best just to
+play with the existing filters.
+In particular,
+\begin{quote}
+{\tt noweave -v} {\it options} {\it inputs} {\tt >/dev/null}
+\end{quote}
+prints (on standard error) the pipeline used by {\tt noweave}
+to implement any set of {\it options}.
+In this section, I give examples of a few nonstandard filters I've
+thrown together for one purpose or another.
+
+{\hfuzz=6.8pt
+This one-line {\tt sed} command makes {\tt noweb} treat two chunk names as
+identical if they differ only in their representation of whitespace:
+\begin{verbatim}
+ sed -e '/^@use /s/[ \t][ \t]*/ /g' -e '/^@defn /s/[ \t][ \t]*/ /g'
+\end{verbatim}
+\par}
+
+This little filter, a Bourne shell script
+written in {\tt awk}~\cite{aho:awk},
+makes the definition of an empty chunk (\verb+<<>>=+)
+stand for a continuation of the previous chunk definition.
+\begin{verbatim}
+awk 'BEGIN { lastdefn = "@defn " }
+/^@defn $/ { print lastdefn; next }
+/^@defn / { lastdefn = $0 }
+{ print }' "$@"
+\end{verbatim}
+
+
+
+To share programs with colleagues who don't enjoy literate
+programming, I use a filter, shown in Figure~\ref{fig:nountangle}, that
+places each line of documentation in a comment and moves it to
+the succeeding code chunk.
+With this filter, \verb+notangle+
+transforms a literate
+program into a traditional commented program, without loss of
+information and with only a modest penalty in readability.
+
+
+As a demonstration, and to help convert nuweb programs to {\tt
+noweb}, I wrote a
+a 55-line Icon program that makes it possible to abbreviate chunk names
+using a trailing ellipsis, as in {\tt WEB}; it appears in the {\tt
+noweb} distribution as
+\verb+icon/disambiguate.nw+.
+
+Kostas Oikonomou of AT\&T Bell Labs and Conrado Martinez-Parra of
+the Univ.\ Politecnica de Catalunya in Barcelona have written filters
+that add prettyprinting to {\tt noweb}.
+Oikonomou's filters prettyprint Icon and Object-Oriented Turing;
+Martinez-Parra's filter prettyprints a variant of Dijkstra's language
+of guarded commands.
+These filters are in the noweb distribution in the \verb+contrib+ directory.
+
+It's also possible to do useful or amusing things by writing new back
+ends.
+Figure~\ref{fig:nocount} shows an {\tt awk} script that gives a count of the
+number of lines of code and of documentation in a group of {\tt noweb}
+files.
+
+\begin{figure}[!b]
+\begin{verbatim}
+BEGIN { bogus = "this is total bogosity"
+ codecount[bogus] = -1; docscount[bogus] = -1
+ }
+/^@file / { thisfile = $2 ; files[thisfile] = 0 }
+/^@begin code/ { code = 1 }
+/^@begin docs/ { code = 0 }
+/^@nl/ {
+ if (code == 0)
+ docscount[thisfile]++
+ else
+ codecount[thisfile]++
+}
+END {
+ printf " Code Docs Both File\n"
+ for (file in files) {
+ printf "%5d %5d %5d %s\n",
+ codecount[file], docscount[file],
+ codecount[file]+docscount[file], file
+ totalcode += codecount[file]
+ totaldocs += docscount[file]
+ }
+ printf "%5d %5d %5d %s\n",
+ totalcode, totaldocs, totalcode+totaldocs, "Total"
+}
+\end{verbatim}
+\caption{Back end for counting lines of code and documentation}
+\ltxlabel{fig:nocount}
+
+\smallskip
+
+\noindent
+The \verb+BEGIN+ code forces \verb+codecount+ and
+\verb+docscount+ to be associative arrays; without it the increment
+operator would fail.
+\end{figure}
+
+
+
+\bibliographystyle{chicago}
+\bibliography{web,ramsey,cs}
+
+\end{document}
diff --git a/web/noweb/src/xdoc/htmltoc.1 b/web/noweb/src/xdoc/htmltoc.1
new file mode 100644
index 0000000000..60bf98a1ce
--- /dev/null
+++ b/web/noweb/src/xdoc/htmltoc.1
@@ -0,0 +1,42 @@
+.TH NOWEB 1 "local 10/40/2008"
+.SH NAME
+htmltoc \- add table of contents to HTML document
+.SH SYNOPSIS
+\fBhtmltoc\fP [\fB\-2345\fP] [file]
+.SH DESCRIPTION
+.I htmltoc
+adds a table of contents to the HTML document named on the command
+line or provided as standard input.
+The table of contents is inserted between
+.B <tableofcontents>
+and
+.B </tableofcontents>,
+which must appear on lines by themselves.
+Any text between those two markers is
+.I discarded.
+These markers are inserted automatically by the
+.IR sl2h (1)
+filter.
+.PP
+The table of contents includes only headers at levels 2, 3, 4, and 5.
+This can be changed by using a command-line
+option, e.g., \fB\-123456789\P to include all possible headers.
+.SH BUGS
+.I htmltoc
+can't cope with a header that is split across multiple lines,
+even though this is legal HTML.
+.SH SEE ALSO
+.IR nowebfilters (7),
+.IR sl2h (1)
+.SH VERSION
+This man page is from
+.I noweb
+version 2.12.
+.SH AUTHOR
+Norman Ramsey, Tufts University.
+Internet address \fBNorman.Ramsey@tufts.edu\fP.
+.br
+Noweb home page at \fBhttp://www.cs.tufts.edu/~nr/noweb\fP.
+
+.PP
+Stephen Parker provided a preliminary version.
diff --git a/web/noweb/src/xdoc/htmltoc.nw b/web/noweb/src/xdoc/htmltoc.nw
new file mode 100644
index 0000000000..7e4e4d56d5
--- /dev/null
+++ b/web/noweb/src/xdoc/htmltoc.nw
@@ -0,0 +1,34 @@
+<<*>>=
+.TH NOWEB 1 "local <<noweb documentation date>>"
+.SH NAME
+htmltoc \- add table of contents to HTML document
+.SH SYNOPSIS
+\fBhtmltoc\fP [\fB\-2345\fP] [file]
+.SH DESCRIPTION
+.I htmltoc
+adds a table of contents to the HTML document named on the command
+line or provided as standard input.
+The table of contents is inserted between
+.B <tableofcontents>
+and
+.B </tableofcontents>,
+which must appear on lines by themselves.
+Any text between those two markers is
+.I discarded.
+These markers are inserted automatically by the
+.IR sl2h (1)
+filter.
+.PP
+The table of contents includes only headers at levels 2, 3, 4, and 5.
+This can be changed by using a command-line
+option, e.g., \fB\-123456789\P to include all possible headers.
+.SH BUGS
+.I htmltoc
+can't cope with a header that is split across multiple lines,
+even though this is legal HTML.
+.SH SEE ALSO
+.IR nowebfilters (7),
+.IR sl2h (1)
+<<AUTHOR section>>
+.PP
+Stephen Parker provided a preliminary version.
diff --git a/web/noweb/src/xdoc/htmltoc.txt b/web/noweb/src/xdoc/htmltoc.txt
new file mode 100644
index 0000000000..2339f73e63
--- /dev/null
+++ b/web/noweb/src/xdoc/htmltoc.txt
@@ -0,0 +1,43 @@
+NOWEB(1) General Commands Manual NOWEB(1)
+
+
+
+NNAAMMEE
+ htmltoc - add table of contents to HTML document
+
+SSYYNNOOPPSSIISS
+ hhttmmllttoocc [--22334455] [file]
+
+DDEESSCCRRIIPPTTIIOONN
+ _h_t_m_l_t_o_c adds a table of contents to the HTML document named on the comâ€
+ mand line or provided as standard input. The table of contents is
+ inserted between <<ttaabblleeooffccoonntteennttss>> and <<//ttaabblleeooffccoonntteennttss>>,, which must
+ appear on lines by themselves. Any text between those two markers is
+ _d_i_s_c_a_r_d_e_d_. These markers are inserted automatically by the _s_l_2_h(1)
+ filter.
+
+ The table of contents includes only headers at levels 2, 3, 4, and 5.
+ This can be changed by using a command-line option, e.g., --112233445566778899PP
+ ttoo iinncclluuddee aallll ppoossssiibbllee hheeaaddeerrss..
+
+BBUUGGSS
+ _h_t_m_l_t_o_c can't cope with a header that is split across multiple lines,
+ even though this is legal HTML.
+
+SSEEEE AALLSSOO
+ _n_o_w_e_b_f_i_l_t_e_r_s(7), _s_l_2_h(1)
+
+VVEERRSSIIOONN
+ This man page is from _n_o_w_e_b version 2.12.
+
+AAUUTTHHOORR
+ Norman Ramsey, Tufts University. Internet address NNoorrmmaann..RRaammâ€â€
+ sseeyy@@ttuuffttss..eedduu.
+ Noweb home page at hhttttpp::////wwwwww..ccss..ttuuffttss..eedduu//~~nnrr//nnoowweebb.
+
+
+ Stephen Parker provided a preliminary version.
+
+
+
+ local 10/40/2008 NOWEB(1)
diff --git a/web/noweb/src/xdoc/ieee.tex b/web/noweb/src/xdoc/ieee.tex
new file mode 100644
index 0000000000..800a9d6121
--- /dev/null
+++ b/web/noweb/src/xdoc/ieee.tex
@@ -0,0 +1,901 @@
+% The formatter used is LaTeX
+
+% symbols that could be defined
+%
+% \dsp double space, figures on figure pages
+% \tr Princeton TR
+% \wbn use consecutive `{\tt WEB} numbering'
+
+
+
+
+\ifx\tr\undefined
+\documentstyle[11pt,noweb,multicol]{article}
+\else
+\documentstyle[11pt,noweb,multicol,tr]{article}
+\fi
+
+\title{Literate-Programming Tools\\Can Be Simple and Extensible}
+\author{Norman Ramsey\thanks{Author's current address is Bellcore, 445
+South Street, Morristown, NJ 07960;
+send email to {\tt norman@bellcore.com}.}\\Department of Computer Science,
+Princeton University}
+
+\ifx\wbn\undefined\else \noweboptions{webnumbering}\fi
+
+\ifx\dsp\undefined\else
+\makeatletter
+\let\@oldfigure=\figure
+\def\figure{\@oldfigure[p]}
+\makeatother
+\fi
+
+
+
+\ifx\tr\undefined
+\date{November 1993}
+\else
+\reportno{CS-TR-351-91}
+\date{October 1991\\Revised August 1992, November 1993}
+\fi
+
+\setcounter{secnumdepth}{0}
+\clubpenalty=10000
+\widowpenalty=10000
+\makeatletter
+\def\refno#1{\nocite{#1}\@ifundefined
+ {b@#1}{{\bf ?}\@warning
+ {Reference number `#1' on page \thepage \space undefined}}%
+{\hbox{\csname b@#1\endcsname}}}
+\makeatother
+
+\def\remark#1{\marginpar{\raggedright\hbadness=10000\footnotesize\it #1}}
+% \def\remark#1{\relax}
+\ifx\dsp\undefined\else\renewcommand{\baselinestretch}{1.6}\fi
+
+\begin{document}
+
+\maketitle
+
+\begin{abstract}
+When it was introduced, literate programming meant {\tt WEB}.
+Desire to use {\tt WEB} with languages other than Pascal led to the
+implementation of many versions.
+{\tt WEB} is complex, and the difficulty of using {\tt WEB} creates
+an artificial barrier to
+experimentation with literate programming.
+{\tt noweb} provides much of the functionality of
+{\tt WEB}, with a fraction of the complexity.
+{\tt noweb} is independent of the target programming language, and its
+formatter-dependent part is 60~lines.
+{\tt noweb} is extensible, because it uses two
+representations of programs: one easily edited by authors and one
+easily manipulated by tools.
+
+This paper explains how to use the {\tt noweb} tools and gives
+examples of their use.
+It sketches the implementation of the tools and describes how new
+tools are added to the set.
+Because
+{\tt WEB} and {\tt noweb} overlap, but each does some things that the
+other cannot,
+this paper enumerates the differences.
+\end{abstract}
+
+\ifx\tr\undefined
+\begin{center}\small
+{\bf Key words:}
+literate~programming, readability, programming~environments
+\end{center}
+\fi
+
+\section{Introduction}
+When literate programming was
+introduced, it was synonymous with {\tt WEB}, a tool
+for writing literate Pascal programs~\cite[Chapter~4]{knuth:literate:book}.
+The idea attracted attention; several examples of literate
+programs were published, and a special forum was created to discuss literate
+programming~%
+\cite{denning:announcing}. % ,gries:pearls,knuth:literate:book,thimbleby:review
+{\tt WEB} was adapted to programming languages other than
+Pascal~\cite{levy:cweb,ramsey:building,thimbleby:cweb}. % guntermann:cweb,sewell:mangle,
+%
+With experience, many {\tt WEB} users became dissatisfied~\cite{ramsey:literate}.
+Some found {\tt WEB} not worth the trouble, as did
+one author of the program appearing in Appendix~C
+of Reference~\refno{sewell:weaving}.
+Others built their own systems for literate
+ programming. % ~\cite{hamilton:expanding,cvw:loom}.
+The literate-programming forum was dropped, on the grounds that
+literate programming had become the province of those who could build
+their own tools~\cite{cvw:assessment}.
+
+{\tt WEB} programmers
+ interleave source code and descriptive text in a single document.
+When using {\tt WEB}, a programmer divides the source code into
+{\em modules}.
+Each module has a documentation part and a code part, and
+modules may be written in any order.
+The programmer is encouraged to choose an order that helps explain the program.
+The code parts are like macro definitions; they have names, and they contain
+both code and references to other modules.
+A {\tt WEB} file represents a single program;
+{\tt TANGLE} extracts that program from the {\tt WEB} source.
+One special module has a code part with no name, and {\tt TANGLE}
+expands the code part of that module to extract the program.
+{\tt WEAVE} converts {\tt WEB} source to
+{\TeX} input, from which {\TeX} can produce high-quality typeset
+documentation of the program.
+
+
+{\tt WEB} is a complex tool.
+In addition to enabling programmers to present pieces of a program in
+any order, it expands three kinds of macros, prettyprints code,
+evaluates some constant expressions,
+provides an integer representation for string literals, and implements
+a simple form of version control.
+The manual for the original version documents 27 ``control sequences''~\cite{knuth:web}.
+The versions for languages other than Pascal offer slightly different
+functions and different sets of control sequences.
+Significant effort is required to make {\tt WEB} usable with a new
+programming language, even when using a tool designed for that
+purpose~\cite{ramsey:building}.
+
+{\tt WEB}'s shortcomings make it difficult to explore the {\em idea}
+of literate programming; too much effort is required to master the
+{\em tool}.
+I designed a new tool that is
+simple, extensible, and independent of the target programming language.
+{\tt noweb} is designed
+around one idea: writing named chunks of code in any order, with
+interleaved documentation.
+Like {\tt WEB}, and like all literate-programming tools, it can
+be used to write a program in pieces and to present those pieces in
+an order that helps explain the program.
+{\tt noweb}'s value lies in its simplicity, which shows that the idea
+of literate programming does not require the complexity of {\tt WEB}.
+
+Users who could not find a satisfactory literate-programming tool
+have had no option other than to write their own tools.
+{\tt noweb} reduces the need for new tools because it is designed to
+be extended.
+It uses Unix pipes to enable users to change existing
+behavior or to add new features {without} recompiling {\tt noweb}.
+Even language-dependent features, like
+prettyprinting and automatic generation of an index, have been added
+to {\tt noweb} without recompiling.
+
+
+
+\section{{\tt noweb}} % , a minimal literate-programming system}
+A {\tt noweb} file contains program source code interleaved with documentation.
+When {\tt notangle} is given a {\tt noweb} file, it writes the program
+ on standard output.
+When {\tt noweave} is given a {\tt noweb} file, it reads the {\tt
+noweb} source and produces, on standard output, {\TeX} source for
+typeset documentation.
+Figure~\ref{transforms} shows how to use {\tt notangle} and {\tt
+noweave} to produce code and documentation for a C~program contained
+in the {\tt noweb} file {\tt foo.nw}.
+
+\begin{figure}
+\footnotesize
+\setlength{\unitlength}{2pt}
+\begin{picture}(170,80)(0,-40)
+\tt
+\put(20,12.5){\makebox(0,0)[l]{\ \tt notangle foo.nw > foo.c}}
+\put(20,-12.5){\makebox(0,0)[l]{\ \tt noweave foo.nw > foo.tex}}
+
+\put(0,-5){\framebox(30,10){foo.nw}}
+\put(15,5){\vector(1,2){7.5}}
+\put(10,20){\framebox(30,10){foo.c}}
+\put(15,-5){\vector(1,-2){7.5}}
+\put(10,-30){\framebox(30,10){foo.tex}}
+
+\put(40,-25){\vector(1,0){35}}
+\put(57.5,-23.5){\makebox(0,0)[b]{latex foo}}
+\put(75,-30){\framebox(30,10){foo.dvi}}
+\put(105,-25){\vector(1,0){35}}
+\put(122.5,-23.5){\makebox(0,0)[b]{\strut \tt dvi foo}}
+ % \shortstack{\strut dvi\\\strut \rm driver}}}
+\put(140,-25){\makebox(0,0)[l]{\rm\strut \ Typeset documentation for
+{\tt foo}}}
+
+\put(40,25){\vector(1,0){35}}
+\put(57.5,26.5){\makebox(0,0)[b]{cc -c foo.c}}
+\put(75,20){\framebox(30,10){foo.o}}
+\put(105,25){\vector(1,0){35}}
+\put(122.5,26.5){\makebox(0,0)[b]{ld foo.o {\ldots}}}
+\put(140,25){\makebox(0,0)[l]{\rm\strut \ Executable \tt a.out}}
+
+
+
+\end{picture}
+
+\caption{Using {\tt noweb} to build code and documentation}
+\label{transforms}
+\end{figure}
+
+A {\tt noweb} file is a sequence of {\em chunks}, which may appear in any order.
+A chunk may contain code or documentation.
+Documentation chunks begin with a line that starts with an at sign ({\tt @})
+followed by a space or newline.
+They have no names.
+Code chunks begin with
+\begin{quote}
+\tt <<{\rm\it chunk name}>>=
+\end{quote}
+on a line by itself.
+The double left angle bracket ({\tt <<}) must be in the first column.
+Chunks are terminated by the beginning of another chunk, or by end of file.
+If the first line in the file does not mark the beginning of a
+chunk, it is assumed to be the first line of a documentation chunk.
+
+Documentation chunks contain text that is ignored by {\tt notangle}
+and copied verbatim to standard output by
+{\tt noweave} (except for quoted code).
+{\tt noweave} can work with {\LaTeX}, or it can use
+% insert a reference to
+a plain-{\TeX} macro package, supplied with {\tt noweb}, that defines
+commands like \verb+\chapter+ and \verb+\section+.
+
+Code chunks contain program source code and references to other code
+chunks.
+Several code chunks may have the same name; {\tt notangle}
+concatenates their definitions to produce a single chunk, just as
+ {\tt TANGLE} does.
+Code chunk definitions are like macro definitions;
+{\tt notangle} extracts a program by expanding one chunk (by default
+the chunk named \verb+<<*>>+).
+The definition of that chunk contains references to other chunks,
+which are themselves expanded, and so on.
+{\tt notangle}'s output is readable; it preserves the indentation of expanded
+chunks with respect to the chunks in which they appear.
+
+Code may be quoted within documentation chunks by placing double
+square brackets around it ({\tt [[}$\ldots${\tt]]}).
+These double square brackets are ignored by {\tt notangle}, but they
+are used by {\tt noweave} to give code special typographic
+treatment.
+
+If double left and right angle brackets are not paired, they are
+treated as literal ``{\tt<<}'' and ``{\tt>>}''. Users can force any
+such brackets, even paired brackets, to be treated as literal by
+using a preceding at sign (e.g.~``{\tt @<<}'').
+
+Any line beginning with ``{\tt@ }'' terminates a code chunk.
+If such a line has the form
+``{\tt@~\char`\%def {\rm\it identifiers}}'',
+it also means that the preceding chunk defines the identifiers listed
+in {\it identifiers}.
+This notation provides a way of marking definitions manually when
+no automatic marking is available.
+
+Figure~\ref{sample-input} shows a fragment of a {\tt noweb} program
+that computes prime numbers.
+The program is derived from the example used in
+Reference~\refno{knuth:literate:book}, Chapter~4, and Figure~\ref{sample-input} should
+be compared with Figure~2b of that paper.
+Figure~\ref{noweave-output} shows the program after processing by {\tt
+noweave} and {\LaTeX}.
+Figure~\ref{notangle-output} shows the beginning of the program as
+extracted by {\tt notangle}.
+A complete example program accompanies this paper.
+
+\begin{figure}
+\begin{verbatim}
+@ This program has no input, because we want to keep it
+simple. The result of the program will be to produce a
+list of the first thousand prime numbers, and this list
+will appear on the [[output]] file.
+
+Since there is no input, we declare the value [[m = 1000]]
+as a compile-time constant. The program itself is capable
+of generating the first [[m]] prime numbers for any
+positive [[m]], as long as the computer's finite
+limitations are not exceeded.
+<<program to print the first thousand prime numbers>>=
+program print_primes(output);
+ const m = 1000;
+ <<other constants of the program>>
+ var <<variables of the program>>
+ begin <<print the first [[m]] prime numbers>>
+ end.
+@ %def print_primes m
+\end{verbatim}
+\caption{Sample {\tt noweb} input, from prime number program}
+\label{sample-input}
+\end{figure}
+
+
+
+\begin{figure}
+\begin{quote}
+\nwbegindocs{4}
+
+This program has no input, because we want to keep it simple.
+The result of the program will be to produce a list of the first
+thousand prime numbers, and this list will appear on the \code{}output\edoc{}
+file.
+
+Since there is no input, we declare the value \code{}m = 1000\edoc{} as a
+compile-time constant.
+The program itself is capable of generating the first \code{}m\edoc{} prime
+numbers for any positive \code{}m\edoc{}, as long as the computer's finite
+limitations are not exceeded.
+\nwenddocs
+\nwbegincode{5}
+\moddef{program to print the first thousand prime numbers}\endmoddef
+program print_primes(output);
+ const m = 1000;
+ \LA{}other constants of the program\RA{}
+ var \LA{}variables of the program\RA{}
+ begin \LA{}print the first \code{}m\edoc{} prime numbers\RA{}
+ end.
+\nwendcode
+\end{quote}
+\caption{Output produced by {\tt noweave} and {\LaTeX} from Figure~\protect\ref{sample-input}}
+\label{noweave-output}
+\end{figure}
+
+\section{Using {\tt noweb}}% experience with noweb?
+
+Experimenting with \verb+noweb+ is easy.
+{\tt noweb} has little syntax: definition and use of code chunks, marking of
+documentation chunks, listing of identifiers defined,
+quoting of code, and quoting of brackets.
+\verb+noweb+ can be used with any programming language, and its
+manual fits on three pages.
+
+\begin{figure}
+\begin{verbatim}
+program print_primes(output);
+ const m = 1000;
+ rr = 50;
+ cc = 4;
+ ww = 10;
+ ord_max = 30; { p_ord_max squared must exceed p_m }
+ var p: array [1..m] of integer;
+ { the first m prime numbers, in increasing order }
+ page_number: integer;
+\end{verbatim}
+\unskip
+\hbox{\hskip2em\tt\vdots}
+\caption{Part of primes program as written by {\tt notangle}}
+\label{notangle-output}
+\end{figure}
+
+
+On a large project, it is essential that compilers and other tools be
+able to refer to locations in the \verb+noweb+ source, even though
+they work with \verb+notangle+'s output~\cite{ramsey:literate}.
+Giving \verb+notangle+ the \verb+-L+ option makes it emit pragmas
+that inform compilers of the placement of lines
+in the \verb+noweb+ source.
+It also preserves the columns in which
+tokens appear.
+If \verb+notangle+ is not given the \verb+-L+ option, it respects the
+indentation of its input, making its output easy to read.
+
+Cross-referencing of chunks and identifiers makes large programs
+easier to understand.
+\verb+noweave -x+ uses {\LaTeX}
+to show on what pages each chunk is defined and used.
+\verb+noweave -index+ adds a local identifier cross-reference after
+each code chunk.
+The example program accompanying this article shows full cross-reference
+information.
+
+
+{\tt WEB} files map one to one with both programs and documents.
+The mapping of \verb+noweb+ files to programs is many to many; the
+mapping of files to documents is many to one.
+Source files are combined by listing their names on \verb+notangle+'s
+or \verb+noweave+'s command line.
+Many programs may be extracted from one source by specifying the names
+of different root chunks, using \verb+notangle+'s \verb+-R+ command-line
+option.
+
+The simplest example of a one-to-many mapping of programs is that of putting
+C~header and program in a single {\tt noweb} file.
+The header comes from the root chunk \LA{}header\RA{}, and the program
+from the default root chunk, \LA{}*\RA{}.
+The following Unix commands extract header \verb+foo.h+ and program
+\verb+foo.c+ from {\tt noweb} file \verb+foo.nw+:
+% This trick is explained on pages 265--266 of Reference~\refno{kernighan:unix}.}
+\begin{quote}
+\begin{verbatim}
+notangle -L foo.nw > foo.c
+notangle -Rheader foo.nw | cpif -ne foo.h
+\end{verbatim}
+\end{quote}
+The \verb+>+ in the first command directs \verb+notangle+'s output to
+the file \verb+foo.c+.
+The \verb+|+ in the second command directs \verb+notangle+'s output to
+the \verb+cpif+ program, which is distributed with {\tt noweb}.
+\verb+cpif -ne foo.h+ compares its input to the contents of file
+\verb+foo.h+; if they differ, the input replaces \verb+foo.h+.
+This trick avoids touching the file \verb+foo.h+ when its contents
+have not changed, which avoids triggering unnecessary recompilations.
+
+A more interesting example is using {\tt noweb} to
+interleave different languages in one source file.
+I wrote an \verb+awk+
+script that read a machine description and emitted a disassembler for
+that machine, and I used {\tt noweb} to combine the script and description
+in a single file, so I could place each part of the input next to the
+code that processed that input.
+The machine description was in the root chunk \LA{}opcodes
+table\RA{}, and the \verb+awk+ script in the default root chunk.
+The processing steps were:
+\begin{verbatim}
+notangle opcodes.nw > opcodes.awk
+notangle -R'opcodes table' opcodes.nw |
+awk -f opcodes.awk > disassem.sml
+\end{verbatim}
+The first line extracts the {\tt awk} program into file {\tt opcodes.awk}.
+The second line extracts the machine description and pipes it to the
+third line, which uses the {\tt awk} program to turn it into a
+dissassembler.
+The disassembler is written to file {\tt disassem.sml}.
+
+Many-to-one mapping of source to program can be used to obtain
+effects similar to those of Ada or Modula-3 generics.
+Figure~\ref{generic-example} shows generic C code that supports lists.
+The code can be
+``instantiated'' by combining it with another \verb+noweb+ file.
+\verb+pair_list.nw+, shown in Figure~\ref{pair-list-example}, specifies
+ lists of integer pairs.
+The two are combined by applying \verb+notangle+ to them both:
+\begin{verbatim}
+notangle pair_list.nw generic_list.nw > pair_list.c
+\end{verbatim}
+{\tt noweb} has no parameter mechanism, so the ``generic'' code must
+refer to a fixed set of symbols, and it cannot be checked for errors
+except by compiling \verb+pair_list.c+.
+These restrictions make {\tt noweb} a poor approximation to real
+generics, but useful nevertheless.
+
+\begin{figure}
+\ifx\dsp\undefined\else\renewcommand{\baselinestretch}{1.3}\fi
+\nwbegindocs{0}
+This list code supports circularly-linked lists represented by a
+pointer to the last element. It is intended to be combined with other
+{\tt noweb} code that defines \LA{}fields of a list element\RA{} (the fields
+found in an element of a list) and that uses \LA{}list
+declarations\RA{} and \LA{}list definitions\RA.
+\nwenddocs
+\nwbegincode{1}
+\moddef{list declarations}\endmoddef
+typedef struct list \{
+ \LA{}fields of a list element\RA{}
+ struct list *_link;
+\} *List;
+
+extern List singleton(void); /* singleton list, uninitialized fields */
+extern List append(List, List); /* destructively append two lists */
+#define last(l) (l)
+#define head(l) ((l) ? (l)->next : 0)
+#define forlist(p,l) for (p=head(l); p; p=(p==last(l) ? 0 : p->next))
+\nwendcode
+\nwbegincode{2}
+\moddef{list definitions}\endmoddef
+List append (List left, List right) \{
+ List temp;
+ if (left == 0) return right;
+ if (right == 0) return left;
+ temp = left->_link; left->_link = right->_link; right->_link = temp;
+ return right;
+\}
+\nwendcode
+\unskip\hbox{\hskip2em\vdots}
+\caption{Generic code for implementing lists in C}
+\label{generic-example}
+\end{figure}
+
+\begin{figure}
+\nwbegincode{1}
+\moddef{*}\endmoddef
+\LA{}list declarations\RA{}
+\LA{}list definitions\RA{}
+\nwendcode
+\nwbegincode{2}
+\moddef{fields of a list element}\endmoddef
+int x;
+int y;
+\nwendcode
+\caption{Program to instantiate lists of integer pairs}
+\label{pair-list-example}
+\end{figure}
+
+\iffalse
+I have used \verb+noweb+ for small programs written in various
+languages, including C, Icon, \verb+awk+, and Modula-3.
+Larger projects have included a code generator for
+Standard ML of New Jersey (written in Standard ML) and
+a multi-architecture debugger, written in Modula-3, C, and
+assembly language.
+A colleague used \verb+noweb+ to write an experimental file
+system in C++.
+
+\unskip
+\vskip0pt plus12pt\penalty-200\vskip0pt plus-12pt
+\noindent The sizes of these programs are % try for better page break
+\nobreak
+\begin{quote}\nobreak
+\catcode`\?=\active\def?{\phantom{0}}
+\catcode`\*=\active\def*{\phantom{,}}
+\leavevmode\rlap{\begin{tabular}{lcc}
+Program&Documentation lines&Total lines\\
+\noalign{\smallskip}
+{\tt markup} and {\tt nt}&?*400&?1,200\\
+ML code generator&?*900&?2,600\\
+Debugger&1,400&11,000\\
+File system&4,400&27,000
+\end{tabular}}
+\end{quote}
+
+\else
+
+I myself have used \verb+noweb+ for code written in various
+languages, including assembly language, \verb+awk+, C, Icon, Modula-3,
+Promela,
+Standard~ML, and \TeX.%
+\footnote{Readers interested in another example of {\tt noweb} can see
+a published version of one of these programs \cite{ramsey:correctness}.}
+These projects have ranged in size from a few hundred to twenty
+thousand lines of code.
+Other users around the world have undertaken
+{\tt noweb} projects of comparable size in C$++$, Modula-2, occam, Parallel C,
+perl, Prolog, and Scheme.
+Two colleagues are using {\tt noweb} to write a book describing the
+design and implementation of a retargetable C compiler.
+
+\fi
+
+\section{Representation of {\tt noweb} files}
+
+The \verb+noweb+ syntax is easy to read, write, and edit, but it is
+not easily manipulated by programs.
+To make it easy to extend \verb+noweb+, I have written
+\verb+markup+, which converts \verb+noweb+ source to
+ a representation that is easily manipulated
+by commonly used Unix tools like {\tt sed} and {\tt awk}.
+In this representation,
+every line begins with {\tt @} and a key word.
+The possibilities are:
+\begin{quote}
+\leavevmode\rlap{\begin{tabular}{ll}
+\tt @begin {\rm\it kind} $n$&Start a chunk\\
+\tt @end {\rm\it kind} $n$&End a chunk\\
+\tt @text {\rm\it string}&{\rm\it string} appeared in a chunk\\
+\tt @nl&A newline appeared in a chunk\\
+\tt @defn {\rm\it name}&The code chunk named {\rm\it name} is being defined\\
+\tt @use {\rm\it name}&A reference to code chunk named {\rm\it name}\\
+\tt @quote&Start of quoted code in a documentation chunk\\
+\tt @endquote&End of quoted code in a documentation chunk\\
+\tt @file {\rm\it filename}&Name of the file from which the chunks came\\
+\tt @line $n$&Next text line came from source line $n$ in current file\\
+\tt @index defn {\rm\it ident}&The current chunk contains a definition of {\rm\it ident}\\
+\tt @index use {\rm\it ident}&The current chunk contains a use of {\rm\it ident}\\
+\tt @index nl {\rm\it ident}&A newline that is part of markup, not part of the chunk\\
+\tt @literal {\rm\it text}&{\tt noweave} copies {\rm\it text} to output\\
+\end{tabular}}
+\end{quote}
+{\tt markup} numbers each chunk, starting at~0.
+It also recognizes and undoes the escape sequence for double brackets,
+e.g.~converting ``{\tt @<<}'' to ``{\tt <<}''.
+{\tt markup}'s output represents a sequence of files.
+Each file is represented by a ``{\tt @file~{\rm\it filename}}'' line,
+followed by a sequence of chunks.
+
+The representation of a documentation chunk is
+\begin{quote}
+\begin{tabular}{ll}
+\tt @begin docs $n$&where $n$ is the chunk number.\\
+{\it docline}&repeated an arbitrary number of times.\\
+\tt @end docs $n$
+\end{tabular}
+\end{quote}
+where {\it docline} may be {\tt @text}, {\tt @nl}, {\tt @quote},
+{\tt @endquote}, {\tt @file}, {\tt @line}, or {\tt @index}.
+Every {\tt @nl} or {\tt @index~nl} corresponds to a newline in the original file.
+{\tt markup} guarantees that quotes are balanced and not nested.
+
+\vskip0pt plus12pt\penalty-200\vskip0pt plus-12pt
+The representation of a code chunk is
+\begin{quote}
+\leavevmode\rlap{\begin{tabular}{ll}
+\tt @begin code $n$&where $n$ is the chunk number.\\
+\tt @defn {\rm\it name}&name of this chunk.\\
+\tt @nl&The newline following {\tt <<{\rm\it name}>>=} in the original file\\
+{\it codeline}&repeated an arbitrary number of times.\\
+\tt @end code $n$
+\end{tabular}}
+\end{quote}
+where {\it codeline} may be {\tt @text}, {\tt @nl}, {\tt @use},
+{\tt @file}, {\tt @line}, or {\tt @index}.
+
+The \verb+noweb+ tools are implemented by piping the output of
+\verb+markup+ to other programs.
+\verb+notangle+ is a Unix shell script that builds a
+pipeline between \verb+markup+ and \verb+nt+, which reads
+and expands definitions of code chunks.
+\verb+noweave+ pipes the output of \verb+markup+ to a 60-line
+\verb+awk+~script that inserts appropriate {\TeX} or {\LaTeX}
+formatting commands.
+
+\section{Extending {\tt noweb}}
+
+Having a format easily read by programs makes {\tt noweb} extensible;
+one can manipulate literate programs using Unix shell scripts and
+filters.
+{\tt notangle} and {\tt noweave} have {\tt -filter} options that can
+be used to insert filters into their pipelines without changing any
+code.
+These filters manipulate the representation described in the previous
+section.
+The results are converted to {\TeX} by {\tt noweave} and to code by
+{\tt notangle}.
+
+
+Filters can be used to change the way {\tt noweb} works; for example,
+a one-line {\tt sed} script makes {\tt noweb} treat two chunk names as
+identical if they differ only in their representation of whitespace.
+A 55-line Icon program makes it possible to abbreviate chunk names
+using a trailing ellipsis, as in {\tt WEB}.
+To share programs with colleagues who don't enjoy literate
+programming, I use a filter that
+places each line of documentation in a comment and moves it to
+the succeeding code chunk.
+With this filter, \verb+notangle+
+transforms a literate
+program into a traditional commented program, without loss of
+information and with only a modest penalty in readability.
+Figure~\ref{nountangle-output} shows the results of applying
+the filter to the prime-number program shown in
+Figure~\ref{sample-input}.
+
+
+
+
+\begin{figure}
+\begin{webcode}\parindent=0pt
+\{ This program has no input, because we want to keep it \}
+\{ simple. The result of the program will be to produce a \}
+\{ list of the first thousand prime numbers, and this list \}
+\{ will appear on the [[output]] file. \}
+\hbox{\hskip2em\tt\vdots}
+\{ <program to print the first thousand prime numbers>= \}
+program print_primes(output);
+ const m = 1000;
+ \{ \\section-The output phase- \}
+ \{ \}
+ \{ <other constants of the program>= \}
+ rr = 50;
+ cc = 4;
+ ww = 10;
+ \{ <other constants of the program>= \}
+ ord_max = 30; \{ p_ord_max squared must exceed p_m \}
+ var \{ How should table [[p]] be represented? Two possibilities \}
+ \{ suggest themselves: We could construct a sufficiently \}
+\hbox{\hskip2em\tt\vdots}
+\end{webcode}
+\caption{Output produced from
+Figure~\protect\ref{sample-input} by filter converting documentation
+chunks into comments.}
+\label{nountangle-output}
+\end{figure}
+
+
+
+Filters can be used to add significant features.
+\verb+noweave+'s cross-reference and indexing features use two
+filters, one that finds uses of defined identifiers and one that
+uses \verb+@literal+ to insert {\LaTeX} cross-reference
+commands.
+In most cases, programmers must mark identifier definitions
+by hand, using ``{\tt @~\%def}'',
+but
+in some cases, a third, language-dependent filter can be used to
+mark identifier definitions,
+making index generation completely automatic.
+Kostas Oikonomou of AT\&T Bell Labs and Conrado Martinez-Parra of
+the Univ.\ Politecnica de Catalunya in Barcelona have written filters
+that add prettyprinting to {\tt noweb}.
+Oikonomou's filters prettyprint Icon and Object-Oriented Turing;
+Martinez-Parra's filter prettyprints a variant of Dijkstra's language
+of guarded commands.
+
+
+\section{Comparing {\tt WEB} and {\tt noweb}}
+
+Unlike {\tt WEB},
+\verb+noweb+ is independent of the target programming language.
+{\tt WEB} tools can be generated for many programming languages,
+but those languages must be lexically similar to C.
+For example, {\tt WEB} can't handle the \verb+awk+ regular-expression
+notation ``\verb+/+\ldots\verb+/+''; every such expression must quoted
+using {\tt WEB}'s ``verbatim'' control sequence.
+The effort required to
+generate {\tt WEB} tools is significant; the prospective user must
+write a specification of several hundred
+lines.
+
+Being independent of the target programming language makes {\tt noweb}
+simpler, but it also means that {\tt noweb} can do less.
+Most of the differences between {\tt WEB} and {\tt noweb} arise
+because {\tt WEB} has language-dependent features that are not present
+in \verb+noweb+.
+These features include
+prettyprinting,
+typesetting comments using {\TeX},
+expanding macros,
+evaluating constant expressions,
+and
+converting string literals to indices into a ``string pool.''
+Among these features,
+\verb+noweb+ users are most likely to miss prettyprinting.
+
+
+Some differences arise because {\tt WEB} and \verb+noweb+ implement
+similar features differently.
+{\tt WEB}'s original {\tt TANGLE} removed white space and folded
+lines to fill each line with tokens,
+making its output unreadable~\cite[Chapter~4, Figure~3]{knuth:literate:book}.
+Later adaptations preserved line breaks but removed other white space.
+By default, \verb+notangle+ preserves whitespace and maintains
+indentation when expanding chunks.
+It can therefore be used with
+languages like Miranda and
+Haskell, in which indentation is significant.
+{\tt TANGLE} cannot.
+
+{\tt WEB}'s {\tt WEAVE} assigns a number to each chunk, and its index
+and cross-reference
+information refer to chunk numbers, not page numbers.
+\verb+noweb+ uses {\LaTeX} to emit index and cross-reference information that
+refer to page numbers.
+Anyone who has read a large literate program will
+appreciate the difference.
+
+{\tt WEB} works poorly with \LaTeX; \LaTeX\ constructs cannot
+be used in {\tt WEB} source, and getting {\tt WEAVE} output
+to work in \LaTeX\ documents requires tedious adjustments by hand.
+\verb+noweb+ works with both plain {\TeX} and {\LaTeX}.
+Both {\tt WEAVE} and {\tt noweave} depend on the text formatter in two
+ways: the source of the program itself, and the supporting macros.
+{\tt WEAVE}'s source (written using {\tt WEB} for C) is
+several thousand lines long, and the formatting code is not isolated.
+{\tt noweave}'s source is a 200-line shell script, and it uses a
+60-line {\tt awk} program to generate {\TeX}.
+Both
+{\tt WEAVE} and {\tt noweave} use about 200 lines of supporting macros
+for plain {\TeX}.
+\verb+noweb+ uses another 300 lines to support {\LaTeX}, primarily
+because the page-based cross-reference mechanism is complex.
+
+{\tt noweb} has
+two features that weren't in the original {\tt WEB}, but that appeared in
+some of {\tt WEB}'s later adaptations;
+{\tt notangle} can extract more than one program from
+a single source file, and it can give a compiler the original locations
+of source lines.
+{\tt noweb} has a related feature not found in the {\tt WEB} variants;
+{\tt noweave} adds no newlines to its output, making it easy to find
+the sources of {\TeX} or {\LaTeX} errors.
+For example, an error on line~634 of a generated
+{\TeX} file is caused by a problem on line~634 of the
+corresponding {\tt noweb} file.
+
+Reviewers have had many expectations of literate-programming
+tools~\cite{thimbleby:review,cvw:assessment}.
+The most important is {\em verisimilitude}: a single
+input should produce both compilable program and publishable document,
+warranting the correctness of the document.
+Others include flexible order of elaboration,
+ability to develop program and documentation concurrently in one
+place, cross-references, and indexing.
+Both {\tt WEB} and {\tt noweb}
+satisfy all these expectations, although in both cases automatic
+indexing is available for a limited set of programming languages.
+
+
+\section{Discussion}
+
+{\tt WEB} takes the monolithic approach to literate programming---it
+does everything.
+{\tt noweb}'s approach is to compose
+simple tools that manipulate files in the {\tt noweb} format.
+Existing Unix tools provide some of the {\tt WEB} features that
+aren't found in \verb+noweb+.
+Unix supplies two macro processors: the C
+preprocessor and the \verb+m4+ macro processor.
+\verb+xstr+ extracts string literals.
+\verb+patch+ provides a form of version control similar to {\tt WEB}'s
+change files.
+Few of {\tt WEB}'s remaining features will be missed; for example, many compilers
+evaluate constant expressions at compile time.
+Experience with {\tt WEB} has suggested that prettyprinting may be
+more trouble than it is worth~\cite{ramsey:literate}.
+
+{\tt noweb} was developed on Unix and uses Unix tools like {\tt
+awk} and the Bourne shell, but the only Unix feature it really needs
+is the pipeline.
+All components written in {\tt awk} have been duplicated in Icon;
+an Icon implementation is freely available from the University of Arizona, and
+it runs on a wide variety of hardware and operating-system platforms.
+{\tt noweb} can be ported to non-Unix platforms provided they have
+pipelines or an emulation thereof, ANSI~C, and either {\tt awk} or Icon.
+For example,
+Lee Wittenberg of Kean College ported {\tt noweb} to MS-DOS by
+rewriting the shell scripts as DOS batch files.
+
+Indexing and cross-referencing make
+{\tt noweb} less simple than it could be.
+Complex {\LaTeX} code is needed to compute page numbers for use in
+cross-reference lists and in the index.
+The ability to use page numbers justifies this complexity, especially
+since the complexity can be hidden from most users.
+Users do need to understand the {\LaTeX} code if they want to customize the
+appearance of their {\tt noweb} documents while retaining {\tt
+noweb}'s use of page numbers for cross-reference.
+Most literate-programming tools
+forbid customization, but not all users will accept such a restriction.
+I have compromised between simplicity and customizability by adding
+{\LaTeX} options for a dozen of the most commonly requested
+customizations; users can choose from among these options without
+understanding {\tt noweb}'s {\LaTeX} code.
+
+
+Four things distinguish {\tt noweb} from previous work.
+{\tt noweb} takes as simple as possible a view of literate programming
+and the tools needed to implement it.
+Instead of relying on a generator or re-implementation to support
+different programming languages, {\tt noweb} is independent of the
+target programming language.
+{\tt noweave}'s dependence on its typesetter is small and isolated,
+instead of being distributed throughout a large implementation.
+Users have extended {\tt noweb} without recompiling its source code.
+
+Experimenting with {\tt noweb} is easy because the tools are simple
+and they work with any language.
+If the experiment is unsatisfying, it is easy to abandon, because
+\verb+notangle+'s output, unlike {\tt TANGLE}'s, is readable.
+\verb+noweb+ is simpler than {\tt WEB}, and it is easier to use and
+understand, but it does less.
+I argue, however, that the benefit of {\tt WEB}'s extra features is
+outweighed by cost of the extra complexity,
+making \verb+noweb+ better for writing literate programs.
+
+\verb+noweb+ can be obtained by
+anonymous {\tt ftp} from CTAN,
+the Comprehensive {\TeX}
+Archive Network, in directory {\tt web/noweb}. CTAN replicas appear
+on
+hosts {\tt ftp.shsu.edu}, {\tt ftp.tex.ac.uk}, and {\tt ftp.uni-stuttgart.de}.
+
+\section{Acknowledgements}
+Mark Weiser's invaluable encouragement provided the impetus for me to
+write this paper, which I did while visiting the Computer
+Science Laboratory of the Xerox Palo Alto Research Center.
+David Hanson suggested and provided the \verb+cpif+ program.
+Preston Briggs developed many of the ideas used in \verb+noweb+'s
+indexing, and he contributed code used in one of the pipeline stages.
+Dave Love provided much-needed {\LaTeX} expertise.
+Comments from David Hanson and from the anonymous referees stimulated
+me to improve the paper.
+The development of {\tt noweb} was supported by a Fannie and John Hertz
+Foundation Fellowship.
+
+This paper was submitted in August, 1991.
+
+\bibliographystyle{abbrv}
+\bibliography{web,cs,ramsey,ml}
+
+\clearpage
+\noweboptions{shift} % needed to make room for wordcount example
+
+\input wc
+
+\end{document}
diff --git a/web/noweb/src/xdoc/manpage.nw b/web/noweb/src/xdoc/manpage.nw
new file mode 100644
index 0000000000..76cc6afcf1
--- /dev/null
+++ b/web/noweb/src/xdoc/manpage.nw
@@ -0,0 +1,681 @@
+<<notangle.1>>=
+.TH NOWEB 1 "local <<noweb documentation date>>"
+.SH NAME
+notangle, noweave, nountangle \- noweb, a literate-programming tool
+.SH SYNOPSIS
+.B notangle
+[\fB\-R\fProotname ...] [\fB\-filter\fP command]
+[\fB\-L\fP[format]] [file] ...
+.br
+\fBnountangle\fP
+[\fB\-ml\fP|\fB\-m3\fP|\fB\-c\fP|\fB\-c++\fP|\fB\-awk\fP|\fB\-tex\fP|\fB\-f77\fP|\fB\-f90\fP|\fB\-lisp\fP|\fB\-matlab\fP]
+[\fB\-R\fProotname ...] [\fB\-filter\fP command] [\fB\-w\fPwidth] [file] ...
+.br
+\fBnoweave\fP [options] [file] ...
+.SH DESCRIPTION
+.I Noweb
+is a literate-programming tool like Knuth's
+.I WEB,
+only simpler.
+A
+.I noweb
+file contains program source code interleaved with documentation.
+When
+.I notangle
+is given a
+.I noweb
+file, it writes the program on standard output.
+When
+.I noweave
+is given a
+.I noweb
+file, it reads the
+.I noweb
+source and produces, on standard output, \fILaTeX\fP, \fITeX\fP, \fItroff\fP,
+or \fIHTML\fP
+source for typeset documentation.
+.I nountangle
+converts a literate program into an ordinary program by
+turning interleaved documentation into comments.
+The file name `\-' refers to standard input.
+.SH FORMAT OF NOWEB FILES
+<<paragraph describing markup of chunks>>
+<<paragraph describing markup of chunks>>=
+A
+.I noweb
+file is a sequence of
+.IR chunks ,
+which may appear in any order.
+A chunk may contain code or documentation.
+Documentation chunks begin with a line that starts with an at sign (@)
+followed by a space or newline.
+They have no names.
+Code chunks begin with
+.br
+@<<\fIchunk name\fP@>>=
+.br
+on a line by itself.
+The double left angle bracket (@<<) must be in the first column.
+Chunks are terminated by the beginning of another chunk, or by end of file.
+If the first line in the file does not mark the beginning of a
+chunk, it is assumed to be the first line of a documentation chunk.
+@
+<<notangle.1>>=
+.PP
+Documentation chunks contain text that is ignored by
+.I notangle
+and copied verbatim to
+standard output
+by
+.I noweave
+(except for quoted code).
+.I noweave
+can work with \fILaTeX\fP, plain \fITeX\fP, \fItroff\fP or \fIHTML\fP.
+With plain \fITeX\fP, it inserts a reference to a
+.I TeX
+macro package, \fInwmac\fP, which defines commands like
+.B \echapter
+and
+.B \esection.
+.PP
+Code chunks contain program source code and references to other code
+chunks.
+Several code chunks may have the same name;
+.I notangle
+concatenates their definitions to produce a single chunk, just as does
+.IR tangle (1).
+Code chunk definitions are like macro definitions;
+.I notangle
+extracts a program by expanding one chunk (by default, the chunk named
+\fB@<<\fP*\fB@>>\fP).
+The definition of that chunk contains references to other chunks, which are
+themselves expanded, and so on.
+\fInotangle\fP's output is readable; it preserves the indentation of expanded
+chunks with respect to the chunks in which they appear.
+.PP
+Code may be quoted within documentation
+chunks by placing double square brackets
+(\fB[[\fI...\fB]]\fR) around it.
+These double square brackets are ignored by
+.I notangle,
+but they may be used by
+.I noweave
+to give the code special typographic treatment, e.g., hypertext links.
+If quoted code ends with three or more square brackets,
+.I noweave
+chooses the rightmost pair, so that, for example, \fB[[a[i]]]\fR is
+parsed correctly.
+The names of
+code chunks may appear within quoted code unless that quoted code is itself
+part of the name of a code chunk.
+.PP
+<<paragraph on escaping angle brackets>>
+<<paragraph on escaping angle brackets>>=
+In code, noweb treats unpaired
+double left or right angle brackets as literal \fB@<<\fP and \fB@>>\fP.
+To force any
+such brackets, even paired brackets or brackets in documentation,
+to be treated as literal, use a preceding at sign (e.g. \fB@@<<\fP).
+<<old paragraph on escaping angle brackets>>=
+If the double left or right angle bracket is to be used
+in code or documentation,
+not as part of a chunk name, it should be preceded by an at sign
+(e.g. \fB@@<<\fP), although the at sign is not required in code if there is no
+matching double bracket.
+<<notangle.1>>=
+.PP
+<<paragraph on escaping initial at sign>>
+<<paragraph on escaping initial at sign>>=
+Some programming or formatting languages may require a single \fB@\fP sign in
+the first column.
+Noweb users may achieve this effect by putting a doubled \fB@@\fP in the first column;
+in this position only, it stands for a single \fB@\fP sign.
+<<paragraph on marking identifier definitions (no longer used)>>=
+Any line beginning with `\fB@ \fP' terminates a code chunk,
+but if the line has the form
+.br
+\fB@ %def \fP\fIidentifiers\fP
+.br
+it is taken to mean that the preceding chunk defines the identifiers listed
+in
+.IR identifiers .
+This list contains identifiers separated by whitespace;
+any sequence of nonwhite characters may be an identifier.
+.I noweb
+uses a simple heuristic to avoid recognizing identifiers
+that are substrings of other identifiers.
+.I "This feature is deprecated."
+.I "Instead, I recommend that you use the"
+.B btdefn
+.I "filter described on the nowebfilters(7) man page."
+<<notangle.1>>=
+.SH TANGLING
+.I notangle
+and
+.I nountangle
+accept the same set of options, although some options have effects only on one
+or the other.
+The options are:
+.TP
+.B \-R\fIname\fR
+Expand the \fB@<<\fIname\fB@>>\fR code chunk.
+The
+.B \-R
+option can be repeated,
+in which case each chunk is written to the output.
+If no
+.B \-R
+option is given, expand the chunk named \fB@<<\fP*\fB@>>\fP.
+.TP
+.B \-L\fIformat\fR
+Emit line number indications at chunk boundaries.
+A line number indication identifies the source of the line that follows it.
+In
+.IR format ,
+.B "%F"
+indicates the name of the source file,
+.B "%L"
+indicates the line number of the source file,
+.B "%N"
+indicates a newline,
+and
+.B "%%"
+indicates a percent sign.
+A sign and digit may be inserted between the percent sign and the `\fBL\fP',
+in which case the line number will be adjusted by that amount.
+If
+.I format
+is omitted, the default format is that accepted by the C preprocessor:
+`\fB#line %L "%F"%N\fR'.
+When using the \fB\-L\fIformat\fR option,
+.I notangle
+ensures that all text appears in the same column in input and output.
+.I nountangle
+ignores this option.
+.IP " "
+Common format strings include:
+.ta \w'zzzSunyFORTRANxxxx'u
+.nf
+ C \fB\-L'#line %L "%F"%N'\fP
+ Sun FORTRAN \fB\-L'\\# %L "%F"%N'\fP
+ Icon \fB\-L'#line %\-1L "%F"%N'\fP
+ Modula-3 \fB\-L'<*LINE %L "%F" *>%N'\fP
+ SML/NJ \fB\-L'(*#line %L "%F"*)'\fP
+.fi
+.IP " "
+To solve the converse problem, that is, to get noweb to do something sensible
+with \fB#line\fP in its input, see the \fBsharpline\fP filter in the examples
+directory.
+.TP
+.B \-t\fIk\fP
+Copy tabs untouched from input to output, and use tabs for indentation,
+assuming stops every \fIk\fP columns.
+By default, tabs are expanded to spaces with stops every 8 columns.
+.TP
+.B \-filter \fIcmd\fP
+Filter the
+.I noweb
+source through
+.I cmd
+after converting it to tool form and before tangling.
+.I notangle
+looks for
+.I cmd
+first on the user's
+.BR PATH ,
+then in
+.BR |LIBDIR| .
+Such filters
+can be used to add features to
+.IR notangle ;
+for an example see
+.BR |LIBDIR|/emptydefn .
+For experts only.
+<<description of -markup option>>
+.TP
+.B "\-awk | \-c | \-icn | \-icon | \-ml | \-m3 | \-pascal | \-f77 | \-f90 | \-tex"
+When
+.I nountangle
+transforms documentation chunks into comments, use the comment format of the language
+named.
+.B \-c
+is the default.
+.I notangle
+ignores these options.
+.TP
+.B \-w\fIn\fP
+When
+.I nountangle
+transforms documentation chunks into comments, create comments on lines of width \fIn\fP.
+.I notangle
+ignores this option.
+.SH WEAVING
+<<man page: WEAVING section>>
+.SH INDEXING AND CROSS-REFERENCE
+<<man page: INDEXING AND CROSS-REFERENCE section>>
+When used with
+.IR LaTeX ,
+.IR troff ,
+or
+.I HTML,
+.I noweave
+can provide indexing and cross-reference information for chunks and for
+programming-language identifiers.
+Identifier definitions may be marked by hand using backticks (`); the
+\fB-filter btdefn\fP option recognizes these markings.
+For some languages, definitions may be found automatically using the
+\fB-autodefs\fP option.
+This section describes the indexing and cross-reference options;
+it might well be skipped on first reading.
+<<noweave man page indexing options>>
+.SH ERROR MESSAGES
+If
+.I notangle
+or
+.I noweave
+encounters a chunk name within documentation, it assumes that this
+indicates an error, usually misspelling ``@<<name@>>=''.
+Other error messages should be self-explanatory.
+.PP
+It is incorrect to refer to a chunk that is never
+defined, but it is OK for chunks to be defined and not used.
+.SH EXAMPLES
+If you have trouble digesting this man page, you're not alone.
+Here are a few examples to get you started.
+I'll assume you have a
+.B foo.nw
+file with a C program in chunk
+.B @<<foo.c@>>
+and a header file in chunk
+.BR @<<foo.h@>> ,
+and that your documentation is marked up using
+.IR latex(1) .
+I'll show you how to build things using the most common options.
+.PP
+To rebuild your C source, try
+.RS
+.B "notangle \-L \-Rfoo.c foo.nw > foo.c"
+.RE
+To rebuild your header file, try
+.RS
+.B "notangle \-Rfoo.h foo.nw | cpif foo.h"
+.RE
+There are two compromises here.
+Omitting \fB\-L\fP keeps \fB#line\fP out of your header file,
+and using \fBcpif\fP prevents the command from rewriting
+.B foo.h
+unless the contents have changed. Thus, this is good code to put in a Makefile rule.
+.PP
+To build a printed document, run
+.RS
+.B "noweave \-autodefs c \-index foo.nw > foo.tex"
+.RE
+If you have your own preamble, containing \fB\\documentclass\fP and all,
+you will also need the \fB\-delay\fP option.
+.PP
+To build a web page, run
+.RS
+.B "noweave \-filter l2h \-autodefs c \-index \-html foo.nw | htmltoc > foo.html"
+.RE
+Have fun!
+.SH FILES
+.PP
+.ta \w'|TEXINPUTS|nwkernel.texxxxx'u
+.nf
+|LIBDIR|/markup markup preprocessor
+|LIBDIR|/unmarkup inverts markup
+|LIBDIR|/nt notangle proper
+|LIBDIR|/finduses find uses of identifiers for index
+|LIBDIR|/noidx generate index and cross-reference info
+|LIBDIR|/toroff back end to emit \fItroff\fP
+|LIBDIR|/totex back end to emit \fITeX\fP or \fILaTeX\fP
+|LIBDIR|/tohtml back end to emit HTML
+|TEXINPUTS|/nwmac.tex formatting \fITeX\fP macros
+|TEXINPUTS|/noweb.sty use in \fILaTeX\fP documents; see \fInowebstyle(7)\fP
+.fi
+.SH SEE ALSO
+.PP
+.IR cpif (1),
+.IR nodefs (1),
+.IR noroots (1),
+.IR noweb (1),
+.IR noindex (1),
+.IR noroff (1),
+.IR nowebstyle (7),
+.IR nowebfilters (7)
+.SH BUGS
+.I notangle
+and
+.I nountangle
+fail if names used on the command line contain single quotes.
+.PP
+Ignoring unused chunks can cause problems;
+if a chunk has
+multiple definitions and one is misspelled,
+the misspelled definition is silently ignored.
+.IR noroots (1)
+can be used to catch this mistake.
+\".PP
+\".I noweb
+\"requires the new version of
+\".IR awk ,
+\"assumed to be called
+\".IR nawk .
+\"DEC
+\".I nawk
+\"has a bug in that that causes
+\".B noweave
+\"to fail to translate braces correctly.
+\"GNU
+\".I gawk
+\"is reported to work.
+\".PP
+\"DEC
+\".I sh
+\"has a bug that causes the
+\".B \-filter
+\"option to fail whenever the filter command contains more than one word.
+.PP
+The
+.I "-L"
+option of
+.I notangle
+puts an implicit initial newline in the format string.
+.PP
+<<paragraph about bogus latex pagestyles>>
+.PP
+.IR latex2html (1)
+mangles some source files.
+.PP
+.I noweave
+has too many options, and this man page is too long.
+<<AUTHOR section>>
+<<description of -markup option>>=
+.TP
+.B "\-markup \fIparser\fP"
+Use
+.I parser
+to parse the input file.
+Enables use of noweb tools on files in other formats;
+for example, the
+.B numarkup
+parser understands
+.IR nuweb (1)
+format.
+See
+.IR nowebfilters (7)
+for more information.
+For experts only.
+<<paragraph about bogus latex pagestyles>>=
+The default
+.I LaTeX
+pagestyles don't set the width of the boxes containing headers and footers.
+Since
+.I noweb
+code paragraphs are extra wide, this
+.I LaTeX
+bug sometimes results in extra-wide headers and footers.
+The remedy is to redefine the relevant
+.B ps@*
+commands;
+.B ps@noweb
+in
+.B noweb.sty
+can be used as an example.
+@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+<<noweb.1>>=
+.TH NOWEB 1 "local <<noweb documentation date>>"
+.SH NAME
+noweb \- a simple literate-programming tool
+.SH SYNOPSIS
+.B noweb
+[\fB-t\fP]
+[\fB-o\fP]
+[\fB-L\fP\fIformat\fP]
+[\fB-markup\fP \fIparser\fP]
+[file] ...
+.SH DESCRIPTION
+.I Noweb
+is a literate-programming tool like
+.I FunnelWEB
+or
+.IR nuweb ,
+only simpler.
+A
+.I noweb
+file contains program source code interleaved with documentation.
+When
+.I noweb
+is invoked, it writes the program source code
+to the output files mentioned in the noweb file, and it writes a
+.I TeX
+file for typeset documentation.
+.PP
+The
+.IR noweb (1)
+command is for people who don't like reading man pages or who are switching from
+.IR nuweb .
+To get the most out of
+.IR noweb ,
+use
+.IR notangle (1)
+and
+.IR noweave (1)
+instead.
+.SH FORMAT OF NOWEB FILES
+<<paragraph describing markup of chunks>>
+.PP
+Documentation chunks contain text that is copied verbatim to the
+.I TeX
+file (except for quoted code).
+.I noweb
+works with \fILaTeX\fP; the first documentation chunk must contain
+a
+.I LaTeX
+.B "\\\\documentclass"
+command, it must contain
+.B "\\\\usepackage{noweb}"
+in the preamble, and finally
+it must also contain a
+.I LaTeX
+.B "\\\\begin{document}"
+command.
+.PP
+Code chunks contain program source code and references to other code
+chunks.
+Several code chunks may have the same name;
+.I noweb
+concatenates their definitions to produce a single chunk, just as
+other literate-programming tools do.
+.I noweb
+looks for chunks that are defined but not used in the source file.
+If the name of such a chunk contains no spaces, the chunk is
+an ``output file;''
+.I noweb
+expands it and writes the result onto the file of the same name.
+A code-chunk definition is like a macro definition;
+it contains references to other chunks, which are
+themselves expanded, and so on.
+\fInoweb\fP's output is readable; it preserves the indentation of expanded
+chunks with respect to the chunks in which they appear.
+.PP
+If a star (\fB*\fP) is appended to the name of an output file,
+.I noweb
+includes line-number information as specified by the \fB\-L\fP\fIformat\fP
+option (or for C if no \fB\-L\fP\fIformat\fP option is given).
+The name itself may not contain shell metacharacters.
+.PP
+Code may be quoted within documentation
+chunks by placing double square brackets
+(\fB[[\fI...\fB]]\fR) around it.
+These double square brackets are used to
+give the code special typographic treatment in the
+.I TeX
+file.
+If quoted code ends with three or more square brackets,
+.I noweb
+chooses the rightmost pair, so that, for example, \fB[[a[i]]]\fR is
+parsed correctly.
+.PP
+<<paragraph on escaping angle brackets>>
+.SH OPTIONS
+.TP
+.B \-t
+Suppress generation of a
+.I TeX
+file.
+.TP
+.B \-o
+Suppress generation of output files.
+.TP
+.B \-L\fIformat\fR
+Use
+.I format
+to format line-number information for starred output files.
+(If the option is omitted, a format suitable for C is used.)
+.I format
+is as defined by
+.IR notangle (1);
+<<description of -markup option>>
+.SH BUGS
+.PP
+Ignoring unused chunks whose names contain spaces
+sometimes causes problems, especially in the case when a chunk has
+multiple definitions and one is misspelled;
+the misspelled definition will be silently ignored.
+.IR noroots (1)
+can be used as a sanity checker to catch this sort of mistake.
+.PP
+.I noweb
+is intended for users who don't want the power or the complexity of
+command-line options.
+More sophisticated users should avoid
+.I noweb
+and use
+.I noweave
+and
+.I notangle
+instead.
+If the design were better, we could all use the same commands.
+.PP
+.I noweb
+requires the new version of
+.IR awk ,
+assumed to be called
+.IR nawk .
+DEC
+.I nawk
+has a bug in that that causes problems with braces in
+.I TeX
+output.
+GNU
+.I gawk
+is reported to work.
+.PP
+<<paragraph about bogus latex pagestyles>>
+.SH SEE ALSO
+.PP
+.IR notangle (1),
+.IR noweave (1),
+.IR noroots (1),
+.IR nountangle (1),
+.IR nowebstyle (7),
+.IR nowebfilters (7),
+.IR nuweb2noweb (1)
+.br
+Norman Ramsey,
+.I "Literate programming simplified, IEEE Software"
+11(5):97-105, September 1994.
+<<AUTHOR section>>
+<<nowebstyle.7>>=
+.TH NOWEB 7 "local <<noweb documentation date>>"
+.SH NAME
+nowebstyle \- \fILaTeX\fP package for \fInoweb\fP
+.SH SYNOPSIS
+.B "\\\\usepackage{noweb}"
+.SH DESCRIPTION
+When
+.I noweave
+generates code for
+.IR LaTeX ,
+the
+.B noweb
+package is required.
+In addition to the necessary arcana, it
+defines a
+.B webcode
+environment in which you can place fragments of
+code, and in which
+only backslash and curly braces have their special meanings;
+all other characters are taken literally.
+It also defines a
+.B noweb
+pagestyle.
+Finally, it defines a
+.B "\\\\noweboptions{...}"
+command that can be used to tinker with the appearance of the output.
+Options are separated by commas and include:
+<<man page: [[\noweboptions]]>>
+.SH CONTROL SEQUENCES
+The noweb package describes a gazillion special control sequences.
+Only a few are listed here.
+<<man page: noweb style control sequences>>
+.SH SEE ALSO
+.IR noweave (1),
+.IR noweb (1)
+<<AUTHOR section>>
+@
+<<cpif.1>>=
+.TH CPIF 1 "local <<noweb documentation date>>"
+.SH NAME
+cpif \- selectively update files
+.SH SYNOPSIS
+.B cpif
+[\fB\-eq\fP|\fB\-ne\fP] file ...
+.SH DESCRIPTION
+.I cpif
+is an auxiliary tool for use with
+.IR notangle (1)
+and
+.IR make (1).
+.I cpif
+compares its standard input to each of the named files,
+overwriting the file if the comparison succeeds or if
+the named file does not exist.
+If neither
+.B \-eq
+or
+.B \-ne
+is specified, the default is
+.BR \-ne .
+Typical usage is in the following default rule, suitable for use in a Makefile.
+.br
+ .nw.h: ; notangle \-Rheader $*.nw | cpif $*.h
+.br
+.SH SEE ALSO
+.IR notangle (1)
+<<AUTHOR section>>
+@
+<<nuweb2noweb.1>>=
+.TH NOWEB 1 "<<noweb documentation date>>"
+.SH NAME
+nuweb2noweb \- convert nuweb files to noweb form
+.SH SYNOPSIS
+.B nuweb2noweb
+file ...
+.SH DESCRIPTION
+.I Nuweb2noweb
+converts a file or files in
+.I nuweb
+format to
+.I noweb
+format, writing the results on standard output.
+Input is from the file(s) named on the command line.
+.SH SEE ALSO
+.PP
+.IR noweb (1),
+.IR nuweb (1)
+<<AUTHOR section>>
+@
+
diff --git a/web/noweb/src/xdoc/nodefs.1 b/web/noweb/src/xdoc/nodefs.1
new file mode 100644
index 0000000000..168cc83949
--- /dev/null
+++ b/web/noweb/src/xdoc/nodefs.1
@@ -0,0 +1,54 @@
+.TH NOWEB 1 "local 10/40/2008"
+.SH NAME
+nodefs \- find definitions in noweb file
+.SH SYNOPSIS
+.B nodefs
+[\fB\-auto\fP \fIlang\fP]
+[\fB\-showauto\fP]
+file ...
+.SH DESCRIPTION
+.I nodefs
+is an auxiliary tool that produces output for use with the
+.B \-indexfrom
+option of
+.IR noweave (1).
+.I nodefs
+searches a
+.I noweb
+file for identifier definitions, printing the identifiers on standard output,
+one per line.
+If the
+.B \-auto \fIlang\fP
+option is given,
+.I nodefs
+tries to discover definitions automatically, assuming the program
+is written in language \fIlang\fP.
+The
+.B \-showauto
+option displays permissible values of \fIlang\fP, which vary but may include
+.B tex
+or
+.BR icon .
+.PP
+For a complete description of using
+.I nodefs
+together with
+.IR noweave (1)
+and
+.IR noindex (1),
+see the man page for
+.IR noindex (1).
+.SH SEE ALSO
+.IR noweave (1),
+.IR noweb (1),
+.IR noindex (1)
+.SH VERSION
+This man page is from
+.I noweb
+version 2.12.
+.SH AUTHOR
+Norman Ramsey, Tufts University.
+Internet address \fBNorman.Ramsey@tufts.edu\fP.
+.br
+Noweb home page at \fBhttp://www.cs.tufts.edu/~nr/noweb\fP.
+
diff --git a/web/noweb/src/xdoc/nodefs.nw b/web/noweb/src/xdoc/nodefs.nw
new file mode 100644
index 0000000000..8053920755
--- /dev/null
+++ b/web/noweb/src/xdoc/nodefs.nw
@@ -0,0 +1,46 @@
+<<*>>=
+.TH NOWEB 1 "local <<noweb documentation date>>"
+.SH NAME
+nodefs \- find definitions in noweb file
+.SH SYNOPSIS
+.B nodefs
+[\fB\-auto\fP \fIlang\fP]
+[\fB\-showauto\fP]
+file ...
+.SH DESCRIPTION
+.I nodefs
+is an auxiliary tool that produces output for use with the
+.B \-indexfrom
+option of
+.IR noweave (1).
+.I nodefs
+searches a
+.I noweb
+file for identifier definitions, printing the identifiers on standard output,
+one per line.
+If the
+.B \-auto \fIlang\fP
+option is given,
+.I nodefs
+tries to discover definitions automatically, assuming the program
+is written in language \fIlang\fP.
+The
+.B \-showauto
+option displays permissible values of \fIlang\fP, which vary but may include
+.B tex
+or
+.BR icon .
+.PP
+For a complete description of using
+.I nodefs
+together with
+.IR noweave (1)
+and
+.IR noindex (1),
+see the man page for
+.IR noindex (1).
+.SH SEE ALSO
+.IR noweave (1),
+.IR noweb (1),
+.IR noindex (1)
+<<AUTHOR section>>
diff --git a/web/noweb/src/xdoc/nodefs.txt b/web/noweb/src/xdoc/nodefs.txt
new file mode 100644
index 0000000000..9725333d28
--- /dev/null
+++ b/web/noweb/src/xdoc/nodefs.txt
@@ -0,0 +1,37 @@
+NOWEB(1) General Commands Manual NOWEB(1)
+
+
+
+NNAAMMEE
+ nodefs - find definitions in noweb file
+
+SSYYNNOOPPSSIISS
+ nnooddeeffss [--aauuttoo _l_a_n_g] [--sshhoowwaauuttoo] file ...
+
+DDEESSCCRRIIPPTTIIOONN
+ _n_o_d_e_f_s is an auxiliary tool that produces output for use with the
+ --iinnddeexxffrroomm option of _n_o_w_e_a_v_e(1). _n_o_d_e_f_s searches a _n_o_w_e_b file for
+ identifier definitions, printing the identifiers on standard output,
+ one per line. If the --aauuttoo _l_a_n_g option is given, _n_o_d_e_f_s tries to disâ€
+ cover definitions automatically, assuming the program is written in
+ language _l_a_n_g. The --sshhoowwaauuttoo option displays permissible values of
+ _l_a_n_g, which vary but may include tteexx or iiccoonn.
+
+ For a complete description of using _n_o_d_e_f_s together with _n_o_w_e_a_v_e(1) and
+ _n_o_i_n_d_e_x(1), see the man page for _n_o_i_n_d_e_x(1).
+
+SSEEEE AALLSSOO
+ _n_o_w_e_a_v_e(1), _n_o_w_e_b(1), _n_o_i_n_d_e_x(1)
+
+VVEERRSSIIOONN
+ This man page is from _n_o_w_e_b version 2.12.
+
+AAUUTTHHOORR
+ Norman Ramsey, Tufts University. Internet address NNoorrmmaann..RRaammâ€â€
+ sseeyy@@ttuuffttss..eedduu.
+ Noweb home page at hhttttpp::////wwwwww..ccss..ttuuffttss..eedduu//~~nnrr//nnoowweebb.
+
+
+
+
+ local 10/40/2008 NOWEB(1)
diff --git a/web/noweb/src/xdoc/noindex.1 b/web/noweb/src/xdoc/noindex.1
new file mode 100644
index 0000000000..7e7dbb5a16
--- /dev/null
+++ b/web/noweb/src/xdoc/noindex.1
@@ -0,0 +1,171 @@
+.TH NOWEB 1 "local 10/40/2008"
+.SH NAME
+noindex \- build external index for noweb document
+.SH SYNOPSIS
+.B noindex \fIbasename\fP\fR[\fP.tex\fR]
+.SH DESCRIPTION
+.I noindex
+looks through
+.I LaTeX
+.B .aux
+files for identifiers that should go in a
+.I noweb
+external index.
+It sorts all identifiers and writes the results on
+.I basename\fB.nwi\fP.
+.SH NOWEB INDEXING STRATEGIES
+A
+.I noweb
+program consists of one or more files.
+In the simple case, these files are run through
+.I noweave
+together, to produce a single
+.I LaTeX
+file.
+.I "noweave \-index"
+suffices to produce an index and cross-referencing information;
+neither
+.I nodefs
+nor
+.I noindex
+is required.
+.PP
+When a
+.I noweb
+program
+consists of several source files, it is often better to run each source file
+through
+.I noweave
+to produce its own
+.I LaTeX
+file, then use
+.I noindex
+to produce an external index.
+This technique has several advantages:
+.IP
+The line numbers in the
+.I LaTeX
+files correspond to the line numbers in the source files, so it is easier
+to diagnose
+.I LaTeX
+errors.
+.IP
+The
+.I LaTeX
+.B "\\\\includeonly"
+feature can be used, making it possible to format parts of large programs while retaining
+complete cross-reference information.
+.IP
+When used with
+.IR make (1),
+the technique
+avoids running
+.I noweave
+over source files that have not changed.
+.IP
+Using the external index places fewer demands on \fILaTeX\fP's memory,
+making it read its
+.B .aux
+files much more quickly.
+.PP
+The disadvantages are that
+.I nodefs
+and
+.I noindex
+are needed for full cross-referencing and a properly sorted index.
+.SH EXAMPLE
+This example assumes a
+.I noweb
+program of three source files:
+.B a.nw ,
+.B b.nw ,
+and
+.BR c.nw .
+The file
+.B doc.tex
+is assumed to contain
+.I LaTeX
+boilerplate, including the commands
+.IP
+\\noweboptions{externalindex}
+.nf
+\\include{a}
+\\include{b}
+\\include{c}
+.fi
+.PP
+The first sequence of steps is to create a file listing all the
+identifiers defined anywhere in
+.BR a ,
+.BR b ,
+or
+.BR c .
+.IP
+nodefs a.nw > a.defs
+.nf
+nodefs b.nw > b.defs
+nodefs c.nw > c.defs
+sort \-u a.defs b.defs c.defs | cpif all.defs
+.fi
+.PP
+Using
+.I "sort \-u"
+and
+.IR cpif (1)
+avoids changing
+.B all.defs
+unless the set of identifiers changes.
+This technique, used in a Makefile, avoids unnecessary rebuilding.
+.PP
+The next series of steps is to create
+.I LaTeX
+files with full cross-reference information for all identifiers.
+.IP
+noweave \-n \-indexfrom all.defs a.nw > a.tex
+.nf
+noweave \-n \-indexfrom all.defs b.nw > b.tex
+noweave \-n \-indexfrom all.defs c.nw > c.tex
+.fi
+.PP
+The final steps run
+.I LaTeX
+once to create
+.B .aux
+files, then
+.I noindex
+to create the index,
+then
+.I LaTeX
+again to format the complete document.
+.IP
+latex doc
+.nf
+noindex doc
+latex doc
+.fi
+.PP
+In a Makefile,
+.I noindex
+can be run before every invocation of
+.I LaTeX.
+.SH BUGS
+.I noindex
+is distributed in awk and Icon versions.
+The awk version is slow and does a poorer job sorting.
+.PP
+There is no comparable machinery to make it possible to use multiple files
+with the HTML back end.
+.SH SEE ALSO
+.IR noweave (1),
+.IR nodefs (1),
+.IR cpif (1)
+.SH VERSION
+This man page is from
+.I noweb
+version 2.12.
+.SH AUTHOR
+Norman Ramsey, Tufts University.
+Internet address \fBNorman.Ramsey@tufts.edu\fP.
+.br
+Noweb home page at \fBhttp://www.cs.tufts.edu/~nr/noweb\fP.
+
diff --git a/web/noweb/src/xdoc/noindex.nw b/web/noweb/src/xdoc/noindex.nw
new file mode 100644
index 0000000000..e51b77cab2
--- /dev/null
+++ b/web/noweb/src/xdoc/noindex.nw
@@ -0,0 +1,163 @@
+<<*>>=
+.TH NOWEB 1 "local <<noweb documentation date>>"
+.SH NAME
+noindex \- build external index for noweb document
+.SH SYNOPSIS
+.B noindex \fIbasename\fP\fR[\fP.tex\fR]
+.SH DESCRIPTION
+.I noindex
+looks through
+.I LaTeX
+.B .aux
+files for identifiers that should go in a
+.I noweb
+external index.
+It sorts all identifiers and writes the results on
+.I basename\fB.nwi\fP.
+.SH NOWEB INDEXING STRATEGIES
+A
+.I noweb
+program consists of one or more files.
+In the simple case, these files are run through
+.I noweave
+together, to produce a single
+.I LaTeX
+file.
+.I "noweave \-index"
+suffices to produce an index and cross-referencing information;
+neither
+.I nodefs
+nor
+.I noindex
+is required.
+.PP
+When a
+.I noweb
+program
+consists of several source files, it is often better to run each source file
+through
+.I noweave
+to produce its own
+.I LaTeX
+file, then use
+.I noindex
+to produce an external index.
+This technique has several advantages:
+.IP
+The line numbers in the
+.I LaTeX
+files correspond to the line numbers in the source files, so it is easier
+to diagnose
+.I LaTeX
+errors.
+.IP
+The
+.I LaTeX
+.B "\\\\includeonly"
+feature can be used, making it possible to format parts of large programs while retaining
+complete cross-reference information.
+.IP
+When used with
+.IR make (1),
+the technique
+avoids running
+.I noweave
+over source files that have not changed.
+.IP
+Using the external index places fewer demands on \fILaTeX\fP's memory,
+making it read its
+.B .aux
+files much more quickly.
+.PP
+The disadvantages are that
+.I nodefs
+and
+.I noindex
+are needed for full cross-referencing and a properly sorted index.
+.SH EXAMPLE
+This example assumes a
+.I noweb
+program of three source files:
+.B a.nw ,
+.B b.nw ,
+and
+.BR c.nw .
+The file
+.B doc.tex
+is assumed to contain
+.I LaTeX
+boilerplate, including the commands
+.IP
+\\noweboptions{externalindex}
+.nf
+\\include{a}
+\\include{b}
+\\include{c}
+.fi
+.PP
+The first sequence of steps is to create a file listing all the
+identifiers defined anywhere in
+.BR a ,
+.BR b ,
+or
+.BR c .
+.IP
+nodefs a.nw > a.defs
+.nf
+nodefs b.nw > b.defs
+nodefs c.nw > c.defs
+sort \-u a.defs b.defs c.defs | cpif all.defs
+.fi
+.PP
+Using
+.I "sort \-u"
+and
+.IR cpif (1)
+avoids changing
+.B all.defs
+unless the set of identifiers changes.
+This technique, used in a Makefile, avoids unnecessary rebuilding.
+.PP
+The next series of steps is to create
+.I LaTeX
+files with full cross-reference information for all identifiers.
+.IP
+noweave \-n \-indexfrom all.defs a.nw > a.tex
+.nf
+noweave \-n \-indexfrom all.defs b.nw > b.tex
+noweave \-n \-indexfrom all.defs c.nw > c.tex
+.fi
+.PP
+The final steps run
+.I LaTeX
+once to create
+.B .aux
+files, then
+.I noindex
+to create the index,
+then
+.I LaTeX
+again to format the complete document.
+.IP
+latex doc
+.nf
+noindex doc
+latex doc
+.fi
+.PP
+In a Makefile,
+.I noindex
+can be run before every invocation of
+.I LaTeX.
+.SH BUGS
+.I noindex
+is distributed in awk and Icon versions.
+The awk version is slow and does a poorer job sorting.
+.PP
+There is no comparable machinery to make it possible to use multiple files
+with the HTML back end.
+.SH SEE ALSO
+.IR noweave (1),
+.IR nodefs (1),
+.IR cpif (1)
+<<AUTHOR section>>
diff --git a/web/noweb/src/xdoc/noindex.txt b/web/noweb/src/xdoc/noindex.txt
new file mode 100644
index 0000000000..a3823e4489
--- /dev/null
+++ b/web/noweb/src/xdoc/noindex.txt
@@ -0,0 +1,103 @@
+NOWEB(1) General Commands Manual NOWEB(1)
+
+
+
+NNAAMMEE
+ noindex - build external index for noweb document
+
+SSYYNNOOPPSSIISS
+ nnooiinnddeexx _b_a_s_e_n_a_m_e[..tteexx]
+
+DDEESSCCRRIIPPTTIIOONN
+ _n_o_i_n_d_e_x looks through _L_a_T_e_X ..aauuxx files for identifiers that should go
+ in a _n_o_w_e_b external index. It sorts all identifiers and writes the
+ results on _b_a_s_e_n_a_m_e..nnwwii_.
+
+NNOOWWEEBB IINNDDEEXXIINNGG SSTTRRAATTEEGGIIEESS
+ A _n_o_w_e_b program consists of one or more files. In the simple case,
+ these files are run through _n_o_w_e_a_v_e together, to produce a single _L_a_T_e_X
+ file. _n_o_w_e_a_v_e _-_i_n_d_e_x suffices to produce an index and cross-referencâ€
+ ing information; neither _n_o_d_e_f_s nor _n_o_i_n_d_e_x is required.
+
+ When a _n_o_w_e_b program consists of several source files, it is often betâ€
+ ter to run each source file through _n_o_w_e_a_v_e to produce its own _L_a_T_e_X
+ file, then use _n_o_i_n_d_e_x to produce an external index. This technique
+ has several advantages:
+
+ The line numbers in the _L_a_T_e_X files correspond to the line numâ€
+ bers in the source files, so it is easier to diagnose _L_a_T_e_X
+ errors.
+
+ The _L_a_T_e_X \\iinncclluuddeeoonnllyy feature can be used, making it possible
+ to format parts of large programs while retaining complete
+ cross-reference information.
+
+ When used with _m_a_k_e(1), the technique avoids running _n_o_w_e_a_v_e
+ over source files that have not changed.
+
+ Using the external index places fewer demands on _L_a_T_e_X's memory,
+ making it read its ..aauuxx files much more quickly.
+
+ The disadvantages are that _n_o_d_e_f_s and _n_o_i_n_d_e_x are needed for full
+ cross-referencing and a properly sorted index.
+
+EEXXAAMMPPLLEE
+ This example assumes a _n_o_w_e_b program of three source files: aa..nnww ,, bb..nnww
+ ,, and cc..nnww. The file ddoocc..tteexx is assumed to contain _L_a_T_e_X boilerplate,
+ including the commands
+
+ \noweboptions{externalindex}
+ \include{a}
+ \include{b}
+ \include{c}
+
+ The first sequence of steps is to create a file listing all the identiâ€
+ fiers defined anywhere in aa, bb, or cc.
+
+ nodefs a.nw > a.defs
+ nodefs b.nw > b.defs
+ nodefs c.nw > c.defs
+ sort -u a.defs b.defs c.defs | cpif all.defs
+
+ Using _s_o_r_t _-_u and _c_p_i_f(1) avoids changing aallll..ddeeffss unless the set of
+ identifiers changes. This technique, used in a Makefile, avoids unnecâ€
+ essary rebuilding.
+
+ The next series of steps is to create _L_a_T_e_X files with full cross-refâ€
+ erence information for all identifiers.
+
+ noweave -n -indexfrom all.defs a.nw > a.tex
+ noweave -n -indexfrom all.defs b.nw > b.tex
+ noweave -n -indexfrom all.defs c.nw > c.tex
+
+ The final steps run _L_a_T_e_X once to create ..aauuxx files, then _n_o_i_n_d_e_x to
+ create the index, then _L_a_T_e_X again to format the complete document.
+
+ latex doc
+ noindex doc
+ latex doc
+
+ In a Makefile, _n_o_i_n_d_e_x can be run before every invocation of _L_a_T_e_X_.
+
+BBUUGGSS
+ _n_o_i_n_d_e_x is distributed in awk and Icon versions. The awk version is
+ slow and does a poorer job sorting.
+
+ There is no comparable machinery to make it possible to use multiple
+ files with the HTML back end.
+
+SSEEEE AALLSSOO
+ _n_o_w_e_a_v_e(1), _n_o_d_e_f_s(1), _c_p_i_f(1)
+
+VVEERRSSIIOONN
+ This man page is from _n_o_w_e_b version 2.12.
+
+AAUUTTHHOORR
+ Norman Ramsey, Tufts University. Internet address NNoorrmmaann..RRaammâ€â€
+ sseeyy@@ttuuffttss..eedduu.
+ Noweb home page at hhttttpp::////wwwwww..ccss..ttuuffttss..eedduu//~~nnrr//nnoowweebb.
+
+
+
+
+ local 10/40/2008 NOWEB(1)
diff --git a/web/noweb/src/xdoc/noroff.1 b/web/noweb/src/xdoc/noroff.1
new file mode 100644
index 0000000000..7d082f1f2e
--- /dev/null
+++ b/web/noweb/src/xdoc/noroff.1
@@ -0,0 +1,57 @@
+.TH NOWEB 1 "local 10/40/2008"
+.SH NAME
+noroff \- format woven \fItroff\fP documentation
+.SH SYNOPSIS
+.B noroff
+.RI [ " groff options " ]
+files ...
+.SH DESCRIPTION
+.I Noroff
+formats documents that have been woven with
+.IR "noweave \-troff" .
+It passes on any options (flags) to
+.IR groff (1),
+and treats any remaining non-option arguments as files to be processed.
+The
+.I groff
+options allow the easy invocation of the
+.IR gpic ,
+.IR gtbl ,
+and/or
+.IR geqn ,
+preprocessors.
+.PP
+If no options are supplied, it defaults to using the
+.B \-mm
+macros, with PostScript output.
+.SH BUGS
+The shell script is probably still not as robust as it needs to be.
+.SH SEE ALSO
+.IR groff (1),
+.IR noweave (1),
+.IR nodefs (1),
+.IR cpif (1)
+.br
+.I "Converting noweb markup to troff markup"
+in the file
+.B src/shell/roff.nw
+in the
+.I noweb
+distribution.
+.SH VERSION
+This man page is from
+.I noweb
+version 2.12.
+.SH AUTHOR
+Norman Ramsey, Tufts University.
+Internet address \fBNorman.Ramsey@tufts.edu\fP.
+.br
+Noweb home page at \fBhttp://www.cs.tufts.edu/~nr/noweb\fP.
+
+.PP
+.I Noroff
+was written by Phil Bewig for SoftQuad
+.IR troff ,
+and enhanced and ported to GNU
+.I troff
+by Arnold Robbins.
diff --git a/web/noweb/src/xdoc/noroff.nw b/web/noweb/src/xdoc/noroff.nw
new file mode 100644
index 0000000000..142fbb229b
--- /dev/null
+++ b/web/noweb/src/xdoc/noroff.nw
@@ -0,0 +1,49 @@
+<<*>>=
+.TH NOWEB 1 "local <<noweb documentation date>>"
+.SH NAME
+noroff \- format woven \fItroff\fP documentation
+.SH SYNOPSIS
+.B noroff
+.RI [ " groff options " ]
+files ...
+.SH DESCRIPTION
+.I Noroff
+formats documents that have been woven with
+.IR "noweave \-troff" .
+It passes on any options (flags) to
+.IR groff (1),
+and treats any remaining non-option arguments as files to be processed.
+The
+.I groff
+options allow the easy invocation of the
+.IR gpic ,
+.IR gtbl ,
+and/or
+.IR geqn ,
+preprocessors.
+.PP
+If no options are supplied, it defaults to using the
+.B \-mm
+macros, with PostScript output.
+.SH BUGS
+The shell script is probably still not as robust as it needs to be.
+.SH SEE ALSO
+.IR groff (1),
+.IR noweave (1),
+.IR nodefs (1),
+.IR cpif (1)
+.br
+.I "Converting noweb markup to troff markup"
+in the file
+.B src/shell/roff.nw
+in the
+.I noweb
+distribution.
+<<AUTHOR section>>
+.PP
+.I Noroff
+was written by Phil Bewig for SoftQuad
+.IR troff ,
+and enhanced and ported to GNU
+.I troff
+by Arnold Robbins.
diff --git a/web/noweb/src/xdoc/noroff.txt b/web/noweb/src/xdoc/noroff.txt
new file mode 100644
index 0000000000..6693710890
--- /dev/null
+++ b/web/noweb/src/xdoc/noroff.txt
@@ -0,0 +1,42 @@
+NOWEB(1) General Commands Manual NOWEB(1)
+
+
+
+NNAAMMEE
+ noroff - format woven _t_r_o_f_f documentation
+
+SSYYNNOOPPSSIISS
+ nnoorrooffff [ _g_r_o_f_f _o_p_t_i_o_n_s ] files ...
+
+DDEESSCCRRIIPPTTIIOONN
+ _N_o_r_o_f_f formats documents that have been woven with _n_o_w_e_a_v_e _-_t_r_o_f_f. It
+ passes on any options (flags) to _g_r_o_f_f(1), and treats any remaining
+ non-option arguments as files to be processed. The _g_r_o_f_f options allow
+ the easy invocation of the _g_p_i_c, _g_t_b_l, and/or _g_e_q_n, preprocessors.
+
+ If no options are supplied, it defaults to using the --mmmm macros, with
+ PostScript output.
+
+BBUUGGSS
+ The shell script is probably still not as robust as it needs to be.
+
+SSEEEE AALLSSOO
+ _g_r_o_f_f(1), _n_o_w_e_a_v_e(1), _n_o_d_e_f_s(1), _c_p_i_f(1)
+ _C_o_n_v_e_r_t_i_n_g _n_o_w_e_b _m_a_r_k_u_p _t_o _t_r_o_f_f _m_a_r_k_u_p in the file ssrrcc//sshheellll//rrooffff..nnww
+ in the _n_o_w_e_b distribution.
+
+VVEERRSSIIOONN
+ This man page is from _n_o_w_e_b version 2.12.
+
+AAUUTTHHOORR
+ Norman Ramsey, Tufts University. Internet address NNoorrmmaann..RRaammâ€â€
+ sseeyy@@ttuuffttss..eedduu.
+ Noweb home page at hhttttpp::////wwwwww..ccss..ttuuffttss..eedduu//~~nnrr//nnoowweebb.
+
+
+ _N_o_r_o_f_f was written by Phil Bewig for SoftQuad _t_r_o_f_f, and enhanced and
+ ported to GNU _t_r_o_f_f by Arnold Robbins.
+
+
+
+ local 10/40/2008 NOWEB(1)
diff --git a/web/noweb/src/xdoc/noroots.1 b/web/noweb/src/xdoc/noroots.1
new file mode 100644
index 0000000000..f08c3d127d
--- /dev/null
+++ b/web/noweb/src/xdoc/noroots.1
@@ -0,0 +1,30 @@
+.TH NOWEB 1 "local 10/40/2008"
+.SH NAME
+noroots \- print roots of a noweb file
+.SH SYNOPSIS
+.B noroots
+[file] ...
+.SH DESCRIPTION
+.I noroots
+finds the roots of a
+.I noweb
+file: it prints the names of all code chunks that are defined but not used.
+See
+.IR noweb (1)
+for an explanation of
+the format of
+.I noweb
+files.
+.SH SEE ALSO
+.IR noweb (1),
+.IR notangle (1)
+.SH VERSION
+This man page is from
+.I noweb
+version 2.12.
+.SH AUTHOR
+Norman Ramsey, Tufts University.
+Internet address \fBNorman.Ramsey@tufts.edu\fP.
+.br
+Noweb home page at \fBhttp://www.cs.tufts.edu/~nr/noweb\fP.
+
diff --git a/web/noweb/src/xdoc/noroots.nw b/web/noweb/src/xdoc/noroots.nw
new file mode 100644
index 0000000000..1db4b3264c
--- /dev/null
+++ b/web/noweb/src/xdoc/noroots.nw
@@ -0,0 +1,22 @@
+<<*>>=
+.TH NOWEB 1 "local <<noweb documentation date>>"
+.SH NAME
+noroots \- print roots of a noweb file
+.SH SYNOPSIS
+.B noroots
+[file] ...
+.SH DESCRIPTION
+.I noroots
+finds the roots of a
+.I noweb
+file: it prints the names of all code chunks that are defined but not used.
+See
+.IR noweb (1)
+for an explanation of
+the format of
+.I noweb
+files.
+.SH SEE ALSO
+.IR noweb (1),
+.IR notangle (1)
+<<AUTHOR section>>
diff --git a/web/noweb/src/xdoc/noroots.txt b/web/noweb/src/xdoc/noroots.txt
new file mode 100644
index 0000000000..91cace55a4
--- /dev/null
+++ b/web/noweb/src/xdoc/noroots.txt
@@ -0,0 +1,30 @@
+NOWEB(1) General Commands Manual NOWEB(1)
+
+
+
+NNAAMMEE
+ noroots - print roots of a noweb file
+
+SSYYNNOOPPSSIISS
+ nnoorroooottss [file] ...
+
+DDEESSCCRRIIPPTTIIOONN
+ _n_o_r_o_o_t_s finds the roots of a _n_o_w_e_b file: it prints the names of all
+ code chunks that are defined but not used. See _n_o_w_e_b(1) for an explaâ€
+ nation of the format of _n_o_w_e_b files.
+
+SSEEEE AALLSSOO
+ _n_o_w_e_b(1), _n_o_t_a_n_g_l_e(1)
+
+VVEERRSSIIOONN
+ This man page is from _n_o_w_e_b version 2.12.
+
+AAUUTTHHOORR
+ Norman Ramsey, Tufts University. Internet address NNoorrmmaann..RRaammâ€â€
+ sseeyy@@ttuuffttss..eedduu.
+ Noweb home page at hhttttpp::////wwwwww..ccss..ttuuffttss..eedduu//~~nnrr//nnoowweebb.
+
+
+
+
+ local 10/40/2008 NOWEB(1)
diff --git a/web/noweb/src/xdoc/notangle.1 b/web/noweb/src/xdoc/notangle.1
new file mode 100644
index 0000000000..870d63e8e7
--- /dev/null
+++ b/web/noweb/src/xdoc/notangle.1
@@ -0,0 +1,641 @@
+.TH NOWEB 1 "local 10/40/2008"
+.SH NAME
+notangle, noweave, nountangle \- noweb, a literate-programming tool
+.SH SYNOPSIS
+.B notangle
+[\fB\-R\fProotname ...] [\fB\-filter\fP command]
+[\fB\-L\fP[format]] [file] ...
+.br
+\fBnountangle\fP
+[\fB\-ml\fP|\fB\-m3\fP|\fB\-c\fP|\fB\-c++\fP|\fB\-awk\fP|\fB\-tex\fP|\fB\-f77\fP|\fB\-f90\fP|\fB\-lisp\fP|\fB\-matlab\fP]
+[\fB\-R\fProotname ...] [\fB\-filter\fP command] [\fB\-w\fPwidth] [file] ...
+.br
+\fBnoweave\fP [options] [file] ...
+.SH DESCRIPTION
+.I Noweb
+is a literate-programming tool like Knuth's
+.I WEB,
+only simpler.
+A
+.I noweb
+file contains program source code interleaved with documentation.
+When
+.I notangle
+is given a
+.I noweb
+file, it writes the program on standard output.
+When
+.I noweave
+is given a
+.I noweb
+file, it reads the
+.I noweb
+source and produces, on standard output, \fILaTeX\fP, \fITeX\fP, \fItroff\fP,
+or \fIHTML\fP
+source for typeset documentation.
+.I nountangle
+converts a literate program into an ordinary program by
+turning interleaved documentation into comments.
+The file name `\-' refers to standard input.
+.SH FORMAT OF NOWEB FILES
+A
+.I noweb
+file is a sequence of
+.IR chunks ,
+which may appear in any order.
+A chunk may contain code or documentation.
+Documentation chunks begin with a line that starts with an at sign (@)
+followed by a space or newline.
+They have no names.
+Code chunks begin with
+.br
+<<\fIchunk name\fP>>=
+.br
+on a line by itself.
+The double left angle bracket (<<) must be in the first column.
+Chunks are terminated by the beginning of another chunk, or by end of file.
+If the first line in the file does not mark the beginning of a
+chunk, it is assumed to be the first line of a documentation chunk.
+.PP
+Documentation chunks contain text that is ignored by
+.I notangle
+and copied verbatim to
+standard output
+by
+.I noweave
+(except for quoted code).
+.I noweave
+can work with \fILaTeX\fP, plain \fITeX\fP, \fItroff\fP or \fIHTML\fP.
+With plain \fITeX\fP, it inserts a reference to a
+.I TeX
+macro package, \fInwmac\fP, which defines commands like
+.B \echapter
+and
+.B \esection.
+.PP
+Code chunks contain program source code and references to other code
+chunks.
+Several code chunks may have the same name;
+.I notangle
+concatenates their definitions to produce a single chunk, just as does
+.IR tangle (1).
+Code chunk definitions are like macro definitions;
+.I notangle
+extracts a program by expanding one chunk (by default, the chunk named
+\fB<<\fP*\fB>>\fP).
+The definition of that chunk contains references to other chunks, which are
+themselves expanded, and so on.
+\fInotangle\fP's output is readable; it preserves the indentation of expanded
+chunks with respect to the chunks in which they appear.
+.PP
+Code may be quoted within documentation
+chunks by placing double square brackets
+(\fB[[\fI...\fB]]\fR) around it.
+These double square brackets are ignored by
+.I notangle,
+but they may be used by
+.I noweave
+to give the code special typographic treatment, e.g., hypertext links.
+If quoted code ends with three or more square brackets,
+.I noweave
+chooses the rightmost pair, so that, for example, \fB[[a[i]]]\fR is
+parsed correctly.
+The names of
+code chunks may appear within quoted code unless that quoted code is itself
+part of the name of a code chunk.
+.PP
+In code, noweb treats unpaired
+double left or right angle brackets as literal \fB<<\fP and \fB>>\fP.
+To force any
+such brackets, even paired brackets or brackets in documentation,
+to be treated as literal, use a preceding at sign (e.g. \fB@<<\fP).
+.PP
+Some programming or formatting languages may require a single \fB@\fP sign in
+the first column.
+Noweb users may achieve this effect by putting a doubled \fB@@\fP in the first column;
+in this position only, it stands for a single \fB@\fP sign.
+.SH TANGLING
+.I notangle
+and
+.I nountangle
+accept the same set of options, although some options have effects only on one
+or the other.
+The options are:
+.TP
+.B \-R\fIname\fR
+Expand the \fB<<\fIname\fB>>\fR code chunk.
+The
+.B \-R
+option can be repeated,
+in which case each chunk is written to the output.
+If no
+.B \-R
+option is given, expand the chunk named \fB<<\fP*\fB>>\fP.
+.TP
+.B \-L\fIformat\fR
+Emit line number indications at chunk boundaries.
+A line number indication identifies the source of the line that follows it.
+In
+.IR format ,
+.B "%F"
+indicates the name of the source file,
+.B "%L"
+indicates the line number of the source file,
+.B "%N"
+indicates a newline,
+and
+.B "%%"
+indicates a percent sign.
+A sign and digit may be inserted between the percent sign and the `\fBL\fP',
+in which case the line number will be adjusted by that amount.
+If
+.I format
+is omitted, the default format is that accepted by the C preprocessor:
+`\fB#line %L "%F"%N\fR'.
+When using the \fB\-L\fIformat\fR option,
+.I notangle
+ensures that all text appears in the same column in input and output.
+.I nountangle
+ignores this option.
+.IP " "
+Common format strings include:
+.ta \w'zzzSunyFORTRANxxxx'u
+.nf
+ C \fB\-L'#line %L "%F"%N'\fP
+ Sun FORTRAN \fB\-L'\\# %L "%F"%N'\fP
+ Icon \fB\-L'#line %\-1L "%F"%N'\fP
+ Modula-3 \fB\-L'<*LINE %L "%F" *>%N'\fP
+ SML/NJ \fB\-L'(*#line %L "%F"*)'\fP
+.fi
+.IP " "
+To solve the converse problem, that is, to get noweb to do something sensible
+with \fB#line\fP in its input, see the \fBsharpline\fP filter in the examples
+directory.
+.TP
+.B \-t\fIk\fP
+Copy tabs untouched from input to output, and use tabs for indentation,
+assuming stops every \fIk\fP columns.
+By default, tabs are expanded to spaces with stops every 8 columns.
+.TP
+.B \-filter \fIcmd\fP
+Filter the
+.I noweb
+source through
+.I cmd
+after converting it to tool form and before tangling.
+.I notangle
+looks for
+.I cmd
+first on the user's
+.BR PATH ,
+then in
+.BR |LIBDIR| .
+Such filters
+can be used to add features to
+.IR notangle ;
+for an example see
+.BR |LIBDIR|/emptydefn .
+For experts only.
+.TP
+.B "\-markup \fIparser\fP"
+Use
+.I parser
+to parse the input file.
+Enables use of noweb tools on files in other formats;
+for example, the
+.B numarkup
+parser understands
+.IR nuweb (1)
+format.
+See
+.IR nowebfilters (7)
+for more information.
+For experts only.
+.TP
+.B "\-awk | \-c | \-icn | \-icon | \-ml | \-m3 | \-pascal | \-f77 | \-f90 | \-tex"
+When
+.I nountangle
+transforms documentation chunks into comments, use the comment format of the language
+named.
+.B \-c
+is the default.
+.I notangle
+ignores these options.
+.TP
+.B \-w\fIn\fP
+When
+.I nountangle
+transforms documentation chunks into comments, create comments on lines of width \fIn\fP.
+.I notangle
+ignores this option.
+.SH WEAVING
+Output from \fInoweave\fP can
+be used in \fITeX\fP documents that
+.B "\\\\input nwmac,"
+in \fILaTeX\fP documents that use the
+.B noweb
+package (see \fInowebstyle(1)\fP),
+and in \fIHTML\fP documents to be browsed with
+.I Mosaic(1).
+.I Noweave
+treats code chunks somewhat like
+.I LaTeX list environments.
+If the ``\fB@ \fP'' that terminates a code chunk is followed immediately by text,
+that text follows the code chunk without a paragraph break.
+If the rest of the line is blank,
+.I noweave
+puts
+.I TeX
+into ``vertical mode,'' and later text starts a fresh, indented paragraph.
+.PP
+No page breaks occur in the middle of code chunks unless necessary to avoid
+an overfull vbox.
+The documentation chunk immediately preceding a code chunk appears on
+the same page as that code chunk unless doing so would violate the previous rule.
+.PP
+.I Noweave
+inserts no extra newlines in its \fITeX\fP output, so the line numbers given
+in
+.I TeX
+error messages are the same as those in the input file.
+.PP
+.I noweave
+has
+options that dictate choice of
+formatter
+and that support different formatting idioms and tools.
+Basic options are described here; options related to index
+and cross-reference information are described in the
+INDEXING AND CROSS-REFERENCE section.
+.TP
+.B \-latex
+Emit LaTeX, including wrapper in
+.B article
+style with the
+.B noweb
+package and page style. (Default)
+.TP
+.B \-tex
+Emit plain TeX, including wrapper with
+.B nwmac
+macros.
+.TP
+.B \-html
+Emit HTML, using HTML wrapper.
+The output is uninteresting without \fB-index\fP or \fB-x\fP.
+The tags \fB<nowebchunks>\fP and \fB<nowebindex>\fP, on lines by themselves,
+produce a list of chunks and an index of identifiers, respectively.
+If these tags are not present, the list and index are placed at the end of the file.
+.TP
+.B \-latex+html
+Assume documentation chunks are LaTeX, but generate HTML for code chunks,
+suitably marked so conversion with
+.I latex2html(1)
+yields reasonable output.
+A LaTeX wrapper is implied, but can be turned off with \fB-n\fP.
+.I Use of this option is
+.B deprecated;
+use
+.B \-html
+with
+.B "\-filter l2h"
+instead.
+.TP
+.B \-troff
+Emit
+.IR troff (1)
+markup (with no wrapper).
+The result should be processed with
+.IR noroff (1).
+Bug reports for
+.B \-troff
+to Arnold Robbins
+.B <arnold@skeeve.com>.
+.TP
+.B \-n
+Don't use any wrapper (header or trailer).
+This option is useful when \fInoweave\fP's output will be
+a part of a larger document.
+See also
+.B \-delay.
+.TP
+.B \-filter \fIcmd\fP
+Filters the
+.I noweb
+source through
+.I cmd
+after converting it to tool form and before converting to
+.I TeX.
+.I noweave
+looks for
+.I cmd
+first on the user's
+.B PATH,
+then in
+.B |LIBDIR|.
+Such filters
+can be used to add features to
+.I noweave;
+for an example, see
+.B |LIBDIR|/noxref.krom.
+.I Noweave
+supports up to four filters; one can get more by shell trickery,
+for example, \fB-filter "icon.filter | noidx"\fP.
+The \fB-autodefs\fP,
+\fB-x\fP, \fB-index\fP, and \fB-indexfrom\fP options are implemented as filters.
+Filters are executed with the shell's
+.B eval
+command, so
+.I cmd
+should be quoted accordingly.
+.TP
+.B "\-markup \fIparser\fP"
+Use
+.I parser
+to parse the input file.
+Enables use of noweb tools on files in other formats;
+for example, the
+.B numarkup
+parser understands
+.IR nuweb (1)
+format.
+See
+.IR nowebfilters (7)
+for more information.
+For experts only.
+.TP
+.B \-option \fIopt\fP
+Adds \fB\enoweboptions{\fP\fIopt\fP\fB}\fP to the
+.I LaTeX
+header.
+See
+.I nowebstyle(1)
+for values of
+.I opt.
+Normally useful only with the
+.B \-latex
+option, but
+.B "\-option longxref"
+works black magic with
+.B \-html.
+.TP
+.B \-delay
+By default,
+.I noweave
+puts file-name and other information into the output before the first chunk
+of the program.
+.B \-delay
+delays that information until after the first documentation chunk, making
+act a little bit like the
+.I WEB
+``limbo.''
+The option is typically used to enable a user to put a specialized
+.I LaTeX
+.B "\\\\documentclass"
+command and other preamble material in the first documentation chunk (i.e.,
+.I before
+the first @ sign).
+This option also forces trailing cross-referencing information to be emitted
+just before the final chunk, instead of at the end of the document;
+the final chunk is expected to contain
+.B "\\\\end{document}."
+The
+.B \-delay
+option implies the
+.B \-n
+option.
+.TP
+.B \-t\fIk\fP
+Expand tabs with stops every \fIk\fP columns.
+(Default is to expand every 8 columns.)
+.TP
+.B \-t
+Copy tabs to the output.
+.TP
+.B \-v
+Print the pipeline and RCS info on standard error.
+.SH INDEXING AND CROSS-REFERENCE
+
+When used with
+.IR LaTeX ,
+.IR troff ,
+or
+.I HTML,
+.I noweave
+can provide indexing and cross-reference information for chunks and for
+programming-language identifiers.
+Identifier definitions may be marked by hand using backticks (`); the
+\fB-filter btdefn\fP option recognizes these markings.
+For some languages, definitions may be found automatically using the
+\fB-autodefs\fP option.
+This section describes the indexing and cross-reference options;
+it might well be skipped on first reading.
+.TP
+.B \-x
+For
+.I LaTeX,
+add a page number to each chunk name identifying the location of that
+chunk's definition, and emit cross-reference information relating definitions and uses.
+For
+.I HTML,
+create hypertext links between uses and definitions of chunks.
+When
+.B noweave -x
+is used with
+.I LaTeX,
+the control sequence
+.B "\\\\nowebchunks"
+expands to a sorted list of all code chunks.
+.TP
+.B \-index
+Build cross-reference information (or hypertext links) for defined identifiers.
+Definitions are those found in the input files by
+.B \-autodefs
+.I language
+or by
+.BR \-filter btdefn.
+Requires
+.I LaTeX
+or
+.I HTML.
+.B \-index
+implies
+.B \-x;
+including both will generate strange-looking output.
+.I noweave
+does not generate
+cross-references to identifiers that appear in quoted code (\fB@[[\fP...\fB@]]\fP),
+but it does generate hypertext links.
+When
+.B noweave -index
+is used with
+.I LaTeX,
+the control sequence
+.B "\\\\nowebindex"
+expands to an index of identifiers.
+.TP
+.B \-indexfrom \fIindex\fP
+Like
+.B \-index,
+but the identifiers to be indexed are taken from file \fIindex\fP.
+See
+.I noindex(1).
+.TP
+.B \-autodefs \fIlang\fP
+Discover identifier definitions automatically.
+Code in chunks must be in language \fIlang\fP.
+Permissible \fIlang\fPs vary but may include
+.B tex
+or
+.B icon.
+Useless without
+.B \-index,
+which it must precede.
+.TP
+.B \-showautodefs
+Show values of \fIlang\fP usable with \fB-autodefs\fP.
+.SH ERROR MESSAGES
+If
+.I notangle
+or
+.I noweave
+encounters a chunk name within documentation, it assumes that this
+indicates an error, usually misspelling ``<<name>>=''.
+Other error messages should be self-explanatory.
+.PP
+It is incorrect to refer to a chunk that is never
+defined, but it is OK for chunks to be defined and not used.
+.SH EXAMPLES
+If you have trouble digesting this man page, you're not alone.
+Here are a few examples to get you started.
+I'll assume you have a
+.B foo.nw
+file with a C program in chunk
+.B <<foo.c>>
+and a header file in chunk
+.BR <<foo.h>> ,
+and that your documentation is marked up using
+.IR latex(1) .
+I'll show you how to build things using the most common options.
+.PP
+To rebuild your C source, try
+.RS
+.B "notangle \-L \-Rfoo.c foo.nw > foo.c"
+.RE
+To rebuild your header file, try
+.RS
+.B "notangle \-Rfoo.h foo.nw | cpif foo.h"
+.RE
+There are two compromises here.
+Omitting \fB\-L\fP keeps \fB#line\fP out of your header file,
+and using \fBcpif\fP prevents the command from rewriting
+.B foo.h
+unless the contents have changed. Thus, this is good code to put in a Makefile rule.
+.PP
+To build a printed document, run
+.RS
+.B "noweave \-autodefs c \-index foo.nw > foo.tex"
+.RE
+If you have your own preamble, containing \fB\\documentclass\fP and all,
+you will also need the \fB\-delay\fP option.
+.PP
+To build a web page, run
+.RS
+.B "noweave \-filter l2h \-autodefs c \-index \-html foo.nw | htmltoc > foo.html"
+.RE
+Have fun!
+.SH FILES
+.PP
+.ta \w'|TEXINPUTS|nwkernel.texxxxx'u
+.nf
+|LIBDIR|/markup markup preprocessor
+|LIBDIR|/unmarkup inverts markup
+|LIBDIR|/nt notangle proper
+|LIBDIR|/finduses find uses of identifiers for index
+|LIBDIR|/noidx generate index and cross-reference info
+|LIBDIR|/toroff back end to emit \fItroff\fP
+|LIBDIR|/totex back end to emit \fITeX\fP or \fILaTeX\fP
+|LIBDIR|/tohtml back end to emit HTML
+|TEXINPUTS|/nwmac.tex formatting \fITeX\fP macros
+|TEXINPUTS|/noweb.sty use in \fILaTeX\fP documents; see \fInowebstyle(7)\fP
+.fi
+.SH SEE ALSO
+.PP
+.IR cpif (1),
+.IR nodefs (1),
+.IR noroots (1),
+.IR noweb (1),
+.IR noindex (1),
+.IR noroff (1),
+.IR nowebstyle (7),
+.IR nowebfilters (7)
+.SH BUGS
+.I notangle
+and
+.I nountangle
+fail if names used on the command line contain single quotes.
+.PP
+Ignoring unused chunks can cause problems;
+if a chunk has
+multiple definitions and one is misspelled,
+the misspelled definition is silently ignored.
+.IR noroots (1)
+can be used to catch this mistake.
+\".PP
+\".I noweb
+\"requires the new version of
+\".IR awk ,
+\"assumed to be called
+\".IR nawk .
+\"DEC
+\".I nawk
+\"has a bug in that that causes
+\".B noweave
+\"to fail to translate braces correctly.
+\"GNU
+\".I gawk
+\"is reported to work.
+\".PP
+\"DEC
+\".I sh
+\"has a bug that causes the
+\".B \-filter
+\"option to fail whenever the filter command contains more than one word.
+.PP
+The
+.I "-L"
+option of
+.I notangle
+puts an implicit initial newline in the format string.
+.PP
+The default
+.I LaTeX
+pagestyles don't set the width of the boxes containing headers and footers.
+Since
+.I noweb
+code paragraphs are extra wide, this
+.I LaTeX
+bug sometimes results in extra-wide headers and footers.
+The remedy is to redefine the relevant
+.B ps@*
+commands;
+.B ps@noweb
+in
+.B noweb.sty
+can be used as an example.
+.PP
+.IR latex2html (1)
+mangles some source files.
+.PP
+.I noweave
+has too many options, and this man page is too long.
+.SH VERSION
+This man page is from
+.I noweb
+version 2.12.
+.SH AUTHOR
+Norman Ramsey, Tufts University.
+Internet address \fBNorman.Ramsey@tufts.edu\fP.
+.br
+Noweb home page at \fBhttp://www.cs.tufts.edu/~nr/noweb\fP.
+
diff --git a/web/noweb/src/xdoc/notangle.txt b/web/noweb/src/xdoc/notangle.txt
new file mode 100644
index 0000000000..a8496e9a0c
--- /dev/null
+++ b/web/noweb/src/xdoc/notangle.txt
@@ -0,0 +1,361 @@
+NOWEB(1) General Commands Manual NOWEB(1)
+
+
+
+NNAAMMEE
+ notangle, noweave, nountangle - noweb, a literate-programming tool
+
+SSYYNNOOPPSSIISS
+ nnoottaannggllee [--RRrootname ...] [--ffiilltteerr command] [--LL[format]] [file] ...
+ nnoouunnttaannggllee [--mmll|--mm33|--cc|--cc++++|--aawwkk|--tteexx|--ff7777|--ff9900|--lliisspp|--mmaattllaabb] [--RRrootâ€
+ name ...] [--ffiilltteerr command] [--wwwidth] [file] ...
+ nnoowweeaavvee [options] [file] ...
+
+DDEESSCCRRIIPPTTIIOONN
+ _N_o_w_e_b is a literate-programming tool like Knuth's _W_E_B_, only simpler. A
+ _n_o_w_e_b file contains program source code interleaved with documentation.
+ When _n_o_t_a_n_g_l_e is given a _n_o_w_e_b file, it writes the program on standard
+ output. When _n_o_w_e_a_v_e is given a _n_o_w_e_b file, it reads the _n_o_w_e_b source
+ and produces, on standard output, _L_a_T_e_X, _T_e_X, _t_r_o_f_f, or _H_T_M_L source for
+ typeset documentation. _n_o_u_n_t_a_n_g_l_e converts a literate program into an
+ ordinary program by turning interleaved documentation into comments.
+ The file name `-' refers to standard input.
+
+FFOORRMMAATT OOFF NNOOWWEEBB FFIILLEESS
+ A _n_o_w_e_b file is a sequence of _c_h_u_n_k_s, which may appear in any order. A
+ chunk may contain code or documentation. Documentation chunks begin
+ with a line that starts with an at sign (@) followed by a space or newâ€
+ line. They have no names. Code chunks begin with
+ <<_c_h_u_n_k _n_a_m_e>>=
+ on a line by itself. The double left angle bracket (<<) must be in the
+ first column. Chunks are terminated by the beginning of another chunk,
+ or by end of file. If the first line in the file does not mark the
+ beginning of a chunk, it is assumed to be the first line of a documenâ€
+ tation chunk.
+
+ Documentation chunks contain text that is ignored by _n_o_t_a_n_g_l_e and
+ copied verbatim to standard output by _n_o_w_e_a_v_e (except for quoted code).
+ _n_o_w_e_a_v_e can work with _L_a_T_e_X, plain _T_e_X, _t_r_o_f_f or _H_T_M_L. With plain _T_e_X,
+ it inserts a reference to a _T_e_X macro package, _n_w_m_a_c, which defines
+ commands like \\cchhaapptteerr and \\sseeccttiioonn..
+
+ Code chunks contain program source code and references to other code
+ chunks. Several code chunks may have the same name; _n_o_t_a_n_g_l_e concateâ€
+ nates their definitions to produce a single chunk, just as does _t_a_n_â€
+ _g_l_e(1). Code chunk definitions are like macro definitions; _n_o_t_a_n_g_l_e
+ extracts a program by expanding one chunk (by default, the chunk named
+ <<<<*>>>>). The definition of that chunk contains references to other
+ chunks, which are themselves expanded, and so on. _n_o_t_a_n_g_l_e's output is
+ readable; it preserves the indentation of expanded chunks with respect
+ to the chunks in which they appear.
+
+ Code may be quoted within documentation chunks by placing double square
+ brackets ([[[[_._._.]]]]) around it. These double square brackets are ignored
+ by _n_o_t_a_n_g_l_e_, but they may be used by _n_o_w_e_a_v_e to give the code special
+ typographic treatment, e.g., hypertext links. If quoted code ends with
+ three or more square brackets, _n_o_w_e_a_v_e chooses the rightmost pair, so
+ that, for example, [[[[aa[[ii]]]]]] is parsed correctly. The names of code
+ chunks may appear within quoted code unless that quoted code is itself
+ part of the name of a code chunk.
+
+ In code, noweb treats unpaired double left or right angle brackets as
+ literal <<<< and >>>>. To force any such brackets, even paired brackets or
+ brackets in documentation, to be treated as literal, use a preceding at
+ sign (e.g. @@<<<<).
+
+ Some programming or formatting languages may require a single @@ sign in
+ the first column. Noweb users may achieve this effect by putting a
+ doubled @@@@ in the first column; in this position only, it stands for a
+ single @@ sign.
+
+TTAANNGGLLIINNGG
+ _n_o_t_a_n_g_l_e and _n_o_u_n_t_a_n_g_l_e accept the same set of options, although some
+ options have effects only on one or the other. The options are:
+
+ --RR_n_a_m_e Expand the <<<<_n_a_m_e>>>> code chunk. The --RR option can be repeated,
+ in which case each chunk is written to the output. If no --RR
+ option is given, expand the chunk named <<<<*>>>>.
+
+ --LL_f_o_r_m_a_t
+ Emit line number indications at chunk boundaries. A line number
+ indication identifies the source of the line that follows it.
+ In _f_o_r_m_a_t, %%FF indicates the name of the source file, %%LL indiâ€
+ cates the line number of the source file, %%NN indicates a newâ€
+ line, and %%%% indicates a percent sign. A sign and digit may be
+ inserted between the percent sign and the `LL', in which case the
+ line number will be adjusted by that amount. If _f_o_r_m_a_t is omitâ€
+ ted, the default format is that accepted by the C preprocessor:
+ `##lliinnee %%LL ""%%FF""%%NN'. When using the --LL_f_o_r_m_a_t option, _n_o_t_a_n_g_l_e
+ ensures that all text appears in the same column in input and
+ output. _n_o_u_n_t_a_n_g_l_e ignores this option.
+
+ Common format strings include:
+ C --LL''##lliinnee %%LL ""%%FF""%%NN''
+ Sun FORTRAN --LL''\\## %%LL ""%%FF""%%NN''
+ Icon --LL''##lliinnee %%--11LL ""%%FF""%%NN''
+ Modula-3 --LL''<<**LLIINNEE %%LL ""%%FF"" **>>%%NN''
+ SML/NJ --LL''((**##lliinnee %%LL ""%%FF""**))''
+
+ To solve the converse problem, that is, to get noweb to do someâ€
+ thing sensible with ##lliinnee in its input, see the sshhaarrpplliinnee filter
+ in the examples directory.
+
+ --tt_k Copy tabs untouched from input to output, and use tabs for
+ indentation, assuming stops every _k columns. By default, tabs
+ are expanded to spaces with stops every 8 columns.
+
+ --ffiilltteerr _c_m_d
+ Filter the _n_o_w_e_b source through _c_m_d after converting it to tool
+ form and before tangling. _n_o_t_a_n_g_l_e looks for _c_m_d first on the
+ user's PPAATTHH, then in ||LLIIBBDDIIRR||. Such filters can be used to add
+ features to _n_o_t_a_n_g_l_e; for an example see ||LLIIBBDDIIRR||//eemmppttyyddeeffnn.
+ For experts only.
+
+ --mmaarrkkuupp _p_a_r_s_e_r
+ Use _p_a_r_s_e_r to parse the input file. Enables use of noweb tools
+ on files in other formats; for example, the nnuummaarrkkuupp parser
+ understands _n_u_w_e_b(1) format. See _n_o_w_e_b_f_i_l_t_e_r_s(7) for more
+ information. For experts only.
+
+ --aawwkk || --cc || --iiccnn || --iiccoonn || --mmll || --mm33 || --ppaassccaall || --ff7777 || --ff9900 || --tteexx
+ When _n_o_u_n_t_a_n_g_l_e transforms documentation chunks into comments,
+ use the comment format of the language named. --cc is the
+ default. _n_o_t_a_n_g_l_e ignores these options.
+
+ --ww_n When _n_o_u_n_t_a_n_g_l_e transforms documentation chunks into comments,
+ create comments on lines of width _n. _n_o_t_a_n_g_l_e ignores this
+ option.
+
+WWEEAAVVIINNGG
+ Output from _n_o_w_e_a_v_e can be used in _T_e_X documents that \\iinnppuutt nnwwmmaacc,, in
+ _L_a_T_e_X documents that use the nnoowweebb package (see _n_o_w_e_b_s_t_y_l_e_(_1_)), and in
+ _H_T_M_L documents to be browsed with _M_o_s_a_i_c_(_1_)_. _N_o_w_e_a_v_e treats code
+ chunks somewhat like _L_a_T_e_X _l_i_s_t _e_n_v_i_r_o_n_m_e_n_t_s_. If the ``@@ '' that terâ€
+ minates a code chunk is followed immediately by text, that text follows
+ the code chunk without a paragraph break. If the rest of the line is
+ blank, _n_o_w_e_a_v_e puts _T_e_X into ``vertical mode,'' and later text starts a
+ fresh, indented paragraph.
+
+ No page breaks occur in the middle of code chunks unless necessary to
+ avoid an overfull vbox. The documentation chunk immediately preceding
+ a code chunk appears on the same page as that code chunk unless doing
+ so would violate the previous rule.
+
+ _N_o_w_e_a_v_e inserts no extra newlines in its _T_e_X output, so the line numâ€
+ bers given in _T_e_X error messages are the same as those in the input
+ file.
+
+ _n_o_w_e_a_v_e has options that dictate choice of formatter and that support
+ different formatting idioms and tools. Basic options are described
+ here; options related to index and cross-reference information are
+ described in the INDEXING AND CROSS-REFERENCE section.
+
+ --llaatteexx Emit LaTeX, including wrapper in aarrttiiccllee style with the nnoowweebb
+ package and page style. (Default)
+
+ --tteexx Emit plain TeX, including wrapper with nnwwmmaacc macros.
+
+ --hhttmmll Emit HTML, using HTML wrapper. The output is uninteresting
+ without --iinnddeexx or --xx. The tags <<nnoowweebbcchhuunnkkss>> and <<nnoowweebbiinnddeexx>>,
+ on lines by themselves, produce a list of chunks and an index of
+ identifiers, respectively. If these tags are not present, the
+ list and index are placed at the end of the file.
+
+ --llaatteexx++hhttmmll
+ Assume documentation chunks are LaTeX, but generate HTML for
+ code chunks, suitably marked so conversion with _l_a_t_e_x_2_h_t_m_l_(_1_)
+ yields reasonable output. A LaTeX wrapper is implied, but can
+ be turned off with --nn. _U_s_e _o_f _t_h_i_s _o_p_t_i_o_n _i_s ddeepprreeccaatteedd;; use
+ --hhttmmll with --ffiilltteerr ll22hh instead.
+
+ --ttrrooffff Emit _t_r_o_f_f(1) markup (with no wrapper). The result should be
+ processed with _n_o_r_o_f_f(1). Bug reports for --ttrrooffff to Arnold Robâ€
+ bins <<aarrnnoolldd@@sskkeeeevvee..ccoomm>>..
+
+ --nn Don't use any wrapper (header or trailer). This option is useâ€
+ ful when _n_o_w_e_a_v_e's output will be a part of a larger document.
+ See also --ddeellaayy..
+
+ --ffiilltteerr _c_m_d
+ Filters the _n_o_w_e_b source through _c_m_d after converting it to tool
+ form and before converting to _T_e_X_. _n_o_w_e_a_v_e looks for _c_m_d first
+ on the user's PPAATTHH,, then in ||LLIIBBDDIIRR||.. Such filters can be used
+ to add features to _n_o_w_e_a_v_e_; for an example, see ||LLIIBBâ€â€
+ DDIIRR||//nnooxxrreeff..kkrroomm.. _N_o_w_e_a_v_e supports up to four filters; one can
+ get more by shell trickery, for example, --ffiilltteerr ""iiccoonn..ffiilltteerr ||
+ nnooiiddxx"". The --aauuttooddeeffss, --xx, --iinnddeexx, and --iinnddeexxffrroomm options are
+ implemented as filters. Filters are executed with the shell's
+ eevvaall command, so _c_m_d should be quoted accordingly.
+
+ --mmaarrkkuupp _p_a_r_s_e_r
+ Use _p_a_r_s_e_r to parse the input file. Enables use of noweb tools
+ on files in other formats; for example, the nnuummaarrkkuupp parser
+ understands _n_u_w_e_b(1) format. See _n_o_w_e_b_f_i_l_t_e_r_s(7) for more
+ information. For experts only.
+
+ --ooppttiioonn _o_p_t
+ Adds \\nnoowweebbooppttiioonnss{{_o_p_t}} to the _L_a_T_e_X header. See _n_o_w_e_b_s_t_y_l_e_(_1_)
+ for values of _o_p_t_. Normally useful only with the --llaatteexx option,
+ but --ooppttiioonn lloonnggxxrreeff works black magic with --hhttmmll..
+
+ --ddeellaayy By default, _n_o_w_e_a_v_e puts file-name and other information into
+ the output before the first chunk of the program. --ddeellaayy delays
+ that information until after the first documentation chunk, makâ€
+ ing act a little bit like the _W_E_B ``limbo.'' The option is typâ€
+ ically used to enable a user to put a specialized _L_a_T_e_X \\ddooccuuâ€â€
+ mmeennttccllaassss command and other preamble material in the first docuâ€
+ mentation chunk (i.e., _b_e_f_o_r_e the first @ sign). This option
+ also forces trailing cross-referencing information to be emitted
+ just before the final chunk, instead of at the end of the docuâ€
+ ment; the final chunk is expected to contain \\eenndd{{ddooccuummeenntt}}..
+ The --ddeellaayy option implies the --nn option.
+
+ --tt_k Expand tabs with stops every _k columns. (Default is to expand
+ every 8 columns.)
+
+ --tt Copy tabs to the output.
+
+ --vv Print the pipeline and RCS info on standard error.
+
+IINNDDEEXXIINNGG AANNDD CCRROOSSSS--RREEFFEERREENNCCEE
+ When used with _L_a_T_e_X, _t_r_o_f_f, or _H_T_M_L_, _n_o_w_e_a_v_e can provide indexing and
+ cross-reference information for chunks and for programming-language
+ identifiers. Identifier definitions may be marked by hand using backâ€
+ ticks (`); the --ffiilltteerr bbttddeeffnn option recognizes these markings. For
+ some languages, definitions may be found automatically using the
+ --aauuttooddeeffss option. This section describes the indexing and cross-referâ€
+ ence options; it might well be skipped on first reading.
+
+ --xx For _L_a_T_e_X_, add a page number to each chunk name identifying the
+ location of that chunk's definition, and emit cross-reference
+ information relating definitions and uses. For _H_T_M_L_, create
+ hypertext links between uses and definitions of chunks. When
+ nnoowweeaavvee --xx is used with _L_a_T_e_X_, the control sequence \\nnoowweebbcchhuunnkkss
+ expands to a sorted list of all code chunks.
+
+ --iinnddeexx Build cross-reference information (or hypertext links) for
+ defined identifiers. Definitions are those found in the input
+ files by --aauuttooddeeffss _l_a_n_g_u_a_g_e or by --ffiilltteerrbtdefn. Requires _L_a_T_e_X
+ or _H_T_M_L_. --iinnddeexx implies --xx;; including both will generate
+ strange-looking output. _n_o_w_e_a_v_e does not generate cross-referâ€
+ ences to identifiers that appear in quoted code (@@[[[[...@@]]]]), but
+ it does generate hypertext links. When nnoowweeaavvee --iinnddeexx is used
+ with _L_a_T_e_X_, the control sequence \\nnoowweebbiinnddeexx expands to an index
+ of identifiers.
+
+ --iinnddeexxffrroomm _i_n_d_e_x
+ Like --iinnddeexx,, but the identifiers to be indexed are taken from
+ file _i_n_d_e_x. See _n_o_i_n_d_e_x_(_1_)_.
+
+ --aauuttooddeeffss _l_a_n_g
+ Discover identifier definitions automatically. Code in chunks
+ must be in language _l_a_n_g. Permissible _l_a_n_gs vary but may
+ include tteexx or iiccoonn.. Useless without --iinnddeexx,, which it must preâ€
+ cede.
+
+ --sshhoowwaauuttooddeeffss
+ Show values of _l_a_n_g usable with --aauuttooddeeffss.
+
+EERRRROORR MMEESSSSAAGGEESS
+ If _n_o_t_a_n_g_l_e or _n_o_w_e_a_v_e encounters a chunk name within documentation, it
+ assumes that this indicates an error, usually misspelling
+ ``<<name>>=''. Other error messages should be self-explanatory.
+
+ It is incorrect to refer to a chunk that is never defined, but it is OK
+ for chunks to be defined and not used.
+
+EEXXAAMMPPLLEESS
+ If you have trouble digesting this man page, you're not alone. Here
+ are a few examples to get you started. I'll assume you have a ffoooo..nnww
+ file with a C program in chunk <<<<ffoooo..cc>>>> and a header file in chunk
+ <<<<ffoooo..hh>>>>, and that your documentation is marked up using _l_a_t_e_x_(_1_).
+ I'll show you how to build things using the most common options.
+
+ To rebuild your C source, try
+ nnoottaannggllee --LL --RRffoooo..cc ffoooo..nnww >> ffoooo..cc
+ To rebuild your header file, try
+ nnoottaannggllee --RRffoooo..hh ffoooo..nnww || ccppiiff ffoooo..hh
+ There are two compromises here. Omitting --LL keeps ##lliinnee out of your
+ header file, and using ccppiiff prevents the command from rewriting ffoooo..hh
+ unless the contents have changed. Thus, this is good code to put in a
+ Makefile rule.
+
+ To build a printed document, run
+ nnoowweeaavvee --aauuttooddeeffss cc --iinnddeexx ffoooo..nnww >> ffoooo..tteexx
+ If you have your own preamble, containing \\ddooccuummeennttccllaassss and all, you
+ will also need the --ddeellaayy option.
+
+ To build a web page, run
+ nnoowweeaavvee --ffiilltteerr ll22hh --aauuttooddeeffss cc --iinnddeexx --hhttmmll ffoooo..nnww || hhttmmllttoocc >>
+ ffoooo..hhttmmll
+ Have fun!
+
+FFIILLEESS
+ |LIBDIR|/markup markup preprocessor
+ |LIBDIR|/unmarkup inverts markup
+ |LIBDIR|/nt notangle proper
+ |LIBDIR|/finduses find uses of identifiers for index
+ |LIBDIR|/noidx generate index and cross-reference info
+ |LIBDIR|/toroff back end to emit _t_r_o_f_f
+ |LIBDIR|/totex back end to emit _T_e_X or _L_a_T_e_X
+ |LIBDIR|/tohtml back end to emit HTML
+ |TEXINPUTS|/nwmac.tex formatting _T_e_X macros
+ |TEXINPUTS|/noweb.sty use in _L_a_T_e_X documents; see _n_o_w_e_b_s_t_y_l_e_(_7_)
+
+SSEEEE AALLSSOO
+ _c_p_i_f(1), _n_o_d_e_f_s(1), _n_o_r_o_o_t_s(1), _n_o_w_e_b(1), _n_o_i_n_d_e_x(1), _n_o_r_o_f_f(1), _n_o_w_e_b_â€
+ _s_t_y_l_e(7), _n_o_w_e_b_f_i_l_t_e_r_s(7)
+
+BBUUGGSS
+ _n_o_t_a_n_g_l_e and _n_o_u_n_t_a_n_g_l_e fail if names used on the command line contain
+ single quotes.
+
+ Ignoring unused chunks can cause problems; if a chunk has multiple defâ€
+ initions and one is misspelled, the misspelled definition is silently
+ ignored. _n_o_r_o_o_t_s(1) can be used to catch this mistake.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The _-_L option of _n_o_t_a_n_g_l_e puts an implicit initial newline in the forâ€
+ mat string.
+
+ The default _L_a_T_e_X pagestyles don't set the width of the boxes containâ€
+ ing headers and footers. Since _n_o_w_e_b code paragraphs are extra wide,
+ this _L_a_T_e_X bug sometimes results in extra-wide headers and footers.
+ The remedy is to redefine the relevant ppss@@** commands; ppss@@nnoowweebb in
+ nnoowweebb..ssttyy can be used as an example.
+
+ _l_a_t_e_x_2_h_t_m_l(1) mangles some source files.
+
+ _n_o_w_e_a_v_e has too many options, and this man page is too long.
+
+VVEERRSSIIOONN
+ This man page is from _n_o_w_e_b version 2.12.
+
+AAUUTTHHOORR
+ Norman Ramsey, Tufts University. Internet address NNoorrmmaann..RRaammâ€â€
+ sseeyy@@ttuuffttss..eedduu.
+ Noweb home page at hhttttpp::////wwwwww..ccss..ttuuffttss..eedduu//~~nnrr//nnoowweebb.
+
+
+
+
+ local 10/40/2008 NOWEB(1)
diff --git a/web/noweb/src/xdoc/noweb.1 b/web/noweb/src/xdoc/noweb.1
new file mode 100644
index 0000000000..44f2847eee
--- /dev/null
+++ b/web/noweb/src/xdoc/noweb.1
@@ -0,0 +1,221 @@
+.TH NOWEB 1 "local 10/40/2008"
+.SH NAME
+noweb \- a simple literate-programming tool
+.SH SYNOPSIS
+.B noweb
+[\fB-t\fP]
+[\fB-o\fP]
+[\fB-L\fP\fIformat\fP]
+[\fB-markup\fP \fIparser\fP]
+[file] ...
+.SH DESCRIPTION
+.I Noweb
+is a literate-programming tool like
+.I FunnelWEB
+or
+.IR nuweb ,
+only simpler.
+A
+.I noweb
+file contains program source code interleaved with documentation.
+When
+.I noweb
+is invoked, it writes the program source code
+to the output files mentioned in the noweb file, and it writes a
+.I TeX
+file for typeset documentation.
+.PP
+The
+.IR noweb (1)
+command is for people who don't like reading man pages or who are switching from
+.IR nuweb .
+To get the most out of
+.IR noweb ,
+use
+.IR notangle (1)
+and
+.IR noweave (1)
+instead.
+.SH FORMAT OF NOWEB FILES
+A
+.I noweb
+file is a sequence of
+.IR chunks ,
+which may appear in any order.
+A chunk may contain code or documentation.
+Documentation chunks begin with a line that starts with an at sign (@)
+followed by a space or newline.
+They have no names.
+Code chunks begin with
+.br
+<<\fIchunk name\fP>>=
+.br
+on a line by itself.
+The double left angle bracket (<<) must be in the first column.
+Chunks are terminated by the beginning of another chunk, or by end of file.
+If the first line in the file does not mark the beginning of a
+chunk, it is assumed to be the first line of a documentation chunk.
+.PP
+Documentation chunks contain text that is copied verbatim to the
+.I TeX
+file (except for quoted code).
+.I noweb
+works with \fILaTeX\fP; the first documentation chunk must contain
+a
+.I LaTeX
+.B "\\\\documentclass"
+command, it must contain
+.B "\\\\usepackage{noweb}"
+in the preamble, and finally
+it must also contain a
+.I LaTeX
+.B "\\\\begin{document}"
+command.
+.PP
+Code chunks contain program source code and references to other code
+chunks.
+Several code chunks may have the same name;
+.I noweb
+concatenates their definitions to produce a single chunk, just as
+other literate-programming tools do.
+.I noweb
+looks for chunks that are defined but not used in the source file.
+If the name of such a chunk contains no spaces, the chunk is
+an ``output file;''
+.I noweb
+expands it and writes the result onto the file of the same name.
+A code-chunk definition is like a macro definition;
+it contains references to other chunks, which are
+themselves expanded, and so on.
+\fInoweb\fP's output is readable; it preserves the indentation of expanded
+chunks with respect to the chunks in which they appear.
+.PP
+If a star (\fB*\fP) is appended to the name of an output file,
+.I noweb
+includes line-number information as specified by the \fB\-L\fP\fIformat\fP
+option (or for C if no \fB\-L\fP\fIformat\fP option is given).
+The name itself may not contain shell metacharacters.
+.PP
+Code may be quoted within documentation
+chunks by placing double square brackets
+(\fB[[\fI...\fB]]\fR) around it.
+These double square brackets are used to
+give the code special typographic treatment in the
+.I TeX
+file.
+If quoted code ends with three or more square brackets,
+.I noweb
+chooses the rightmost pair, so that, for example, \fB[[a[i]]]\fR is
+parsed correctly.
+.PP
+In code, noweb treats unpaired
+double left or right angle brackets as literal \fB<<\fP and \fB>>\fP.
+To force any
+such brackets, even paired brackets or brackets in documentation,
+to be treated as literal, use a preceding at sign (e.g. \fB@<<\fP).
+.SH OPTIONS
+.TP
+.B \-t
+Suppress generation of a
+.I TeX
+file.
+.TP
+.B \-o
+Suppress generation of output files.
+.TP
+.B \-L\fIformat\fR
+Use
+.I format
+to format line-number information for starred output files.
+(If the option is omitted, a format suitable for C is used.)
+.I format
+is as defined by
+.IR notangle (1);
+.TP
+.B "\-markup \fIparser\fP"
+Use
+.I parser
+to parse the input file.
+Enables use of noweb tools on files in other formats;
+for example, the
+.B numarkup
+parser understands
+.IR nuweb (1)
+format.
+See
+.IR nowebfilters (7)
+for more information.
+For experts only.
+.SH BUGS
+.PP
+Ignoring unused chunks whose names contain spaces
+sometimes causes problems, especially in the case when a chunk has
+multiple definitions and one is misspelled;
+the misspelled definition will be silently ignored.
+.IR noroots (1)
+can be used as a sanity checker to catch this sort of mistake.
+.PP
+.I noweb
+is intended for users who don't want the power or the complexity of
+command-line options.
+More sophisticated users should avoid
+.I noweb
+and use
+.I noweave
+and
+.I notangle
+instead.
+If the design were better, we could all use the same commands.
+.PP
+.I noweb
+requires the new version of
+.IR awk ,
+assumed to be called
+.IR nawk .
+DEC
+.I nawk
+has a bug in that that causes problems with braces in
+.I TeX
+output.
+GNU
+.I gawk
+is reported to work.
+.PP
+The default
+.I LaTeX
+pagestyles don't set the width of the boxes containing headers and footers.
+Since
+.I noweb
+code paragraphs are extra wide, this
+.I LaTeX
+bug sometimes results in extra-wide headers and footers.
+The remedy is to redefine the relevant
+.B ps@*
+commands;
+.B ps@noweb
+in
+.B noweb.sty
+can be used as an example.
+.SH SEE ALSO
+.PP
+.IR notangle (1),
+.IR noweave (1),
+.IR noroots (1),
+.IR nountangle (1),
+.IR nowebstyle (7),
+.IR nowebfilters (7),
+.IR nuweb2noweb (1)
+.br
+Norman Ramsey,
+.I "Literate programming simplified, IEEE Software"
+11(5):97-105, September 1994.
+.SH VERSION
+This man page is from
+.I noweb
+version 2.12.
+.SH AUTHOR
+Norman Ramsey, Tufts University.
+Internet address \fBNorman.Ramsey@tufts.edu\fP.
+.br
+Noweb home page at \fBhttp://www.cs.tufts.edu/~nr/noweb\fP.
+
diff --git a/web/noweb/src/xdoc/noweb.txt b/web/noweb/src/xdoc/noweb.txt
new file mode 100644
index 0000000000..3b9964fe4c
--- /dev/null
+++ b/web/noweb/src/xdoc/noweb.txt
@@ -0,0 +1,123 @@
+NOWEB(1) General Commands Manual NOWEB(1)
+
+
+
+NNAAMMEE
+ noweb - a simple literate-programming tool
+
+SSYYNNOOPPSSIISS
+ nnoowweebb [--tt] [--oo] [--LL_f_o_r_m_a_t] [--mmaarrkkuupp _p_a_r_s_e_r] [file] ...
+
+DDEESSCCRRIIPPTTIIOONN
+ _N_o_w_e_b is a literate-programming tool like _F_u_n_n_e_l_W_E_B or _n_u_w_e_b, only simâ€
+ pler. A _n_o_w_e_b file contains program source code interleaved with docuâ€
+ mentation. When _n_o_w_e_b is invoked, it writes the program source code to
+ the output files mentioned in the noweb file, and it writes a _T_e_X file
+ for typeset documentation.
+
+ The _n_o_w_e_b(1) command is for people who don't like reading man pages or
+ who are switching from _n_u_w_e_b. To get the most out of _n_o_w_e_b, use _n_o_t_a_n_â€
+ _g_l_e(1) and _n_o_w_e_a_v_e(1) instead.
+
+FFOORRMMAATT OOFF NNOOWWEEBB FFIILLEESS
+ A _n_o_w_e_b file is a sequence of _c_h_u_n_k_s, which may appear in any order. A
+ chunk may contain code or documentation. Documentation chunks begin
+ with a line that starts with an at sign (@) followed by a space or newâ€
+ line. They have no names. Code chunks begin with
+ <<_c_h_u_n_k _n_a_m_e>>=
+ on a line by itself. The double left angle bracket (<<) must be in the
+ first column. Chunks are terminated by the beginning of another chunk,
+ or by end of file. If the first line in the file does not mark the
+ beginning of a chunk, it is assumed to be the first line of a documenâ€
+ tation chunk.
+
+ Documentation chunks contain text that is copied verbatim to the _T_e_X
+ file (except for quoted code). _n_o_w_e_b works with _L_a_T_e_X; the first docuâ€
+ mentation chunk must contain a _L_a_T_e_X \\ddooccuummeennttccllaassss command, it must
+ contain \\uusseeppaacckkaaggee{{nnoowweebb}} in the preamble, and finally it must also
+ contain a _L_a_T_e_X \\bbeeggiinn{{ddooccuummeenntt}} command.
+
+ Code chunks contain program source code and references to other code
+ chunks. Several code chunks may have the same name; _n_o_w_e_b concatenates
+ their definitions to produce a single chunk, just as other literate-
+ programming tools do. _n_o_w_e_b looks for chunks that are defined but not
+ used in the source file. If the name of such a chunk contains no spaâ€
+ ces, the chunk is an ``output file;'' _n_o_w_e_b expands it and writes the
+ result onto the file of the same name. A code-chunk definition is like
+ a macro definition; it contains references to other chunks, which are
+ themselves expanded, and so on. _n_o_w_e_b's output is readable; it preâ€
+ serves the indentation of expanded chunks with respect to the chunks in
+ which they appear.
+
+ If a star (**) is appended to the name of an output file, _n_o_w_e_b includes
+ line-number information as specified by the --LL_f_o_r_m_a_t option (or for C
+ if no --LL_f_o_r_m_a_t option is given). The name itself may not contain shell
+ metacharacters.
+
+ Code may be quoted within documentation chunks by placing double square
+ brackets ([[[[_._._.]]]]) around it. These double square brackets are used to
+ give the code special typographic treatment in the _T_e_X file. If quoted
+ code ends with three or more square brackets, _n_o_w_e_b chooses the rightâ€
+ most pair, so that, for example, [[[[aa[[ii]]]]]] is parsed correctly.
+
+ In code, noweb treats unpaired double left or right angle brackets as
+ literal <<<< and >>>>. To force any such brackets, even paired brackets or
+ brackets in documentation, to be treated as literal, use a preceding at
+ sign (e.g. @@<<<<).
+
+OOPPTTIIOONNSS
+ --tt Suppress generation of a _T_e_X file.
+
+ --oo Suppress generation of output files.
+
+ --LL_f_o_r_m_a_t
+ Use _f_o_r_m_a_t to format line-number information for starred output
+ files. (If the option is omitted, a format suitable for C is
+ used.) _f_o_r_m_a_t is as defined by _n_o_t_a_n_g_l_e(1);
+
+ --mmaarrkkuupp _p_a_r_s_e_r
+ Use _p_a_r_s_e_r to parse the input file. Enables use of noweb tools
+ on files in other formats; for example, the nnuummaarrkkuupp parser
+ understands _n_u_w_e_b(1) format. See _n_o_w_e_b_f_i_l_t_e_r_s(7) for more
+ information. For experts only.
+
+BBUUGGSS
+ Ignoring unused chunks whose names contain spaces sometimes causes
+ problems, especially in the case when a chunk has multiple definitions
+ and one is misspelled; the misspelled definition will be silently
+ ignored. _n_o_r_o_o_t_s(1) can be used as a sanity checker to catch this sort
+ of mistake.
+
+ _n_o_w_e_b is intended for users who don't want the power or the complexity
+ of command-line options. More sophisticated users should avoid _n_o_w_e_b
+ and use _n_o_w_e_a_v_e and _n_o_t_a_n_g_l_e instead. If the design were better, we
+ could all use the same commands.
+
+ _n_o_w_e_b requires the new version of _a_w_k, assumed to be called _n_a_w_k. DEC
+ _n_a_w_k has a bug in that that causes problems with braces in _T_e_X output.
+ GNU _g_a_w_k is reported to work.
+
+ The default _L_a_T_e_X pagestyles don't set the width of the boxes containâ€
+ ing headers and footers. Since _n_o_w_e_b code paragraphs are extra wide,
+ this _L_a_T_e_X bug sometimes results in extra-wide headers and footers.
+ The remedy is to redefine the relevant ppss@@** commands; ppss@@nnoowweebb in
+ nnoowweebb..ssttyy can be used as an example.
+
+SSEEEE AALLSSOO
+ _n_o_t_a_n_g_l_e(1), _n_o_w_e_a_v_e(1), _n_o_r_o_o_t_s(1), _n_o_u_n_t_a_n_g_l_e(1), _n_o_w_e_b_s_t_y_l_e(7),
+ _n_o_w_e_b_f_i_l_t_e_r_s(7), _n_u_w_e_b_2_n_o_w_e_b(1)
+ Norman Ramsey, _L_i_t_e_r_a_t_e _p_r_o_g_r_a_m_m_i_n_g _s_i_m_p_l_i_f_i_e_d_, _I_E_E_E _S_o_f_t_w_a_r_e
+ 11(5):97-105, September 1994.
+
+VVEERRSSIIOONN
+ This man page is from _n_o_w_e_b version 2.12.
+
+AAUUTTHHOORR
+ Norman Ramsey, Tufts University. Internet address NNoorrmmaann..RRaammâ€â€
+ sseeyy@@ttuuffttss..eedduu.
+ Noweb home page at hhttttpp::////wwwwww..ccss..ttuuffttss..eedduu//~~nnrr//nnoowweebb.
+
+
+
+
+ local 10/40/2008 NOWEB(1)
diff --git a/web/noweb/src/xdoc/nowebfilters.7 b/web/noweb/src/xdoc/nowebfilters.7
new file mode 100644
index 0000000000..f15261134c
--- /dev/null
+++ b/web/noweb/src/xdoc/nowebfilters.7
@@ -0,0 +1,211 @@
+.TH NOWEB 7 "local 10/40/2008"
+.SH NAME
+nowebfilters \- filters and parsers for use with noweb
+.SH SYNOPSIS
+[\fBnoweave\fP|\fBnotangle\fP|\fBnoweb\fP]
+[\fB\-filter\fP \fIfilter\fP|\fB\-markup\fP \fIparser\fP] ...
+.SH DESCRIPTION
+This man page documents the various filters and parsers that are
+supplied with
+.IR noweb (1).
+A filter, which transforms the pipeline representation, is used with the
+.B \-filter
+option.
+A parser, which reads a source file and emits the pipeline representation,
+is used with the
+.B \-markup
+option.
+Not all filters and parsers are available at all installations.
+.SH FILTERS
+.TP
+.B autodefs.*
+.I noweave's
+.B \-autodefs
+and
+.B \-showautodefs
+options use these filters, which automatically find defined identifiers.
+The
+.B *
+stands for the name of a programming language.
+(Icon installation only.)
+.TP
+.B btdefn
+The
+.B btdefn
+filter uses Dave Hanson's convention to mark definitions.
+In code chunks, each defining instances of an identifier should be preceded by
+a single backtick character (ASCII 140).
+The
+.B btdefn
+filter removes these backticks from the code and converts them to definitions,
+thus:
+.BR "`definition".
+It, not
+.BR "@ %def" ,
+should be used with both
+.IR notangle (1)
+and
+.IR noweave (1),
+at least for programs written in C-like languages.
+.TP
+.B disambiguate
+The
+.B disambiguate
+filter makes it possible to abbreviate chunk names using a trailing ellipsis
+(three periods), in the style of WEB and
+.IR nuweb (1).
+.TP
+.BI docs2comments " options"
+The
+.B docs2comments
+filter converts documentation chunks to comments in code chunks.
+Options include
+.BR "\-all" ,
+which converts all documentation chunks into comments;
+.B "\-one"
+converts only one documentation chunk preceding each code chunk.
+The
+.BI "\-w" k
+option formats comments
+.I k
+columns wide.
+.IP
+Other options control the language and style of the comment.
+Languages available include
+.BR "\-awk" ,
+.BR "\-c" ,
+.BR "\-c++" ,
+.BR "\-f77" ,
+.BR "\-f90" ,
+.BR "\-icn" ,
+.BR "\-icon" ,
+.BR "\-lisp" ,
+.BR "\-m3" ,
+.BR "\-ml" ,
+.BR "\-ocamlweb" ,
+.BR "\-pascal" ,
+.BR "\-scm" ,
+and
+.BR "\-tex" .
+.IP
+Norman recommends using
+.BR notangle (1)
+with
+.B docstocomments
+instead of
+.BR nountangle (1).
+(Icon installation only.)
+.TP
+.B elide \fIpatterns\fP
+The
+.B elide
+filter
+removes from the stream any code chunk matching
+any of the arguments.
+Each argument is a pattern in which
+.B ?
+matches any single character and
+.B * matches any sequence of characters.
+.TP
+.B emptydefn
+The
+.B emptydefn
+filter makes an empty definition (\fB<<>>=\fP) an abbreviation for
+a continuation of the previous definition.
+.TP
+\fBl2h\fP [\fB\-show\-unknowns\fP] [\fB\-html\-quotes\fP]
+The
+.B l2h
+filter converts LaTeX to HTML in documentation chunks.
+If the \fB\-show\-unknowns\fP options is given, unrecognized LaTeX control
+sequences appear in bold in the output.
+If the \fB\-html\-quotes\fP option is given,
+.B l2h
+converts LaTeX double-quote ligatures into HTML 4 double-quote entities.
+.B l2h
+uses the LaTeX-generated .toc and .bbl files to help create table of contents
+and bibliography.
+(Icon installation only.)
+.TP
+.B pipedocs\fI command\fP
+The
+.B pipedocs
+filter runs each documentation chunk through an invocation of
+.IR command ,
+which may be any Unix command.
+The Noweb library includes the command
+.BR h2a ,
+which uses
+.IR lynx (1)
+to convert HTML to
+ASCII.
+.TP
+.BI xchunks " files"
+The
+.B xchunks
+filter pulls in code chunks from an external source.
+The
+.I files
+argument lists one or more noweb files, which are used only for their
+definitions of code chunks.
+Empty chunk definitions in the main document are replaced with
+the external definitions of the same name.
+This filter makes it possible to include the same code chunks
+in multiple documents, or even the same code chunks multiple
+times in the same document.
+(Icon installation only.)
+.SH PARSERS
+A parser converts a source file to the noweb pipeline format,
+interpreting the ``markup'' in that file.
+By default, the tools use the standard noweb markup, but some installations
+may support nuweb markup as well.
+Parsers include
+.TP
+.B markup
+Converts standard
+.IR noweb (1)
+markup to pipeline format.
+.TP
+.B numarkup
+Converts
+.IR nuweb (1)
+markup to noweb pipeline format.
+It is not part of the standard installation, but it can be found in \fInoweb\fP's
+.B contrib/norman
+directory.
+.SH FILES
+All filters and parsers are stored in
+.B |LIBDIR|
+.SH BUGS
+It is possible to tell
+.B l2h
+about new control sequences by putting special TeX comments in one's
+documentation chunks, but there's no documentation.
+Use the source, Luke.
+.PP
+.B numarkup
+loses information, e.g., about the proper treatment of tabs.
+It also doesn't compensate for \fInotangle\fP's newline-removal
+heuristic, which means results on
+.I nuweb
+files may differ subtly from those produced by
+.I nuweb.
+.PP
+Many filters are not available in installations that use Awk instead of Icon.
+.SH SEE ALSO
+.IR noweave (1),
+.IR notangle (1),
+.IR noweb (1)
+.br
+The
+.I "Noweb Hacker's Guide"
+.SH VERSION
+This man page is from
+.I noweb
+version 2.12.
+.SH AUTHOR
+Norman Ramsey, Tufts University.
+Internet address \fBNorman.Ramsey@tufts.edu\fP.
+.br
+Noweb home page at \fBhttp://www.cs.tufts.edu/~nr/noweb\fP.
+
diff --git a/web/noweb/src/xdoc/nowebfilters.nw b/web/noweb/src/xdoc/nowebfilters.nw
new file mode 100644
index 0000000000..14b2bb49fe
--- /dev/null
+++ b/web/noweb/src/xdoc/nowebfilters.nw
@@ -0,0 +1,203 @@
+<<*>>=
+.TH NOWEB 7 "local <<noweb documentation date>>"
+.SH NAME
+nowebfilters \- filters and parsers for use with noweb
+.SH SYNOPSIS
+[\fBnoweave\fP|\fBnotangle\fP|\fBnoweb\fP]
+[\fB\-filter\fP \fIfilter\fP|\fB\-markup\fP \fIparser\fP] ...
+.SH DESCRIPTION
+This man page documents the various filters and parsers that are
+supplied with
+.IR noweb (1).
+A filter, which transforms the pipeline representation, is used with the
+.B \-filter
+option.
+A parser, which reads a source file and emits the pipeline representation,
+is used with the
+.B \-markup
+option.
+Not all filters and parsers are available at all installations.
+.SH FILTERS
+.TP
+.B autodefs.*
+.I noweave's
+.B \-autodefs
+and
+.B \-showautodefs
+options use these filters, which automatically find defined identifiers.
+The
+.B *
+stands for the name of a programming language.
+(Icon installation only.)
+.TP
+.B btdefn
+The
+.B btdefn
+filter uses Dave Hanson's convention to mark definitions.
+In code chunks, each defining instances of an identifier should be preceded by
+a single backtick character (ASCII 140).
+The
+.B btdefn
+filter removes these backticks from the code and converts them to definitions,
+thus:
+.BR "`definition".
+It, not
+.BR "@ %def" ,
+should be used with both
+.IR notangle (1)
+and
+.IR noweave (1),
+at least for programs written in C-like languages.
+.TP
+.B disambiguate
+The
+.B disambiguate
+filter makes it possible to abbreviate chunk names using a trailing ellipsis
+(three periods), in the style of WEB and
+.IR nuweb (1).
+.TP
+.BI docs2comments " options"
+The
+.B docs2comments
+filter converts documentation chunks to comments in code chunks.
+Options include
+.BR "\-all" ,
+which converts all documentation chunks into comments;
+.B "\-one"
+converts only one documentation chunk preceding each code chunk.
+The
+.BI "\-w" k
+option formats comments
+.I k
+columns wide.
+.IP
+Other options control the language and style of the comment.
+Languages available include
+.BR "\-awk" ,
+.BR "\-c" ,
+.BR "\-c++" ,
+.BR "\-f77" ,
+.BR "\-f90" ,
+.BR "\-icn" ,
+.BR "\-icon" ,
+.BR "\-lisp" ,
+.BR "\-m3" ,
+.BR "\-ml" ,
+.BR "\-ocamlweb" ,
+.BR "\-pascal" ,
+.BR "\-scm" ,
+and
+.BR "\-tex" .
+.IP
+Norman recommends using
+.BR notangle (1)
+with
+.B docstocomments
+instead of
+.BR nountangle (1).
+(Icon installation only.)
+.TP
+.B elide \fIpatterns\fP
+The
+.B elide
+filter
+removes from the stream any code chunk matching
+any of the arguments.
+Each argument is a pattern in which
+.B ?
+matches any single character and
+.B * matches any sequence of characters.
+.TP
+.B emptydefn
+The
+.B emptydefn
+filter makes an empty definition (\fB@<<@>>=\fP) an abbreviation for
+a continuation of the previous definition.
+.TP
+\fBl2h\fP [\fB\-show\-unknowns\fP] [\fB\-html\-quotes\fP]
+The
+.B l2h
+filter converts LaTeX to HTML in documentation chunks.
+If the \fB\-show\-unknowns\fP options is given, unrecognized LaTeX control
+sequences appear in bold in the output.
+If the \fB\-html\-quotes\fP option is given,
+.B l2h
+converts LaTeX double-quote ligatures into HTML 4 double-quote entities.
+.B l2h
+uses the LaTeX-generated .toc and .bbl files to help create table of contents
+and bibliography.
+(Icon installation only.)
+.TP
+.B pipedocs\fI command\fP
+The
+.B pipedocs
+filter runs each documentation chunk through an invocation of
+.IR command ,
+which may be any Unix command.
+The Noweb library includes the command
+.BR h2a ,
+which uses
+.IR lynx (1)
+to convert HTML to
+ASCII.
+.TP
+.BI xchunks " files"
+The
+.B xchunks
+filter pulls in code chunks from an external source.
+The
+.I files
+argument lists one or more noweb files, which are used only for their
+definitions of code chunks.
+Empty chunk definitions in the main document are replaced with
+the external definitions of the same name.
+This filter makes it possible to include the same code chunks
+in multiple documents, or even the same code chunks multiple
+times in the same document.
+(Icon installation only.)
+.SH PARSERS
+A parser converts a source file to the noweb pipeline format,
+interpreting the ``markup'' in that file.
+By default, the tools use the standard noweb markup, but some installations
+may support nuweb markup as well.
+Parsers include
+.TP
+.B markup
+Converts standard
+.IR noweb (1)
+markup to pipeline format.
+.TP
+.B numarkup
+Converts
+.IR nuweb (1)
+markup to noweb pipeline format.
+It is not part of the standard installation, but it can be found in \fInoweb\fP's
+.B contrib/norman
+directory.
+.SH FILES
+All filters and parsers are stored in
+.B |LIBDIR|
+.SH BUGS
+It is possible to tell
+.B l2h
+about new control sequences by putting special TeX comments in one's
+documentation chunks, but there's no documentation.
+Use the source, Luke.
+.PP
+.B numarkup
+loses information, e.g., about the proper treatment of tabs.
+It also doesn't compensate for \fInotangle\fP's newline-removal
+heuristic, which means results on
+.I nuweb
+files may differ subtly from those produced by
+.I nuweb.
+.PP
+Many filters are not available in installations that use Awk instead of Icon.
+.SH SEE ALSO
+.IR noweave (1),
+.IR notangle (1),
+.IR noweb (1)
+.br
+The
+.I "Noweb Hacker's Guide"
+<<AUTHOR section>>
diff --git a/web/noweb/src/xdoc/nowebfilters.txt b/web/noweb/src/xdoc/nowebfilters.txt
new file mode 100644
index 0000000000..485674ffdc
--- /dev/null
+++ b/web/noweb/src/xdoc/nowebfilters.txt
@@ -0,0 +1,131 @@
+NOWEB(7) Miscellaneous Information Manual NOWEB(7)
+
+
+
+NNAAMMEE
+ nowebfilters - filters and parsers for use with noweb
+
+SSYYNNOOPPSSIISS
+ [nnoowweeaavvee|nnoottaannggllee|nnoowweebb] [--ffiilltteerr _f_i_l_t_e_r|--mmaarrkkuupp _p_a_r_s_e_r] ...
+
+DDEESSCCRRIIPPTTIIOONN
+ This man page documents the various filters and parsers that are supâ€
+ plied with _n_o_w_e_b(1). A filter, which transforms the pipeline represenâ€
+ tation, is used with the --ffiilltteerr option. A parser, which reads a
+ source file and emits the pipeline representation, is used with the
+ --mmaarrkkuupp option. Not all filters and parsers are available at all
+ installations.
+
+FFIILLTTEERRSS
+ aauuttooddeeffss..**
+ _n_o_w_e_a_v_e_'_s --aauuttooddeeffss and --sshhoowwaauuttooddeeffss options use these filters,
+ which automatically find defined identifiers. The ** stands for
+ the name of a programming language. (Icon installation only.)
+
+ bbttddeeffnn The bbttddeeffnn filter uses Dave Hanson's convention to mark definiâ€
+ tions. In code chunks, each defining instances of an identifier
+ should be preceded by a single backtick character (ASCII 140).
+ The bbttddeeffnn filter removes these backticks from the code and conâ€
+ verts them to definitions, thus: ``ddeeffiinniittiioonn. It, not @@ %%ddeeff,
+ should be used with both _n_o_t_a_n_g_l_e(1) and _n_o_w_e_a_v_e(1), at least
+ for programs written in C-like languages.
+
+ ddiissaammbbiigguuaattee
+ The ddiissaammbbiigguuaattee filter makes it possible to abbreviate chunk
+ names using a trailing ellipsis (three periods), in the style of
+ WEB and _n_u_w_e_b(1).
+
+ ddooccss22ccoommmmeennttss _o_p_t_i_o_n_s
+ The ddooccss22ccoommmmeennttss filter converts documentation chunks to comâ€
+ ments in code chunks. Options include --aallll, which converts all
+ documentation chunks into comments; --oonnee converts only one docuâ€
+ mentation chunk preceding each code chunk. The --ww_k option forâ€
+ mats comments _k columns wide.
+
+ Other options control the language and style of the comment.
+ Languages available include --aawwkk, --cc, --cc++++, --ff7777, --ff9900, --iiccnn,
+ --iiccoonn, --lliisspp, --mm33, --mmll, --ooccaammllwweebb, --ppaassccaall, --ssccmm, and --tteexx.
+
+ Norman recommends using nnoottaannggllee(1) with ddooccssttooccoommmmeennttss instead
+ of nnoouunnttaannggllee(1). (Icon installation only.)
+
+ eelliiddee _p_a_t_t_e_r_n_s
+ The eelliiddee filter removes from the stream any code chunk matching
+ any of the arguments. Each argument is a pattern in which ??
+ matches any single character and ** mmaattcchheess aannyy sseeqquueennccee ooff cchhaarrâ€â€
+ aacctteerrss..
+
+ eemmppttyyddeeffnn
+ The eemmppttyyddeeffnn filter makes an empty definition (<<<<>>>>==) an abbreâ€
+ viation for a continuation of the previous definition.
+
+ ll22hh [--sshhooww--uunnkknnoowwnnss] [--hhttmmll--qquuootteess]
+ The ll22hh filter converts LaTeX to HTML in documentation chunks.
+ If the --sshhooww--uunnkknnoowwnnss options is given, unrecognized LaTeX conâ€
+ trol sequences appear in bold in the output. If the
+ --hhttmmll--qquuootteess option is given, ll22hh converts LaTeX double-quote
+ ligatures into HTML 4 double-quote entities. ll22hh uses the
+ LaTeX-generated .toc and .bbl files to help create table of conâ€
+ tents and bibliography. (Icon installation only.)
+
+ ppiippeeddooccss _c_o_m_m_a_n_d
+ The ppiippeeddooccss filter runs each documentation chunk through an
+ invocation of _c_o_m_m_a_n_d, which may be any Unix command. The Noweb
+ library includes the command hh22aa, which uses _l_y_n_x(1) to convert
+ HTML to ASCII.
+
+ xxcchhuunnkkss _f_i_l_e_s
+ The xxcchhuunnkkss filter pulls in code chunks from an external source.
+ The _f_i_l_e_s argument lists one or more noweb files, which are used
+ only for their definitions of code chunks. Empty chunk definiâ€
+ tions in the main document are replaced with the external defiâ€
+ nitions of the same name. This filter makes it possible to
+ include the same code chunks in multiple documents, or even the
+ same code chunks multiple times in the same document. (Icon
+ installation only.)
+
+PPAARRSSEERRSS
+ A parser converts a source file to the noweb pipeline format, interâ€
+ preting the ``markup'' in that file. By default, the tools use the
+ standard noweb markup, but some installations may support nuweb markup
+ as well. Parsers include
+
+ mmaarrkkuupp Converts standard _n_o_w_e_b(1) markup to pipeline format.
+
+ nnuummaarrkkuupp
+ Converts _n_u_w_e_b(1) markup to noweb pipeline format. It is not
+ part of the standard installation, but it can be found in
+ _n_o_w_e_b's ccoonnttrriibb//nnoorrmmaann directory.
+
+FFIILLEESS
+ All filters and parsers are stored in ||LLIIBBDDIIRR||
+
+BBUUGGSS
+ It is possible to tell ll22hh about new control sequences by putting speâ€
+ cial TeX comments in one's documentation chunks, but there's no docuâ€
+ mentation. Use the source, Luke.
+
+ nnuummaarrkkuupp loses information, e.g., about the proper treatment of tabs.
+ It also doesn't compensate for _n_o_t_a_n_g_l_e's newline-removal heuristic,
+ which means results on _n_u_w_e_b files may differ subtly from those proâ€
+ duced by _n_u_w_e_b_.
+
+ Many filters are not available in installations that use Awk instead of
+ Icon.
+
+SSEEEE AALLSSOO
+ _n_o_w_e_a_v_e(1), _n_o_t_a_n_g_l_e(1), _n_o_w_e_b(1)
+ The _N_o_w_e_b _H_a_c_k_e_r_'_s _G_u_i_d_e
+
+VVEERRSSIIOONN
+ This man page is from _n_o_w_e_b version 2.12.
+
+AAUUTTHHOORR
+ Norman Ramsey, Tufts University. Internet address NNoorrmmaann..RRaammâ€â€
+ sseeyy@@ttuuffttss..eedduu.
+ Noweb home page at hhttttpp::////wwwwww..ccss..ttuuffttss..eedduu//~~nnrr//nnoowweebb.
+
+
+
+
+ local 10/40/2008 NOWEB(7)
diff --git a/web/noweb/src/xdoc/nowebstyle.7 b/web/noweb/src/xdoc/nowebstyle.7
new file mode 100644
index 0000000000..fbc8612049
--- /dev/null
+++ b/web/noweb/src/xdoc/nowebstyle.7
@@ -0,0 +1,180 @@
+.TH NOWEB 7 "local 10/40/2008"
+.SH NAME
+nowebstyle \- \fILaTeX\fP package for \fInoweb\fP
+.SH SYNOPSIS
+.B "\\\\usepackage{noweb}"
+.SH DESCRIPTION
+When
+.I noweave
+generates code for
+.IR LaTeX ,
+the
+.B noweb
+package is required.
+In addition to the necessary arcana, it
+defines a
+.B webcode
+environment in which you can place fragments of
+code, and in which
+only backslash and curly braces have their special meanings;
+all other characters are taken literally.
+It also defines a
+.B noweb
+pagestyle.
+Finally, it defines a
+.B "\\\\noweboptions{...}"
+command that can be used to tinker with the appearance of the output.
+Options are separated by commas and include:
+.TP
+.B margintag
+Put the sub-page number (tag) of each code-chunk definition in the
+left margin. (Default)
+.TP
+.B nomargintag
+Don't use margin tags.
+.TP
+.B shift
+Shift text to the left so that long code lines won't extend
+off the right-hand side of the page.
+.TP
+.B smallcode
+Set code in
+.I LaTeX
+.B "\\\\small"
+font instead of
+.B "\\\\normalsize."
+Similar options exist for all the
+.I LaTeX
+size-changing commands.
+.TP
+.B longxref, shortxref, noxref
+Choose a style for chunk cross-reference.
+Long style uses small paragraphs after each chunk, as in Knuth.
+Short style uses symbols on the definition line, as in Hanson.
+.B noxref
+provides no chunk cross-reference.
+Defaults to
+.B shortxref.
+.TP
+.B alphasubpage, numsubpage, nosubpage
+Number chunks by the number of the page on which they appear,
+followed by an alphabetic (numeric, not used) ``sub-page'' indicator.
+Defaults to
+.B alphasubpage.
+.B nosubpage
+implies
+.B nomargintag.
+.TP
+.B webnumbering
+Number chunks consecutively, in
+.I WEB
+style, instead of using sub-page numbers.
+.TP
+.B subscriptidents, nosubscriptidents, hyperidents, nohyperidents
+Controls subscripting of identifiers in code, including quoted code.
+Selecting
+.B subscriptidents
+means an identifier appearing in a code chunk (or in quoted code
+within a documentation
+chunk) will be subscripted with the chunk number of its definition.
+.B hyperidents
+means such identifiers will be hyperlinked to their definitions,
+provided of course that a hypertext package like
+.B hyperref
+is loaded.
+.B nosubscriptidents
+and
+.B nohyperidents
+are equivalent, and they turn off such markings.
+The default is
+.B hyperidents.
+.TP
+.B subscriptquotedidents, nosubscriptquotedidents, hyperquotedidents, nohyperquotedidents
+Controls linking of identifiers as above, but applies only to uses of
+identifiers
+in quoted code.
+.TP
+.B hideunuseddefs
+Omit defined but unused identifiers from
+the local identifier cross-reference (Preston Briggs).
+.TP
+.B noidentxref
+Omit the local identifier cross-reference which follows each code chunk.
+.TP
+.B externalindex
+Use an index generated with
+.I noindex(1)
+(q.v.).
+.TP
+.B longchunks
+When expanding
+.B "\\\\nowebchunks,"
+show page numbers of definitions and uses of each chunk.
+.TP
+.B english, french, german, portuges, icelandic
+Write cross-reference information in the language specified.
+Defaults to
+.B english.
+.SH CONTROL SEQUENCES
+The noweb package describes a gazillion special control sequences.
+Only a few are listed here.
+.PP \" .TP will not work with the backslashes on the next line. Period.
+\fB\\nextchunklabel{l}\fP
+.RS
+Associates label \fBl\fP
+with the sub-page reference of the next code chunk.
+Can be used in for concise chunk cross-reference with, e.g.,
+\fBchunk~\\subpageref{l}\fP.
+.RE
+.PP
+.B "\\\\nwanchorto{URL}{anchor text}"
+.RS
+Creates a link to the given URL with the given anchor text.
+Implemented in
+.I latex(1)
+using footnotes, but
+.I sl2h(1)
+translates this to
+.B "<a href=URL>anchor text</a>"
+.RE
+.PP
+.B "\\\\nwanchorname{name}{anchor text}"
+.RS
+Creates an anchor point for a hyperlink.
+Implemented in
+.I latex(1)
+using
+.B "\\\\label",
+but
+.I sl2h(1)
+translates this to
+.B "<a name=name>anchor text</a>"
+.RE
+.PP
+.B "\\\\ifhtml ... \\\\fi"
+.RS
+Text between
+.B "\\\\ifhtml"
+and
+.B "\\\\fi"
+is ignored by
+.I latex(1),
+but
+.I sl2h(1)
+and the
+.I l2h
+noweb filter translate the text into HTML.
+.RE
+.SH SEE ALSO
+.IR noweave (1),
+.IR noweb (1)
+.SH VERSION
+This man page is from
+.I noweb
+version 2.12.
+.SH AUTHOR
+Norman Ramsey, Tufts University.
+Internet address \fBNorman.Ramsey@tufts.edu\fP.
+.br
+Noweb home page at \fBhttp://www.cs.tufts.edu/~nr/noweb\fP.
+
diff --git a/web/noweb/src/xdoc/nowebstyle.txt b/web/noweb/src/xdoc/nowebstyle.txt
new file mode 100644
index 0000000000..b822675a51
--- /dev/null
+++ b/web/noweb/src/xdoc/nowebstyle.txt
@@ -0,0 +1,123 @@
+NOWEB(7) Miscellaneous Information Manual NOWEB(7)
+
+
+
+NNAAMMEE
+ nowebstyle - _L_a_T_e_X package for _n_o_w_e_b
+
+SSYYNNOOPPSSIISS
+ \\uusseeppaacckkaaggee{{nnoowweebb}}
+
+DDEESSCCRRIIPPTTIIOONN
+ When _n_o_w_e_a_v_e generates code for _L_a_T_e_X, the nnoowweebb package is required.
+ In addition to the necessary arcana, it defines a wweebbccooddee environment
+ in which you can place fragments of code, and in which only backslash
+ and curly braces have their special meanings; all other characters are
+ taken literally. It also defines a nnoowweebb pagestyle. Finally, it
+ defines a \\nnoowweebbooppttiioonnss{{......}} command that can be used to tinker with
+ the appearance of the output. Options are separated by commas and
+ include:
+
+ mmaarrggiinnttaagg
+ Put the sub-page number (tag) of each code-chunk definition in
+ the left margin. (Default)
+
+ nnoommaarrggiinnttaagg
+ Don't use margin tags.
+
+ sshhiifftt Shift text to the left so that long code lines won't extend off
+ the right-hand side of the page.
+
+ ssmmaallllccooddee
+ Set code in _L_a_T_e_X \\ssmmaallll font instead of \\nnoorrmmaallssiizzee.. Similar
+ options exist for all the _L_a_T_e_X size-changing commands.
+
+ lloonnggxxrreeff,, sshhoorrttxxrreeff,, nnooxxrreeff
+ Choose a style for chunk cross-reference. Long style uses
+ small paragraphs after each chunk, as in Knuth. Short style
+ uses symbols on the definition line, as in Hanson. nnooxxrreeff proâ€
+ vides no chunk cross-reference. Defaults to sshhoorrttxxrreeff..
+
+ aallpphhaassuubbppaaggee,, nnuummssuubbppaaggee,, nnoossuubbppaaggee
+ Number chunks by the number of the page on which they appear,
+ followed by an alphabetic (numeric, not used) ``sub-page'' indiâ€
+ cator. Defaults to aallpphhaassuubbppaaggee.. nnoossuubbppaaggee implies nnoommaarrggiinnâ€â€
+ ttaagg..
+
+ wweebbnnuummbbeerriinngg
+ Number chunks consecutively, in _W_E_B style, instead of using sub-
+ page numbers.
+
+ ssuubbssccrriippttiiddeennttss,, nnoossuubbssccrriippttiiddeennttss,, hhyyppeerriiddeennttss,, nnoohhyyppeerriiddeennttss
+ Controls subscripting of identifiers in code, including quoted
+ code. Selecting ssuubbssccrriippttiiddeennttss means an identifier appearing
+ in a code chunk (or in quoted code within a documentation chunk)
+ will be subscripted with the chunk number of its definition.
+ hhyyppeerriiddeennttss means such identifiers will be hyperlinked to their
+ definitions, provided of course that a hypertext package like
+ hhyyppeerrrreeff is loaded. nnoossuubbssccrriippttiiddeennttss and nnoohhyyppeerriiddeennttss are
+ equivalent, and they turn off such markings. The default is
+ hhyyppeerriiddeennttss..
+
+ ssuubbssccrriippttqquuootteeddiiddeennttss,, nnoossuubbssccrriippttqquuootteeddiiddeennttss,, hhyyppeerrqquuootteeddiiddeennttss,,
+ nnoohhyyppeerrqquuootteeddiiddeennttss
+ Controls linking of identifiers as above, but applies only to
+ uses of identifiers in quoted code.
+
+ hhiiddeeuunnuusseeddddeeffss
+ Omit defined but unused identifiers from the local identifier
+ cross-reference (Preston Briggs).
+
+ nnooiiddeennttxxrreeff
+ Omit the local identifier cross-reference which follows each
+ code chunk.
+
+ eexxtteerrnnaalliinnddeexx
+ Use an index generated with _n_o_i_n_d_e_x_(_1_) (q.v.).
+
+ lloonnggcchhuunnkkss
+ When expanding \\nnoowweebbcchhuunnkkss,, show page numbers of definitions
+ and uses of each chunk.
+
+ eenngglliisshh,, ffrreenncchh,, ggeerrmmaann,, ppoorrttuuggeess,, iicceellaannddiicc
+ Write cross-reference information in the language specified.
+ Defaults to eenngglliisshh..
+
+CCOONNTTRROOLL SSEEQQUUEENNCCEESS
+ The noweb package describes a gazillion special control sequences.
+ Only a few are listed here.
+
+ \\nneexxttcchhuunnkkllaabbeell{{ll}}
+ Associates label ll with the sub-page reference of the next code
+ chunk. Can be used in for concise chunk cross-reference with,
+ e.g., cchhuunnkk~~\\ssuubbppaaggeerreeff{{ll}}.
+
+ \\nnwwaanncchhoorrttoo{{UURRLL}}{{aanncchhoorr tteexxtt}}
+ Creates a link to the given URL with the given anchor text.
+ Implemented in _l_a_t_e_x_(_1_) using footnotes, but _s_l_2_h_(_1_) translates
+ this to <<aa hhrreeff==UURRLL>>aanncchhoorr tteexxtt<<//aa>>
+
+ \\nnwwaanncchhoorrnnaammee{{nnaammee}}{{aanncchhoorr tteexxtt}}
+ Creates an anchor point for a hyperlink. Implemented in
+ _l_a_t_e_x_(_1_) using \\llaabbeell ,, but _s_l_2_h_(_1_) translates this to <<aa
+ nnaammee==nnaammee>>aanncchhoorr tteexxtt<<//aa>>
+
+ \\iiffhhttmmll ...... \\ffii
+ Text between \\iiffhhttmmll and \\ffii is ignored by _l_a_t_e_x_(_1_)_, but _s_l_2_h_(_1_)
+ and the _l_2_h noweb filter translate the text into HTML.
+
+SSEEEE AALLSSOO
+ _n_o_w_e_a_v_e(1), _n_o_w_e_b(1)
+
+VVEERRSSIIOONN
+ This man page is from _n_o_w_e_b version 2.12.
+
+AAUUTTHHOORR
+ Norman Ramsey, Tufts University. Internet address NNoorrmmaann..RRaammâ€â€
+ sseeyy@@ttuuffttss..eedduu.
+ Noweb home page at hhttttpp::////wwwwww..ccss..ttuuffttss..eedduu//~~nnrr//nnoowweebb.
+
+
+
+
+ local 10/40/2008 NOWEB(7)
diff --git a/web/noweb/src/xdoc/nuweb2noweb.1 b/web/noweb/src/xdoc/nuweb2noweb.1
new file mode 100644
index 0000000000..4205a06e63
--- /dev/null
+++ b/web/noweb/src/xdoc/nuweb2noweb.1
@@ -0,0 +1,28 @@
+.TH NOWEB 1 "10/40/2008"
+.SH NAME
+nuweb2noweb \- convert nuweb files to noweb form
+.SH SYNOPSIS
+.B nuweb2noweb
+file ...
+.SH DESCRIPTION
+.I Nuweb2noweb
+converts a file or files in
+.I nuweb
+format to
+.I noweb
+format, writing the results on standard output.
+Input is from the file(s) named on the command line.
+.SH SEE ALSO
+.PP
+.IR noweb (1),
+.IR nuweb (1)
+.SH VERSION
+This man page is from
+.I noweb
+version 2.12.
+.SH AUTHOR
+Norman Ramsey, Tufts University.
+Internet address \fBNorman.Ramsey@tufts.edu\fP.
+.br
+Noweb home page at \fBhttp://www.cs.tufts.edu/~nr/noweb\fP.
+
diff --git a/web/noweb/src/xdoc/nuweb2noweb.txt b/web/noweb/src/xdoc/nuweb2noweb.txt
new file mode 100644
index 0000000000..98d08d56e1
--- /dev/null
+++ b/web/noweb/src/xdoc/nuweb2noweb.txt
@@ -0,0 +1,30 @@
+NOWEB(1) General Commands Manual NOWEB(1)
+
+
+
+NNAAMMEE
+ nuweb2noweb - convert nuweb files to noweb form
+
+SSYYNNOOPPSSIISS
+ nnuuwweebb22nnoowweebb file ...
+
+DDEESSCCRRIIPPTTIIOONN
+ _N_u_w_e_b_2_n_o_w_e_b converts a file or files in _n_u_w_e_b format to _n_o_w_e_b format,
+ writing the results on standard output. Input is from the file(s)
+ named on the command line.
+
+SSEEEE AALLSSOO
+ _n_o_w_e_b(1), _n_u_w_e_b(1)
+
+VVEERRSSIIOONN
+ This man page is from _n_o_w_e_b version 2.12.
+
+AAUUTTHHOORR
+ Norman Ramsey, Tufts University. Internet address NNoorrmmaann..RRaammâ€â€
+ sseeyy@@ttuuffttss..eedduu.
+ Noweb home page at hhttttpp::////wwwwww..ccss..ttuuffttss..eedduu//~~nnrr//nnoowweebb.
+
+
+
+
+ 10/40/2008 NOWEB(1)
diff --git a/web/noweb/src/xdoc/onepage.tex b/web/noweb/src/xdoc/onepage.tex
new file mode 100644
index 0000000000..3eb228f888
--- /dev/null
+++ b/web/noweb/src/xdoc/onepage.tex
@@ -0,0 +1,197 @@
+\documentclass{article}
+\usepackage{alltt,multicol,array,tabularx}
+\pagestyle{empty}
+\usepackage{vmargin}
+\setpapersize{USletter}
+\setmarginsrb{0.75in}{0.75in}{0.75in}{0.75in}{0pt}{0pt}{0pt}{0pt}
+
+
+\newenvironment{mytt}{\alltt\def\\{\(\backslash\)}}{\endalltt}
+\def\.{\char`\\}
+\def\{{\char`\{}
+\def\}{\char`\}}
+
+\setcounter{secnumdepth}{0}
+
+
+\newcommand\code[1]{$\langle$\emph{#1}$\rangle$}
+
+\begin{document}
+\raggedright
+
+\parskip=0.5\baselineskip plus 0.2\baselineskip
+\parindent=0pt
+
+\hbox{}
+\kern-1in
+\advance\voffset by0.5in
+
+\begin{center}
+{\Large A One-Page Guide to Using \texttt{noweb} with {\LaTeX}}
+
+\smallskip
+
+{Norman Ramsey\\after Lee Wittenberg and Carl Gregory}
+\end{center}
+
+
+\begin{multicols}{2}[\section{The \texttt{noweb} file \texttt{foo.nw}}]
+
+\vbox{
+\centerline{\large\textbf{Documentation}}
+
+\verb+@+ in column~1 of a line by itself starts a documentation chunk.
+
+Text is in {\LaTeX}; use \verb+[[+\ldots \verb+]]+ for embedded code
+fragments.
+
+\texttt{noweave} automatically wraps file in
+\begin{quote}
+{\ttfamily\begin{tabular}{|l|}\hline
+\.documentclass\{article\}\\
+\.usepackage\{noweb\}\\
+\.begin\{document\}\\
+~~\vdots\\
+\.end\{document\}\\
+\hline
+\end{tabular}}
+\end{quote}
+To avoid wrapper, put \verb+\documentclass+ and
+\verb+\usepackage+ in your source and use \texttt{noweave~-delay}.
+}
+
+\vskip 0pt plus1in
+\penalty-500
+
+\vbox{
+\centerline{\large\textbf{Code}}
+
+\verb+<<+\ldots \emph{name of chunk}\ldots \verb+>>=+ in column~1 of a
+line by itself starts a code chunk.
+
+Code is in any language; use \verb+<<+\ldots \verb+>>+ to include
+other code chunks by reference.
+
+\emph{You can write multiple code chunks with the same name}; they are
+concatenated.
+
+Name chunks inside functions with verbs, e.g.,
+\code{copy all lines from \texttt{\upshape in} to \texttt{\upshape
+out}, adding markup}.
+
+Name chunks holding declarations with nouns, e.g., \code{private
+function prototypes} or \code{definitions of exported functions}.
+
+Name top-level ``root'' chunks after the files they are to
+represent, e.g., \verb+<<foo.c>>=+ or \verb+<<foo.h>>=+.
+}
+\vskip 0pt plus3in
+
+\end{multicols}
+
+
+\emph{For emacs users}:
+A first line of \verb+% -*- mode: Noweb; noweb-code-mode: c-mode -*-+
+is useful (to set editing mode for code chunks).
+The Unix \texttt{teTeX} distribution comes with helpful Info files
+that cover {\LaTeX} and \texttt{dvips}.
+
+
+
+
+\section{Typical Commands}
+
+\noindent
+\begin{tabularx}\textwidth{@{}>{\ttfamily}l>{\raggedright\arraybackslash}X}
+notangle -L -Rfoo.c foo.nw > foo.c&Extract file \texttt{foo.c}, with \texttt{\#line}\\
+notangle -Rfoo.h foo.nw | cpif foo.h&Extract file \texttt{foo.h} if it
+has changed (without \texttt{\#line}).\\
+\small noweave -filter l2h -index -html foo.nw > foo.html&
+ Create HTML, converting documentation from {\LaTeX}.\\
+noweave -x foo.nw > foo.tex& Create {\LaTeX} document with
+cross-reference, no index.\\
+latex foo; latex foo& Process {\LaTeX} into ``device-independent''
+(\texttt{dvi}) file.\\
+latex '\.scrollmode \.input foo'& Alternate {\LaTeX} command for use in
+Makefile.\\
+dvips -o foo.ps foo&Convert \texttt{foo.dvi} into PostScript.\\
+\end{tabularx}
+
+
+\begin{multicols}{2}[\section{Minimal {\LaTeX}}]
+
+\emph{Special characters}\hfil\break
+Not to be typed in text; OK in code\hfil\break
+\hbox{\qquad \verb=% \ { } $ & # ^ _ ~=}
+
+\emph{Escapes for specials}\hfil\break
+\hbox{\qquad \verb=\% $\backslash$ \{ \} \$ \& \# \_=}
+
+\emph{Blank line} is new paragraph.
+
+Write \verb+``quotes''+ to get ``quotes.'' Never \verb+"quotes"+.
+
+\newenvironment{sample}[1]{\begin{tabular}{@{}l>{\ttfamily}l}\emph{#1}}{\end{tabular}}
+
+\begin{sample}{Titles}
+&\.title\{\ldots\}\\
+&\.author\{\ldots\}\\
+&\.maketitle\\
+\end{sample}
+
+
+
+\begin{sample}{Sectioning}
+&\.section\{\ldots\}\\
+&\.subsection\{\ldots\}\\
+&\.subsubsection\{\ldots\}\\
+\end{sample}
+
+\begin{sample}{Fonts}
+&\.emph\{{\normalfont\emph{emphasis}}\}\\
+&\.textbf\{{\normalfont\textbf{bold}}\}\\
+&\.texttt\{{\normalfont\texttt{typewriter}}\}\\
+&\.textit\{{\normalfont\textit{italics}}\}\\
+&\.textsf\{{\normalfont\textsf{sans serif}}\}\\
+&\.textsc\{{\normalfont\textsc{small caps}}\}\\
+\end{sample}
+
+\newdimen\onecol
+\onecol=0.25\textwidth
+\advance\onecol by -0.33in
+
+
+{\noindent\parskip=0pt
+\begin{tabular}{@{}lp{\onecol}p{\onecol}}
+\emph{Lists}&
+\texttt{List of items}
+\par\kern-0.8\baselineskip
+\begin{verbatim}
+\begin{itemize}
+\item one
+\item two
+\item three
+\end{itemize}
+\end{verbatim}
+\par\kern-2.5\baselineskip\hbox{}
+& List of items
+\begin{itemize}
+\item one
+\item two
+\item three
+\end{itemize}
+\par\kern-2.5\baselineskip\hbox{}
+\\
+&\multicolumn2{l}{Also \texttt{\.begin\{enumerate\}} for numbered lists.}
+\end{tabular}}
+
+Get the right version; you want {\LaTeX}2$\varepsilon$, not {\LaTeX}~2.09.
+
+
+\end{multicols}
+
+
+\end{document}
+
+
+
diff --git a/web/noweb/src/xdoc/representation.tex b/web/noweb/src/xdoc/representation.tex
new file mode 100644
index 0000000000..a4c74c4405
--- /dev/null
+++ b/web/noweb/src/xdoc/representation.tex
@@ -0,0 +1,90 @@
+\documentstyle[11pt]{article}
+\title{Representation used by the {\tt noweb} tools}
+\author{Norman Ramsey}
+\date{October 1991}
+\setcounter{secnumdepth}{0}
+
+\makeatletter
+\def\refno#1{\nocite{#1}\@ifundefined
+ {b@#1}{{\bf ?}\@warning
+ {Reference number `#1' on page \thepage \space undefined}}%
+{\hbox{\csname b@#1\endcsname}}}
+\makeatother
+
+\def\remark#1{\marginpar{\raggedright\hbadness=10000\footnotesize\it #1}}
+% \def\remark#1{\relax}
+
+\begin{document}
+
+%\maketitle
+\section{Representation used by the {\tt noweb} tools}
+
+{\tt Markup} converts a file from the human syntax to the format used
+by the {\tt noweb} tools, and
+{\tt unmarkup} is its inverse.
+This document is not complete by itself, but should
+ provide enough information so programmers can examine the
+output of {\tt markup} and write tools that manipulate that output.
+Study of the existing tools, especially {\tt nountangle} and {\tt
+unmarkup}, is recommended.
+
+Every line begins with {\tt @} and a key word.
+The possible lines are:
+\begin{quote}
+\begin{tabular}{ll}
+\tt @begin {\it kind} $n$&Start a chunk\\
+\tt @end {\it kind} $n$&End a chunk\\
+\tt @text {\it string}&{\it string} appeared in a chunk\\
+\tt @nl&A newline\\
+\tt @defn {\it name}&The code chunk named {\it name} is being defined\\
+\tt @use {\it name}&A reference to code chunk named {\it name}\\
+\tt @quote&Start of quoted code in a documentation chunk\\
+\tt @endquote&End of quoted code in a documentation chunk\\
+\tt @file {\it filename}&Name of the file from which the chunks came\\
+\tt @literal {\it text}&Used internally by {\tt noxref} and {\tt noweave}\\
+\end{tabular}
+\end{quote}
+
+{\tt Markup} expands tabs on input (tab stops are every 8~columns).
+It numbers each chunk, starting at~0.
+It also recognizes and undoes all the appropriate escape sequences,
+for example converting {\tt @<<} to {\tt <<}.
+
+{\tt Markup}'s output is a sequence of files.
+Each file is represented by a ``{\tt @file~{\it filename}}'' line,
+followed by a sequence of chunks.
+
+The representation of a documentation chunk is
+\begin{quote}
+\begin{tabular}{ll}
+\tt @begin docs $n$&where $n$ is the chunk number.\\
+{\it docline}&repeated an arbitrary number of times.\\
+\tt @end docs $n$
+\end{tabular}
+\end{quote}
+where {\it docline} may be {\tt @text}, {\tt @nl}, {\tt @quote}, or
+{\tt @endquote}.
+Every {\tt @nl} corresponds to the corresponding newline in the
+human-readable form.
+Quotes must be balanced and may not be nested.
+
+The representation of a code chunk is
+\begin{quote}
+\begin{tabular}{ll}
+\tt @begin code $n$&where $n$ is the chunk number.\\
+\tt @defn {\it name}&name of this chunk.\\
+\tt @nl&The newline following {\tt <<{\it name}>>=} in the original file\\
+{\it codeline}&repeated an arbitrary number of times.\\
+\tt @end code $n$
+\end{tabular}
+\end{quote}
+where {\it codeline} may be {\tt @text}, {\tt @nl}, or {\tt @use}.
+
+{\tt noxref} may add lines of the form
+\begin{quote}
+\tt @literal {\it text}
+\end{quote}
+These lines are used to pass literal {\LaTeX} code through the second
+stage of {\tt noweave} without any alteration.
+
+\end{document}
diff --git a/web/noweb/src/xdoc/sl2h.1 b/web/noweb/src/xdoc/sl2h.1
new file mode 100644
index 0000000000..de5144657e
--- /dev/null
+++ b/web/noweb/src/xdoc/sl2h.1
@@ -0,0 +1,40 @@
+.TH NOWEB 1 "local 10/40/2008"
+.SH NAME
+sl2h \- simple latex to HTML converter
+.SH SYNOPSIS
+\fBsl2h\fP [\fB\-show\-unknowns\fP] [\fB\-html\-quotes\fP] [file ...]
+.SH DESCRIPTION
+.I sl2h
+is a simple converter from
+.IR latex (1)
+format to HTML
+(which can be used with, e.g., \fInetscape\fP(1) or \fIMosaic\fP(1)).
+If the \fB\-show\-unknowns\fP options is given, unrecognized
+.I LaTeX
+control
+sequences appear in bold in the output.
+If the \fB\-html\-quotes\fP option is given,
+.B sl2h
+converts LaTeX double-quote ligatures into HTML 4 double-quote entities.
+.I sl2h
+uses the LaTeX-generated .toc and .bbl files to help create table of contents
+and bibliography.
+.SH BUGS
+It is possible to tell
+.B sl2h
+about new control sequences by putting special TeX comments in one's
+documentation chunks, but there's no documentation.
+Use the source, Luke.
+.SH SEE ALSO
+.IR nowebfilters (7),
+.IR htmltoc (1)
+.SH VERSION
+This man page is from
+.I noweb
+version 2.12.
+.SH AUTHOR
+Norman Ramsey, Tufts University.
+Internet address \fBNorman.Ramsey@tufts.edu\fP.
+.br
+Noweb home page at \fBhttp://www.cs.tufts.edu/~nr/noweb\fP.
+
diff --git a/web/noweb/src/xdoc/sl2h.nw b/web/noweb/src/xdoc/sl2h.nw
new file mode 100644
index 0000000000..13c0db484f
--- /dev/null
+++ b/web/noweb/src/xdoc/sl2h.nw
@@ -0,0 +1,32 @@
+<<*>>=
+.TH NOWEB 1 "local <<noweb documentation date>>"
+.SH NAME
+sl2h \- simple latex to HTML converter
+.SH SYNOPSIS
+\fBsl2h\fP [\fB\-show\-unknowns\fP] [\fB\-html\-quotes\fP] [file ...]
+.SH DESCRIPTION
+.I sl2h
+is a simple converter from
+.IR latex (1)
+format to HTML
+(which can be used with, e.g., \fInetscape\fP(1) or \fIMosaic\fP(1)).
+If the \fB\-show\-unknowns\fP options is given, unrecognized
+.I LaTeX
+control
+sequences appear in bold in the output.
+If the \fB\-html\-quotes\fP option is given,
+.B sl2h
+converts LaTeX double-quote ligatures into HTML 4 double-quote entities.
+.I sl2h
+uses the LaTeX-generated .toc and .bbl files to help create table of contents
+and bibliography.
+.SH BUGS
+It is possible to tell
+.B sl2h
+about new control sequences by putting special TeX comments in one's
+documentation chunks, but there's no documentation.
+Use the source, Luke.
+.SH SEE ALSO
+.IR nowebfilters (7),
+.IR htmltoc (1)
+<<AUTHOR section>>
diff --git a/web/noweb/src/xdoc/sl2h.txt b/web/noweb/src/xdoc/sl2h.txt
new file mode 100644
index 0000000000..026157c740
--- /dev/null
+++ b/web/noweb/src/xdoc/sl2h.txt
@@ -0,0 +1,39 @@
+NOWEB(1) General Commands Manual NOWEB(1)
+
+
+
+NNAAMMEE
+ sl2h - simple latex to HTML converter
+
+SSYYNNOOPPSSIISS
+ ssll22hh [--sshhooww--uunnkknnoowwnnss] [--hhttmmll--qquuootteess] [file ...]
+
+DDEESSCCRRIIPPTTIIOONN
+ _s_l_2_h is a simple converter from _l_a_t_e_x(1) format to HTML (which can be
+ used with, e.g., _n_e_t_s_c_a_p_e(1) or _M_o_s_a_i_c(1)). If the --sshhooww--uunnkknnoowwnnss
+ options is given, unrecognized _L_a_T_e_X control sequences appear in bold
+ in the output. If the --hhttmmll--qquuootteess option is given, ssll22hh converts
+ LaTeX double-quote ligatures into HTML 4 double-quote entities. _s_l_2_h
+ uses the LaTeX-generated .toc and .bbl files to help create table of
+ contents and bibliography.
+
+BBUUGGSS
+ It is possible to tell ssll22hh about new control sequences by putting speâ€
+ cial TeX comments in one's documentation chunks, but there's no docuâ€
+ mentation. Use the source, Luke.
+
+SSEEEE AALLSSOO
+ _n_o_w_e_b_f_i_l_t_e_r_s(7), _h_t_m_l_t_o_c(1)
+
+VVEERRSSIIOONN
+ This man page is from _n_o_w_e_b version 2.12.
+
+AAUUTTHHOORR
+ Norman Ramsey, Tufts University. Internet address NNoorrmmaann..RRaammâ€â€
+ sseeyy@@ttuuffttss..eedduu.
+ Noweb home page at hhttttpp::////wwwwww..ccss..ttuuffttss..eedduu//~~nnrr//nnoowweebb.
+
+
+
+
+ local 10/40/2008 NOWEB(1)
diff --git a/web/noweb/src/xdoc/techrep.bbl b/web/noweb/src/xdoc/techrep.bbl
new file mode 100644
index 0000000000..84381e2975
--- /dev/null
+++ b/web/noweb/src/xdoc/techrep.bbl
@@ -0,0 +1,68 @@
+\begin{thebibliography}{10}
+
+\bibitem{denning:announcing}
+P.~J. Denning.
+\newblock Announcing literate programming.
+\newblock {\em Communications of the ACM}, 30(7):593, July 1987.
+
+\bibitem{guntermann:cweb}
+K.~Guntermann and J.~Schrod.
+\newblock {{\tt WEB}} adapted to {C}.
+\newblock {\em {TUG}boat}, 7(3):134--137, Oct. 1986.
+
+\bibitem{knuth:web}
+D.~E. Knuth.
+\newblock The {{\tt WEB}} system of structured documentation.
+\newblock Technical Report 980, Stanford Computer Science, Stanford,
+ California, Sept. 1983.
+
+\bibitem{knuth:literate:book}
+D.~E. Knuth.
+\newblock {\em Literate Programming}.
+\newblock Stanford University, Stanford, California, 1992.
+
+\bibitem{levy:cweb}
+S.~Levy.
+\newblock {\tt WEB} adapted to {C}, another approach.
+\newblock {\em TUGBoat}, 8(1):12--13, Apr. 1987.
+
+\bibitem{ramsey:building}
+N.~Ramsey.
+\newblock {L}iterate programming: {\hskip 0pt plus 0.5em}{W}eaving a
+ language-independent {{\tt WEB}}.
+\newblock {\em Communications of the ACM}, 32(9):1051--1055, Sept. 1989.
+
+\bibitem{ramsey:correctness}
+N.~Ramsey.
+\newblock Correctness of trap-based breakpoint implementations.
+\newblock In {\em Proceedings of the 21st ACM Symposium on the Principles of
+ Programming Languages}, pages 15--24, Portland, Oregon, Jan. 1994.
+
+\bibitem{ramsey:literate}
+N.~Ramsey and C.~Marceau.
+\newblock Literate programming on a team project.
+\newblock {\em Software---Practice \& Experience}, 21(7):677--683, July 1991.
+
+\bibitem{sewell:weaving}
+W.~Sewell.
+\newblock {\em Weaving a Program: Literate Programming in {\tt WEB}}.
+\newblock Van Nostrand Reinhold, New York, 1989.
+
+\bibitem{thimbleby:cweb}
+H.~Thimbleby.
+\newblock Experiences of `literate programming' using cweb (a variant of
+ {K}nuth's {WEB}).
+\newblock {\em Computer Journal}, 29(3):201--211, 1986.
+
+\bibitem{thimbleby:review}
+H.~Thimbleby.
+\newblock A review of {Donald} {C}. {L}indsay's text file difference utility,
+ {{\em diff}}.
+\newblock {\em Communications of the ACM}, 32(6):752--755, June 1989.
+
+\bibitem{cvw:assessment}
+C.~J. Van~Wyk.
+\newblock Literate programming: An assessment.
+\newblock {\em Communications of the ACM}, 33(3):361--365, March 1990.
+
+\end{thebibliography}
diff --git a/web/noweb/src/xdoc/techrep.tex b/web/noweb/src/xdoc/techrep.tex
new file mode 100644
index 0000000000..da88461018
--- /dev/null
+++ b/web/noweb/src/xdoc/techrep.tex
@@ -0,0 +1,901 @@
+% The formatter used is LaTeX
+
+% symbols that could be defined
+%
+% \dsp double space, figures on figure pages
+% \tr Princeton TR
+% \wbn use consecutive `{\tt WEB} numbering'
+
+
+
+
+\ifx\tr\undefined
+\documentstyle[11pt,noweb,multicol]{article}
+\else
+\documentstyle[11pt,noweb,multicol,tr]{article}
+\fi
+
+\title{Literate-Programming Tools\\Can Be Simple and Extensible}
+\author{Norman Ramsey\thanks{Author's current address is Bellcore, 445
+South Street, Morristown, NJ 07960;
+send email to {\tt norman@bellcore.com}.}\\Department of Computer Science,
+Princeton University}
+
+\ifx\wbn\undefined\else \noweboptions{webnumbering}\fi
+
+\ifx\dsp\undefined\else
+\makeatletter
+\let\@oldfigure=\figure
+\def\figure{\@oldfigure[p]}
+\makeatother
+\fi
+
+
+
+\ifx\tr\undefined
+\date{November 1993}
+\else
+\reportno{CS-TR-351-91}
+\date{October 1991\\Revised August 1992, November 1993}
+\fi
+
+\setcounter{secnumdepth}{0}
+\clubpenalty=10000
+\widowpenalty=10000
+\makeatletter
+\def\refno#1{\nocite{#1}\@ifundefined
+ {b@#1}{{\bf ?}\@warning
+ {Reference number `#1' on page \thepage \space undefined}}%
+{\hbox{\csname b@#1\endcsname}}}
+\makeatother
+
+\def\remark#1{\marginpar{\raggedright\hbadness=10000\footnotesize\it #1}}
+% \def\remark#1{\relax}
+\ifx\dsp\undefined\else\renewcommand{\baselinestretch}{1.6}\fi
+
+\begin{document}
+
+\maketitle
+
+\begin{abstract}
+When it was introduced, literate programming meant {\tt WEB}.
+Desire to use {\tt WEB} with languages other than Pascal led to the
+implementation of many versions.
+{\tt WEB} is complex, and the difficulty of using {\tt WEB} creates
+an artificial barrier to
+experimentation with literate programming.
+{\tt noweb} provides much of the functionality of
+{\tt WEB}, with a fraction of the complexity.
+{\tt noweb} is independent of the target programming language, and its
+formatter-dependent part is 60~lines.
+{\tt noweb} is extensible, because it uses two
+representations of programs: one easily edited by authors and one
+easily manipulated by tools.
+
+This paper explains how to use the {\tt noweb} tools and gives
+examples of their use.
+It sketches the implementation of the tools and describes how new
+tools are added to the set.
+Because
+{\tt WEB} and {\tt noweb} overlap, but each does some things that the
+other cannot,
+this paper enumerates the differences.
+\end{abstract}
+
+\ifx\tr\undefined
+\begin{center}\small
+{\bf Key words:}
+literate~programming, readability, programming~environments
+\end{center}
+\fi
+
+\section{Introduction}
+When literate programming was
+introduced, it was synonymous with {\tt WEB}, a tool
+for writing literate Pascal programs~\cite[Chapter~4]{knuth:literate:book}.
+The idea attracted attention; several examples of literate
+programs were published, and a special forum was created to discuss literate
+programming~%
+\cite{denning:announcing}. % ,gries:pearls,knuth:literate:book,thimbleby:review
+{\tt WEB} was adapted to programming languages other than
+Pascal~\cite{levy:cweb,ramsey:building,thimbleby:cweb}. % guntermann:cweb,sewell:mangle,
+%
+With experience, many {\tt WEB} users became dissatisfied~\cite{ramsey:literate}.
+Some found {\tt WEB} not worth the trouble, as did
+one author of the program appearing in Appendix~C
+of Reference~\refno{sewell:weaving}.
+Others built their own systems for literate
+ programming. % ~\cite{hamilton:expanding,cvw:loom}.
+The literate-programming forum was dropped, on the grounds that
+literate programming had become the province of those who could build
+their own tools~\cite{cvw:assessment}.
+
+{\tt WEB} programmers
+ interleave source code and descriptive text in a single document.
+When using {\tt WEB}, a programmer divides the source code into
+{\em modules}.
+Each module has a documentation part and a code part, and
+modules may be written in any order.
+The programmer is encouraged to choose an order that helps explain the program.
+The code parts are like macro definitions; they have names, and they contain
+both code and references to other modules.
+A {\tt WEB} file represents a single program;
+{\tt TANGLE} extracts that program from the {\tt WEB} source.
+One special module has a code part with no name, and {\tt TANGLE}
+expands the code part of that module to extract the program.
+{\tt WEAVE} converts {\tt WEB} source to
+{\TeX} input, from which {\TeX} can produce high-quality typeset
+documentation of the program.
+
+
+{\tt WEB} is a complex tool.
+In addition to enabling programmers to present pieces of a program in
+any order, it expands three kinds of macros, prettyprints code,
+evaluates some constant expressions,
+provides an integer representation for string literals, and implements
+a simple form of version control.
+The manual for the original version documents 27 ``control sequences''~\cite{knuth:web}.
+The versions for languages other than Pascal offer slightly different
+functions and different sets of control sequences.
+Significant effort is required to make {\tt WEB} usable with a new
+programming language, even when using a tool designed for that
+purpose~\cite{ramsey:building}.
+
+{\tt WEB}'s shortcomings make it difficult to explore the {\em idea}
+of literate programming; too much effort is required to master the
+{\em tool}.
+I designed a new tool that is
+simple, extensible, and independent of the target programming language.
+{\tt noweb} is designed
+around one idea: writing named chunks of code in any order, with
+interleaved documentation.
+Like {\tt WEB}, and like all literate-programming tools, it can
+be used to write a program in pieces and to present those pieces in
+an order that helps explain the program.
+{\tt noweb}'s value lies in its simplicity, which shows that the idea
+of literate programming does not require the complexity of {\tt WEB}.
+
+Users who could not find a satisfactory literate-programming tool
+have had no option other than to write their own tools.
+{\tt noweb} reduces the need for new tools because it is designed to
+be extended.
+It uses Unix pipes to enable users to change existing
+behavior or to add new features {without} recompiling {\tt noweb}.
+Even language-dependent features, like
+prettyprinting and automatic generation of an index, have been added
+to {\tt noweb} without recompiling.
+
+
+
+\section{{\tt noweb}} % , a minimal literate-programming system}
+A {\tt noweb} file contains program source code interleaved with documentation.
+When {\tt notangle} is given a {\tt noweb} file, it writes the program
+ on standard output.
+When {\tt noweave} is given a {\tt noweb} file, it reads the {\tt
+noweb} source and produces, on standard output, {\TeX} source for
+typeset documentation.
+Figure~\ref{transforms} shows how to use {\tt notangle} and {\tt
+noweave} to produce code and documentation for a C~program contained
+in the {\tt noweb} file {\tt foo.nw}.
+
+\begin{figure}
+\footnotesize
+\setlength{\unitlength}{2pt}
+\begin{picture}(170,80)(0,-40)
+\tt
+\put(20,12.5){\makebox(0,0)[l]{\ \tt notangle foo.nw > foo.c}}
+\put(20,-12.5){\makebox(0,0)[l]{\ \tt noweave foo.nw > foo.tex}}
+
+\put(0,-5){\framebox(30,10){foo.nw}}
+\put(15,5){\vector(1,2){7.5}}
+\put(10,20){\framebox(30,10){foo.c}}
+\put(15,-5){\vector(1,-2){7.5}}
+\put(10,-30){\framebox(30,10){foo.tex}}
+
+\put(40,-25){\vector(1,0){35}}
+\put(57.5,-23.5){\makebox(0,0)[b]{latex foo}}
+\put(75,-30){\framebox(30,10){foo.dvi}}
+\put(105,-25){\vector(1,0){35}}
+\put(122.5,-23.5){\makebox(0,0)[b]{\strut \tt dvi foo}}
+ % \shortstack{\strut dvi\\\strut \rm driver}}}
+\put(140,-25){\makebox(0,0)[l]{\rm\strut \ Typeset documentation for
+{\tt foo}}}
+
+\put(40,25){\vector(1,0){35}}
+\put(57.5,26.5){\makebox(0,0)[b]{cc -c foo.c}}
+\put(75,20){\framebox(30,10){foo.o}}
+\put(105,25){\vector(1,0){35}}
+\put(122.5,26.5){\makebox(0,0)[b]{ld foo.o {\ldots}}}
+\put(140,25){\makebox(0,0)[l]{\rm\strut \ Executable \tt a.out}}
+
+
+
+\end{picture}
+
+\caption{Using {\tt noweb} to build code and documentation}
+\label{transforms}
+\end{figure}
+
+A {\tt noweb} file is a sequence of {\em chunks}, which may appear in any order.
+A chunk may contain code or documentation.
+Documentation chunks begin with a line that starts with an at sign ({\tt @})
+followed by a space or newline.
+They have no names.
+Code chunks begin with
+\begin{quote}
+\tt <<{\rm\it chunk name}>>=
+\end{quote}
+on a line by itself.
+The double left angle bracket ({\tt <<}) must be in the first column.
+Chunks are terminated by the beginning of another chunk, or by end of file.
+If the first line in the file does not mark the beginning of a
+chunk, it is assumed to be the first line of a documentation chunk.
+
+Documentation chunks contain text that is ignored by {\tt notangle}
+and copied verbatim to standard output by
+{\tt noweave} (except for quoted code).
+{\tt noweave} can work with {\LaTeX}, or it can use
+% insert a reference to
+a plain-{\TeX} macro package, supplied with {\tt noweb}, that defines
+commands like \verb+\chapter+ and \verb+\section+.
+
+Code chunks contain program source code and references to other code
+chunks.
+Several code chunks may have the same name; {\tt notangle}
+concatenates their definitions to produce a single chunk, just as
+ {\tt TANGLE} does.
+Code chunk definitions are like macro definitions;
+{\tt notangle} extracts a program by expanding one chunk (by default
+the chunk named \verb+<<*>>+).
+The definition of that chunk contains references to other chunks,
+which are themselves expanded, and so on.
+{\tt notangle}'s output is readable; it preserves the indentation of expanded
+chunks with respect to the chunks in which they appear.
+
+Code may be quoted within documentation chunks by placing double
+square brackets around it ({\tt [[}$\ldots${\tt]]}).
+These double square brackets are ignored by {\tt notangle}, but they
+are used by {\tt noweave} to give code special typographic
+treatment.
+
+If double left and right angle brackets are not paired, they are
+treated as literal ``{\tt<<}'' and ``{\tt>>}''. Users can force any
+such brackets, even paired brackets, to be treated as literal by
+using a preceding at sign (e.g.~``{\tt @<<}'').
+
+Any line beginning with ``{\tt@ }'' terminates a code chunk.
+If such a line has the form
+``{\tt@~\char`\%def {\rm\it identifiers}}'',
+it also means that the preceding chunk defines the identifiers listed
+in {\it identifiers}.
+This notation provides a way of marking definitions manually when
+no automatic marking is available.%
+\footnote{Starting with version~2.10, this form is deprecated; new
+code should use \texttt{-filter~btdefn}.}
+
+Figure~\ref{sample-input} shows a fragment of a {\tt noweb} program
+that computes prime numbers.
+The program is derived from the example used in
+Reference~\refno{knuth:literate:book}, Chapter~4, and Figure~\ref{sample-input} should
+be compared with Figure~2b of that paper.
+Figure~\ref{noweave-output} shows the program after processing by {\tt
+noweave} and {\LaTeX}.
+Figure~\ref{notangle-output} shows the beginning of the program as
+extracted by {\tt notangle}.
+A complete example program accompanies this paper.
+
+\begin{figure}
+\begin{verbatim}
+@ This program has no input, because we want to keep it
+simple. The result of the program will be to produce a
+list of the first thousand prime numbers, and this list
+will appear on the [[output]] file.
+
+Since there is no input, we declare the value [[m = 1000]]
+as a compile-time constant. The program itself is capable
+of generating the first [[m]] prime numbers for any
+positive [[m]], as long as the computer's finite
+limitations are not exceeded.
+<<program to print the first thousand prime numbers>>=
+program print_primes(output);
+ const m = 1000;
+ <<other constants of the program>>
+ var <<variables of the program>>
+ begin <<print the first [[m]] prime numbers>>
+ end.
+\end{verbatim}
+\caption{Sample {\tt noweb} input, from prime number program}
+\label{sample-input}
+\end{figure}
+
+
+
+\begin{figure}
+\begin{quote}
+\nwbegindocs{4}
+
+This program has no input, because we want to keep it simple.
+The result of the program will be to produce a list of the first
+thousand prime numbers, and this list will appear on the \code{}output\edoc{}
+file.
+
+Since there is no input, we declare the value \code{}m = 1000\edoc{} as a
+compile-time constant.
+The program itself is capable of generating the first \code{}m\edoc{} prime
+numbers for any positive \code{}m\edoc{}, as long as the computer's finite
+limitations are not exceeded.
+\nwenddocs
+\nwbegincode{5}
+\moddef{program to print the first thousand prime numbers}\endmoddef
+program print_primes(output);
+ const m = 1000;
+ \LA{}other constants of the program\RA{}
+ var \LA{}variables of the program\RA{}
+ begin \LA{}print the first \code{}m\edoc{} prime numbers\RA{}
+ end.
+\nwendcode
+\end{quote}
+\caption{Output produced by {\tt noweave} and {\LaTeX} from Figure~\protect\ref{sample-input}}
+\label{noweave-output}
+\end{figure}
+
+\section{Using {\tt noweb}}% experience with noweb?
+
+Experimenting with \verb+noweb+ is easy.
+{\tt noweb} has little syntax: definition and use of code chunks, marking of
+documentation chunks, listing of identifiers defined,
+quoting of code, and quoting of brackets.
+\verb+noweb+ can be used with any programming language, and its
+manual fits on three pages.
+
+\begin{figure}
+\begin{verbatim}
+program print_primes(output);
+ const m = 1000;
+ rr = 50;
+ cc = 4;
+ ww = 10;
+ ord_max = 30; { p_ord_max squared must exceed p_m }
+ var p: array [1..m] of integer;
+ { the first m prime numbers, in increasing order }
+ page_number: integer;
+\end{verbatim}
+\unskip
+\hbox{\hskip2em\tt\vdots}
+\caption{Part of primes program as written by {\tt notangle}}
+\label{notangle-output}
+\end{figure}
+
+
+On a large project, it is essential that compilers and other tools be
+able to refer to locations in the \verb+noweb+ source, even though
+they work with \verb+notangle+'s output~\cite{ramsey:literate}.
+Giving \verb+notangle+ the \verb+-L+ option makes it emit pragmas
+that inform compilers of the placement of lines
+in the \verb+noweb+ source.
+It also preserves the columns in which
+tokens appear.
+If \verb+notangle+ is not given the \verb+-L+ option, it respects the
+indentation of its input, making its output easy to read.
+
+Cross-referencing of chunks and identifiers makes large programs
+easier to understand.
+\verb+noweave -x+ uses {\LaTeX}
+to show on what pages each chunk is defined and used.
+\verb+noweave -index+ adds a local identifier cross-reference after
+each code chunk.
+The example program accompanying this article shows full cross-reference
+information.
+
+
+{\tt WEB} files map one to one with both programs and documents.
+The mapping of \verb+noweb+ files to programs is many to many; the
+mapping of files to documents is many to one.
+Source files are combined by listing their names on \verb+notangle+'s
+or \verb+noweave+'s command line.
+Many programs may be extracted from one source by specifying the names
+of different root chunks, using \verb+notangle+'s \verb+-R+ command-line
+option.
+
+The simplest example of a one-to-many mapping of programs is that of putting
+C~header and program in a single {\tt noweb} file.
+The header comes from the root chunk \LA{}header\RA{}, and the program
+from the default root chunk, \LA{}*\RA{}.
+The following Unix commands extract header \verb+foo.h+ and program
+\verb+foo.c+ from {\tt noweb} file \verb+foo.nw+:
+% This trick is explained on pages 265--266 of Reference~\refno{kernighan:unix}.}
+\begin{quote}
+\begin{verbatim}
+notangle -L foo.nw > foo.c
+notangle -Rheader foo.nw | cpif -ne foo.h
+\end{verbatim}
+\end{quote}
+The \verb+>+ in the first command directs \verb+notangle+'s output to
+the file \verb+foo.c+.
+The \verb+|+ in the second command directs \verb+notangle+'s output to
+the \verb+cpif+ program, which is distributed with {\tt noweb}.
+\verb+cpif -ne foo.h+ compares its input to the contents of file
+\verb+foo.h+; if they differ, the input replaces \verb+foo.h+.
+This trick avoids touching the file \verb+foo.h+ when its contents
+have not changed, which avoids triggering unnecessary recompilations.
+
+A more interesting example is using {\tt noweb} to
+interleave different languages in one source file.
+I wrote an \verb+awk+
+script that read a machine description and emitted a disassembler for
+that machine, and I used {\tt noweb} to combine the script and description
+in a single file, so I could place each part of the input next to the
+code that processed that input.
+The machine description was in the root chunk \LA{}opcodes
+table\RA{}, and the \verb+awk+ script in the default root chunk.
+The processing steps were:
+\begin{verbatim}
+notangle opcodes.nw > opcodes.awk
+notangle -R'opcodes table' opcodes.nw |
+awk -f opcodes.awk > disassem.sml
+\end{verbatim}
+The first line extracts the {\tt awk} program into file {\tt opcodes.awk}.
+The second line extracts the machine description and pipes it to the
+third line, which uses the {\tt awk} program to turn it into a
+dissassembler.
+The disassembler is written to file {\tt disassem.sml}.
+
+Many-to-one mapping of source to program can be used to obtain
+effects similar to those of Ada or Modula-3 generics.
+Figure~\ref{generic-example} shows generic C code that supports lists.
+The code can be
+``instantiated'' by combining it with another \verb+noweb+ file.
+\verb+pair_list.nw+, shown in Figure~\ref{pair-list-example}, specifies
+ lists of integer pairs.
+The two are combined by applying \verb+notangle+ to them both:
+\begin{verbatim}
+notangle pair_list.nw generic_list.nw > pair_list.c
+\end{verbatim}
+{\tt noweb} has no parameter mechanism, so the ``generic'' code must
+refer to a fixed set of symbols, and it cannot be checked for errors
+except by compiling \verb+pair_list.c+.
+These restrictions make {\tt noweb} a poor approximation to real
+generics, but useful nevertheless.
+
+\begin{figure}
+\ifx\dsp\undefined\else\renewcommand{\baselinestretch}{1.3}\fi
+\nwbegindocs{0}
+This list code supports circularly-linked lists represented by a
+pointer to the last element. It is intended to be combined with other
+{\tt noweb} code that defines \LA{}fields of a list element\RA{} (the fields
+found in an element of a list) and that uses \LA{}list
+declarations\RA{} and \LA{}list definitions\RA.
+\nwenddocs
+\nwbegincode{1}
+\moddef{list declarations}\endmoddef
+typedef struct list \{
+ \LA{}fields of a list element\RA{}
+ struct list *_link;
+\} *List;
+
+extern List singleton(void); /* singleton list, uninitialized fields */
+extern List append(List, List); /* destructively append two lists */
+#define last(l) (l)
+#define head(l) ((l) ? (l)->next : 0)
+#define forlist(p,l) for (p=head(l); p; p=(p==last(l) ? 0 : p->next))
+\nwendcode
+\nwbegincode{2}
+\moddef{list definitions}\endmoddef
+List append (List left, List right) \{
+ List temp;
+ if (left == 0) return right;
+ if (right == 0) return left;
+ temp = left->_link; left->_link = right->_link; right->_link = temp;
+ return right;
+\}
+\nwendcode
+\unskip\hbox{\hskip2em\vdots}
+\caption{Generic code for implementing lists in C}
+\label{generic-example}
+\end{figure}
+
+\begin{figure}
+\nwbegincode{1}
+\moddef{*}\endmoddef
+\LA{}list declarations\RA{}
+\LA{}list definitions\RA{}
+\nwendcode
+\nwbegincode{2}
+\moddef{fields of a list element}\endmoddef
+int x;
+int y;
+\nwendcode
+\caption{Program to instantiate lists of integer pairs}
+\label{pair-list-example}
+\end{figure}
+
+\iffalse
+I have used \verb+noweb+ for small programs written in various
+languages, including C, Icon, \verb+awk+, and Modula-3.
+Larger projects have included a code generator for
+Standard ML of New Jersey (written in Standard ML) and
+a multi-architecture debugger, written in Modula-3, C, and
+assembly language.
+A colleague used \verb+noweb+ to write an experimental file
+system in C++.
+
+\unskip
+\vskip0pt plus12pt\penalty-200\vskip0pt plus-12pt
+\noindent The sizes of these programs are % try for better page break
+\nobreak
+\begin{quote}\nobreak
+\catcode`\?=\active\def?{\phantom{0}}
+\catcode`\*=\active\def*{\phantom{,}}
+\leavevmode\rlap{\begin{tabular}{lcc}
+Program&Documentation lines&Total lines\\
+\noalign{\smallskip}
+{\tt markup} and {\tt nt}&?*400&?1,200\\
+ML code generator&?*900&?2,600\\
+Debugger&1,400&11,000\\
+File system&4,400&27,000
+\end{tabular}}
+\end{quote}
+
+\else
+
+I myself have used \verb+noweb+ for code written in various
+languages, including assembly language, \verb+awk+, C, Icon, Modula-3,
+Promela,
+Standard~ML, and \TeX.%
+\footnote{Readers interested in another example of {\tt noweb} can see
+a published version of one of these programs \cite{ramsey:correctness}.}
+These projects have ranged in size from a few hundred to twenty
+thousand lines of code.
+Other users around the world have undertaken
+{\tt noweb} projects of comparable size in C$++$, Modula-2, occam, Parallel C,
+perl, Prolog, and Scheme.
+Two colleagues are using {\tt noweb} to write a book describing the
+design and implementation of a retargetable C compiler.
+
+\fi
+
+\section{Representation of {\tt noweb} files}
+
+The \verb+noweb+ syntax is easy to read, write, and edit, but it is
+not easily manipulated by programs.
+To make it easy to extend \verb+noweb+, I have written
+\verb+markup+, which converts \verb+noweb+ source to
+ a representation that is easily manipulated
+by commonly used Unix tools like {\tt sed} and {\tt awk}.
+In this representation,
+every line begins with {\tt @} and a key word.
+The possibilities are:
+\begin{quote}
+\leavevmode\rlap{\begin{tabular}{ll}
+\tt @begin {\rm\it kind} $n$&Start a chunk\\
+\tt @end {\rm\it kind} $n$&End a chunk\\
+\tt @text {\rm\it string}&{\rm\it string} appeared in a chunk\\
+\tt @nl&A newline appeared in a chunk\\
+\tt @defn {\rm\it name}&The code chunk named {\rm\it name} is being defined\\
+\tt @use {\rm\it name}&A reference to code chunk named {\rm\it name}\\
+\tt @quote&Start of quoted code in a documentation chunk\\
+\tt @endquote&End of quoted code in a documentation chunk\\
+\tt @file {\rm\it filename}&Name of the file from which the chunks came\\
+\tt @line $n$&Next text line came from source line $n$ in current file\\
+\tt @index defn {\rm\it ident}&The current chunk contains a definition of {\rm\it ident}\\
+\tt @index use {\rm\it ident}&The current chunk contains a use of {\rm\it ident}\\
+\tt @index nl {\rm\it ident}&A newline that is part of markup, not part of the chunk\\
+\tt @literal {\rm\it text}&{\tt noweave} copies {\rm\it text} to output\\
+\end{tabular}}
+\end{quote}
+{\tt markup} numbers each chunk, starting at~0.
+It also recognizes and undoes the escape sequence for double brackets,
+e.g.~converting ``{\tt @<<}'' to ``{\tt <<}''.
+{\tt markup}'s output represents a sequence of files.
+Each file is represented by a ``{\tt @file~{\rm\it filename}}'' line,
+followed by a sequence of chunks.
+
+The representation of a documentation chunk is
+\begin{quote}
+\begin{tabular}{ll}
+\tt @begin docs $n$&where $n$ is the chunk number.\\
+{\it docline}&repeated an arbitrary number of times.\\
+\tt @end docs $n$
+\end{tabular}
+\end{quote}
+where {\it docline} may be {\tt @text}, {\tt @nl}, {\tt @quote},
+{\tt @endquote}, {\tt @file}, {\tt @line}, or {\tt @index}.
+Every {\tt @nl} or {\tt @index~nl} corresponds to a newline in the original file.
+{\tt markup} guarantees that quotes are balanced and not nested.
+
+\vskip0pt plus12pt\penalty-200\vskip0pt plus-12pt
+The representation of a code chunk is
+\begin{quote}
+\leavevmode\rlap{\begin{tabular}{ll}
+\tt @begin code $n$&where $n$ is the chunk number.\\
+\tt @defn {\rm\it name}&name of this chunk.\\
+\tt @nl&The newline following {\tt <<{\rm\it name}>>=} in the original file\\
+{\it codeline}&repeated an arbitrary number of times.\\
+\tt @end code $n$
+\end{tabular}}
+\end{quote}
+where {\it codeline} may be {\tt @text}, {\tt @nl}, {\tt @use},
+{\tt @file}, {\tt @line}, or {\tt @index}.
+
+The \verb+noweb+ tools are implemented by piping the output of
+\verb+markup+ to other programs.
+\verb+notangle+ is a Unix shell script that builds a
+pipeline between \verb+markup+ and \verb+nt+, which reads
+and expands definitions of code chunks.
+\verb+noweave+ pipes the output of \verb+markup+ to a 60-line
+\verb+awk+~script that inserts appropriate {\TeX} or {\LaTeX}
+formatting commands.
+
+\section{Extending {\tt noweb}}
+
+Having a format easily read by programs makes {\tt noweb} extensible;
+one can manipulate literate programs using Unix shell scripts and
+filters.
+{\tt notangle} and {\tt noweave} have {\tt -filter} options that can
+be used to insert filters into their pipelines without changing any
+code.
+These filters manipulate the representation described in the previous
+section.
+The results are converted to {\TeX} by {\tt noweave} and to code by
+{\tt notangle}.
+
+
+Filters can be used to change the way {\tt noweb} works; for example,
+a one-line {\tt sed} script makes {\tt noweb} treat two chunk names as
+identical if they differ only in their representation of whitespace.
+A 55-line Icon program makes it possible to abbreviate chunk names
+using a trailing ellipsis, as in {\tt WEB}.
+To share programs with colleagues who don't enjoy literate
+programming, I use a filter that
+places each line of documentation in a comment and moves it to
+the succeeding code chunk.
+With this filter, \verb+notangle+
+transforms a literate
+program into a traditional commented program, without loss of
+information and with only a modest penalty in readability.
+Figure~\ref{nountangle-output} shows the results of applying
+the filter to the prime-number program shown in
+Figure~\ref{sample-input}.
+
+
+
+
+\begin{figure}
+\begin{webcode}\parindent=0pt
+\{ This program has no input, because we want to keep it \}
+\{ simple. The result of the program will be to produce a \}
+\{ list of the first thousand prime numbers, and this list \}
+\{ will appear on the [[output]] file. \}
+\hbox{\hskip2em\tt\vdots}
+\{ <program to print the first thousand prime numbers>= \}
+program print_primes(output);
+ const m = 1000;
+ \{ \\section-The output phase- \}
+ \{ \}
+ \{ <other constants of the program>= \}
+ rr = 50;
+ cc = 4;
+ ww = 10;
+ \{ <other constants of the program>= \}
+ ord_max = 30; \{ p_ord_max squared must exceed p_m \}
+ var \{ How should table [[p]] be represented? Two possibilities \}
+ \{ suggest themselves: We could construct a sufficiently \}
+\hbox{\hskip2em\tt\vdots}
+\end{webcode}
+\caption{Output produced from
+Figure~\protect\ref{sample-input} by filter converting documentation
+chunks into comments.}
+\label{nountangle-output}
+\end{figure}
+
+
+
+Filters can be used to add significant features.
+\verb+noweave+'s cross-reference and indexing features use two
+filters, one that finds uses of defined identifiers and one that
+uses \verb+@literal+ to insert {\LaTeX} cross-reference
+commands.
+In many cases, a third, language-dependent filter can be used to
+mark identifier definitions,
+making index generation completely automatic;
+otherwise, the \verb+btdefn+ filter can be used to interpret
+hand-place backticks (`) as marking definitions.
+Kostas Oikonomou of AT\&T Bell Labs and Conrado Martinez-Parra of
+the Univ.\ Politecnica de Catalunya in Barcelona have written filters
+that add prettyprinting to {\tt noweb}.
+Oikonomou's filters prettyprint Icon and Object-Oriented Turing;
+Martinez-Parra's filter prettyprints a variant of Dijkstra's language
+of guarded commands.
+
+
+\section{Comparing {\tt WEB} and {\tt noweb}}
+
+Unlike {\tt WEB},
+\verb+noweb+ is independent of the target programming language.
+{\tt WEB} tools can be generated for many programming languages,
+but those languages must be lexically similar to C.
+For example, {\tt WEB} can't handle the \verb+awk+ regular-expression
+notation ``\verb+/+\ldots\verb+/+''; every such expression must quoted
+using {\tt WEB}'s ``verbatim'' control sequence.
+The effort required to
+generate {\tt WEB} tools is significant; the prospective user must
+write a specification of several hundred
+lines.
+
+Being independent of the target programming language makes {\tt noweb}
+simpler, but it also means that {\tt noweb} can do less.
+Most of the differences between {\tt WEB} and {\tt noweb} arise
+because {\tt WEB} has language-dependent features that are not present
+in \verb+noweb+.
+These features include
+prettyprinting,
+typesetting comments using {\TeX},
+expanding macros,
+evaluating constant expressions,
+and
+converting string literals to indices into a ``string pool.''
+Among these features,
+\verb+noweb+ users are most likely to miss prettyprinting.
+
+
+Some differences arise because {\tt WEB} and \verb+noweb+ implement
+similar features differently.
+{\tt WEB}'s original {\tt TANGLE} removed white space and folded
+lines to fill each line with tokens,
+making its output unreadable~\cite[Chapter~4, Figure~3]{knuth:literate:book}.
+Later adaptations preserved line breaks but removed other white space.
+By default, \verb+notangle+ preserves whitespace and maintains
+indentation when expanding chunks.
+It can therefore be used with
+languages like Miranda and
+Haskell, in which indentation is significant.
+{\tt TANGLE} cannot.
+
+{\tt WEB}'s {\tt WEAVE} assigns a number to each chunk, and its index
+and cross-reference
+information refer to chunk numbers, not page numbers.
+\verb+noweb+ uses {\LaTeX} to emit index and cross-reference information that
+refer to page numbers.
+Anyone who has read a large literate program will
+appreciate the difference.
+
+{\tt WEB} works poorly with \LaTeX; \LaTeX\ constructs cannot
+be used in {\tt WEB} source, and getting {\tt WEAVE} output
+to work in \LaTeX\ documents requires tedious adjustments by hand.
+\verb+noweb+ works with both plain {\TeX} and {\LaTeX}.
+Both {\tt WEAVE} and {\tt noweave} depend on the text formatter in two
+ways: the source of the program itself, and the supporting macros.
+{\tt WEAVE}'s source (written using {\tt WEB} for C) is
+several thousand lines long, and the formatting code is not isolated.
+{\tt noweave}'s source is a 200-line shell script, and it uses a
+60-line {\tt awk} program to generate {\TeX}.
+Both
+{\tt WEAVE} and {\tt noweave} use about 200 lines of supporting macros
+for plain {\TeX}.
+\verb+noweb+ uses another 300 lines to support {\LaTeX}, primarily
+because the page-based cross-reference mechanism is complex.
+
+{\tt noweb} has
+two features that weren't in the original {\tt WEB}, but that appeared in
+some of {\tt WEB}'s later adaptations;
+{\tt notangle} can extract more than one program from
+a single source file, and it can give a compiler the original locations
+of source lines.
+{\tt noweb} has a related feature not found in the {\tt WEB} variants;
+{\tt noweave} adds no newlines to its output, making it easy to find
+the sources of {\TeX} or {\LaTeX} errors.
+For example, an error on line~634 of a generated
+{\TeX} file is caused by a problem on line~634 of the
+corresponding {\tt noweb} file.
+
+Reviewers have had many expectations of literate-programming
+tools~\cite{thimbleby:review,cvw:assessment}.
+The most important is {\em verisimilitude}: a single
+input should produce both compilable program and publishable document,
+warranting the correctness of the document.
+Others include flexible order of elaboration,
+ability to develop program and documentation concurrently in one
+place, cross-references, and indexing.
+Both {\tt WEB} and {\tt noweb}
+satisfy all these expectations, although in both cases automatic
+indexing is available for a limited set of programming languages.
+
+
+\section{Discussion}
+
+{\tt WEB} takes the monolithic approach to literate programming---it
+does everything.
+{\tt noweb}'s approach is to compose
+simple tools that manipulate files in the {\tt noweb} format.
+Existing Unix tools provide some of the {\tt WEB} features that
+aren't found in \verb+noweb+.
+Unix supplies two macro processors: the C
+preprocessor and the \verb+m4+ macro processor.
+\verb+xstr+ extracts string literals.
+\verb+patch+ provides a form of version control similar to {\tt WEB}'s
+change files.
+Few of {\tt WEB}'s remaining features will be missed; for example, many compilers
+evaluate constant expressions at compile time.
+Experience with {\tt WEB} has suggested that prettyprinting may be
+more trouble than it is worth~\cite{ramsey:literate}.
+
+{\tt noweb} was developed on Unix and uses Unix tools like {\tt
+awk} and the Bourne shell, but the only Unix feature it really needs
+is the pipeline.
+All components written in {\tt awk} have been duplicated in Icon;
+an Icon implementation is freely available from the University of Arizona, and
+it runs on a wide variety of hardware and operating-system platforms.
+{\tt noweb} can be ported to non-Unix platforms provided they have
+pipelines or an emulation thereof, ANSI~C, and either {\tt awk} or Icon.
+For example,
+Lee Wittenberg of Kean College ported {\tt noweb} to MS-DOS by
+rewriting the shell scripts as DOS batch files.
+
+Indexing and cross-referencing make
+{\tt noweb} less simple than it could be.
+Complex {\LaTeX} code is needed to compute page numbers for use in
+cross-reference lists and in the index.
+The ability to use page numbers justifies this complexity, especially
+since the complexity can be hidden from most users.
+Users do need to understand the {\LaTeX} code if they want to customize the
+appearance of their {\tt noweb} documents while retaining {\tt
+noweb}'s use of page numbers for cross-reference.
+Most literate-programming tools
+forbid customization, but not all users will accept such a restriction.
+I have compromised between simplicity and customizability by adding
+{\LaTeX} options for a dozen of the most commonly requested
+customizations; users can choose from among these options without
+understanding {\tt noweb}'s {\LaTeX} code.
+
+
+Four things distinguish {\tt noweb} from previous work.
+{\tt noweb} takes as simple as possible a view of literate programming
+and the tools needed to implement it.
+Instead of relying on a generator or re-implementation to support
+different programming languages, {\tt noweb} is independent of the
+target programming language.
+{\tt noweave}'s dependence on its typesetter is small and isolated,
+instead of being distributed throughout a large implementation.
+Users have extended {\tt noweb} without recompiling its source code.
+
+Experimenting with {\tt noweb} is easy because the tools are simple
+and they work with any language.
+If the experiment is unsatisfying, it is easy to abandon, because
+\verb+notangle+'s output, unlike {\tt TANGLE}'s, is readable.
+\verb+noweb+ is simpler than {\tt WEB}, and it is easier to use and
+understand, but it does less.
+I argue, however, that the benefit of {\tt WEB}'s extra features is
+outweighed by cost of the extra complexity,
+making \verb+noweb+ better for writing literate programs.
+
+\verb+noweb+ can be obtained by
+anonymous {\tt ftp} from CTAN,
+the Comprehensive {\TeX}
+Archive Network, in directory {\tt web/noweb}. CTAN replicas appear
+on
+hosts {\tt ftp.shsu.edu}, {\tt ftp.tex.ac.uk}, and {\tt ftp.uni-stuttgart.de}.
+
+\section{Acknowledgements}
+Mark Weiser's invaluable encouragement provided the impetus for me to
+write this paper, which I did while visiting the Computer
+Science Laboratory of the Xerox Palo Alto Research Center.
+David Hanson suggested and provided the \verb+cpif+ program.
+Preston Briggs developed many of the ideas used in \verb+noweb+'s
+indexing, and he contributed code used in one of the pipeline stages.
+Dave Love provided much-needed {\LaTeX} expertise.
+Comments from David Hanson and from the anonymous referees stimulated
+me to improve the paper.
+The development of {\tt noweb} was supported by a Fannie and John Hertz
+Foundation Fellowship.
+
+This paper was submitted in August, 1991.
+
+\bibliographystyle{abbrv}
+\bibliography{web,cs,ramsey,ml}
+
+\clearpage
+\noweboptions{shift} % needed to make room for wordcount example
+
+\input wc
+
+\end{document}
diff --git a/web/noweb/test/regression b/web/noweb/test/regression
new file mode 100755
index 0000000000..c66eb0cb71
--- /dev/null
+++ b/web/noweb/test/regression
@@ -0,0 +1,82 @@
+#!/usr/bin/env lua5.1-courseware
+
+require 'osutil'
+
+local posix = require 'courseware-posix'
+
+local stringf = string.format
+local function runf(...) return os.execute(string.format(...)) end
+local function eprintf(...) return io.stderr:write(string.format(...)) end
+
+local backends = { 'toascii', 'toroff', 'unmarkup', 'nt', 'tohtml', 'totex' }
+
+local filters = { 'noidx' }
+
+local fields = (require 'flags').parser()
+ :string('old', '/usr/lib/noweb'):help('installation directory of old version')
+ :numarg(1)
+ :parse(arg)
+
+local newdir = assert(arg[1])
+
+local function outfiles(command)
+ local tmp = os.capture 'mktemp'
+ local tmp2 = os.capture 'mktemp'
+ runf('%s > %s 2> %s', command, tmp, tmp2)
+ return tmp, tmp2
+end
+
+local options = { nt = '-R*' }
+
+local pipelines = { }
+do
+ local function extend(c, i)
+ local n = i == nil and #pipelines or i < 0 and #pipelines + 1 + i or i
+ assert(pipelines[n])
+ local next = stringf('%s | %s', pipelines[n], stringf('$L/%s %s', c, options[c] or ''))
+ table.insert(pipelines, next)
+ end
+
+ table.insert(pipelines, '$L/markup %s')
+ for _, f in ipairs(filters) do
+ if posix.access(stringf('%s/%s', newdir, f)) then
+ extend(f)
+ end
+ end
+ for i = 1, #pipelines do
+ for _, b in ipairs(backends) do
+ extend(b, i)
+ end
+ end
+end
+
+local sources = os.capture('echo $HOME/noweb/dist/src/c/*.nw')
+
+
+for _, p in ipairs(pipelines) do
+ eprintf('%s\n', p)
+ for f in sources:gmatch '%S+' do
+ local oldc = stringf(p:gsub('%$L', fields.old), f)
+ local newc = stringf(p:gsub('%$L', newdir), f)
+ local oldout, o2 = outfiles(oldc)
+ local newout, n2 = outfiles(newc)
+
+ local rc = runf('cmp -s %s %s', oldout, newout)
+ local rc2 = runf('cmp -s %s %s', o2, n2)
+ if rc ~= 0 or rc2 ~= 0 then
+ eprintf('FAILED: %s\n %s\n', oldc, newc)
+ if rc2 ~= 0 then
+ runf('colordiff -u %s %s | head -40', o2, n2)
+ end
+ if rc ~= 0 then
+ runf('colordiff -u %s %s | head -40', oldout, newout)
+ end
+ os.exit(1)
+ else
+ os.remove(oldout)
+ os.remove(newout)
+ end
+ end
+end
+
+